2015-12-14 27 views
6

Tôi đang cố gắng mã hóa và giải mã Strings trong ứng dụng Android của mình nhưng tôi vẫn gặp lỗi InvalidKeyException.Lỗi giải mã Android

Đây là mã của tôi: Phương pháp

// Tạo phím

public void generateKeys() { 
    Calendar cal = Calendar.getInstance(); 
    Date now = cal.getTime(); 
    cal.add(Calendar.YEAR, 25); 
    Date end = cal.getTime(); 

    KeyPairGenerator kpg = null; 
    try { 
     kpg = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore"); 
    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } catch (NoSuchProviderException e) { 
     e.printStackTrace(); 
    } 
    try { 
     kpg.initialize(new KeyPairGeneratorSpec.Builder(context) 
       .setAlias(KEY_ALIAS) 
       .setStartDate(now) 
       .setEndDate(end) 
       .setSerialNumber(BigInteger.valueOf(1)) 
       .setSubject(new X500Principal("CN=" + KEY_ALIAS)) 
       .build()); 
    } catch (InvalidAlgorithmParameterException e) { 
     e.printStackTrace(); 
    } 

    KeyPair kp = kpg.generateKeyPair(); 

    KeyStore ks = null; 
    try { 
     ks = KeyStore.getInstance("AndroidKeyStore"); 
     ks.load(null); 
     Enumeration<String> aliases = ks.aliases(); 
    } catch (KeyStoreException e) { 
     e.printStackTrace(); 
    } catch (CertificateException e) { 
     e.printStackTrace(); 
    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

    KeyStore.Entry entry = null; 
    try { 
     entry = ks.getEntry(KEY_ALIAS, null); 
    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } catch (UnrecoverableEntryException e) { 
     e.printStackTrace(); 
    } catch (KeyStoreException e) { 
     e.printStackTrace(); 
    } 
    if (!(entry instanceof KeyStore.PrivateKeyEntry)) { 
     Log.e(LOG_TAG, "Not an instance of PrivateKeyEntry."); 
    } 
    else{ 
     privKey = ((KeyStore.PrivateKeyEntry) entry).getPrivateKey(); 
     pubKey = ((KeyStore.PrivateKeyEntry) entry).getCertificate().getPublicKey(); 
    } 

} 

// Mã hóa Phương pháp

private String encryptString(String value){ 
    byte[] encodedBytes = null; 
    try { 
     Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL"); 
     cipher.init(Cipher.ENCRYPT_MODE, pubKey); 
     encodedBytes = cipher.doFinal(value.getBytes()); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

    return Base64.encodeToString(encodedBytes, Base64.DEFAULT); 
} 

// Decrypt Phương pháp

private String decryptString(String value){ 
    byte[] decodedBytes = null; 
    try { 
     Cipher c = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL"); 
     c.init(Cipher.DECRYPT_MODE, privKey); 
     decodedBytes = c.doFinal(Base64.decode(value, Base64.DEFAULT)); 
    } catch (Exception e) { 
     e.printStackTrace(); 
     Log.e("Error", "Error = " + e); 
     return "SECURE_FAILURE"; 
    } 

    return new String(decodedBytes); 
} 

// Kiểm tra Mã số

generateKeys(); 
    String encrypted = encryptString("Hello World"); 
    Log.e("Encrypt", "encrypted = " + encrypted); 
    String decrypted = decryptString(encrypted); 
    Log.e("Decrypt", "decrypted = " + decrypted); 

Dường như mã hóa hoạt động OK vì nó in ra một cái gì đó như thế này:

encrypted = SbA2iWWKQbDL7NTA9xvtjD/viYDdpx9fLRYTSZ8UQzdBy3QLqzkswBY21ErH7FPza3vZys4E4PZw uxaGkRz0aC0FLqsYlbpcJernGm5+D5lRcBOaZmgkNY9pMf0YP75cBbcJdcmb1rDaH40nCRDnEoXv rGESJRqT6p0NMzlZqdd9KO3tqfExwgservAWxPNtRDBbMgE4I/09418jM5Ock5eayfOuv/STwEy6 Ecd56UjFH63h+gP6ed2aMDhBVeExMxvdloY+VnsAxS5Dkoc2GdaljtjRuPK48HQASoJK8EwAMNpz

Nhưng khi tôi cố gắng để giải mã tôi nhận được lỗi sau:

java.security.InvalidKeyException: Need RSA private or public key

tôi có thể 't hình tại sao tôi nhận được ngoại lệ này? Có ai giúp được không?

+0

Bất kỳ may mắn nào? Tôi nhận được cùng một ngoại lệ trong Android Marshmallow. – Luis

+0

Tôi đã sửa nó bằng cách sử dụng một nhà cung cấp khác ... xem câu trả lời của tôi dưới đây. – Luis

+1

Trừ khi có một số lý do để cần các khóa công khai/riêng tư mã hóa không đối xứng (RSA) chỉ sử dụng mã hóa đối xứng như AES. Mã hóa đối xứng là sự lựa chọn chung cho việc mã hóa dữ liệu. Độ dài dữ liệu mã hóa không đối xứng được giới hạn ở kích thước khóa và thực sự chậm và không an toàn hơn. – zaph

Trả lời

9

Hãy thử sử dụng một nhà cung cấp khác nhau, như thế này:

Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidKeyStoreBCWorkaround"); 
+2

Làm việc cho tôi, mặc dù một số giải thích sẽ là tuyệt vời. – Waboodoo

8

này làm việc cho tôi:

private Cipher getCipher() { 
    try { 
     if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { // below android m 
      return Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL"); // error in android 6: InvalidKeyException: Need RSA private or public key 
     } 
     else { // android m and above 
      return Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidKeyStoreBCWorkaround"); // error in android 5: NoSuchProviderException: Provider not available: AndroidKeyStoreBCWorkaround 
     } 
    } catch(Exception exception) { 
     throw new RuntimeException("getCipher: Failed to get an instance of Cipher", exception); 
    } 
} 
2

Loại bỏ các nhà cung cấp làm việc cho tôi:

Cipher.getInstance("RSA/ECB/PKCS1Padding") 

Từ Java docs: " Phương pháp này duyệt qua danh sách Nhà cung cấp bảo mật đã đăng ký, bắt đầu với Nhà cung cấp được ưu tiên nhất. đối tượng pher đóng gói triển khai CipherSpi từ Nhà cung cấp đầu tiên hỗ trợ thuật toán được chỉ định được trả về. "

Các vấn đề liên quan