[英]Android public key encryption
我的 Android 應用程序實現了 RSA 加密,但是后端無法解密應用程序生成的令牌。 這是代碼,在調用之前已經刪除了公鑰的開頭和結尾行,可能是什么問題?
String encryptedToken = Base64.encodeToString(encrypt(publicKey, "4111111111111111"), Base64.NO_WRAP);
public static byte[] encrypt(String publicKey, String data) {
if (TextUtils.isEmpty(publicKey) || TextUtils.isEmpty(data)) {
return null;
}
try {
// Decode the modified public key into a byte[]
byte[] publicKeyByteArray = Base64.decode(publicKey.getBytes("UTF-8"),Base64.NO_WRAP);
Cipher mCipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKeyByteArray);
Key key = keyFactory.generatePublic(x509KeySpec);
mCipher.init(Cipher.ENCRYPT_MODE, key);
return mCipher.doFinal(data.getBytes("UTF-8"));
}
catch (UnsupportedEncodingException e) {
Log.e("RSAKEY", e.getMessage());
}
catch (NoSuchPaddingException e) {
Log.e("RSAKEY", e.getMessage());
} catch (NoSuchAlgorithmException e) {
Log.e("RSAKEY", e.getMessage());
} catch (InvalidKeyException e) {
Log.e("RSAKEY", e.getMessage());
} catch (InvalidKeySpecException e) {
Log.e("RSAKEY", e.getMessage());
} catch (IllegalBlockSizeException e) {
Log.e("RSAKEY", e.getMessage());
} catch (BadPaddingException e) {
Log.e("RSAKEY", e.getMessage());
}
return null;
}
后端團隊提供了以下有效的示例代碼,但它適用於桌面 Java。 Android 庫沒有 Base64.getEncoder 方法。 它與我寫的非常相似,但我的只是不起作用。
// Decode the modified public key into a byte[]
byte[] publicKeyByteArray = Base64.getDecoder().decode(publicKey.getBytes(StandardCharsets.UTF_8));
// Create a PublicKey from the byte array
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyByteArray);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(keySpec);
// Get an instance of the Cipher and perform the encryption
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] cipherText = cipher.doFinal(ccNum.getBytes(StandardCharsets.UTF_8));
// Get the encrypted value as a Base64-encoded String
String encodeToStr = Base64.getEncoder().encodeToString(cipherText);
// Print out the encoded, encrypted string
System.out.println("Encrypted and Encoded String: " + encodeToStr);
我在每一步都比較了字節數組值。 桌面密碼和安卓密碼得到完全相同的輸入。 然而,Android 代碼 cipher.doFinal 的結果無法被后端解密。 如果我將桌面結果放到 REST 調用正文中,它們就可以正常工作,所以這不是由 REST 調用引起的。
我還嘗試在 Android 上創建一個公鑰/私鑰對,並使用生成的公鑰進行加密,而不是使用我們后端的公鑰,並使用私鑰解密並且它可以工作。 所以密碼也有效,只是后端以某種方式期待不同的東西
團隊中終於有人破解了這個問題。 原因是Android操作系統使用Bouncy Castle,后端使用Sun作為Provider,導致后端拋出BadPaddingException。 為了使其工作,需要在 Android 上以這種方式初始化密碼:
mCipher.init(Cipher.ENCRYPT_MODE, key, new
OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA1,
PSource.PSpecified.DEFAULT));
在這篇文章中查看更多詳細信息: http : //bouncy-castle.1462172.n4.nabble.com/Problems-with-OAEP-SHA-256-hash-crypto-td1466852.html
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.