【问题标题】:Sending messages between two clients, how to verify the identity of the sender?两个客户端之间发送消息,如何验证发送者的身份?
【发布时间】:2010-11-04 01:19:29
【问题描述】:

假设您有两个客户端,C1 和 C2,每个客户端都有一个与之关联的 GUID。

当您在 C2 上收到一条消息时,假定来自 C1(通过检查 GUID 并看到它与 C1 的 GUID 匹配),但是由于不能保证该消息来自 C1(C3 可能刚刚发送了消息,在消息头中发送了 C1 的 GUID)必须验证消息实际上来自 C1。

我一直在研究使用非对称加密 (RSA) 让 C1 发送一条包含 [C1.GUID; RSAEncrypt(C2.PUBLIC_KEY, C1.GUID); MESSAGE] 的消息,然后让 C2 基本上做这样的检查(python 伪代码):

message.GUID == RSADecrypt(C2.PRIVATE_KEY, message.ENCRYPTED_GUID)

这是一种可行的方法吗?还是有其他一些更聪明/更明显的方法来验证消息的发件人?

【问题讨论】:

  • 你考虑过 SSL 吗?
  • @battal - SSL 仅加密客户端 1 和客户端 2 之间的信息。它无助于验证客户端 1 是客户端 1 而不是客户端 3。它只会阻止客户端 3 监听事务。
  • 您没有告诉如何您发送消息。您可能希望使用 WCF,它允许您为此目的使用 X.509 证书。您无需编写任何程序即可使用该证书,只需将证书添加到您的配置文件中即可。此处显示了一个示例:codeproject.com/KB/WCF/wcfcertificates.aspx
  • @0xA3,好主意,但这更像是一个关于如何验证发件人身份的一般问题(即使应用程序是用 F#/C#/.NET 编写的),不,我不能由于设备限制,不能使用 WCF。
  • 即使在编辑之后,这仍然是不安全的,不能用于您的目的!公钥意味着任何人都知道。但是你的概念需要保密!你需要一个数字签名!

标签: c# .net encryption rsa encryption-asymmetric


【解决方案1】:

为此目的发明了非对称算法,这就是数字签名的工作方式。

但是,您的方法存在一些问题。任何拥有收件人公钥的人都可以伪造签名。此外,签名根本没有改变!任何拦截消息的人都可以伪装成有效的发件人。非对称加密的目的是通过密钥交换来解决这些问题,这是数字签名的概念,它基本上是您正在折腾的消息的非对称加密哈希。

对于 RSA,您需要做更多工作才能从基本算法创建数字签名,请参阅维基百科了解更多详细信息:http://en.wikipedia.org/wiki/RSA#Signing_messages

我只是使用图书馆中的数字签名算法。第一次谷歌搜索出现了 Python:

http://www.example-code.com/python/pythonrsa.asp

http://www.chilkatsoft.com/dsa-python.asp

【讨论】:

    【解决方案2】:

    这种方法的问题是任何机器都可以捕获 guid 和 rsa-encrypted-guid 并以同样的方式传递它们。您还没有真正创建任何只能由接收客户端预测的独特挑战/响应标准。您需要的是完全独特的东西,不能仅仅通过查看传递的参数来获得。可能是这样的:

    [ClientName; RSA-ENCRYPTED(GUID+Timestamp); MESSAGE]
    

    在此方法中,RSA 加密将使用 Client2 的公钥完成,因此只有 Client2 的私钥可以解锁它。使用 ClientName,Client2 可以从数据源检索预期的 GUID,然后将返回的 GUID 与加密中的 GUID 匹配。我将时间戳的使用结合为盐,以便加密的字符串每次都以不同的方式出现。使用时间戳作为盐的随机化被认为是非常弱的,但它明白了这一点。可以实现其他更安全/随机的算法。

    【讨论】:

      【解决方案3】:

      任何在客户端和服务器之间监视消息的人都可以伪造新消息,客户端的GUID 永远不会改变,RSA-ENCRYPTED-GUID 也不会改变。

      考虑切换到此消息模型:[GUID; ENCRYPTED_CONTENT_CHECKSUM; CONTENT]

      Checksum(message.CONTENT) == 
          RSADescrypt(C1.PUBLIC_KEY, message.ENCRYPTED_CONTENT_CHECKSUM)
      

      不过,任何监视消息的人都可以重新发送以前发送的消息。

      【讨论】:

        【解决方案4】:

        公钥和私钥是要走的路。我假设您不关心加密数据,但您确实关心数据是否“授权”。

        假设你有 3 台电脑

        比较 1 比较2 Comp3

        假设您希望 Comp1 向 Comp3 发送消息。您不在乎消息是否被拦截,但您确实在乎它不是伪造的。

        Comp1 将使用其私钥对消息进行数字签名

        Comp2 会拦截 Comp1 到 Comp3 的消息,但不能在不使签名失效的情况下更改消息

        Comp2 会将消息转发到 Comp3

        Comp3 将使用 Comp1 的公钥解密签名并使用签名中的哈希来验证内容。

        现在如果你想加密数据,你需要增加一个额外的步骤

        Comp1 将使用其私钥对消息进行数字签名

        Comp1 将生成一个随机加密密钥(通常为 AES)并对消息进行加密。

        Comp1 将获取该加密密钥并使用 Comp3 的公钥对其进行加密

        Comp2 会截取消息,但没有 Comp3 的私钥就无法读取它

        Comp2 会将消息转发到 Comp3

        Comp3 将使用它的私钥来解密 AES 密钥

        Comp3 将使用 AES 密钥解密整个消息

        Comp3 将通过使用 Comp1 的公钥解密签名来验证消息。

        签名包含消息的哈希,如果哈希和消息的哈希匹配,那么数据是完整的。

        您可以在负载中包含 GUID 以用作查找来决定使用哪些公钥。

        附:您将需要使用内置方法来签署消息。让框架做散列/等

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2023-01-07
          • 2020-12-18
          • 2012-03-06
          • 2022-10-22
          • 1970-01-01
          • 2015-12-13
          • 1970-01-01
          相关资源
          最近更新 更多