我正在编写一个客户端/服务器 TCP 程序,并希望使用 TLS 加密和验证连接。我的计划是让客户端向服务器提交公共 RSA 密钥,然后使用私钥和用户名来验证客户端的身份并加密连接。
GnuTLS 文档还有很多不足之处,但我找到了一个很好的 PSK 示例并尝试对其进行调整以使用 RSA 非对称密钥。在解决了这个问题之后,特别是文档中没有明确描述的各种晦涩的细节之后,我让客户端停止抱怨“没有找到支持的密码套件”,但现在服务器可以了。
在互联网上进行更多搜索后,我发现了一个测试程序,它是 GnuTLS CI 的一部分,用于测试 RSA-PSK,我意识到共享密钥仍然是对称的。RSA-PSK 不是我想的那样。
我真的不喜欢使用对称密钥,因为它需要在服务器端以普通方式存储,因此不安全。
然而,对 RSA 密钥交换的简要介绍表明,不涉及用户名,它实际上是基于证书的,并且服务器使用自己的私钥,而所有客户端都使用相同的公钥。因此,不可能保证客户的身份。
在花了一天时间试图让 TLS 工作,并且不愿意重新发明轮子(这总是存在安全风险)之后,我在这里询问,以防有任何专家可以建议我如何实现我正在寻求的目标实现。
唯一想到的解决方案是相当肮脏和hacky(并且重新发明轮子),即实现一个pre-TLS-handshake握手,客户端生成一个随机密钥,用它的私钥对其进行加密,然后发送它和用户名到服务器,然后使用公钥对其进行解密。然后 GnuTLS 可以使用随机密钥进行正常的对称 PSK 密钥交换。
我不明白为什么 GnuTLS 无论如何都没有实现这样的东西。我所期望的是 GnuTLS 客户端将用户名发送到服务器,然后服务器通过生成用于加密的密钥并使用客户端的公钥对其进行加密并将加密的密钥发送到客户端来执行密钥交换。客户端使用其私钥解密密钥,你瞧,密钥交换已安全完成,TLS 通道已打开。
总而言之:
1)如何实现我需要实现的目标(最好使用 GnuTLS)?
2) 为什么 RSA-PSK 不能按我的预期工作,而是使用对称密钥和证书?