Skip to content

Instantly share code, notes, and snippets.

@kibotu
Forked from Shahbazsultan/MyActivity.java
Created January 16, 2020 09:54
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 kibotu/b3869445282d7db2168d852a43f2c0df to your computer and use it in GitHub Desktop.
Save kibotu/b3869445282d7db2168d852a43f2c0df to your computer and use it in GitHub Desktop.
Keystore android encryption and decryption
public class MyActivity extends AppCompatActivity{
@Override
public void onCreate(Bundle savedInstanceState) {
setcontentView(R.layout.myview);
//To set the encrypted string to keystore
SharedPrefUtils.put(MyActivity.this , "My Key" ,"My keys value");
//To get the decrypted string from keystore
String decryptedKey = SharedPrefUtils.get(MyActivity.this , "My Key");
}
}
public class SharedPrefUtils {
private static final String TAG = SharedPrefUtils.class.getSimpleName();
private static final String KEYSTORE = "AndroidKeyStore";
private static final String ALIAS = "MY_APP";
private static final String TYPE_RSA = "RSA";
private static final String CYPHER = "RSA/ECB/PKCS1Padding";
private static final String ENCODING = "UTF-8";
public static void put(Context ctx, String key, String value) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
if (value == null) {
prefs.edit().putString(key, null).apply();
} else {
try {
prefs.edit().putString(key, encryptString(ctx, value)).apply();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static String get(Context ctx, String key) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
final String pref = prefs.getString(key, "");
if (!TextUtils.isEmpty(pref)) {
return decryptString(ctx, pref);
}
return null;
}
private static String encryptString(Context context, String toEncrypt) {
try {
final KeyStore.PrivateKeyEntry privateKeyEntry = getPrivateKey(context);
if (privateKeyEntry != null) {
final PublicKey publicKey = privateKeyEntry.getCertificate().getPublicKey();
// Encrypt the text
Cipher input = Cipher.getInstance(CYPHER);
input.init(Cipher.ENCRYPT_MODE, publicKey);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CipherOutputStream cipherOutputStream = new CipherOutputStream(
outputStream, input);
cipherOutputStream.write(toEncrypt.getBytes(ENCODING));
cipherOutputStream.close();
byte[] vals = outputStream.toByteArray();
return Base64.encodeToString(vals, Base64.DEFAULT);
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return null;
}
private static String decryptString(Context context, String encrypted) {
try {
KeyStore.PrivateKeyEntry privateKeyEntry = getPrivateKey(context);
if (privateKeyEntry != null) {
final PrivateKey privateKey = privateKeyEntry.getPrivateKey();
Cipher output = Cipher.getInstance(CYPHER);
output.init(Cipher.DECRYPT_MODE, privateKey);
CipherInputStream cipherInputStream = new CipherInputStream(
new ByteArrayInputStream(Base64.decode(encrypted, Base64.DEFAULT)), output);
ArrayList<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, ENCODING);
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return null;
}
private static KeyStore.PrivateKeyEntry getPrivateKey(Context context) throws KeyStoreException,
CertificateException, NoSuchAlgorithmException,
IOException, UnrecoverableEntryException {
KeyStore ks = KeyStore.getInstance(KEYSTORE);
// Weird artifact of Java API. If you don't have an InputStream to load, you still need
// to call "load", or it'll crash.
ks.load(null);
// Load the key pair from the Android Key Store
KeyStore.Entry entry = ks.getEntry(ALIAS, null);
/* If the entry is null, keys were never stored under this alias.
*/
if (entry == null) {
VICLog.i(TAG, "No key found under alias: " + ALIAS);
VICLog.i(TAG, "Generating new key...");
try {
createKeys(context);
// reload keystore
ks = KeyStore.getInstance(KEYSTORE);
ks.load(null);
// reload key pair
entry = ks.getEntry(ALIAS, null);
if (entry == null) {
VICLog.v(TAG, "Generating new key failed...");
return null;
}
} catch (NoSuchProviderException e) {
VICLog.v(TAG, "Generating new key failed...");
e.printStackTrace();
return null;
} catch (InvalidAlgorithmParameterException e) {
VICLog.v(TAG, "Generating new key failed...");
e.printStackTrace();
return null;
}
}
/* If entry is not a KeyStore.PrivateKeyEntry, it might have gotten stored in a previous
* iteration of your application that was using some other mechanism, or been overwritten
* by something else using the same keystore with the same alias.
* You can determine the type using entry.getClass() and debug from there.
*/
if (!(entry instanceof KeyStore.PrivateKeyEntry)) {
VICLog.v(TAG, "Not an instance of a PrivateKeyEntry");
VICLog.v(TAG, "Exiting signData()...");
return null;
}
return (KeyStore.PrivateKeyEntry) entry;
}
/**
* Creates a public and private key and stores it using the Android Key Store, so that only
* this application will be able to access the keys.
*/
private static void createKeys(Context context) throws NoSuchProviderException,
NoSuchAlgorithmException, InvalidAlgorithmParameterException {
// Create a start and end time, for the validity range of the key pair that's about to be
// generated.
Calendar start = new GregorianCalendar();
Calendar end = new GregorianCalendar();
end.add(Calendar.YEAR, 25);
// The KeyPairGeneratorSpec object is how parameters for your key pair are passed
// to the KeyPairGenerator. For a fun home game, count how many classes in this sample
// start with the phrase "KeyPair".
KeyPairGeneratorSpec spec =
new KeyPairGeneratorSpec.Builder(context)
// You'll use the alias later to retrieve the key. It's a key for the key!
.setAlias(ALIAS)
// The subject used for the self-signed certificate of the generated pair
.setSubject(new X500Principal("CN=" + ALIAS))
// The serial number used for the self-signed certificate of the
// generated pair.
.setSerialNumber(BigInteger.valueOf(1337))
// Date range of validity for the generated pair.
.setStartDate(start.getTime())
.setEndDate(end.getTime())
.build();
// Initialize a KeyPair generator using the the intended algorithm (in this example, RSA
// and the KeyStore. This example uses the AndroidKeyStore.
final KeyPairGenerator kpGenerator = KeyPairGenerator.getInstance(TYPE_RSA, KEYSTORE);
kpGenerator.initialize(spec);
final KeyPair kp = kpGenerator.generateKeyPair();
VICLog.d(TAG, "Public Key is: " + kp.getPublic().toString());
}
}
@kibotu
Copy link
Author

kibotu commented Jan 16, 2020

noteworthy is that the keystore can store only 1kb on most devices per entry, so if you plan on putting something bigger is to split it,

also there is a library:
https://github.com/adorsys/secure-storage-android

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment