在Android M和旧版本中使用KeyStore加密和解密用户名?

时间:2022-04-06 15:11:15

i'm trying to encrypt and decrypt username in app using KeyStore,

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

Using KeyPairGeneratorSpec to create the key in older version like 18 to 22,

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

KeyPairGeneratorSpec as been depricated in version 23 of android M, But Android M supports KeyGenParameterSpec.

KeyPairGeneratorSpec已经在Android M的第23版中进行了描述,但是Android M支持KeyGenParameterSpec。

Does this KeyGenParameterSpec supports backward comparability or how do i do this ?

此KeyGenParameterSpec是否支持向后兼容性或我如何执行此操作?

Im trying out some thing like this , is there any better solution for this. This works fine as off now!

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

At the time of Ciper.getInstance in encryption and Decryption i need to do this. is there any single parameter "RSA/ECB/OAEPWithSHA-256AndMGF1Padding" or "RSA/ECB/PKCS1Padding" i can pass for both the version ?

在加密和解密的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");
        }

Below code works fine as off now , let me know how do i improve this.

下面的代码现在运行正常,请告诉我如何改进它。

Key Generator :

密钥生成器:

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();
}

Encryption code :

加密代码:

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.!");
    }
}

Decryption Code :

解密代码:

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.!");
    }

}

1 个解决方案

#1


4  

the cypher transformation depends on what parameters you give to KeyGenParameterSpec or KeyPairGeneratorSpec. If you want to use "RSA/ECB/PKCS1Padding" in both cases (Android M and below) change

密码转换取决于您为KeyGenParameterSpec或KeyPairGeneratorSpec提供的参数。如果要在两种情况下使用“RSA / ECB / PKCS1Padding”(Android M及以下)更改

spec.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)

to

spec.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)

You can check which algorithms are available with the following piece of code:

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

    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());
        }
    }

I avoided writing a lot of if-else by declaring an interface IKeyStoreHandler which provides all the necessary methods (add / remove keys, list all keys by their aliases, get private / public key, decrypt / encrypt text) and implementing it for both cases.

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

#1


4  

the cypher transformation depends on what parameters you give to KeyGenParameterSpec or KeyPairGeneratorSpec. If you want to use "RSA/ECB/PKCS1Padding" in both cases (Android M and below) change

密码转换取决于您为KeyGenParameterSpec或KeyPairGeneratorSpec提供的参数。如果要在两种情况下使用“RSA / ECB / PKCS1Padding”(Android M及以下)更改

spec.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)

to

spec.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)

You can check which algorithms are available with the following piece of code:

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

    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());
        }
    }

I avoided writing a lot of if-else by declaring an interface IKeyStoreHandler which provides all the necessary methods (add / remove keys, list all keys by their aliases, get private / public key, decrypt / encrypt text) and implementing it for both cases.

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