如何仅使用对称加密在客户端和服务器之间以安全的方式发送数据

How to send data in secure way between client and server using only Symmetric cryptography

我将采取以下步骤 send/received 客户端和服务器之间的数据。但我不确定是否所有步骤都足够安全且无法拦截。如果有的话,请告诉我如何修补安全漏洞? 请注意:

  • 这是对称加密的全部内容,而不是 Public/Private 密钥方法。所以'salt'和'entropy'是客户端和服务器之间的秘密。
  • 出于某些原因,我cannot/don不使用 SSL 或 TLS 协议。所以没有证书颁发机构等
  • 只能使用标准的密码函数和方法(没有发明)。
  • 数据未通过安全 (HTTPS) 连接发送。
  • 我不能在这里使用会话,因为它们是两个不同的应用程序。
  • 第一次-注册(用户输入新用户名和新密码)

    1. 客户端
      1. 为用户创建一个CSPRNG salt
        1. 在用户机器上保存salt
      2. 在内存中创建一个熵(时间值的 base64,例如 [一天中的小时]+[一年中的第几天])
      3. Post 密码(明文的 base64 ), salt, and entropy 到服务器
    2. 服务器端
      1. 对于从客户端接收到的消息
        1. 检查熵是否匹配(例如与[一天中的小时]+[一年中的一天]的base64匹配).
        2. 计算 salt 和密码的散列 (SHA1)(明文的 base64)- 因为散列必须始终在服务器上完成。
        3. 保存 salt 和计算的散列到数据库

    下次-登录(用户输入用户名和密码)

    1. 客户端
      1. 从用户机器读取salt
      2. 计算salt的哈希值(SHA1)和输入的密码(明文的base64)
      3. Post 密码(明文的 base64),和盐,以及计算到服务器的散列​​
    2. 服务器端
      1. 从数据库中取盐'stored hash'
      2. 从客户端收到的消息
        1. 将消息拆分为 3 个部分:密码(paintext 的 base64);盐; 'received hash'
        2. 比较'received hash'和'stored hash';如果它们匹配,则用户是真正的用户而不是黑客

    从用户向服务器发送 TemperProof queryString

    1. 客户端
      1. 从用户机器读取盐
      2. 在内存中创建一个熵(时间值的base64,例如[一天中的小时]+[一年中的第几天])
      3. 计算queryString(明文的base64)的散列(SHA1),salt,熵
      4. Post querystring(明文的base64),salt和熵,以及计算到服务器的哈希值
    2. 服务器端
      1. 从数据库中检索salt
      2. 对于从客户端接收到的消息
        1. 将消息拆分为4个部分:queryString(base64绘画文本);盐;熵; 'received hash'
        2. 检查熵是否匹配(例如,使用 [一天中的小时]+[一年中的天] 的 base64)。
        3. 计算queryString(明文的base64)的哈希(SHA1)和盐和熵。
        4. 将计算的哈希与拆分消息的第4部分('received hash')进行比较;如果它们匹配,queryString 是真实的

    从服务器向用户发回答案

    1. 服务器端
      1. 使用数据库查询计算答案
      2. 从数据库中检索盐
      3. 在内存中创建一个熵(时间值的 base64,例如 [小时一天中的一天]+[一年中的一天])
      4. 计算答案的散列 (SHA1)(明文的 base64),以及盐和熵
      5. Post answer(明文的base64),salt,entropy,计算出的散列给客户端
    2. 客户端
      1. 从用户机器读取盐
      2. 在内存中创建一个熵(时间值的base64,例如[小时the day]+[day of the year])
      3. 将收到的消息拆分为 4 个部分:answer(paintext 的 base64);盐;熵; 'received hash'
      4. 检查熵是否匹配(例如,使用 [一天中的小时]+[一年中的天] 的 base64)。
      5. 计算答案(明文的base64)的哈希(SHA1)和盐和熵。
      6. 将计算的哈希与拆分消息的第4部分('received hash')进行比较;如果匹配,则答案是真实的

    我认为以下方面是弱点。你能告诉我如何解决这些问题并指出其他可能的漏洞吗?

      A) 第一次 - 注册: 如果黑客在步骤 1.3
    中找到熵,他可以 post 垃圾填满数据库
      B) 下次 - 登录: 我想不出一种方法来为步骤 1.2 中的散列密码添加熵,因为这样我就无法与步骤 2.2.2 中的服务器数据库

    谢谢

    如果您完全关心安全性,请立即停止...

    你需要做什么:

    1) 忘记设计你自己的加密协议......依赖众所周知的加密也意味着你不要设计那种东西

    2) 分层思考......你需要在将它们从 A 传输到 B 时保密......这意味着你有一个传输层......如果你想要安全,有一个那个的名字...
    T传输 LS安全 -> https://en.wikipedia.org/wiki/Transport_Layer_Security

    3) 当你在这里做出像 "i have 2 applications so i can not have sessions" 这样的假设时,请提供你认为那样的原因......当你想到单点登录之类的东西时,你可以有很多应用程序在一堆不同的平台上共享一种身份验证方法甚至会话数据......也许只是你不知道你实际上可以有会话......

    4) 仔细阅读您使用的术语……您误解了熵……没有办法 "checking if entropy matches"……加密相关案例中的熵意味着在不可预测的输入方面的随机性功能......如果你有日期和时间之类的东西,即使你散列它,它也可能看起来是随机的......但是对于有时钟的人来说这是非常可预测的......如果通信可以与价值的创造时间,那么如果它是基于时钟的,那么你的价值不包含大量的熵......同样,不要在这里设计你自己的东西,并寻找提供可靠,加密安全随机性的熵源(CSPRNG ...不只是 PRNG)

    5) ... 你 misunderstood/misused 盐... 在客户端机器上不会生成任何内容
    不需要保留在客户端计算机上

    7) 密码散列 再次......不要在这里拿出你自己的东西...... 为每个密码创建足够长的随机盐(至少哈希长度)。使用像 PBKDF2 这样具有高迭代计数参数的慢散列函数。原因是测试密码变得很慢...您的服务器必须为每次登录尝试计算一次...攻击者必须为每次密码测试尝试计算一次...您可以负担得起测试200 毫秒 ... 对于攻击者来说,这意味着需要更多的硬件来破解您的密码存储...

    更新:
    你想要它,你得到它......

    中间人对您的架构的概念验证攻击:

    客户:爱丽丝
    服务器:鲍勃
    attacker/eavesdropper: 晚上

    1. 爱丽丝使用您的注册服务并创建了一个帐户
      1.1 alice 创建一个 CSPRNG 盐并以安全的方式存储它
      1.2 alice收集任意量的熵并用base64
      编码 1.3 alice发送Password(明文的base64)、salt、entropy给bob
      ----------截获------------
    2. eve 拦截了 alice 和 bob 之间的通信并获得了...
      2.1 ...base 64编码密码 -> base64解码 -> 明文密码
      2.2 ...盐
      2.3 ...熵值
      2.4 alice将截获的通信原封不动地转发给bob

    --- 协议被破坏 ---
    现在,鲍勃在所有进一步的交流中都无法区分爱丽丝和夏娃

    upd2:

    查看您传输的(明文)邮件:
    登录:
    Post 密码(明文的 base64)和盐,以及计算到服务器的哈希 将查询字符串从用户发送到服务器:
    Post querystring(base64 of the plaintext), and salt, and entropy, and the computed hash to the server 答案:
    Post answer(明文的 base64),salt,熵,计算出的散列给客户端

    现在,对于这些消息中的任何一条,让我们看看怀有恶意的人会从中获悉哪些信息:

    所有明文信息,也就是说,所有... 对于登录,我们获得明文密码,意味着从现在开始攻击者可以识别为有效用户

    对于您想要的查询字符串和答案,提供一种方法来查看 request/answer 是否未被调和。

    所以,如果攻击者现在拦截了您的通信,他怎么能在不被注意到的情况下更改查询字符串呢? 攻击者拆分您的消息,并更改 he/she 想要的任何内容 然后 he/she 将 forged_hash 计算为 sha1(salt_from_the_original_message,tampered_querystring) 并发送 base64(tampered_querystring),salt_from_the_original_message,entropy_from_original_message ,forged_hash 到服务器 ...

    答案是一样的:

    攻击者拦截原始答案,更改答案中的任何内容并根据已知信息(更改和原始盐)重新计算哈希值

    1. 解决方案是使用带TLS 1.2的HTTPS并固定证书,有免费的证书解决方案。

    2. 一段时间以来,使用哈希(在本例中为 SHA1)来保护密码并不是很好的安全做法。作为参考,请参阅 DRAFT NIST Special Publication 800-63B Digital Authentication Guideline.

    3. 必须使用迭代的 HMAC 而非单个散列来保护密码。有关密码的更多信息,请参阅 Jim Fenton 的 Toward Better Password Requirements,尤其是幻灯片 23。这似乎与 Pluralsight 训练不一致,最佳实践随着时间的推移而改变。