Skip to content

Instantly share code, notes, and snippets.

@eoinahern
Created December 20, 2018 17:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eoinahern/258bd7eb245b47bd5b116afe1407b037 to your computer and use it in GitHub Desktop.
Save eoinahern/258bd7eb245b47bd5b116afe1407b037 to your computer and use it in GitHub Desktop.
android keystore encryption class
public class KeyStoreHelper {
private static final String ALIAS = "mikey";
private static final String ANDROID_KEYSTORE = "AndroidKeyStore";
private final Context context;
private Calendar start;
private Calendar end;
private KeyStore keyStore;
public KeyStoreHelper(Context context, String keyStoreName) {
this.context = context;
try {
keyStore = KeyStore.getInstance(keyStoreName);
keyStore.load(null);
} catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException e) {
Timber.e(e);
}
}
public KeyStore getKeyStore() {
return keyStore;
}
private CipherOutputStream createCipherStream(ByteArrayOutputStream outputStream, Cipher cipher, String input) {
CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, cipher);
try {
cipherOutputStream.write(input.getBytes("UTF-8"));
cipherOutputStream.close();
} catch (IOException e) {
Timber.e(e);
}
return cipherOutputStream;
}
public synchronized String encryptString(String unencryptedStr) throws KeyStoreException {
if (!keyStore.containsAlias(ALIAS)) {
generateKeyPair(ALIAS);
}
KeyStore.PrivateKeyEntry privateKeyEntry;
RSAPublicKey publicKey;
try {
privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(ALIAS, null);
publicKey = (RSAPublicKey) privateKeyEntry.getCertificate().getPublicKey();
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
createCipherStream(outputStream, cipher, unencryptedStr);
byte[] bytes = outputStream.toByteArray();
return Base64.encodeToString(bytes, Base64.DEFAULT);
} catch (NoSuchPaddingException | InvalidKeyException | UnrecoverableEntryException | NoSuchAlgorithmException e) {
Timber.e(e);
return "";
}
}
public synchronized String decryptString(String encryptedString) {
try {
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(ALIAS, null);
Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding");
output.init(Cipher.DECRYPT_MODE, privateKeyEntry.getPrivateKey());
CipherInputStream cipherInputStream = new CipherInputStream(
new ByteArrayInputStream(Base64.decode(encryptedString, Base64.DEFAULT)), output);
List<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);
}
return new String(bytes, 0, bytes.length, "UTF-8");
} catch (IOException | NoSuchAlgorithmException | UnrecoverableEntryException | InvalidKeyException | KeyStoreException | NoSuchPaddingException e) {
Timber.e(e);
return "";
}
}
private void generateKeyPair(String alias) {
initCalendarElements();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
getKeyPairAPIBelow23();
} else {
getKeyPairAPIOver23(alias);
}
}
private void initCalendarElements() {
start = Calendar.getInstance();
end = Calendar.getInstance();
end.add(Calendar.YEAR, 5);
}
private KeyPair getKeyPairAPIBelow23() {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, ANDROID_KEYSTORE);
keyPairGenerator.initialize(new KeyPairGeneratorSpec.Builder(context)
.setAlias(ALIAS)
.setSubject(new X500Principal("CN=" + ALIAS))
.setSerialNumber(BigInteger.ONE)
.setStartDate(start.getTime())
.setEndDate(end.getTime())
.build());
return keyPairGenerator.generateKeyPair();
} catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) {
Timber.e(e);
return null;
}
}
@RequiresApi(Build.VERSION_CODES.M)
private KeyPair getKeyPairAPIOver23(String alias) {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, ANDROID_KEYSTORE);
keyPairGenerator.initialize(new KeyGenParameterSpec.Builder(alias, KeyProperties.PURPOSE_SIGN |
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setDigests(KeyProperties.DIGEST_SHA1, KeyProperties.DIGEST_SHA512)
.setCertificateSubject(new X500Principal("CN=" + alias))
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
.setCertificateSerialNumber(BigInteger.ONE)
.build());
return keyPairGenerator.generateKeyPair();
} catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) {
Timber.e(e);
return null;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment