使用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签署的事实有关。有没有解决这个问题的方法?

+0

*“当我解密这个密文,有时零字节仍是生成的字节数组中,其他时候它不是。 “* - 请[编辑]你的问题给一些例子。 –

+0

我刚刚意识到,零字节后的填充数据的第一位是0时,零字节不会出现。如果它是1,则它工作正常。这肯定与BigIntegers签名有关。 – metroidsocrates

+0

这就是你手工完成RSA的过程。 BigInteger算术没有关于您希望答案有多大的概念。如果结果是25,无论模数有多大,你都会得到一个字节。你必须自己添加零。您可能需要编写一个采用BigInteger和期望长度的方法,并返回一个长度为大的字节数组,并根据需要预置零。 –

new BigInteger(data)始终以双补码表示法解析数据,其中最重要的位用信号表示符号。在RSA,所有的数字都是积极的,所以你可以设置登录为1

new BigInteger(1, data) 
+0

我试过了。它不能解决问题。 – metroidsocrates

+0

你是否这样做加密? –

+0

我做了加密和解密。 – metroidsocrates