我正在尝试使用 KeyStore 加密字符串并使用这篇文章作为引用。

KeyPairGeneratorSpec replacement with KeyGenParameterSpec.Builder equivalents - Keystore operation failed

然而,当我解密字符串时,我不断收到这个“错误的 base-64”。我不明白如何解决这个问题。我知道加密的字符串包含解密器不知道的字符。但我不明白修复。

我看到了一些类似的帖子,但没有太大帮助,因为答案中没有代码。

java.lang.IllegalArgumentException: bad base-64

这是我的测试代码的片段,有人可以告诉我如何解密我的字符串吗?

Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL"); 
inCipher.init(Cipher.ENCRYPT_MODE, publicKey); 
 
Cipher outCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL"); 
outCipher.init(Cipher.DECRYPT_MODE, privateKey); 
 
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 
CipherOutputStream cipherOutputStream = new CipherOutputStream( 
        outputStream, inCipher); 
cipherOutputStream.write(plainText.getBytes("UTF-8")); 
cipherOutputStream.close(); 
 
String ecryptedText = outputStream.toString(); 
Log.d(TAG, "Encrypt = " + ecryptedText); 
 
String cipherText = ecryptedText; 
CipherInputStream cipherInputStream = new CipherInputStream( 
        new ByteArrayInputStream(Base64.decode(cipherText, Base64.DEFAULT)), outCipher); 
ArrayList<Byte> values = new ArrayList<>(); 
int nextByte; 
while ((nextByte = cipherInputStream.read()) != -1) { 
    values.add((byte)nextByte); 
} 
 
byte[] bytes = new byte[values.size()]; 
for(int i = 0; i < bytes.length; i++) { 
    bytes[i] = values.get(i).byteValue(); 
} 
 
String finalText = new String(bytes, 0, bytes.length, "UTF-8"); 
Log.d(TAG, "Decrypt = " + ecryptedText); 

请您参考如下方法:

这是一个关于如何使用 Android KeyStore 的工作示例使用 ByteArrayOutputStream 加密/解密内存字符串和 ByteArrayInputStream .注意提供者更改,为 >= 6使用 "AndroidKeyStoreBCWorkaround"对于旧版本使用 "AndroidOpenSSL" .此外,您必须使用 Base64.encodeToString 将加密数据编码为 Base64 字符串。像这样:

String ecryptedText = Base64.encodeToString(outputStream.toByteArray(), Base64.DEFAULT); 

我的最终工作示例基于您的代码

try { 
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance( 
            KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore"); 
    keyPairGenerator.initialize( 
            new KeyGenParameterSpec.Builder( 
                    "key1", 
                    KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) 
                    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1) 
                    .build()); 
    KeyPair keyPair = keyPairGenerator.generateKeyPair(); 
 
    // error in android 6: InvalidKeyException: Need RSA private or public key AndroidOpenSSL 
    // error in android 5: NoSuchProviderException: Provider not available: AndroidKeyStoreBCWorkaround 
    String provider = Build.VERSION.SDK_INT < Build.VERSION_CODES.M ? "AndroidOpenSSL" : "AndroidKeyStoreBCWorkaround"; 
 
    Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider); 
    inCipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic()); 
 
    Cipher outCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider); 
    outCipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate()); 
 
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 
    CipherOutputStream cipherOutputStream = new CipherOutputStream( 
            outputStream, inCipher); 
 
    String plainText = "This is a text"; 
 
    cipherOutputStream.write(plainText.getBytes("UTF-8")); 
    cipherOutputStream.close(); 
 
    String ecryptedText = Base64.encodeToString(outputStream.toByteArray(), Base64.DEFAULT); 
    Log.d(TAG, "Encrypt = " + ecryptedText); 
 
    String cipherText = ecryptedText; 
    CipherInputStream cipherInputStream = new CipherInputStream( 
            new ByteArrayInputStream(Base64.decode(cipherText, Base64.DEFAULT)), outCipher); 
 
    ArrayList<Byte> values = new ArrayList<>(); 
    int nextByte; 
    while ((nextByte = cipherInputStream.read()) != -1) { 
        values.add((byte)nextByte); 
    } 
 
    byte[] bytes = new byte[values.size()]; 
    for(int i = 0; i < bytes.length; i++) { 
        bytes[i] = values.get(i).byteValue(); 
    } 
 
    String finalText = new String(bytes, 0, bytes.length, "UTF-8"); 
    Log.d(TAG, "Decrypt = " + finalText); 
} catch (javax.crypto.NoSuchPaddingException e) { 
    Log.e(TAG, Log.getStackTraceString(e)); 
} catch (IOException e) { 
    Log.e(TAG, Log.getStackTraceString(e)); 
} catch (NoSuchAlgorithmException e) { 
    Log.e(TAG, Log.getStackTraceString(e)); 
} catch (NoSuchProviderException e) { 
    Log.e(TAG, Log.getStackTraceString(e)); 
} catch (InvalidAlgorithmParameterException e) { 
    Log.e(TAG, Log.getStackTraceString(e)); 
} catch (InvalidKeyException e) { 
    Log.e(TAG, Log.getStackTraceString(e)); 
} catch (UnsupportedOperationException e) { 
    Log.e(TAG, Log.getStackTraceString(e)); 
} 

输出

D/MainActivity: Encrypt = rejkfeas3HgYnZOlC4S/R3KvlMTyiBjr5T6LqWGj9bq6nvpM0KBsoeYtr4OdCLITFX5GojuO4VpB 
                Hy11n8zc9JcAx4IFW0Aw0/DfCmMDvIomQItBAaIWewZqNHc0UwS0y/JRhAe8SiTz5sFJ6Abvgax6 
                vEfbYT0gzok+qtlfBNQLPvXejquhc0pZBaX1RgKDZyEJh3DBVRaFDgogK8XphaI/xtd1Cww9uO63 
                QxA7HfrFUN8rJXrHF4EMi/yrDxs2xVHGF0v21xeuXRwLW9JXYn4fFAJJ0Jr8N5f03UDuKeNlI568 
                RFVOGH7WpOLvKN4CDlsC+DT4Z8YVIOdtS/tO+Q== 
D/MainActivity: Decrypt = This is a text 



更新

对于 Android API 19,你只需要使用之前的 KeyStore API KeyPairGeneratorSpec而不是 KeyGenParameterSpec像这样:

try { 
    Calendar start = Calendar.getInstance(); 
    Calendar end = Calendar.getInstance(); 
    end.add(Calendar.YEAR, 1); 
 
    KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(this) 
        .setAlias("key1") 
        .setSubject(new X500Principal("CN=Sample Name, O=Android Authority")) 
        .setSerialNumber(BigInteger.ONE) 
        .setStartDate(start.getTime()) 
        .setEndDate(end.getTime()) 
        .build(); 
 
    KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore"); 
    generator.initialize(spec); 
 
    // error in android 6: InvalidKeyException: Need RSA private or public key AndroidOpenSSL 
    // error in android 5: NoSuchProviderException: Provider not available: AndroidKeyStoreBCWorkaround 
    String provider = Build.VERSION.SDK_INT < Build.VERSION_CODES.M ? "AndroidOpenSSL" : "AndroidKeyStoreBCWorkaround"; 
 
    KeyPair keyPair = generator.generateKeyPair(); 
 
    Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider); 
    inCipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic()); 
 
    Cipher outCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider); 
    outCipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate()); 
 
 
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 
    CipherOutputStream cipherOutputStream = new CipherOutputStream( 
            outputStream, inCipher); 
 
    String plainText = "This is a text"; 
 
    cipherOutputStream.write(plainText.getBytes("UTF-8")); 
    cipherOutputStream.close(); 
 
    String ecryptedText = Base64.encodeToString(outputStream.toByteArray(), Base64.DEFAULT); 
    Log.d(TAG, "Encrypt = " + ecryptedText); 
 
    String cipherText = ecryptedText; 
    CipherInputStream cipherInputStream = new CipherInputStream( 
            new ByteArrayInputStream(Base64.decode(cipherText, Base64.DEFAULT)), outCipher); 
 
    ArrayList<Byte> values = new ArrayList<>(); 
    int nextByte; 
    while ((nextByte = cipherInputStream.read()) != -1) { 
        values.add((byte)nextByte); 
    } 
 
    byte[] bytes = new byte[values.size()]; 
    for(int i = 0; i < bytes.length; i++) { 
        bytes[i] = values.get(i).byteValue(); 
    } 
 
    String finalText = new String(bytes, 0, bytes.length, "UTF-8"); 
    Log.d(TAG, "Decrypt = " + finalText); 
} catch (javax.crypto.NoSuchPaddingException e) { 
    Log.e(TAG, Log.getStackTraceString(e)); 
} catch (IOException e) { 
    Log.e(TAG, Log.getStackTraceString(e)); 
} catch (NoSuchAlgorithmException e) { 
    Log.e(TAG, Log.getStackTraceString(e)); 
} catch (NoSuchProviderException e) { 
    Log.e(TAG, Log.getStackTraceString(e)); 
} catch (InvalidAlgorithmParameterException e) { 
    Log.e(TAG, Log.getStackTraceString(e)); 
} catch (InvalidKeyException e) { 
    Log.e(TAG, Log.getStackTraceString(e)); 
} catch (UnsupportedOperationException e) { 
    Log.e(TAG, Log.getStackTraceString(e)); 
} 


评论关闭
IT序号网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!