使用RSA交换对称密钥的问题,编码大小大于块大小

时间:2016-12-07 03:42:06

标签: java c# encryption cryptography rsa

我正在为涉及大量跨平台安全网络通信的项目实施hybrid cryptosystem。在这种情况下,通信方运行.NET和Java,因此我分别使用每个堆栈提供的密码系统框架。

我可以在两个系统上成功生成相同大小(4096位)的密钥对,并成功传输密钥并将其加载到远程系统中,以便我可以使用远程系统的公钥对每个密钥进行加密。机。

然后,我在两个系统上生成对称密钥和IV,并尝试在两个系统之间交换对称密钥。 不幸的是,在我对自定义通信协议中的密钥和IV信息进行编码后,数据大于密钥大小(不是很多,它通常在600以上) 1000字节区域,但仍然超过我的密钥大小的~500字节限制)。

我的解决方案是拆分数据,并在适当大小的块上运行RSA加密。但是,我不知道分块的大小,因为我听过很多不同的公式,例如:

  • ((KEY_SIZE) / 8) - 11
  • ((KEY_SIZE) / 8) - 42

但是,每当我使用第一个块大小(((KEY_SIZE) / 8) - 11加密到501字节)加密信息时,RSACryptoServiceProvider.Encrypt(byte[] data, bool fOAEP)会抛出Bad Length!错误。每当我使用第二个块大小(((KEY_SIZE) / 8) - 42)时,它就成功处理了块,但它给了我一个513字节的输出(似乎任何0-500字节之间的输入被填充到这个513字节值,我假设OAEP正在做它的工作),根据我的Java密码系统(javax.crypto.IllegalBlockSizeException: Data must not be longer than 512 bytes),它太大而无法使用我的4096位密钥进行解密。如果是这种情况,为什么.NET密码系统给我一个带有OAEP的513字节输出,如果它不能以这个大小解密?

我的.NET RSA加密实现如下。_rsaProvider已使用有效的远程公钥进行初始化。 RSA_BUFFER_SIZE是相对于KEY_SIZE(即4096)的常数(如果RSA_BUFFER_SIZE为501则不起作用,但对于496及以下工作似乎,如上所述) :

        byte[] block;
        using (MemoryStream stream = new MemoryStream())
        {
            int read = 0;
            while (read < data.Length)
            {
                block = new byte[RSA_BUFFER_SIZE]; 
                int toRead = Math.Min(data.Length - read, block.Length);
                Buffer.BlockCopy(data, read, block, 0, toRead);
                read += toRead;
                byte[] decrypted = _rsaProvider.Encrypt(block, true);
                stream.Write(decrypted, 0, decrypted.Length);
            }
            return stream.ToArray();
        }

以下是解密此信息的Java实现(RSA_BUFFER_SIZE使用与上面相同的逻辑大小和相同的密钥大小):

    byte[] block;
    ByteArrayOutputStream output = new ByteArrayOutputStream();
    int read = 0;
    while (read < data.length) {
        block = new byte[RSA_BUFFER_SIZE];
        int toRead = Math.min(data.length - read, block.length);
        System.arraycopy(data, read, block, 0, toRead);
        read += toRead;
        output.write(_localAsymmetricCipher.doFinal(block));
    }
    byte[] ret = output.toByteArray();
    output.close();
    return ret;

我的实施有问题吗?

1 个答案:

答案 0 :(得分:0)

看起来它实际上与this question的问题相同。我在Java系统上生成的公钥在模数BigInteger中具有前导零。通过切断第一个字节来解决。