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



我正在构建一个应用程序,希望对我构建数据同步过程的方法和支持它的API提供一些反馈。就上下文而言,以下是我的应用程序/API的指导原则:

  • 免费:我根本不想向使用应用程序/API的人收费
  • 开源:应用程序和API的源代码可供公众随意使用
  • 分散:支持应用程序的API服务可以由任何服务器上的任何人运行,并可供应用程序用户使用
  • 匿名:用户不应该注册该服务,也不应该提交任何将与他们的数据一起存储的个人身份信息
  • 安全:用户的数据在发送到服务器之前应该加密,任何有权访问服务器的人都不能读取用户的数据

我将在公共服务器上实现API的实例,该实例将在应用程序中默认选择。这样,应用程序的初始用户可以直接同步他们的数据,而无需找到或设置API服务的实例。随着时间的推移,如果该应用程序很受欢迎,那么用户将有望为自己设置API服务的其他实例,或者如果他们希望使用不同的实例(或者如果主实例空间不足、宕机等),则向该应用程序的其他用户提供这些实例。他们甚至可以在自己的应用程序中访问API。从本质上讲,我希望他们能够选择自给自足,而不必出于隐私、弹性、成本节约等原因,依赖他人为他们提供服务实例。注意:有问题的数据不敏感(即财务等),但它是个人的。

用户的同步过程是这样的:

  1. 用户下载应用程序,并在使用应用程序的过程中创建数据
  2. 当用户准备好初始同步时,他们会在密码字段中输入一个"密码",用于创建一个复杂的密钥来加密他们的数据。他们的密码以纯文本形式存储在本地,但从不发送到服务器
  3. 用户点击"同步"按钮,他们的数据被加密(使用他们的密码)并发送到指定的(或默认的)API实例,并通过给他们一个由应用程序保存的唯一ID来响应
  4. 对于未来的同步,在将其数据发送到API之前,将使用其保存的密码对其数据进行本地加密,并将其唯一ID与更新服务器上同步数据的唯一ID一起发送
  5. 当检索同步数据时,他们的唯一ID被发送到API,后者以他们的加密数据进行响应。然后,他们本地存储的密码用于解密数据,供应用程序使用

我在javascript中实现了该应用程序,在Node.js(restify)中实现了API,并将MongoDB作为后端,因此在实践中,对服务器的同步请求如下:

1.初始同步

POST/api/数据

岗位主体:

{
"data":"DWCx6wR9ggPqPRrhU4O4oLN5P09onApoAULX4Xt+ckxswtFNH/QQ+Y/RgxdU+8+8/muo4jo/jKnHssSezvjq6aPvYK+EAzAoRmXenAgUwHOjbiAXFqF8gScbbuLRlF0MsTKn/puIyFnvJd..."
}

响应:

{
"id":"507f191e810c19729de860ea",
"lastUpdated":"2016-07-06T12:43:16.866Z"
}

2.获取同步数据

GET/api/data/507f191e810c19729de860ea

响应:

{
"data":"DWCx6wR9ggPqPRrhU4O4oLN5P09onApoAULX4Xt+ckxswtFNH/QQ+Y/RgxdU+8+8/muo4jo/jKnHssSezvjq6aPvYK+EAzAoRmXenAgUwHOjbiAXFqF8gScbbuLRlF0MsTKn/puIyFnvJd...",
"lastUpdated":"2016-07-06T12:43:16.866Z"
}

3.更新同步数据

POST/api/data/507f191e810c19729de860ea

岗位主体:

{
"data":"DWCx6wR9ggPqPRrhU4O4oLN5P09onApoAULX4Xt+ckxswtFNH/QQ+Y/RgxdU+8+8/muo4jo/jKnHssSezvjq6aPvYK+EAzAoRmXenAgUwHOjbiAXFqF8gScbbuLRlF0MsTKn/puIyFnvJd..."
}

响应:

{
"lastUpdated":"2016-07-06T13:21:23.837Z"
}

他们在MongoDB中的数据如下:

{
"id":"507f191e810c19729de860ea",
"data":"DWCx6wR9ggPqPRrhU4O4oLN5P09onApoAULX4Xt+ckxswtFNH/QQ+Y/RgxdU+8+8/muo4jo/jKnHssSezvjq6aPvYK+EAzAoRmXenAgUwHOjbiAXFqF8gScbbuLRlF0MsTKn/puIyFnvJd...",
"lastUpdated":"2016-07-06T13:21:23.837Z"
}

加密目前使用CryptoJS的AES实现。当应用程序将用户的密码作为密码短语提供给AES"加密"功能时,它会生成一个256位的密钥,用于在发送到API之前加密用户的数据。

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

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

帖子正文:

{
"data":"This is my anyold data..."
}

在遵守上述指导原则的同时,我能做些什么来防止这种情况发生吗?

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

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

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

你可以在不需要其他账户的情况下,通过使用captchas或类似的自动使用保护措施来防止滥用。如果你需要对新账户进行拦截,并对所有账户的数据量和通话频率设置限制,你应该可以

为了防止意外的明文数据,您可以为每个帐户生成一个辅助密钥,然后使用公共辅助密钥在服务器上检查消息是否可以解密。类似这样的东西:

data = secondary_key(user_private_key(cleartext))

通过这种方式,数据将始终被加密,在最坏的情况下,服务器将能够读取数据,但其他服务器则无法读取。

对API的一些评论:)如果您已经在使用HTTP和POST,那么实际上不需要id。CCD_ 2通常返回指向创建的数据的CCD_ 3。然后你可以GETURI,或PUT它来改变:

POST /api/data
{"data": "..."}

响应:

Location: /api/data/12345
{"data": "...", "lastmodified": "..." }

更改:

PUT /api/data/12345
{"data": "..."}

您不必这样做,但它可能更容易在客户端实现,甚至可能有助于缓存和缓存无效。

相关内容

  • 没有找到相关文章

最新更新