使用Java BigIntegers在RSA中解密时,如何在原始数据的开头保留零字节?

时间:2017-04-06 21:32:55

标签: java encryption rsa biginteger public-key-encryption

我正在实现我自己的RSA版本,以及Java中的填充方案RSA-OAEP。这是我的基本算法代码:

public byte[] encrypt(byte[] data, RSA_PublicKey publicKey) {
   BigInteger message = new BigInteger(data);
   BigInteger n = publicKey.getModulus(); //RSA Modulus
   BigInteger e = publicKey.getPublicExponent(); //RSA Public Exponent
   if (message.compareTo(n) >= 0) {
       throw new InvalidDataException();
   }
   byte[] cipherText = message.modPow(e, n).toByteArray(); //Encryption
   return cipherText;
}

public byte[] decrypt(byte[] data, RSA_PrivateKey privateKey) {
   BigInteger cipherText = new BigInteger(data);
   BigInteger n = privateKey.getModulus(); //RSA Modulus
   BigInteger d = privateKey.getPrivateExponent(); //RSA Private Exponent
   if (cipherText.compareTo(n) >= 0) {
       throw new InvalidDataException();
   }
   if (cipherText.compareTo(n.subtract(BigInteger.ONE)) == 1) {
       throw new InvalidDataException();
   }
   byte[] message = cipherText.modPow(d, n).toByteArray(); //Decryption
   return message;
}

在RSA-OAEP中,在加密之前使用掩码生成功能对数据和随机种子执行一系列操作。零填充数据前面放置一个零字节。这就是我的代码中的样子:

buffer = ByteBuffer.allocate(k);
buffer.put((byte)0);
buffer.put(maskedSeed);
buffer.put(maskedDB);
byte[] em = buffer.array();
byte[] cipherText = encrypt(em, publicKey);
return cipherText

当我解密这个密文时,有时零字节仍然在结果字节数组中,有时则不是。例如,这个数据(十六进制)在加密之前和解密之后是相同的:

00c127a743b56f53e46223eba367b63d3378648c1d5ce3e8eec1f714c099a15b674c528d5051c1c9a32dc39fb13ee745864c7f572fa950dc8336a54d89503754f6c18dd463ec1633e6e94638230d9b10cc6e2904f4c69247a8bac0c60885b37b8adefe3b682b3a6d39f445447fa2f173b408346d3d0db086e199ef9c1fd0d14f

然而,这个数据:

001c924b794c178c9955d4f3211c67ecda59ffe8c4be55c101bcd5ff3ce0a746ca447b5fc8fd8725cbb083e4b9244cf49b6ca84465680c0c49bec2bab3dfab6371673f0d01605d641330592ffb8915229c2dc4ea1ffcdf8a9a0e461fdf224f5cf57f74affac9d35dd3ce61ff1dd068a8c9495290735415984ddb71515823f746

被解密为:

1c924b794c178c9955d4f3211c67ecda59ffe8c4be55c101bcd5ff3ce0a746ca447b5fc8fd8725cbb083e4b9244cf49b6ca84465680c0c49bec2bab3dfab6371673f0d01605d641330592ffb8915229c2dc4ea1ffcdf8a9a0e461fdf224f5cf57f74affac9d35dd3ce61ff1dd068a8c9495290735415984ddb71515823f746

根据RSA标准,应该检查解密的填充数据以查找该零字节以确保其被正确填充,并且如果不是则返回错误消息。我相信这与BigIntegers签署的事实有关。这个问题有一些解决方法吗?

1 个答案:

答案 0 :(得分:0)

new BigInteger(data)始终以二补码表示法解析数据,其中最高有效位表示符号。在RSA中,所有数字都是正数,因此您可以将符号设置为1

new BigInteger(1, data)