如何用Java对大数据进行RSA加解密

发布于 2025-01-10 04:47:04 字数 1113 浏览 0 评论 0原文

我正在尝试使用 RSA 和 OAEPPadding 对实际较大的数据(例如 10 KB)执行非对称加密和解密。

许多 Stackoverflow 文章提到使用混合方法 [不对称 + 对称],但我并不是在寻找这种方法。我故意要求非对称加密。

我初始化了加密和解密密码,如下所示:

mDecryptCipher = Cipher.getInstance("RSA/None/OAEPPadding", new BouncyCastleProvider());
mDecryptCipher.init(Cipher.DECRYPT_MODE, mPrivateKey);
Log.d(TAG, "Decrypt Cipher is successfully created");

mEncryptCipher = Cipher.getInstance("RSA/None/OAEPPadding", new BouncyCastleProvider());
mEncryptCipher.init(Cipher.ENCRYPT_MODE, mPublicKey);
Log.d(TAG, "Encrypt Cipher is successfully created");

以下是我尝试加密或解密大小为 10 KB 的大数据的代码。

// Encrypt
byte[] encryptedPayload = mEncryptCipher.doFinal(payload);

// Decrypt
byte[] decryptedPayload = mDecryptCipher.doFinal(payload);

以下是我收到的异常:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: too much data for RSA block
    at org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi.engineDoFinal(Unknown Source)
    at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2205)

请让我知道如何对大数据执行 RSA 加密和解密。

I am trying to perform Asymmetric Encryption and Decryption using RSA and OAEPPadding on actually larger data, say, 10 KB.

Many Stackoverflow articles mentioned to use the Hybrid approach [Assymmetric + Symmetric] but I am not looking for that. I purposely require Asymmetric Encryption.

I initialized the Encrypt and Decrypt Ciphers as follows:

mDecryptCipher = Cipher.getInstance("RSA/None/OAEPPadding", new BouncyCastleProvider());
mDecryptCipher.init(Cipher.DECRYPT_MODE, mPrivateKey);
Log.d(TAG, "Decrypt Cipher is successfully created");

mEncryptCipher = Cipher.getInstance("RSA/None/OAEPPadding", new BouncyCastleProvider());
mEncryptCipher.init(Cipher.ENCRYPT_MODE, mPublicKey);
Log.d(TAG, "Encrypt Cipher is successfully created");

Following is the code by which I am trying to Encrypt or Decrypt the large data of size 10 KB.

// Encrypt
byte[] encryptedPayload = mEncryptCipher.doFinal(payload);

// Decrypt
byte[] decryptedPayload = mDecryptCipher.doFinal(payload);

Following is the exception I received:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: too much data for RSA block
    at org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi.engineDoFinal(Unknown Source)
    at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2205)

Please let me know how to perform RSA Encryption and Decryption on large data.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

世态炎凉 2025-01-17 04:47:04

Java Cipher 对象允许我们检索块大小,并使用它来执行重复的加密和解密,这将使我们克服“RSA 块数据太多”例外。

以下是加密的逻辑:

public byte[] encrypt(String data) {
    Log.d(TAG, "Encryption begins");
    byte[] payload = data.getBytes(StandardCharsets.UTF_8);
    int payloadLength = payload.length;
    int blockSize = mEncryptCipher.getBlockSize();
    Log.d(TAG, "blockSize: " + blockSize + "; payloadLength: " + payloadLength);

    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    int start = 0, end = 0;
    while (end < payloadLength) {
        end = end + blockSize;
        if (end > payloadLength) {
            end = payloadLength;
        }
        Log.d(TAG, "start: " + start + "; end: " + end + "; block: " + (end - start));
        try {
            byte[] encryptedSlice = mEncryptCipher.doFinal(payload, start, (end - start));
            Log.d(TAG, "Encrypted Slice Length: " + encryptedSlice.length);
            stream.write(encryptedSlice);
            start = end;
        } catch (IOException | BadPaddingException | IllegalBlockSizeException e) {
            Log.e(TAG, "update failed");
            e.printStackTrace();
            break;
        }
    }
    byte[] encryptedPayload = stream.toByteArray();
    try {
        stream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    Log.d(TAG, "encryptedPayload length: " + encryptedPayload.length);
    byte[] base64EncryptedPayload = org.apache.commons.codec.binary.Base64.encodeBase64(encryptedPayload);
    Log.d(TAG, "base64EncryptedPayload length: " + base64EncryptedPayload.length);
    Log.d(TAG, "Encryption ends");
    return base64EncryptedPayload;
}

以下是解密的逻辑:

public String decrypt(byte[] base64EncodedData) {
    Log.d(TAG, "Decryption begins");
    Log.d(TAG, "base64EncodedData length: " + base64EncodedData.length);
    byte[] encryptedData = org.apache.commons.codec.binary.Base64.decodeBase64(base64EncodedData);
    Log.d(TAG, "encryptedData length: " + encryptedData.length);

    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    int payloadLength = encryptedData.length;
    int blockSize = mDecryptCipher.getBlockSize();
    int start = 0, end = 0;
    while (start < payloadLength) {
        end = end + blockSize;
        if (end > payloadLength) {
            end = payloadLength;
        }

        Log.d(TAG, "start: " + start + "; end: " + end + "; block: " + (end - start));
        try {
            byte[] decryptedBlockData = mDecryptCipher.doFinal(encryptedData, start, (end - start));
            Log.d(TAG, "decryptedBlockData Length: " + decryptedBlockData.length);
            stream.write(decryptedBlockData);
            start = end;
        } catch (BadPaddingException | IllegalBlockSizeException | IOException e) {
            Log.e(TAG, "Slicing failed");
            e.printStackTrace();
            break;
        }
    }
    String payload = stream.toString();
    try {
        stream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    Log.d(TAG, "Decryption ends");
    return payload;
}

请注意,在我的例子中,以下是 Cipher 对象的详细信息:

EncryptCipher:

getBlockSize: 470
getAlgorithm: RSA/None/OAEPPadding
getProvider Name: BC
getProvider Info: BouncyCastle Security Provider v1.70

DecryptCipher:

getBlockSize: 512
getAlgorithm: RSA/None/OAEPPadding
getProvider Name: BC
getProvider Info: BouncyCastle Security Provider v1.70

我是开放的以及任何更好的解决方案。

The Java Cipher objects allow us to retrieve the block sizes and using that we would be performing a repetitive kind of encryption as well as decryption which would let us over-come the "too much data for RSA block" exception.

Following is the logic for Encryption:

public byte[] encrypt(String data) {
    Log.d(TAG, "Encryption begins");
    byte[] payload = data.getBytes(StandardCharsets.UTF_8);
    int payloadLength = payload.length;
    int blockSize = mEncryptCipher.getBlockSize();
    Log.d(TAG, "blockSize: " + blockSize + "; payloadLength: " + payloadLength);

    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    int start = 0, end = 0;
    while (end < payloadLength) {
        end = end + blockSize;
        if (end > payloadLength) {
            end = payloadLength;
        }
        Log.d(TAG, "start: " + start + "; end: " + end + "; block: " + (end - start));
        try {
            byte[] encryptedSlice = mEncryptCipher.doFinal(payload, start, (end - start));
            Log.d(TAG, "Encrypted Slice Length: " + encryptedSlice.length);
            stream.write(encryptedSlice);
            start = end;
        } catch (IOException | BadPaddingException | IllegalBlockSizeException e) {
            Log.e(TAG, "update failed");
            e.printStackTrace();
            break;
        }
    }
    byte[] encryptedPayload = stream.toByteArray();
    try {
        stream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    Log.d(TAG, "encryptedPayload length: " + encryptedPayload.length);
    byte[] base64EncryptedPayload = org.apache.commons.codec.binary.Base64.encodeBase64(encryptedPayload);
    Log.d(TAG, "base64EncryptedPayload length: " + base64EncryptedPayload.length);
    Log.d(TAG, "Encryption ends");
    return base64EncryptedPayload;
}

Following is the logic for Decryption:

public String decrypt(byte[] base64EncodedData) {
    Log.d(TAG, "Decryption begins");
    Log.d(TAG, "base64EncodedData length: " + base64EncodedData.length);
    byte[] encryptedData = org.apache.commons.codec.binary.Base64.decodeBase64(base64EncodedData);
    Log.d(TAG, "encryptedData length: " + encryptedData.length);

    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    int payloadLength = encryptedData.length;
    int blockSize = mDecryptCipher.getBlockSize();
    int start = 0, end = 0;
    while (start < payloadLength) {
        end = end + blockSize;
        if (end > payloadLength) {
            end = payloadLength;
        }

        Log.d(TAG, "start: " + start + "; end: " + end + "; block: " + (end - start));
        try {
            byte[] decryptedBlockData = mDecryptCipher.doFinal(encryptedData, start, (end - start));
            Log.d(TAG, "decryptedBlockData Length: " + decryptedBlockData.length);
            stream.write(decryptedBlockData);
            start = end;
        } catch (BadPaddingException | IllegalBlockSizeException | IOException e) {
            Log.e(TAG, "Slicing failed");
            e.printStackTrace();
            break;
        }
    }
    String payload = stream.toString();
    try {
        stream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    Log.d(TAG, "Decryption ends");
    return payload;
}

Please note that in my case following are the details of the Cipher objects:

EncryptCipher:

getBlockSize: 470
getAlgorithm: RSA/None/OAEPPadding
getProvider Name: BC
getProvider Info: BouncyCastle Security Provider v1.70

DecryptCipher:

getBlockSize: 512
getAlgorithm: RSA/None/OAEPPadding
getProvider Name: BC
getProvider Info: BouncyCastle Security Provider v1.70

I am open to any better solution as well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文