I get an error trying to generate a key for certain devices. I\'m able to reproduce the error on a Samsung Galaxy Note running 4.4.2.
java.lang.IllegalStateExcep
I think this is the right direction: Right click on project > Android Tools > Export Signed Application Package The Export Android Application wizard appears. Select the project I want to export, click Next. The Keystore Selection screen appears.
If your code is OK then remember that you need to set up a PIN/PW/Fingerprint (Secure unlock) for your device so that the keystore starts functioning. A simple swipe will give such error if you try to generate keypairs.
public class EncryptionApi18AndAbove{
private Context context;
private KeyStore keyStore;
private static String alias = "alias";
public EncryptionApi18AndAbove(Context context) {
this.context = context;
try {
keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
} catch (Exception e) {
// bla bla
}
}
private String createNewKeys(String alias, Context context) {
try {
if (!keyStore.containsAlias(alias)) {
Calendar start = Calendar.getInstance();
Calendar end = Calendar.getInstance();
end.add(Calendar.YEAR, 1);
KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context)
.setAlias(alias)
.setSubject(new X500Principal("CN=Sample Name, O=Android Authority"))
.setSerialNumber(BigInteger.ONE)
.setStartDate(start.getTime())
.setEndDate(end.getTime())
.build();
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
generator.initialize(spec);
generator.initialize(spec);
generator.generateKeyPair();
}
} catch (Exception e) {
//bla bla
}
return alias;
}
@Override
public String encrypt(String text) {
if (text == null || text.length() == 0) {
return text;
}
try {
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(createNewKeys(alias, context), null);
PublicKey publicKey = privateKeyEntry.getCertificate().getPublicKey();
Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
inCipher.init(Cipher.ENCRYPT_MODE, publicKey);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CipherOutputStream cipherOutputStream = new CipherOutputStream(
outputStream, inCipher);
cipherOutputStream.write(text.getBytes("UTF-8"));
cipherOutputStream.close();
return Base64.encodeToString(outputStream.toByteArray(), Base64.DEFAULT);
} catch (Exception e) {
//bla bla
}
return text;
}
@Override
public String decrypt(String text) {
if (text == null || text.length() == 0) {
return text;
}
try {
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(createNewKeys(alias, context), null);
PrivateKey privateKey = privateKeyEntry.getPrivateKey();
Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding");
output.init(Cipher.DECRYPT_MODE, privateKey);
CipherInputStream cipherInputStream = new CipherInputStream(
new ByteArrayInputStream(Base64.decode(text, 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).byteValue();
}
return new String(bytes, 0, bytes.length, "UTF-8");
} catch (Exception e) {
// bla bla
}
return text;
}
}
You can use this class . This is works min SDK 18 and above. You can create Android Keystore key , decrypt and encrypt simple text.
While I don't know the full answer, I can help continue your search. The binder implementation on the other side of mBinder is the native keystore. If I recall fully, it's behavior is to either 1) support key operations at a software level, or 2) delegate to a OEM-provided keymaster library that (presumably) interfaces to the OEM's hardware-backed keystore. More info on this here, here, and here.
Note: I'll forgo SO's normal policy of pulling the external link content into the answer, since I'm linking you out to three articles that are all >1 page and it seems a bit ridiculous to post a 6-page answer ;-)