专门针对安全性

时间:2016-07-12 11:23:19

标签: javascript api rest security encryption

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

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

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

用户的同步过程如下:

  1. 用户下载应用程序,并在使用该应用程序的过程中创建数据。
  2. 当用户准备初始同步时,他们输入一个"密码"在密码字段中,用于创建用于加密其数据的复杂密钥。他们的密码以纯文本格式存储在本地,但从未发送到服务器。
  3. 用户点击"同步"按钮,他们的数据被加密(使用他们的密码)并发送到指定的(或默认的)API实例,并通过给他们一个由应用程序保存的唯一ID进行响应。
  4. 对于将来的同步,他们的数据会在发送到API之前使用他们保存的密码进行本地加密,并附带更新服务器上同步数据的唯一ID。
  5. 检索同步数据时,会将其唯一ID发送给API,该API会使用其加密数据进行响应。然后,他们使用本地存储的密码来解密数据以供应用程序使用。
  6. 我已经在javascript中实现了应用程序,并且使用MongoDB作为后端在Node.js(restify)中实现了API,因此实际上对服务器的同步请求如下所示:

    1。初始同步

    POST / api / data

    发帖机构:

    {
        "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相当容易猜测,恶意用户可能通过猜测其ID来请求其他人的数据(按照步骤2.获取同步数据)。但是,如果它们成功,它们将仅检索加密数据,并且不具有用于解密它的密钥。这同样适用于有权访问服务器上数据库的任何人。
    • 鉴于上述情况,CryptoJS AES实施是否足够安全,以便恶意用户检测到用户的加密数据的真实可能性,他们实际上无法解密数据?
    • 由于API对任何人开放,并且未审核或检查提交的数据,因此任何人都可能提交他们希望存储在服务中的任何数据,例如:

    发帖机构:

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

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

    • 一般滥用服务,例如用户垃圾邮件初始同步(上面的步骤1)反复填写服务器上的空间;或某些用户使用不成比例的大量服务器空间。我已经实现了一些功能来防范这种情况,例如为一天的初始同步记录IP(不会保留不长于此),以便将单个IP限制为每天初始同步的设定数量。我也限制了同步的帖子体型。这些选项在API中是可配置的,因此如果用户不喜欢公共API实例上的这些限制,他们可以托管自己的实例并根据自己的喜好调整设置。

    所以,我很感激任何根据我的指导原则对这种方法有任何想法或反馈的人。我无法找到其他应用尝试类似方法的任何示例,因此,如果有人知道任何可以链接到他们并且可以链接到他们,我将不胜感激。

1 个答案:

答案 0 :(得分:0)

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

您可以使用验证码或类似防范自动使用来防止滥用,而无需其他帐户。如果您需要新帐户,并对数据量和通话频率的所有帐户设置限制,您应该没问题。

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

data = secondary_key(user_private_key(cleartext))

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

对您的API发表一些评论:)如果您已经在使用HTTP和POST,那么您真的不需要idPOST通常会返回指向已创建数据的URI。然后,您可GET URIPUT进行更改:

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

响应:

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

要改变它:

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

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