Last active
September 12, 2023 12:40
-
-
Save JosiasSena/3bf4ca59777f7dedcaf41a495d96d984 to your computer and use it in GitHub Desktop.
Encryptor and Decryptor for data encryption.decryption using the Android KeyStore.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
_____ _____ _ | |
| __ \ / ____| | | | |
| | | | ___| | _ __ _ _ _ __ | |_ ___ _ __ | |
| | | |/ _ \ | | '__| | | | '_ \| __/ _ \| '__| | |
| |__| | __/ |____| | | |_| | |_) | || (_) | | | |
|_____/ \___|\_____|_| \__, | .__/ \__\___/|_| | |
__/ | | | |
|___/|_| | |
*/ | |
class DeCryptor { | |
private static final String TRANSFORMATION = "AES/GCM/NoPadding"; | |
private static final String ANDROID_KEY_STORE = "AndroidKeyStore"; | |
private KeyStore keyStore; | |
DeCryptor() throws CertificateException, NoSuchAlgorithmException, KeyStoreException, | |
IOException { | |
initKeyStore(); | |
} | |
private void initKeyStore() throws KeyStoreException, CertificateException, | |
NoSuchAlgorithmException, IOException { | |
keyStore = KeyStore.getInstance(ANDROID_KEY_STORE); | |
keyStore.load(null); | |
} | |
String decryptData(final String alias, final byte[] encryptedData, final byte[] encryptionIv) | |
throws UnrecoverableEntryException, NoSuchAlgorithmException, KeyStoreException, | |
NoSuchProviderException, NoSuchPaddingException, InvalidKeyException, IOException, | |
BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException { | |
final Cipher cipher = Cipher.getInstance(TRANSFORMATION); | |
final GCMParameterSpec spec = new GCMParameterSpec(128, encryptionIv); | |
cipher.init(Cipher.DECRYPT_MODE, getSecretKey(alias), spec); | |
return new String(cipher.doFinal(encryptedData), "UTF-8"); | |
} | |
private SecretKey getSecretKey(final String alias) throws NoSuchAlgorithmException, | |
UnrecoverableEntryException, KeyStoreException { | |
return ((KeyStore.SecretKeyEntry) keyStore.getEntry(alias, null)).getSecretKey(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
______ _____ _ | |
| ____| / ____| | | | |
| |__ _ __ | | _ __ _ _ _ __ | |_ ___ _ __ | |
| __| | '_ \| | | '__| | | | '_ \| __/ _ \| '__| | |
| |____| | | | |____| | | |_| | |_) | || (_) | | | |
|______|_| |_|\_____|_| \__, | .__/ \__\___/|_| | |
__/ | | | |
|___/|_| | |
*/ | |
class EnCryptor { | |
private static final String TRANSFORMATION = "AES/GCM/NoPadding"; | |
private static final String ANDROID_KEY_STORE = "AndroidKeyStore"; | |
private byte[] encryption; | |
private byte[] iv; | |
EnCryptor() { | |
} | |
byte[] encryptText(final String alias, final String textToEncrypt) | |
throws UnrecoverableEntryException, NoSuchAlgorithmException, KeyStoreException, | |
NoSuchProviderException, NoSuchPaddingException, InvalidKeyException, IOException, | |
InvalidAlgorithmParameterException, SignatureException, BadPaddingException, | |
IllegalBlockSizeException { | |
final Cipher cipher = Cipher.getInstance(TRANSFORMATION); | |
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(alias)); | |
iv = cipher.getIV(); | |
return (encryption = cipher.doFinal(textToEncrypt.getBytes("UTF-8"))); | |
} | |
@NonNull | |
private SecretKey getSecretKey(final String alias) throws NoSuchAlgorithmException, | |
NoSuchProviderException, InvalidAlgorithmParameterException { | |
final KeyGenerator keyGenerator = KeyGenerator | |
.getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE); | |
keyGenerator.init(new KeyGenParameterSpec.Builder(alias, | |
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) | |
.setBlockModes(KeyProperties.BLOCK_MODE_GCM) | |
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) | |
.build()); | |
return keyGenerator.generateKey(); | |
} | |
byte[] getEncryption() { | |
return encryption; | |
} | |
byte[] getIv() { | |
return iv; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
_____ _ _ _ | |
/ ____| | | | | | | | |
| (___ __ _ _ __ ___ _ __ | | ___ | | | |___ __ _ __ _ ___ | |
\___ \ / _` | '_ ` _ \| '_ \| |/ _ \ | | | / __|/ _` |/ _` |/ _ \ | |
____) | (_| | | | | | | |_) | | __/ | |__| \__ \ (_| | (_| | __/ | |
|_____/ \__,_|_| |_| |_| .__/|_|\___| \____/|___/\__,_|\__, |\___| | |
| | __/ | | |
|_| |___/ | |
*/ | |
public class MainActivity extends AppCompatActivity { | |
private static final String TAG = MainActivity.class.getSimpleName(); | |
private static final String SAMPLE_ALIAS = "MYALIAS"; | |
@BindView (R.id.toolbar) | |
Toolbar toolbar; | |
@BindView (R.id.ed_text_to_encrypt) | |
EditText edTextToEncrypt; | |
@BindView (R.id.tv_encrypted_text) | |
TextView tvEncryptedText; | |
@BindView (R.id.tv_decrypted_text) | |
TextView tvDecryptedText; | |
private EnCryptor encryptor; | |
private DeCryptor decryptor; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_main); | |
ButterKnife.bind(this); | |
setSupportActionBar(toolbar); | |
encryptor = new EnCryptor(); | |
try { | |
decryptor = new DeCryptor(); | |
} catch (CertificateException | NoSuchAlgorithmException | KeyStoreException | | |
IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
@OnClick ({R.id.btn_encrypt, R.id.btn_decrypt}) | |
public void onClick(final View view) { | |
final int id = view.getId(); | |
switch (id) { | |
case R.id.btn_encrypt: | |
encryptText(); | |
break; | |
case R.id.btn_decrypt: | |
decryptText(); | |
break; | |
} | |
} | |
private void decryptText() { | |
try { | |
tvDecryptedText.setText(decryptor | |
.decryptData(SAMPLE_ALIAS, encryptor.getEncryption(), encryptor.getIv())); | |
} catch (UnrecoverableEntryException | NoSuchAlgorithmException | | |
KeyStoreException | NoSuchPaddingException | NoSuchProviderException | | |
IOException | InvalidKeyException e) { | |
Log.e(TAG, "decryptData() called with: " + e.getMessage(), e); | |
} catch (IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e) { | |
e.printStackTrace(); | |
} | |
} | |
private void encryptText() { | |
try { | |
final byte[] encryptedText = encryptor | |
.encryptText(SAMPLE_ALIAS, edTextToEncrypt.getText().toString()); | |
tvEncryptedText.setText(Base64.encodeToString(encryptedText, Base64.DEFAULT)); | |
} catch (UnrecoverableEntryException | NoSuchAlgorithmException | NoSuchProviderException | | |
KeyStoreException | IOException | NoSuchPaddingException | InvalidKeyException e) { | |
Log.e(TAG, "onClick() called with: " + e.getMessage(), e); | |
} catch (InvalidAlgorithmParameterException | SignatureException | | |
IllegalBlockSizeException | BadPaddingException e) { | |
e.printStackTrace(); | |
} | |
} | |
} |
Here's what I have done to handle API < 23:
private SecretKey getSecretKey(final String alias) throws NoSuchAlgorithmException,
NoSuchProviderException, InvalidAlgorithmParameterException {
KeyGenerator keyGenerator;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE);
keyGenerator.init(new KeyGenParameterSpec.Builder(alias,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.build());
} else {
keyGenerator = KeyGenerator.getInstance("AES", ANDROID_KEY_STORE);
SecureRandom secureRandom = new SecureRandom(alias.getBytes());
keyGenerator.init(KEY_SIZE, secureRandom);
}
return keyGenerator.generateKey();
}
And how to delete key?
Hi, what is the license on this code?
@Matthcw none, feel free to do whatever you want with it
Perfect, thanks!
…________________________________
From: Josias Sena ***@***.***>
Sent: 09 April 2021 22:07
To: JosiasSena ***@***.***>
Cc: Matthew Mukalere ***@***.***>; Mention ***@***.***>
Subject: Re: JosiasSena/DeCryptor.java
@JosiasSena commented on this gist.
________________________________
@Matthcw<https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FMatthcw&data=04%7C01%7C%7C8744b6fcb694401ebc6a08d8fb9b78da%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637535992448198726%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=4OlUI%2BNl34lFEQaxTNnuqxrdRJpOvbZ5SdGt4gRBAV4%3D&reserved=0> none, feel free to do whatever you want with it
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub<https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgist.github.com%2F3bf4ca59777f7dedcaf41a495d96d984%23gistcomment-3700185&data=04%7C01%7C%7C8744b6fcb694401ebc6a08d8fb9b78da%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637535992448208681%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=uzT2gdMDA40QCYSfGp7rJodDFZ5nPJPtD%2BpcP97dBBk%3D&reserved=0>, or unsubscribe<https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FADHJSARIRCNH2C2XBIHKI2DTH5UAVANCNFSM4HY56TPA&data=04%7C01%7C%7C8744b6fcb694401ebc6a08d8fb9b78da%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637535992448208681%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=XM0p1OHM%2BWvsF05Hs2k72ToNC6iCjxH4MuMOcub6v2c%3D&reserved=0>.
Hello, my question is if there is a way to retrieve a stored value with just knowing the alias. The thing is that the method to retreive it is coupled with the encryption and the iv... thanks!!
it gave error javax.crypto.illegalblocksizeexception while decrypting the code could you help me out
Thanks for sharing! This code is really helpful!
Anyway, can i use this code for encrypting/decrypting android fingerprint information (data)?
If someone needs it, I have created Example app for this code: https://github.com/luskan/EncryptDecryptApp
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@sharmpuneet are you able to solve this