使用Java BigIntegers在RSA中解密时,如何在原始数据的开头保留零字节?
我正在实现我自己的RSA版本,以及Java中的填充方案RSA-OAEP。这是我的基本算法代码:使用Java BigIntegers在RSA中解密时,如何在原始数据的开头保留零字节?
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签署的事实有关。有没有解决这个问题的方法?
new BigInteger(data)
始终以双补码表示法解析数据,其中最重要的位用信号表示符号。在RSA,所有的数字都是积极的,所以你可以设置登录为1
:
new BigInteger(1, data)
*“当我解密这个密文,有时零字节仍是生成的字节数组中,其他时候它不是。 “* - 请[编辑]你的问题给一些例子。 –
我刚刚意识到,零字节后的填充数据的第一位是0时,零字节不会出现。如果它是1,则它工作正常。这肯定与BigIntegers签名有关。 – metroidsocrates
这就是你手工完成RSA的过程。 BigInteger算术没有关于您希望答案有多大的概念。如果结果是25,无论模数有多大,你都会得到一个字节。你必须自己添加零。您可能需要编写一个采用BigInteger和期望长度的方法,并返回一个长度为大的字节数组,并根据需要预置零。 –