Шифрование и расшифровка имени пользователя с помощью KeyStore в Android M и более старой версии?
Я пытаюсь зашифровать и дешифровать имя пользователя в приложении с помощью KeyStore,
Использование KeyPairGeneratorSpec для создания ключа в более старой версии, например, с 18 по 22,
KeyPairGeneratorSpec как лишенный версии 23 android M,
Но 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.!");
}
}
Ответы
Ответ 1
преобразование cypher зависит от параметров, которые вы даете KeyGenParameterSpec
или KeyPairGeneratorSpec
.
Если вы хотите использовать "RSA/ECB/PKCS1Padding"
в обоих случаях (Android M и ниже), измените
spec.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)
to
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());
}
}
Я избегал писать много if-else, объявляя интерфейс IKeyStoreHandler, который предоставляет все необходимые методы (добавляет/удаляет ключи, перечисляет все ключи по их псевдонимам, получает частный/открытый ключ, расшифровывает/шифрует текст) и реализует его для обоих случаев.