Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 加密密钥交换的同行审查_Java_Cryptography_Rsa_Aes_Diffie Hellman - Fatal编程技术网

Java 加密密钥交换的同行审查

Java 加密密钥交换的同行审查,java,cryptography,rsa,aes,diffie-hellman,Java,Cryptography,Rsa,Aes,Diffie Hellman,在过去的几天里,我一直在玩Bouncy Castle(java),我相信我可以安全地与Diffie-Hellman交换密钥 在阅读了许多强调正确实现加密交换的困难的帖子之后,我希望您能对我的工作发表诚实的意见。 所有底层密码操作都基于Bouncy Castle,因此可能被认为是可靠的 String message = "Hello World"; AESCipher aes_client = new AESCipher(256); RSACipher rsa_serve

在过去的几天里,我一直在玩Bouncy Castle(java),我相信我可以安全地与Diffie-Hellman交换密钥

在阅读了许多强调正确实现加密交换的困难的帖子之后,我希望您能对我的工作发表诚实的意见。 所有底层密码操作都基于Bouncy Castle,因此可能被认为是可靠的

    String message = "Hello World";

    AESCipher aes_client = new AESCipher(256);
    RSACipher rsa_server = new RSACipher(2048);

    // (Public key sent over the wire)
    RSACipher rsa_client = new RSACipher(rsa_server.getPublicKey().getModulus(),
                                         rsa_server.getPublicKey().getExponent());

    // The client encodes his AES key with the RSA public key:
    byte[] aes_key = rsa_client.encode(aes_client.getKeyBytes());
    byte[] aes_iv = rsa_client.encode(aes_client.getInitializationVector());

    // (Data sent back over the wire)
    byte[] decoded_aes_key = rsa_server.decode(aes_key);
    byte[] decoded_aes_iv = rsa_server.decode(aes_iv);

    // The server creates an AES server which uses the client key:
    AESCipher aes_server = new AESCipher(decoded_aes_key, decoded_aes_iv);

    byte[] encoded_message = aes_client.encode(message.getBytes());
    byte[] decoded_message = aes_server.decode(encoded_message);

    System.out.println(new String(decoded_message));
这种交换可以被认为是安全的吗?我是否应该坚持使用SSL套接字,即使这会影响我的努力工作? 提前感谢您的输入


(顺便说一句,我的Bouncy Castle包装库是完全开源的,所以如果您需要存储库的URL,请告诉我。)

我只想指出,IV通常不会加密。我想这没有什么害处,但也没有必要。

(您的协议中没有Diffie Hellman,只有RSA和对称加密。)

第一个基本注意事项是,您的协议容易受到主动攻击。“中间人”是一个经典(攻击者截取公钥,用他自己的替换)。此外,您只有对称加密,但没有MAC。假设您的攻击模型只针对被动攻击者;大多数时候,至少可以说,这是一个非常大胆的假设。事实上,我很难想象这样一种情况:窃听者可以查看传输的字节,但无法发送自己的消息。除非通过完整性检查在经过身份验证的隧道中运行整个过程(SSL有一种模式,但这种模式不符合要点)

您正在加密不需要的IV(IV不是密钥,否则它将被称为“密钥”,而不是IV)。您需要从IV中随机生成每个加密消息。假设您使用CBC模式,可以接受将消息中最后一个加密的块用作下一条消息的IV。然而,对具有相同对称加密密钥的两条不同消息重复使用IV将是致命的。由于Bouncy Castle没有任何名为
AESChipher
的类,因此您的示例代码不会告诉我们您是否在使用具有正确链接模式和正确IV管理的AES。还要注意,重用上一条消息中的最后一个加密块仅在消息按顺序发送且没有消息丢失时有效。更可靠的解决方案是:

  • 为每条消息选择一个新的random IV(通过加密强RNG,例如
    java.security.SecureRandom
  • 将IV和加密数据的串联作为编码消息发送
  • 这允许接收器恢复IV(作为第一个消息块),然后处理消息,而不管之前的消息是否已发送和接收。同样,如果只是通过简单的“重播攻击”(攻击者发送以前发送的消息的副本),主动攻击者可能会在该方案中造成严重破坏

    作为旁注,
    String.getBytes()
    新字符串(byte[])
    使用平台默认编码,这在客户端和服务器之间可能有所不同。最好使用显式字符集,例如UTF-8:
    message.getBytes(“UTF-8”)
    新字符串(解码的消息,“UTF-8”)


    总的来说,安全感和傲慢并不能很好地结合在一起。准备好抛弃你的代码。您真正应该使用标准协议(如SSL/TLS)的主要原因是安全性无法验证。如果有人(例如你的老板)问你是什么让你认为协议是安全的,你会告诉他什么?“Stack Overflow上的某个人告诉我的”

    可能是一个更好的问题,因为我不知道这个网站。谢谢你提供的信息,我会问你的问题。您需要一些根证书来验证服务器公钥。或者客户端已经安装了公钥?以上都没有:MITM尚未被识别为对我的应用程序的威胁。被动窃听是这里唯一的目标。预安装公钥是一个可行的选择。@Executifs,如果您能确保非常可信的连接(没有DNS攻击?),您应该可以。虽然交换sym的方法更简单。密钥只是一个SSL套接字(通常是https)和交换,使用/AES/RCx/whateverI继续,我总是很高兴学到一些东西。感谢您提供的额外信息。我假设OP不传输字符串,但byte[]和getBytes()仅用于测试用例。非常感谢您宝贵的建议。我确实在使用CBC模式,但我不知道不重用IVs。这将立即修复。此外,您还说服我放弃在生产环境中使用代码。不过,我坚持要弄清这一点,所以我想我会寻找有知识的人,他们愿意就整个代码库向我提供建议。再次感谢。