在Android中解密加密数据时出现BadPaddingException异常

7

我对安卓系统的安全概念不太了解。

我一直在阅读一些博客,想了解如何使用公钥来加密数据,再使用相应的私钥进行解密。加密似乎没有任何问题,但是当我尝试解密时,它会抛出以下异常:

javax.crypto.BadPaddingException: error:0407106B:rsa routines:RSA_padding_check_PKCS1_type_2:block type is not 02.

我的代码如下:

public String RSAEncrypt(final String plain, PublicKey publicKey ) throws NoSuchAlgorithmException, NoSuchPaddingException,
    InvalidKeyException, IllegalBlockSizeException, BadPaddingException {

    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    byte [] encryptedBytes = cipher.doFinal(plain.getBytes());
    String encrypted = bytesToString(encryptedBytes);
    System.out.println("EEncrypted?????" + encrypted );
    return encrypted;
}

public String RSADecrypt(String encryptedBytes,PrivateKey privateKey ) throws NoSuchAlgorithmException, NoSuchPaddingException,
    InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException {
    Cipher cipher1 = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    cipher1.init(Cipher.DECRYPT_MODE, privateKey);
    byte [] decryptedBytes = cipher1.doFinal(stringToBytes(encryptedBytes));

    String decrypted = new String(decryptedBytes);
    System.out.println("DDecrypted?????" + decrypted);
    return decrypted;
    }

public  String bytesToString(byte[] b) {
    byte[] b2 = new byte[b.length + 1];
    b2[0] = 1;
    System.arraycopy(b, 0, b2, 1, b.length);
    return new BigInteger(b2).toString(36);
}

public  byte[] stringToBytes(String s) {
    byte[] b2 = new BigInteger(s, 36).toByteArray();
    return Arrays.copyOfRange(b2, 1, b2.length);
}

堆栈跟踪如下:

07-28 11:27:35.119: I/System.out(22933): KEYSTORE : String to encrypt = > Hello
07-28 11:27:35.119: I/System.out(22933): KEYSTORE : [B@41bbf4d0
07-28 11:27:38.422: I/System.out(22933): KEYSTORE : String to Decrypt = > UJGAchuDhu3mqH5YPjmYqKBapJYMjJRk9g6HIy8bANooWorzwqgiEo+dOse6Nfq7i0yzw/Wt7TSdTNiYROxehkZvEx/mW5+Niw1CgZ2y9b/ijTeNTF+7aGPrqfDXJ38hUFdTPc6oNl2FVOIafncGOSK9po1JOAYeK0JiA2KrACfPLPjsLQSRzseThyYGxttRM7qbx/N0VTmlTeuNpLFld8Gtw3fHR8UoLGkH/OTFYPLZBVNE8t/oCCy8FpcCu9SGXxF8vh1R4rq15bfyyh9sBU9RuVtoLM0wDSbKixHhNOwwx2Z/A+SHDaQD9C+x3p1AnS9FYZm0Y07E+VYQWqzOpw
07-28 11:27:38.562: W/System.err(22933): javax.crypto.BadPaddingException: error:0407106B:rsa routines:RSA_padding_check_PKCS1_type_2:block type is not 02
07-28 11:27:41.515: D/WifiNative-wlan0(773): doString: SIGNAL_POLL
07-28 11:27:41.515: W/WifiHW(773): QCOM Debug wifi_send_command "IFNAME=wlan0 SIGNAL_POLL"
07-28 11:27:41.525: D/wpa_supplicant(16189): nl80211: survey data missing!
07-2
07-28 11:27:56.612: W/WifiHW(773): QCOM Debug wifi_send_command "IFNAME=wlan0 SIGNAL_POLL"
07-28 11:27:56.612: D/wpa_supplicant(16189): nl80211: survey data missing!
07-28 11:27:56.622: I/wpa_supplicant(16189): environment dirty rate=0 [0][0][0]
07-28 11:27:56.622: D/WifiStateMachine(773): fetchRssiAndLinkSpeedNative RSSI = -62 abnormalRssiCnt = 0 newLinkSpeed = 58
07-28 11:27:56.622: D/WifiStateMachine(773): fetchRssiAndLinkSpeedNative mLinkspeedCount = 2, mLinkspeedSum: 116

我不确定我的问题出在哪里。

3个回答

7
< p >当填充(用于填充太小的加密块的字节)与指定格式(例如 PKCS1、OAEP 等)不匹配时,会发生 BadPaddingException。这可能有几个原因:

  1. 您在加密和解密时使用了不同的 RSA 模式。
  2. 从加密获得的数据(byte [])与传递给解密的数据不同。
  3. (您正在使用错误的 KeyPair。)

由于您正在使用 getInstance("RSA") 进行加密和 getInstance("RSA/ECB/PKCS1Padding") 进行解密来初始化 RSA,所以在 Android 上可能不是默认的 ECB/PKCS1Padding(即使在桌面 Java 上应该是如此)。

因此,请在 RSAEncrypt() 中尝试以下内容:

cipher.getInstance("RSA/ECB/PKCS1Padding");

如果这不起作用,请确保在解密时传递给的确切相同的< byte[] >与加密中获得的一样。

(顺便说一下,您的代码在我的桌面Java7上运行良好。)


顺便问一下,您知道如何检查使用别名值生成的密钥的有效性吗? - ARP
我不确切知道你的意思。(也许需要开一个新的问题并附上适当的代码?) 我假设你使用 KeyPairGenerator.getInstance("RSA").generateKeyPair(); 进行密钥生成? 那么实际上就不需要验证密钥了。 - i_turo
好的。在我的情况下,我为Cipher的两个实例指定了相同的转换算法。当我在桌面上进行单元测试时,它可以正常工作。但是当我在Android上运行它时,它会抛出异常。很奇怪。 - TheRealChx101

1
你必须将消息分成块。
可以使用以下类。
// 注意:RSA有块限制,文本大小必须<(SIZE/8),否则您将看到[太多数据用于RSA块]
public class RSA
{
private RSAPublicKey internalPublicKey;
private RSAPrivateCrtKey internalPrivateKey;
private int SIZE = -1;
private String cipherAlgorithm = "RSA/None/PKCS1PADDING";
private String keyAlgorithm = "RSA";
private int b64State = Base64.NO_WRAP;
private static int b64State_static = Base64.NO_WRAP;

public RSA(int size)
{
    SIZE = size;
    init();
}

public RSA(int size, RSAPublicKey puk, RSAPrivateCrtKey prk)
{
    if(puk == null)
        throw new RuntimeException("Err: PublicKey is null.");

    if(prk != null)
    {
        if(!puk.getModulus().equals(prk.getModulus()))
            throw new RuntimeException("Err: PublicKey not matched by PrivateKey.");
    }

    SIZE = size;
    internalPublicKey = puk;
    internalPrivateKey = prk;
}

private void init()
{
    try
    {
        //SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithSHA256And256BitAES-CBC-BC");
        KeyPairGenerator kpg = KeyPairGenerator.getInstance(keyAlgorithm);
        kpg.initialize(SIZE); //initialize(SIZE, new SecureRandom());

        KeyPair kp = kpg.genKeyPair();
        internalPublicKey = (RSAPublicKey) kp.getPublic();
        internalPrivateKey = (RSAPrivateCrtKey) kp.getPrivate();
    }
    catch(Exception e)
    {throw new RuntimeException("Err: init RSA. " + e.toString());}
}

public int getSize()
{
    return SIZE;
}

public RSAPublicKey getPublicKey()
{
    return internalPublicKey;
}

public RSAPrivateCrtKey getPrivateKey()
{
    return internalPrivateKey;
}

public String getPublicModule()
{
    String s = internalPublicKey.toString();

    return s.substring(s.indexOf("modulus")+8, s.indexOf(",publicExponent"));
}

public BigInteger getPublicModuleInt()
{
    return internalPublicKey.getModulus();
}

public String getPublicExponent()
{
    String s = internalPublicKey.toString();

    return s.substring(s.indexOf("publicExponent")+15, s.lastIndexOf("}"));
}

public BigInteger getPublicExponentInt()
{
    return internalPublicKey.getPublicExponent();
}

public String getPrivateExponent()
{
    String s = internalPrivateKey.toString();
    return s.substring(s.indexOf("privateExponent")+16, s.indexOf(",primeP"));
}

public String getPrimP()
{
    String s = internalPrivateKey.toString();
    return s.substring(s.indexOf("primeP=")+7, s.indexOf(",primeQ"));
}

public String getPrimQ()
{
    String s = internalPrivateKey.toString();
    return s.substring(s.indexOf("primeQ=")+7, s.indexOf(",primeExponentP"));
}

public String getPrimExponentP()
{
    String s = internalPrivateKey.toString();
    return s.substring(s.indexOf("primeExponentP=")+15, s.indexOf(",primeExponentQ"));
}

public String getPrimExponentQ()
{
    String s = internalPrivateKey.toString();
    return s.substring(s.indexOf("primeExponentQ=")+15, s.indexOf(",crtCoefficient"));
}

public String getCrtCoefficient()
{
    String s = internalPrivateKey.toString();
    return s.substring(s.indexOf("crtCoefficient=")+15, s.lastIndexOf(","));
}

public byte[] getPublicKeyAsByte()
{
    return internalPublicKey.getEncoded();
}

public byte[] getPrivateKeyAsByte()
{
    return internalPrivateKey.getEncoded();
}

public void changeCipherAlgorithm(String algorithm)
{
    cipherAlgorithm = algorithm;
}

public byte[] getEncrypt(byte[] plain)
{
    try
    {
        Cipher cipher = Cipher.getInstance(cipherAlgorithm);
        cipher.init(Cipher.ENCRYPT_MODE, internalPublicKey);

        return cipher.doFinal(plain);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt(byte[] plain), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public byte[] getEncrypt(String plain)
{
    try
    {
        return getEncrypt(plain.getBytes("UTF-8"));
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt(String x), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public String getEncryptToB64(byte[] plain)
{
    return Base64.encodeToString(getEncrypt(plain), b64State);
}

public byte[] getLargeEncrypt(byte[] plain, boolean byPadding) //byPadding = true if use RSA/xxx/xxxPADDING
{
    ByteArrayOutputStream out = new ByteArrayOutputStream();

    try
    {
        int n = byPadding ? (getSize()/8) -11: (getSize()/8);

        int offset = 0;

        while(offset < plain.length)
        {
            byte[] section = Arrays.copyOfRange(plain, offset, Math.min(offset+n, plain.length));

            byte[] cache = getEncrypt(section);
            out.write(cache, 0, cache.length);

            offset += n;
        }

        return out.toByteArray();
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getLargeEncrypt(String x), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public byte[] getLargeEncrypt(String plain, boolean byPadding) //byPadding = true if use RSA/xxx/xxxPADDING
{
    return getLargeEncrypt(plain.getBytes(Charset.forName("UTF-8")), byPadding);
}

public String getLargeEncryptToB64(String plain, boolean byPadding) //byPadding = true if use RSA/xxx/xxxPADDING
{
    return Base64.encodeToString(getLargeEncrypt(plain, byPadding), Base64.NO_WRAP);
}

public String getLargeEncryptToB64Block(String plain, boolean byPadding) //byPadding = true if use RSA/xxx/xxxPADDING
{
    StringBuilder sb = new StringBuilder();

    try
    {
        byte[] enc = plain.getBytes("UTF-8");
        int n = byPadding ? (getSize()/8) -11: (getSize()/8);

        int offset = 0;

        while(offset < enc.length)
        {
            byte[] section = Arrays.copyOfRange(enc, offset, Math.min(offset+n, enc.length));

            sb.append(getEncryptToB64(section));

            offset += n;
        }
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getLargeEncryptToB64Block(String x), ", Constants.DEFAULT_ALERT_STATE);
    }

    return sb.toString();
}

public String getLargeDecryptFromB64Block(String enc)
{
    ByteArrayOutputStream out = new ByteArrayOutputStream();

    try
    {
        int n = (getSize()/8)-11;
        int x = getEncryptToB64(TextHelper.generateString(n).getBytes("UTF-8")).length();
        String[] ex = TextHelper.splitFix(enc, x);

        for(int i=0; i<ex.length; i++)
        {
            byte[] sec = Base64.decode(ex[i], Base64.NO_WRAP);
            out.write(sec, 0, sec.length);
            //sb.append(getDecryptFromB64(ex[i]));
        }

        return getLargeDecryptToString(out.toByteArray());//sb.toString()
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getLargeDecryptFromB64Block(String x), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public byte[] getLargeDecrypt(byte[] enc)
{
    ByteArrayOutputStream out = new ByteArrayOutputStream();

    try
    {
        int n = (getSize()/8);
        int offset = 0;

        while(offset < enc.length)
        {
            byte[] section = Arrays.copyOfRange(enc, offset, Math.min(offset+n, enc.length));

            byte[] cache = getDecrypt(section);
            out.write(cache, 0, cache.length);

            offset += n;
        }

        return out.toByteArray();
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getLargeDecrypt(byte[] x), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public String getLargeDecryptToString(byte[] enc)
{
    return new String(getLargeDecrypt(enc), Charset.forName("UTF-8"));
}

public String getLargeDecryptFromB64(String encB64)
{
    return getLargeDecryptToString(Base64.decode(encB64, Base64.NO_WRAP));
}

public byte[] getDecrypt(byte[] encryptedBytes)
{
    try
    {
        Cipher cipher = Cipher.getInstance(cipherAlgorithm);
        cipher.init(Cipher.DECRYPT_MODE, internalPrivateKey);

        return cipher.doFinal(encryptedBytes);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getDecrypt(byte[] x), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public String getDecryptFromB64(String encrypted)
{
    try
    {
        byte[] b = Base64.decode(encrypted.getBytes("UTF-8"), b64State);
        return getDecryptAsString(b);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getDecryptFromB64(String x), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public String getDecryptAsString(byte[] encryptedBytes)
{
    return new String(getDecrypt(encryptedBytes), Charset.forName("UTF-8"));
}

public static byte[] getEncrypt(byte[] plain, PublicKey pk, Cipher cipher)
{
    try
    {
        cipher.init(Cipher.ENCRYPT_MODE, pk);
        return cipher.doFinal(plain);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt(byte[] x, PublicKey pk, Cipher cipher), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static byte[] getEncrypt(String plain, PublicKey pk, Cipher cipher)
{
    try
    {
        return getEncrypt(plain.getBytes("UTF-8"), pk, cipher);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt(String x, PublicKey pk, Cipher cipher), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static byte[] getDecrypt(byte[] encryptedBytes, PrivateKey pk, Cipher cipher)
{
    try
    {
        cipher.init(Cipher.DECRYPT_MODE, pk);
        return cipher.doFinal(encryptedBytes);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static String getDecryptAsString(byte[] encryptedBytes,  PrivateKey pk, Cipher cipher)
{
    try
    {
        return new String(getDecrypt(encryptedBytes, pk, cipher), "UTF-8");
    }
    catch(Exception e){}
    return null;
}

public static byte[] getDecrypt(final byte[] encryptedBytes, byte[] privateKey, Cipher cipher)
{
    try
    {
        KeyFactory keyFac = KeyFactory.getInstance("RSA");
        KeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
        PrivateKey pk = keyFac.generatePrivate(keySpec);

        cipher.init(Cipher.DECRYPT_MODE, pk);
        return cipher.doFinal(encryptedBytes);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static String getDecryptAsString(final byte[] encryptedBytes, byte[] privateKey, Cipher cipher)
{
    return new String(getDecrypt(encryptedBytes, privateKey, cipher), Charset.forName("UTF-8"));
}

public static byte[] sign(byte[] forSign, PrivateKey byThisKey)
{
    try
    {
        Signature privateSignature = Signature.getInstance("SHA1withRSA");//or SHA256withRSA
        privateSignature.initSign(byThisKey);
        privateSignature.update(forSign);

        return privateSignature.sign();
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: sign(), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static String sign(String forSign, PrivateKey byThisKey)
{
    return Base64.encodeToString(sign(forSign.getBytes(), byThisKey), b64State_static);
}

public static boolean verify(String plainText, String signature, PublicKey publicKey)
{
    Signature publicSignature;

    try
    {
        publicSignature = Signature.getInstance("SHA1withRSA");
        publicSignature.initVerify(publicKey);
        publicSignature.update(plainText.getBytes());

        byte[] signatureBytes = Base64.decode(signature, b64State_static);

        return publicSignature.verify(signatureBytes);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: verify(), ", Constants.DEFAULT_ALERT_STATE);
    }

    return false;
}

public static RSAPublicKey generatePublicKey(String modulus, String exponent)
{
    try
    {
        BigInteger modBigInteger = new BigInteger(modulus, 16);
        BigInteger exBigInteger = new BigInteger(exponent, 16);
        RSAPublicKeySpec spec = new RSAPublicKeySpec(modBigInteger, exBigInteger);

        KeyFactory factory = KeyFactory.getInstance("RSA");
        return (RSAPublicKey) factory.generatePublic(spec);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt(), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static RSAPublicKey generatePublicKey(BigInteger modulus, BigInteger exponent)
{
    try
    {
        RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, exponent);

        KeyFactory factory = KeyFactory.getInstance("RSA");
        return (RSAPublicKey) factory.generatePublic(spec);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt(), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static RSAPublicKey generatePublicKeyFromDotNet(String modulus, String exponent)
{
    return generatePublicKey(RSA.parseDotNetBigInt(modulus), RSA.parseDotNetBigInt(exponent));
}

public static RSAPrivateCrtKey generatePrivateKeyFromDotNet(String modulus, String pubEx, String priEx, String p, String q, String dp, String dq,String invQ)
{
    return generatePrivateKey(RSA.parseDotNetBigInt(modulus), RSA.parseDotNetBigInt(pubEx), RSA.parseDotNetBigInt(priEx), RSA.parseDotNetBigInt(p)
    ,RSA.parseDotNetBigInt(q),RSA.parseDotNetBigInt(dp), RSA.parseDotNetBigInt(dq), RSA.parseDotNetBigInt(invQ));
}

public static PublicKey generateBCPublicKey(String modulus, String exponent)
{
    try
    {
        BigInteger modBigInteger = new BigInteger(modulus, 16);
        BigInteger exBigInteger = new BigInteger(exponent, 16);
        RSAPublicKeySpec spec = new RSAPublicKeySpec(modBigInteger, exBigInteger);

        KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
        return factory.generatePublic(spec);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getBCPublicKey(), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static RSAPrivateCrtKey generatePrivateKey(String modulus, String publicExpo, String privateExpo, String primP, String primQ, String ePrimP, String ePrimQ, String cof)
{
    try
    {
        BigInteger module = new BigInteger(modulus, 16);
        BigInteger expo1 = new BigInteger(publicExpo, 16);
        BigInteger expo2 = new BigInteger(privateExpo, 16);
        BigInteger prim_P = new BigInteger(primP, 16);
        BigInteger prim_Q = new BigInteger(primQ, 16);
        BigInteger prim_EP = new BigInteger(ePrimP, 16);
        BigInteger prim_EQ = new BigInteger(ePrimQ, 16);
        BigInteger coefficient = new BigInteger(cof, 16);
        /*BigInteger module = new BigInteger(1, Base64.encode(modulus.getBytes(), b64State));*/

        RSAPrivateCrtKeySpec spec = new RSAPrivateCrtKeySpec(module, expo1, expo2, prim_P, prim_Q, prim_EP, prim_EQ, coefficient);

        KeyFactory factory = KeyFactory.getInstance("RSA");
        return (RSAPrivateCrtKey) factory.generatePrivate(spec);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static RSAPrivateCrtKey generatePrivateKey(BigInteger modulus, BigInteger publicExpo, BigInteger privateExpo, BigInteger primP, BigInteger primQ, BigInteger ePrimP, BigInteger ePrimQ, BigInteger cof)
{
    try
    {
        RSAPrivateCrtKeySpec spec = new RSAPrivateCrtKeySpec(modulus, publicExpo, privateExpo, primP, primQ, ePrimP, ePrimQ, cof);

        KeyFactory factory = KeyFactory.getInstance("RSA");
        return (RSAPrivateCrtKey) factory.generatePrivate(spec);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static PrivateKey generateBCPrivateKey(String modulus, String publicExpo, String privateExpo, String primP, String primQ, String ePrimP, String ePrimQ, String cof)
{
    try
    {
        BigInteger module = new BigInteger(modulus, 16);
        BigInteger expo1 = new BigInteger(publicExpo, 16);
        BigInteger expo2 = new BigInteger(privateExpo, 16);
        BigInteger prim_P = new BigInteger(primP, 16);
        BigInteger prim_Q = new BigInteger(primQ, 16);
        BigInteger prim_EP = new BigInteger(ePrimP, 16);
        BigInteger prim_EQ = new BigInteger(ePrimQ, 16);
        BigInteger coefficient = new BigInteger(cof, 16);

        RSAPrivateCrtKeySpec spec = new RSAPrivateCrtKeySpec(module, expo1, expo2, prim_P, prim_Q, prim_EP, prim_EQ, coefficient);

        KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
        return factory.generatePrivate(spec);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static Cipher generateCipher(String alg,@Nullable String provider)
{
    try
    {
        if(provider == null)
            return Cipher.getInstance(alg);
        else
            return Cipher.getInstance(alg, provider);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: generateCipher(), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static BigInteger parseDotNetBigInt(String b64BigInt)
{
    try
    {
        String modulusHex = Hex.encodeHex(Base64.decode(b64BigInt.getBytes("UTF-8"), Base64.NO_WRAP));
        return new BigInteger(modulusHex, 16);
    }
    catch (Exception ex)
    {
        ThreadHelper.exceptionAlert(ex, Constants.TAG_FOR_LOG, "Err: parseDotNetBigInt(),", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static String privateKeyToXMLString(RSAPrivateCrtKey key)
{
    try
    {
        Document xml = privateKeyToXML(key);
        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        StringWriter sw = new StringWriter();
        transformer.transform(new DOMSource(xml), new StreamResult(sw));
        return sw.getBuffer().toString();
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: privateKeyToXMLString(RSAPrivateCrtKey x),", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static String publicKeyToXMLString(RSAPublicKey key)
{
    try
    {
        Document xml = publicKeyToXML(key);

        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        StringWriter sw = new StringWriter();
        transformer.transform(new DOMSource(xml), new StreamResult(sw));

        return sw.getBuffer().toString();
    }
    catch(Exception e){}

    return null;
}

public static Document publicKeyToXML(RSAPublicKey key)
{
    try
    {
        Document result = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        Element rsaKeyValue = result.createElement("RSAKeyValue");
        result.appendChild(rsaKeyValue);
        Element modulus = result.createElement("Modulus");
        rsaKeyValue.appendChild(modulus);

        byte[] modulusBytes = key.getModulus().toByteArray();
        modulusBytes = stripLeadingZeros(modulusBytes);

        modulus.appendChild(result.createTextNode(new String(Base64.encode(modulusBytes, b64State_static))));

        Element exponent = result.createElement("Exponent");
        rsaKeyValue.appendChild(exponent);

        byte[] exponentBytes = key.getPublicExponent().toByteArray();

        exponent.appendChild(result.createTextNode(new String(Base64.encode(exponentBytes, b64State_static))));

        return result;
    }
    catch(Exception e){}

    return null;
}

public static Document privateKeyToXML(RSAPrivateCrtKey key)
{
    try
    {
        Document result = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();

        Element rsaKeyValue = result.createElement("RSAKeyValue");
        result.appendChild(rsaKeyValue);

        Element modulus = result.createElement("Modulus");
        rsaKeyValue.appendChild(modulus);

        Element exponent = result.createElement("Exponent");
        rsaKeyValue.appendChild(exponent);

        Element P = result.createElement("P");
        rsaKeyValue.appendChild(P);

        Element Q = result.createElement("Q");
        rsaKeyValue.appendChild(Q);

        Element DP = result.createElement("DP");
        rsaKeyValue.appendChild(DP);

        Element DQ = result.createElement("DQ");
        rsaKeyValue.appendChild(DQ);

        Element InverseQ = result.createElement("InverseQ");
        rsaKeyValue.appendChild(InverseQ);

        Element D = result.createElement("D");
        rsaKeyValue.appendChild(D);

        byte[] modulusBytes = key.getModulus().toByteArray();
        modulusBytes = stripLeadingZeros(modulusBytes);
        modulus.appendChild(result.createTextNode(new String(Base64.encode(modulusBytes, b64State_static))));

        byte[] pubExponent = key.getPublicExponent().toByteArray();
        exponent.appendChild(result.createTextNode(new String(Base64.encode(pubExponent, b64State_static))));

        byte[] p = key.getPrimeP().toByteArray();
        P.appendChild(result.createTextNode(new String(Base64.encode(p, b64State_static))));

        byte[] q = key.getPrimeQ().toByteArray();
        Q.appendChild(result.createTextNode(new String(Base64.encode(q, b64State_static))));

        byte[] ep = key.getPrimeExponentP().toByteArray();
        DP.appendChild(result.createTextNode(new String(Base64.encode(ep, b64State_static))));

        byte[] eq = key.getPrimeExponentP().toByteArray();
        DQ.appendChild(result.createTextNode(new String(Base64.encode(eq, b64State_static))));

        byte[] cof = key.getCrtCoefficient().toByteArray();
        InverseQ.appendChild(result.createTextNode(new String(Base64.encode(cof, b64State_static))));

        byte[] priExponent = key.getPrivateExponent().toByteArray();
        D.appendChild(result.createTextNode(new String(Base64.encode(priExponent, b64State_static))));

        return result;
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static byte[] stripLeadingZeros(byte[] input)
{
    while (input[0] == (byte) 0)
    {
        input = Arrays.copyOfRange(input, 1, input.length);
    }

    return input;
}

public static void saveKey(File file, PublicKey key)
{
    try
    {
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key.getEncoded());
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(x509EncodedKeySpec.getEncoded());
        fos.close();
    }
    catch(Exception e){}
}

public static void saveKey(File file, PrivateKey key)
{
    try
    {
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key.getEncoded());
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(pkcs8EncodedKeySpec.getEncoded());
        fos.close();
    }
    catch(Exception e){}
}

public PublicKey openPublicKey(String path, String algorithm)
{
    try
    {
        File filePublicKey = new File(path);
        FileInputStream fis = new FileInputStream(path);
        byte[] encodedPublicKey = new byte[(int) filePublicKey.length()];
        fis.read(encodedPublicKey);
        fis.close();

        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedPublicKey);
        return keyFactory.generatePublic(publicKeySpec);
    }
    catch(Exception e){}

    return null;
}

public PrivateKey openPrivateKey(String path, String algorithm)
{
    try
    {
        File filePrivateKey = new File(path);
        FileInputStream fis = new FileInputStream(path);
        byte[] encodedPrivateKey = new byte[(int) filePrivateKey.length()];
        fis.read(encodedPrivateKey);
        fis.close();

        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);//RSA
        PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
        return keyFactory.generatePrivate(privateKeySpec);
    }
    catch(Exception e){}

    return null;
}

public static RSAPublicKey fetchPublicKeyFromXML(Document xml)
{
    try
    {
        Element root = XMLMaster.getRoot(xml);
        String mud = XMLMaster.getTextContent(root, "Modulus", 0);
        String pubE = XMLMaster.getNodeValue(root, "Exponent", 0);

        return generatePublicKeyFromDotNet(mud, pubE);
    }
    catch (Throwable e)
    {
        //throw new RuntimeException("Err: can not fetch PublicKey. " + e.toString());
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: can not fetch PublicKey. ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static RSAPrivateCrtKey fetchPrivateKeyFromXML(Document xml)
{
    try
    {
        Element root = XMLMaster.getRoot(xml);
        String mud = XMLMaster.getTextContent(root, "Modulus", 0);
        String pubE = XMLMaster.getNodeValue(root, "Exponent", 0);
        String priE = XMLMaster.getNodeValue(root, "D", 0);
        String p = XMLMaster.getNodeValue(root, "P", 0);
        String Q = XMLMaster.getNodeValue(root, "Q", 0);
        String EP = XMLMaster.getNodeValue(root, "DP", 0);
        String EQ = XMLMaster.getNodeValue(root, "DQ", 0);
        String cof = XMLMaster.getNodeValue(root, "InverseQ", 0);

        return generatePrivateKeyFromDotNet(mud, pubE, priE, p, Q, EP, EQ, cof);
    }
    catch (Throwable e)
    {
        throw new RuntimeException("Err: can not fetch PrivateKey. " + e.toString());
    }
}

public static PrivateKey loadPrivateKey(String privateKeyB64)
{
    try
    {
        byte[] buffer = Base64.decode(privateKeyB64, Base64.NO_WRAP);

        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(keySpec);

        //Class c = Reflector.getClassByAddressName("com.android.org.conscrypt.OpenSSLRSAPrivateKey");
        //RSAPrivateKeySpec privSpec = new RSAPrivateKeySpec(modules, d);
    }
    catch (Throwable e)
    {
        throw new RuntimeException("Err: can not load PrivateKey. " + e.toString());
    }
}

public String convertCaseToString(BigInteger num)
{
    return num.toString(16);
} // Use: convertCaseToString(rsa.getPublicModule())

}


0

因为您正在处理加密数据,所以不太可能直接将其转换为字符串(每个字节可能不对应于可存储在String中的字符)- 因此我预计bytesToString(encryptedBytes)通常会失败。首先尝试将加密数据转换为Base64,然后它将始终可存储在String中。然后您只需执行相反的操作即可解密:

// to encrypt and get a String object
byte[] encode = Base64.encode(encryptedBytes, Base64.NO_PADDING|Base64.NO_WRAP);
String encryptedDataStr = new String(encode);

然后你可以做一些事情(比如存储)加密的数据字符串或其他。然后稍后再处理...

// to decrypt
byte[] encryptedBytes = Base64.decode(encryptedDataStr, Base64.NO_PADDING|Base64.NO_WRAP);
byte [] decryptedBytes = cipher1.doFinal(encryptedBytes);

祝你好运!


我刚刚尝试了上面的解决方案,但没有成功。它仍然抛出相同的异常。 - ARP
你能提供堆栈跟踪吗? - Nebu
bytesToString 方法不会直接转换为字符串,它使用一种自行开发但足够的方法对字节进行编码。 - President James K. Polk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接