【问题标题】:Why do encryped RSA bytes in Java variate?为什么 Java 中加密的 RSA 字节会发生变化?
【发布时间】:2021-09-09 04:55:21
【问题描述】:

我尝试编写混合加密来在服务器和客户端之间进行通信。所以我从客户端发送一个公共 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));

安全类方法:

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);
    }


谢谢!

【问题讨论】:

  • 正确生成的 AES 密钥应该是任意二进制数据,而不是字符——来自 Java KeyGenerator 肯定 的一个是——而 Java String 并非经常用于设计不保留二进制数据。将 AES 密钥视为byte[],而不是String
  • 你得到什么异常?您的应用是否在等待接收/发送一些数据?您似乎以假设长度发送/接收数据。正如已经回答的那样,如果您的密钥包含不可打印的字符,new String(buffer) 肯定会废弃这些

标签: java arrays encryption rsa encryption-asymmetric


【解决方案1】:

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

   return new String(buffer);

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

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

当给定字节在默认字符集中无效时,此构造函数的行为未指定。当需要对解码过程进行更多控制时,应使用CharsetDecoder 类。

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

只需将 AES 密钥保留为字节,该部分应该被修复。


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


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

【讨论】:

  • 嗨,Maarten,感谢您对我的回答发表评论。你是对的,我完全错了。
  • 没问题 :) 很高兴您以您的方式对它做出反应。
猜你喜欢
  • 1970-01-01
  • 2018-12-08
  • 1970-01-01
  • 2010-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-02
  • 1970-01-01
相关资源
最近更新 更多