为什么 Java 中的加密 RSA 字节会发生变化?

Why do encryped RSA bytes in Java variate?

我尝试编写混合加密代码以在服务器和客户端之间进行通信。所以我从客户端发送一个 public RSA 密钥,服务器加密他的 AES 密钥并将其发回。但是如果我在客户端解密它,密钥比我发送的要长,我不知道为什么...

这里是代码:

客户:

socket.getOutputStream().write(security.getKeyPair().getPublic().getEncoded());
byte[] keyBuffer = new byte[512];
socket.getInputStream().read(keyBuffer);
security.setKey(new SecretKeySpec(security.decryptRSA(keyBuffer).getBytes(), "AES"));

服务器:

byte[] keyBuffer = new byte[550];
this.socket.getInputStream().read(keyBuffer);
PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(keyBuffer));
this.socket.getOutputStream().write(this.security.encryptRSA(this.security.getKey().getEncoded(), publicKey));

安全class方法:

public byte[] encryptRSA(byte[] message, PublicKey key) {
        byte[] buffer = message;
        try {
            this.cipher = Cipher.getInstance("RSA");
            this.cipher.init(Cipher.ENCRYPT_MODE, key);
            buffer = this.cipher.doFinal(buffer);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
            e.printStackTrace();
        }

        return buffer;
    }


public String decryptRSA(byte[] message) {
        byte[] buffer = message;
        try {
            this.cipher = Cipher.getInstance("RSA");
            this.cipher.init(Cipher.DECRYPT_MODE, this.keyPair.getPrivate());
            buffer = this.cipher.doFinal(buffer);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
            e.printStackTrace();
        }

        return new String(buffer);
    }


谢谢!

问题可能是您不必要地对代码进行了字符串化:

   return new String(buffer);

这将以某种方式将缓冲区解释为字符串。但是,密钥由随机字节组成,可能会解码为意外字符。然后使用 .getBytes() 恢复为字节,但到那时为时已晚。

来自 Java String(byte[]): String 构造函数文档:

The behavior of this constructor when the given bytes are not valid in the default charset is unspecified. The CharsetDecoder class should be used when more control over the decoding process is required.

通常虽然它只是默默地丢弃无法解码的字节,但也可能会用 Unicode 字符或问号表示未知编码。在任何这些操作中,信息都会丢失。

只需将 AES 密钥保留为字节即可,这部分应该是固定的。


除此之外,readreadNBytes​ 不同(只有 read 是错误的),但这可能不是错误;你会遇到 RSA 的麻烦,而不是 AES 密钥,如果这是问题的话。


请注意,您可以检索以字节为单位的模数大小以确定要读取的字节数,因此您也不需要在那里有一个 512 常量(我会写成 KEY_SIZE / Byte.SIZE 其中 KEY_SIZE = 4096 至少清楚地表明缓冲区与密钥大小相同。