解密RSA数据时出错Java:javax.crypto.BadPaddingException:解密错误

时间:2014-09-06 09:41:41

标签: java encryption cryptography rsa

我在使用Java中的RSA解密数据(或者也可能是加密错误)时遇到问题。 我想用String中的更多信息加密公钥,然后解密这个公钥并用它加密(我使用2048 RSA):

加密:

public void saveExportToFile(String fileName, BigInteger mod, BigInteger exp, String info, PublicKey puk) throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectOutputStream oout = new ObjectOutputStream(new BufferedOutputStream(baos));
    try {
        oout.writeObject(mod);
        oout.writeObject(exp);
        oout.writeChars(info);
        oout.close();
        baos.close();
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, puk);

        FileOutputStream fos = new FileOutputStream(new File(fileName));
        BufferedOutputStream bos = new BufferedOutputStream(fos);

        byte[] data = baos.toByteArray();

        int i = 0;
        byte[] buffer = new byte[128];
        byte[] cipherData = null;
        while (i < data.length) {
            if (i+128 >= data.length) {
                buffer = new byte[data.length - i];
                System.arraycopy(data, i, buffer, 0, data.length - i);
                cipherData = cipher.doFinal(buffer);
                bos.write(cipherData);
            } else {
                System.arraycopy(data, i, buffer, 0, 128);
                cipherData = cipher.doFinal(buffer);
                bos.write(cipherData);
            }
            i += 128;
        }

        bos.close();
    } catch (Exception e) {
        throw new IOException("Unexpected error", e);
    }
}

解密:

public void getDataFromRSA(String sendname, PrivateKey privateKey) {
    try {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(sendname)));

        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        int length = 0;
        int allLength = 0;
        byte[] buffer = new byte[128];
        byte[] bufferAC = null;
        byte[] outData = null;
        byte[] allData = null;
        byte[] tmpData = null;
        while ( (length = bis.read(buffer)) != -1) {
            if (length < 128) {
                bufferAC = new byte[length];
                System.arraycopy(buffer, 0, bufferAC, 0, length);
                outData = cipher.doFinal(bufferAC);
            } else {
                outData = cipher.doFinal(buffer); // HERE IS THE ERROR
            }
            allLength += outData.length;
            tmpData = allData;
            allData = new byte[allLength];
            System.arraycopy(tmpData, 0, allData, 0, tmpData.length);
            System.arraycopy(outData, 0, allData, tmpData.length, outData.length);
        }
    } catch (IOException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | ClassNotFoundException | InvalidKeySpecException e) {
        e.printStackTrace();
    }
}

修改 好吧,我似乎并不像我想的那样了解加密。我只想使用RSA(如果可能的话),因为我不需要多次传输信息(信息大小各不相同)。我编辑了这样的加密:

int i = 0;
byte[] buffer = new byte[245];
byte[] cipherData = null;
while (i < data.length) {
    if (i+245 >= data.length) {
        buffer = new byte[data.length - i];
        System.arraycopy(data, i, buffer, 0, data.length - i);
    } else {
        System.arraycopy(data, i, buffer, 0, 245);
    }
    cipherData = cipher.update(buffer);
    bos.write(cipherData);
    i += 245;
}
bos.write(cipher.doFinal()); // HERE IS THE ERROR
bos.close();

现在我得到javax.crypto.IllegalBlockSizeException: Data must not be longer than 245 bytes(为缓冲区大小尝试了几个较低的值)。是因为数据长度不是blocksize的倍数?这可以解决吗?谢谢你的回答。

2 个答案:

答案 0 :(得分:3)

首先,您应该使用混合加密,即首先使用对称密码加密数据,然后使用RSA密钥加密随机密钥 - 将两者都发送到接收方。

其次,您不应该在循环中为单个消息执行doFinal。请改用update和一个doFinal

第三,2048位是256字节。只要您继续尝试解密128个字节而不是256个字节,您将获得此异常。通常我使用2048 / Byte.SIZE代替它,它使代码更具可读性并避免错误。

答案 1 :(得分:0)

当您尝试使用私钥加密数据并使用公钥解密时,会发生此异常,您需要撤消此操作,或者必须使用单个密钥来加密和解密数据。这将解决此异常。