BadPaddingException解密Android中的加密数据

我是Android安全概念的新手。

我一直在阅读一些博客,以了解我们可以使用公钥加密数据,并可以使用相应的私钥解密它。 加密似乎没有任何问题,但是当我尝试解密时,它会抛出:

javax.crypto.BadPaddingException:错误:0407106B:rsa例程:RSA_padding_check_PKCS1_type_2:块类型不是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 

我不确定哪里出错了。

当填充(填充太小的加密块的字节)与指定的格式(例如PKCS1,OAEP,…)不匹配时,会发生BadPaddingException 。 这可能有以下几个原因:

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

由于您使用getInstance("RSA")进行加密初始化RSA,并使用getInstance("RSA/ECB/PKCS1Padding")进行解密,因此ECB / PKCS1Padding可能不是Android上的默认值(即使它应该在桌面上) -Java)。

所以在RSAEncrypt()试试这个:

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

如果这不起作用,请确保将从加密中的cipher.doFinal()获得的完全相同的byte []传递给解密中的cipher.doFinal()

(您的代码适用于我的桌面Java7顺便说一句。)

因为您正在使用加密数据,所以不太可能将它直接转换为String(每个字节可能与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); 

然后你可以做一些东西(比如存储)encryptedDataStr或whaterver。 然后……

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

祝你好运!

你必须将消息分解为块。

可以使用下面的课程。

//注意: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 

}