Javascript 专门针对安全性的应用程序API设计建议

Javascript 专门针对安全性的应用程序API设计建议,javascript,api,rest,security,encryption,Javascript,Api,Rest,Security,Encryption,我正在构建一个应用程序,希望得到一些关于我构建数据同步过程的方法和支持该过程的API的反馈。以下是我的应用程序/API的指导原则: 免费:我根本不想向使用应用程序/API的人收费 开源:应用程序和API的源代码可供公众随意使用 分散:支持应用程序的API服务可以由任何服务器上的任何人运行,并可供应用程序用户使用 匿名:用户不必注册该服务,也不必提交任何与数据一起存储的个人身份信息 安全:用户的数据在发送到服务器之前应该进行加密,任何能够访问服务器的人都应该没有读取用户数据的能力 我将在公共服

我正在构建一个应用程序,希望得到一些关于我构建数据同步过程的方法和支持该过程的API的反馈。以下是我的应用程序/API的指导原则:

  • 免费:我根本不想向使用应用程序/API的人收费
  • 开源:应用程序和API的源代码可供公众随意使用
  • 分散:支持应用程序的API服务可以由任何服务器上的任何人运行,并可供应用程序用户使用
  • 匿名:用户不必注册该服务,也不必提交任何与数据一起存储的个人身份信息
  • 安全:用户的数据在发送到服务器之前应该进行加密,任何能够访问服务器的人都应该没有读取用户数据的能力
我将在公共服务器上实现API的一个实例,默认情况下将在应用程序中选择该实例。这样,应用程序的初始用户就可以直接同步数据,而无需查找或设置API服务的实例。随着时间的推移,如果应用程序很受欢迎,那么用户希望为自己设置API服务的其他实例,或者在希望使用其他实例的情况下(或者如果主实例空间不足、出现故障等),为应用程序的其他用户提供API服务。他们甚至可以在自己的应用程序中访问API。基本上,出于隐私、弹性、成本节约等原因,我希望他们能够选择自给自足,而不必依赖他人为他们提供服务实例。注意:相关数据不敏感(即财务等),但属于个人数据

用户的同步旅程如下所示:

{
    "id":"507f191e810c19729de860ea",
    "data":"DWCx6wR9ggPqPRrhU4O4oLN5P09onApoAULX4Xt+ckxswtFNH/QQ+Y/RgxdU+8+8/muo4jo/jKnHssSezvjq6aPvYK+EAzAoRmXenAgUwHOjbiAXFqF8gScbbuLRlF0MsTKn/puIyFnvJd...",
    "lastUpdated":"2016-07-06T13:21:23.837Z"
}
data = secondary_key(user_private_key(cleartext))
  • 用户下载应用程序,并在使用应用程序的过程中创建数据
  • 当用户准备好进行初始同步时,他们会在密码字段中输入一个“密码”,用于创建一个复杂的密钥来加密他们的数据。他们的密码以明文形式存储在本地,但从未发送到服务器
  • 用户单击“同步”按钮,他们的数据将被加密(使用密码)并发送到指定(或默认)API实例,并通过给他们一个由应用程序保存的唯一ID进行响应
  • 对于将来的同步,在将其数据发送到API之前,将使用保存的密码对其数据进行本地加密,并使用其唯一ID更新服务器上的同步数据
  • 检索同步数据时,其唯一ID将发送到API,API将以其加密数据进行响应。然后使用本地存储的密码解密数据,供应用程序使用
  • 我已经用javascript实现了应用程序,并在Node.js(restify)中使用MongoDB作为后端实现了API,因此在实践中,对服务器的同步请求如下所示:

    {
        "id":"507f191e810c19729de860ea",
        "data":"DWCx6wR9ggPqPRrhU4O4oLN5P09onApoAULX4Xt+ckxswtFNH/QQ+Y/RgxdU+8+8/muo4jo/jKnHssSezvjq6aPvYK+EAzAoRmXenAgUwHOjbiAXFqF8gScbbuLRlF0MsTKn/puIyFnvJd...",
        "lastUpdated":"2016-07-06T13:21:23.837Z"
    }
    
    data = secondary_key(user_private_key(cleartext))
    
    1。初始同步

    POST/api/data

    邮政机构:

    {
        "data":"DWCx6wR9ggPqPRrhU4O4oLN5P09onApoAULX4Xt+ckxswtFNH/QQ+Y/RgxdU+8+8/muo4jo/jKnHssSezvjq6aPvYK+EAzAoRmXenAgUwHOjbiAXFqF8gScbbuLRlF0MsTKn/puIyFnvJd..."
    }
    
    {
        "data":"DWCx6wR9ggPqPRrhU4O4oLN5P09onApoAULX4Xt+ckxswtFNH/QQ+Y/RgxdU+8+8/muo4jo/jKnHssSezvjq6aPvYK+EAzAoRmXenAgUwHOjbiAXFqF8gScbbuLRlF0MsTKn/puIyFnvJd..."
    }
    
    {
        "data":"This is my anyold data..."
    }
    
    答复:

    {
        "id":"507f191e810c19729de860ea",
        "lastUpdated":"2016-07-06T12:43:16.866Z"
    }
    
    {
        "data":"DWCx6wR9ggPqPRrhU4O4oLN5P09onApoAULX4Xt+ckxswtFNH/QQ+Y/RgxdU+8+8/muo4jo/jKnHssSezvjq6aPvYK+EAzAoRmXenAgUwHOjbiAXFqF8gScbbuLRlF0MsTKn/puIyFnvJd...",
        "lastUpdated":"2016-07-06T12:43:16.866Z"
    }
    
    {
        "lastUpdated":"2016-07-06T13:21:23.837Z"
    }
    
    Location: /api/data/12345
    {"data": "...", "lastmodified": "..." }
    
    2。获取同步数据

    GET/api/data/507f191e810c19729de860ea

    答复:

    {
        "id":"507f191e810c19729de860ea",
        "lastUpdated":"2016-07-06T12:43:16.866Z"
    }
    
    {
        "data":"DWCx6wR9ggPqPRrhU4O4oLN5P09onApoAULX4Xt+ckxswtFNH/QQ+Y/RgxdU+8+8/muo4jo/jKnHssSezvjq6aPvYK+EAzAoRmXenAgUwHOjbiAXFqF8gScbbuLRlF0MsTKn/puIyFnvJd...",
        "lastUpdated":"2016-07-06T12:43:16.866Z"
    }
    
    {
        "lastUpdated":"2016-07-06T13:21:23.837Z"
    }
    
    Location: /api/data/12345
    {"data": "...", "lastmodified": "..." }
    
    3。更新同步数据

    POST/api/data/507f191e810c19729de860ea

    邮政机构:

    {
        "data":"DWCx6wR9ggPqPRrhU4O4oLN5P09onApoAULX4Xt+ckxswtFNH/QQ+Y/RgxdU+8+8/muo4jo/jKnHssSezvjq6aPvYK+EAzAoRmXenAgUwHOjbiAXFqF8gScbbuLRlF0MsTKn/puIyFnvJd..."
    }
    
    {
        "data":"DWCx6wR9ggPqPRrhU4O4oLN5P09onApoAULX4Xt+ckxswtFNH/QQ+Y/RgxdU+8+8/muo4jo/jKnHssSezvjq6aPvYK+EAzAoRmXenAgUwHOjbiAXFqF8gScbbuLRlF0MsTKn/puIyFnvJd..."
    }
    
    {
        "data":"This is my anyold data..."
    }
    
    答复:

    {
        "id":"507f191e810c19729de860ea",
        "lastUpdated":"2016-07-06T12:43:16.866Z"
    }
    
    {
        "data":"DWCx6wR9ggPqPRrhU4O4oLN5P09onApoAULX4Xt+ckxswtFNH/QQ+Y/RgxdU+8+8/muo4jo/jKnHssSezvjq6aPvYK+EAzAoRmXenAgUwHOjbiAXFqF8gScbbuLRlF0MsTKn/puIyFnvJd...",
        "lastUpdated":"2016-07-06T12:43:16.866Z"
    }
    
    {
        "lastUpdated":"2016-07-06T13:21:23.837Z"
    }
    
    Location: /api/data/12345
    {"data": "...", "lastmodified": "..." }
    
    他们在MongoDB中的数据如下所示:

    {
        "id":"507f191e810c19729de860ea",
        "data":"DWCx6wR9ggPqPRrhU4O4oLN5P09onApoAULX4Xt+ckxswtFNH/QQ+Y/RgxdU+8+8/muo4jo/jKnHssSezvjq6aPvYK+EAzAoRmXenAgUwHOjbiAXFqF8gScbbuLRlF0MsTKn/puIyFnvJd...",
        "lastUpdated":"2016-07-06T13:21:23.837Z"
    }
    
    data = secondary_key(user_private_key(cleartext))
    
    加密目前使用CryptoJS的AES实现。由于应用程序将用户密码作为密码短语提供给AES“encrypt”函数,因此它会生成一个256位密钥,用于在发送到API之前加密用户数据

    这概括了同步过程,它相当简单,但显然它需要安全可靠。我关注的是:

    • 由于MongoDB ObjectID相当容易猜测,恶意用户可能会通过猜测他人的ID来请求他人的数据(按照步骤2.获取同步数据)。但是,如果他们成功,他们将只检索加密数据,而没有解密数据的密钥。这同样适用于任何有权访问服务器上数据库的人
    • 鉴于上述情况,CryptoJS AES实现是否足够安全,以便在恶意用户检索用户加密数据的实际可能性中,他们实际上无法解密数据
    • 由于API对任何人开放,并且不审核或检查提交的数据,因此任何人都可能提交他们希望存储在服务中的任何数据,例如:
    邮政机构:

    {
        "data":"DWCx6wR9ggPqPRrhU4O4oLN5P09onApoAULX4Xt+ckxswtFNH/QQ+Y/RgxdU+8+8/muo4jo/jKnHssSezvjq6aPvYK+EAzAoRmXenAgUwHOjbiAXFqF8gScbbuLRlF0MsTKn/puIyFnvJd..."
    }
    
    {
        "data":"DWCx6wR9ggPqPRrhU4O4oLN5P09onApoAULX4Xt+ckxswtFNH/QQ+Y/RgxdU+8+8/muo4jo/jKnHssSezvjq6aPvYK+EAzAoRmXenAgUwHOjbiAXFqF8gScbbuLRlF0MsTKn/puIyFnvJd..."
    }
    
    {
        "data":"This is my anyold data..."
    }
    
    在遵守上述指导原则的同时,我能做些什么切实可行的事情来防范这种情况

    • 一般滥用服务,如用户反复发送初始同步(上面的步骤1),以填满服务器上的空间;或者一些用户使用了过多的服务器空间。我已经实现了一些防止这种情况发生的功能,比如记录一天初始同步的IP(不超过一天),以便将单个IP限制为每天一定数量的初始同步。我还限制了同步的正文大小。但是,这些选项在API中是可配置的,因此如果用户不喜欢公共API实例上的这些限制,他们可以托管自己的实例,并根据自己的喜好调整设置

    就这样,我非常感谢任何人根据我的指导原则对这种方法有任何想法或反馈。我找不到任何其他应用程序尝试过类似方法的例子,因此如果有人知道并可以链接到它们,我将不胜感激。

    我无法评论特定AES算法/密钥是否安全,但假设它们是安全的(并且密钥生成正确),如果其他用户可以访问加密数据,这应该不是问题

    您可以通过使用CAPTCHA或类似的防止自动使用的措施来防止滥用,而无需其他帐户。如果您需要新客户的catcha,请