首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Android KeyStore RSA 加解密實戰:私鑰無法導出時的正確解密姿勢

     編輯:程式設計疑難解答

問題現象

使用 AndroidKeyStore 存儲 RSA 私鑰後,調用 PrivateKey.getEncoded() 返回 null,導致傳統 Cipher.getInstance("RSA") 初始化失敗,解密拋出異常。

根本原因

AndroidKeyStore 為了安全,永不導出私鑰原始字節。私鑰僅存在於安全硬件(TEE/StrongBox)中,只能通過 Cipher 間接使用,不能直接獲取字節數組。

正確解密代碼

public static byte[] decryptRSA(byte[] encryptedData, PrivateKey privateKey) {
    try {
        // 關鍵:必須指定完整的變換字符串,包含模式和填充
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(encryptedData);
    } catch (Exception e) {
        Log.e("RSA_Decrypt", "解密失敗", e);
        return null;
    }
}

關鍵點解析

  1. 變換字符串必須完整:"RSA" 等價於 "RSA/ECB/PKCS1Padding",但在某些 Android 版本上省略模式/填充會導致預設值不一致,顯式指定最安全。
  2. PrivateKey 直接傳給 Cipher.init:KeyStore 返回的 PrivateKey 實例已封裝硬件操作,無需也不允許提取字節。
  3. 加密端對應:加密時同樣使用 "RSA/ECB/PKCS1Padding",且公鑰可通過 Certificate.getPublicKey() 獲取並正常導出。

完整流程回顧

// 存儲
KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null);
KeyStore.PrivateKeyEntry entry = new KeyStore.PrivateKeyEntry(privateKey, certificateChain);
ks.setEntry("alias", entry, new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT)
    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
    .build());

// 取出並解密
KeyStore.PrivateKeyEntry retrieved = (KeyStore.PrivateKeyEntry) ks.getEntry("alias", null);
PrivateKey pk = retrieved.getPrivateKey();
byte[] plain = decryptRSA(cipherText, pk);

注意事項

  • Android 6.0 (API 23) 以上才完整支持 KeyStore RSA。
  • 密鑰生成時需設定 setDigests(KeyProperties.DIGEST_NONE) 若不簽名僅加密。
  • 測試時請使用真機,模擬器可能不支持硬件隔離。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved