我正在使用RSA加密文本和解密文本。公钥和私钥是使用openssl工具生成的。
解密数据时遇到“ java.lang.ArrayIndexOutOfBoundsException:RSA块数据过多”异常。

这是RSA util类:

package studio.uphie.app;

import android.util.Base64;

import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

/**
 * Created by Uphie on 2016/4/11.
 */
public class RSA {

    private static String RSA = "RSA";

    /**
     *
     * @param text    text to be encrypted
     * @param pub_key rsa public key
     * @return encrypted data in byte-array form
     */
    public static byte[] encryptData(String text, String pub_key) {
        try {
            byte[] data = text.getBytes();
            PublicKey publicKey = getPublicKey(Base64.decode(pub_key.getBytes(), Base64.DEFAULT));

            Cipher cipher = Cipher.getInstance(RSA);
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            return cipher.doFinal(data);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     *
     * @param text    text to be decrypted
     * @param pri_key rsa private key
     * @return
     */
    public static byte[] decryptData(String text, String pri_key) {
        try {
            byte[] data = text.getBytes();
            PrivateKey privateKey = getPrivateKey(Base64.decode(pri_key.getBytes(),Base64.DEFAULT));

            Cipher cipher = Cipher.getInstance(RSA);
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            return cipher.doFinal(data);
        } catch (Exception e) {
            //"java.lang.ArrayIndexOutOfBoundsException: too much data for RSA block" exception occurs here.
            return null;
        }
    }

    /**
     *
     * @param keyBytes
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     */
    public static PublicKey getPublicKey(byte[] keyBytes) throws NoSuchAlgorithmException, InvalidKeySpecException {
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        return keyFactory.generatePublic(keySpec);
    }

    /**
     *
     * @param keyBytes
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     */
    public static PrivateKey getPrivateKey(byte[] keyBytes) throws NoSuchAlgorithmException,
            InvalidKeySpecException {
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        return keyFactory.generatePrivate(keySpec);
    }
}


以及加密和解密数据的代码段:

 //encrypt
 byte[] e = RSA.encryptData(text, PUBLIC_KEY);
 String result = Base64.encodeToString(e, Base64.DEFAULT);
 tv_encrypted.setText(result);

 //decrypt
 byte[] d = RSA.decryptData(text, PRIVATE_KEY);
 String result = Base64.encodeToString(d, Base64.DEFAULT);
 tv_decrypted.setText("Decrypted result:\n" + result);


我知道原因可能是要解密的文本太长,但我只加密了“ abc”,然后解密了加密的“ abc”。如果要加密或解密的文本应比rsa私钥小11个字节,那么如何处理加密长文本?我该怎么解决?我是RSA的新手。

提前致谢!

最佳答案

您缺少代码中的某些步骤,因此无法检查。但是,有一些线索可以提示问题。您的decryptData方法采用String参数,然后调用String.getBytes()获取数据,然后将其解密。但是,加密的结果是字节序列,而不是任何有效String的编码。也许您打算对base64解码输入而不是调用getBytes()。通常,要执行解密和解码,必须逆转在加密和编码过程中执行的步骤。因此,如果明文是byte [],则步骤为:

字节[]→加密→字节[]→Base64编码→字符串。

然后,在解密方向上,您必须从Base64字符串开始,顺序如下:

字符串→Base64解码→字节[]→解密→字节[]

同样,另一个不好的做法,也是许多可移植性错误的根源是使用默认值。您在两个地方使用默认值,它们都很麻烦。首先,您使用默认的no-args String.getBytes()方法,并且大概将其与one-arg String (byte [])构造函数进行匹配。这使用平台默认字符集,但是在不同平台上可能有所不同。因此,请始终指定一个字符集。对于大多数应用,“ UTF-8”是理想选择。其次,您在不指定填充的情况下调用Cipher.getInstance('RSA')。 Oracle的Java和Android的Java将为您提供不同的填充,因此您的代码将无法在平台之间移植。始终指定完整的填充字符串。如果您需要可移植到较早的Java实现中,那么在这里进行选择就困难得多。 OAEP填充应该是您的首选,因此Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");可能是正确的选择。参见this进行进一步的讨论。

有关如何加密较长的文本,请参见answer from Henry

关于android - java.lang.ArrayIndexOutOfBoundsException:RSA块的数据过多,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36544306/

10-14 05:08