【问题标题】:Encryption & Decryption of username using KeyStore in Android M & older version?在 Android M 和旧版本中使用 KeyStore 加密和解密用户名?
【发布时间】:2016-02-18 15:47:46
【问题描述】:

我正在尝试使用 KeyStore 加密和解密应用程序中的用户名,

使用 KeyPairGeneratorSpec 在 18 到 22 等旧版本中创建密钥,

KeyPairGeneratorSpec 在 android M 版本 23 中被贬低, 但 Android M 支持 KeyGenParameterSpec。

这个 KeyGenParameterSpec 是否支持向后可比性,或者我该怎么做?

我正在尝试这样的事情,有没有更好的解决方案。 现在可以正常使用了!

在 Ciper.getInstance 进行加密和解密时,我需要这样做。 是否有任何单个参数“RSA/ECB/OAEPWithSHA-256AndMGF1Padding”或“RSA/ECB/PKCS1Padding”我可以为这两个版本传递

if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M){
            c =  Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
        }else{
            c =  Cipher.getInstance("RSA/ECB/PKCS1Padding");
        }

下面的代码现在可以正常工作了,让我知道如何改进它。

密钥生成器:

genkey(){
KeyPairGenerator generator = KeyPairGenerator .getInstance(KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
            if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M){
                TCLog.e(TAG,"Current version is 23(MashMello)");
                //Api level 23

                KeyGenParameterSpec spec = new  KeyGenParameterSpec.Builder(
                             keyName,
                            KeyProperties.PURPOSE_DECRYPT | KeyProperties.PURPOSE_ENCRYPT )
                            .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
                            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)
                            .build();
                generator.initialize(spec);
            }else{
                TCLog.e(TAG,"Current version is < 23(MashMello)");
                //api level 17+ 4.4.3
                KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(getActivity())
                        .setAlias(keyName)
                        .setSubject(new X500Principal("CN=Sample Name, O=Android Authority"))
                        .setSerialNumber(BigInteger.ONE)
                        .setStartDate(start.getTime())
                        .setEndDate(end.getTime())
                        .build();
                generator.initialize(spec);
            }
           KeyPair keyPair = generator.generateKeyPair();
}

加密代码:

doEncription(){
 try {
        KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(keyName, null);
        PublicKey publicKey = (PublicKey) privateKeyEntry.getCertificate().getPublicKey();
        Cipher c;
        if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M){
            c =  Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
        }else{
            c =  Cipher.getInstance("RSA/ECB/PKCS1Padding");
        }

        c.init(Cipher.ENCRYPT_MODE, publicKey);
        encodedUser = c.doFinal(userName.getBytes());
        encodedPassword = c.doFinal(userPassword.getBytes());

        userName = Base64.encodeToString(encodedUser, Base64.DEFAULT);
        userPassword = Base64.encodeToString(encodedPassword, Base64.DEFAULT);
        // Log.e("MainActivity","AES Encription Error.!");
    } catch (Exception e) {
        Log.e("MainActivity", "AES Encription Error.!");
    }
}

解密代码:

doDecryption(){
    try {
        KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(keyName, null);
        PrivateKey privateKey = (PrivateKey) privateKeyEntry.getPrivateKey();

        Cipher c;
        if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M){
            c =  Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
        }else{
            c =  Cipher.getInstance("RSA/ECB/PKCS1Padding");
        }
        c.init(Cipher.DECRYPT_MODE, privateKey);
        decodedUser = c.doFinal(encodedUser);
        decodedPassword = c.doFinal(encodedPassword);

    } catch (Exception e) {
        Log.e("MainActivity", "AES Decryption Error.!");
    }

}

【问题讨论】:

  • @nikolay-elenkov 你能快速看一下这段代码吗?加密敏感数据安全吗?
  • 你能告诉我一个链接我在哪里可以找到完整的代码或者你在哪里得到代码?

标签: android encryption cryptography rsa android-keystore


【解决方案1】:

密码转换取决于您提供给KeyGenParameterSpecKeyPairGeneratorSpec 的参数。 如果您想在两种情况下(Android M 及以下)都使用"RSA/ECB/PKCS1Padding",请更改

spec.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)

spec.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)

您可以通过以下代码检查哪些算法可用:

    Provider[] providers = Security.getProviders();
    for (Provider p : providers) {
        Log.d(TAG, "provider: " + p.getName());
        Set<Provider.Service> services = p.getServices();
        for (Provider.Service s : services) {
            Log.d(TAG, "--> algorithm: " + s.getAlgorithm());
        }
    }

我通过声明一个接口 IKeyStoreHandler 来避免编写大量 if-else,该接口提供所有必要的方法(添加/删除密钥、按别名列出所有密钥、获取私钥/公钥、解密/加密文本)并实现它对于这两种情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-10
    • 1970-01-01
    • 1970-01-01
    • 2016-07-19
    • 2018-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多