2016-07-12 28 views
1

我正在构建一个应用程序,并希望对构建数据同步过程和支持它的API的方法提供一些反馈。对于上下文,这些是我的应用程序/ API的指导原则:专门针对安全性的应用程序API设计建议

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

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

用户的同步之旅是这样的:

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

我实现了在JavaScript的应用程序,并作为后端的Node.js的(的RESTify)与MongoDB中的API,所以在实践中,同步对服务器的请求是这样的:

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 /数据/ 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“加密”功能,因此它会在发送给API之前生成一个256位密钥,用于加密用户的数据。

这是关于总结同步过程,它非常简单,但显然它需要安全和可靠。我的担心是:

  • 由于MongoDB的对象ID是很容易猜到,它有可能是恶意用户可以请求别人的数据(按照步骤2.获取同步数据)通过猜测他们的ID。但是,如果它们成功了,它们只会检索加密的数据,并且不会有解密它的密钥。任何人都可以访问服务器上的数据库,这同样适用。
  • 考虑到上述情况,CryptoJS AES实施是否足够安全,以至于用户的加密数据实际上可能由恶意用户检索到,他们实际上不能解密数据?
  • 由于API是对所有人开放,不审计或检查提交的数据,任何人都可能会提出他们希望被存储在服务中的任何数据,例如:

帖子正文:

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

在坚持上述指导原则的同时,我能做些什么来防范这一点吗?

  • 服务的一般滥用,例如用户反复发送初始同步(上面的第1步)以填满服务器上的空间;或某些用户使用不成比例的大量服务器空间。我已经实施了一些功能来防止这种情况发生,例如记录一天IP的初始同步(不保留更长时间),以便将单个IP限制为每天一组初始同步。此外,我正在限制同步的帖子主体大小。但是,这些选项可以在API中配置,因此如果用户不喜欢公共API实例的这些限制,他们可以托管自己的实例并根据自己的喜好调整设置。

就这样,我希望任何对我的指导原则有任何想法或有关此方法的反馈意见。我找不到其他应用程序尝试过类似方法的示例,因此如果有人知道任何其他应用程序并且可以链接到它们,我会很感激。

回答

0

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

您可以通过使用验证码或类似的自动防护措施来防止滥用,而无需使用其他帐户。如果您需要在新帐户上使用catcha帐户,并为数据量和通话频率上的所有帐户设置限制,则应该可以。

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

data = secondary_key(user_private_key(cleartext)) 

这样的数据总是被加密,并且在最坏的情况下,服务器将能够读取它,但其他人不会。

对你的API的一些评论:)如果你已经使用HTTP和POST,你并不需要idPOST通常会返回指向创建的数据的URI。然后,您可以GETURI,或PUT它改变:

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

响应:

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

要改变它:

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

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

+0

非常感谢Robert的有用建议,并花时间回答。 –