I want to store key value pair(Key and Value) into android keystore - android-6.0-marshmallow

I followed the bellow sample
https://nelenkov.blogspot.in/2012/05/storing-application-secrets-in-androids.html
It worked fine till marshmallow in marshmallow it is giving some exception and I am not able to store the Key and value pair to keystore.
Bellow code I am getting exception
For this last step there seem to be two options:
keyStore.setKeyEntry(String alias, byte[] key, Certificate[] chain);
or
keyStore.setKeyEntry(String alias, Key key, char[] password, Certificate[] chain);
I started with the second of the two, but received java.security.KeyStoreException: entries cannot be protected with passwords .... Okay, that's odd, why would there be a method that guarantees to throw an exception? Let's try door number 1.
At which point, when I call setKeyEntry, and pass keyPair.getPrivate().getEncoded() as the second argument, I receive java.security.KeyStoreException: Operation not supported because key encoding is unknown from the system.
byte[] encodedKey = Base64.encode("keytostore".getBytes(),
Base64.DEFAULT);
SecretKey originalKey = new SecretKeySpec(encodedKey, 0,
encodedKey.length, "AES");
KeyStore instance = KeyStore.getInstance("AndroidKeyStore");
instance.load(null);
instance.setEntry(
"key1",
new KeyStore.SecretKeyEntry(originalKey),
new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT
| KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(
KeyProperties.ENCRYPTION_PADDING_NONE)
.build());

Related

HSM decryption + encryption chaining

My application is acting as a switchboard to transfer very sensitive messages between two parties and I'm trying to figure out how I can do this without "looking" at the message they're trying to send.
I have a HSM, and I've generated a keypair for the sender - they're going to encrypt the message with their public key that I gave them, and I can decrypt the message using the private key I have in the HSM.
I'm going to then pass that message on by encrypting it with the public key of the ultimate receiver, which I have.
Is there any way to chain these two operations inside the HSM, without having the decrypted message anywhere near my application memory? I would like the plaintext content to never leave the boundaries of the HSM.
I know that some HSMs have a CodeSafe / SEE machine feature that lets me write embedded system code and run it inside the HSM, before I get into that I'd like to see if there's a way using the general PKCS / JCE / CNG APIs to do this safely.
If all you need is to re-encrypt the same secret under a different key, you can use C_Unwrap to create a temporal HSM object with value of the translated secret and then use C_Wrap to encrypt the value of this temporal HSM object for all the recipients.
This way the secret will never leave HSM.
Something like this (verified to be working on SafeNet Luna 7 with RSA-OAEP):
// Your private key for 'decrypting' secret. Must have key unwrapping allowed
CK_OBJECT_HANDLE hsmPrivateKey = ... ;
// Encrypted secret
byte[] wrappedKey = ... ; //
// Template for temporal generic secret key with value of the secret
CK_ATTRIBUTE[] tempTemplate = new CK_ATTRIBUTE[] {
new CK_ATTRIBUTE(CKA.CLASS, CKO.SECRET_KEY),
new CK_ATTRIBUTE(CKA.KEY_TYPE, CKK.GENERIC_SECRET),
new CK_ATTRIBUTE(CKA.TOKEN, false),
new CK_ATTRIBUTE(CKA.PRIVATE, true),
new CK_ATTRIBUTE(CKA.EXTRACTABLE, true),
new CK_ATTRIBUTE(CKA.SENSITIVE, true),
new CK_ATTRIBUTE(CKA.ENCRYPT, false),
new CK_ATTRIBUTE(CKA.DECRYPT, false),
new CK_ATTRIBUTE(CKA.WRAP, false),
new CK_ATTRIBUTE(CKA.UNWRAP, false),
new CK_ATTRIBUTE(CKA.SIGN, false),
new CK_ATTRIBUTE(CKA.VERIFY, false),
new CK_ATTRIBUTE(CKA.DERIVE, false)
};
// Unwrapping/decryption mechanism
CK_MECHANISM mechanism = ... ;
// Handle for temporal generic secret key with value of the secret
CK_OBJECT_HANDLE temporalValueHandle = new CK_OBJECT_HANDLE();
// Unwrap/decrypt the secret into temporal key
CryptokiEx.C_UnwrapKey(session, mechanism, hsmPrivateKey, wrappedKey, wrappedKey.length, tempTemplate, tempTemplate.length, temporalValueHandle);
// Wrap/encrypt the secret for recipients. Recipient public keys must have key wrapping allowed
for(CK_OBJECT_HANDLE recipientPublicKey : ... ) {
LongRef resSize = new LongRef(0);
CryptokiEx.C_WrapKey(session, mechanism, recipientPublicKey, temporalValueHandle, null, resSize);
byte[] rewrappedKey = new byte[CryptokiUtils.safeIntCast(resSize.value)];
CryptokiEx.C_WrapKey(session, mechanism, recipientPublicKey, temporalValueHandle, rewrappedKey, resSize);
System.out.println("Re-wrapped key: " + bytesToHexString(rewrappedKey));
}
// Delete temporal generic secret key
CryptokiEx.C_DestroyObject(session, temporalValueHandle);
Good luck!

Decryption failed after registering AeadConfig more than once?

I'm encrypting some text and trying to decrypt it, however it's failing to decrypt when I am using a different AeadConfig.register() to decrypt than to encrypt. I'm wondering how to resolve this problem because I'll be encrypting on one activity and decrypting in another activity. I've simplified it for the sake of giving an example below.
This works, if I just pass the aead as a parameter, but I'm not sure if that's something I should be doing.
private fun deletableEncrypt() {
AeadConfig.register()
val keysetHandle: KeysetHandle = KeysetHandle.generateNew(AeadKeyTemplates.AES128_GCM)
val aead: Aead = AeadFactory.getPrimitive(keysetHandle)
val plainText = "Hello world"
val aad = "masterpassword"
val cipherText = aead.encrypt(plainText.toByteArray(), aad.toByteArray())
Log.d(TAG, cipherText.toString())
dbHelper.insertNewRow("text", cipherText,
"moreText")
}
private fun deleteableDecrypt() {
AeadConfig.register()
val keysetHandle: KeysetHandle = KeysetHandle.generateNew(AeadKeyTemplates.AES128_GCM)
val aead: Aead = AeadFactory.getPrimitive(keysetHandle)
val aad = "masterpassword"
val cipherText = dbHelper.getAllEncrypts()[0]
val decrypted = aead.decrypt(cipherText, aad.toByteArray())
}
Right now the decryption throws an exception. I think its' caused by the aeadConfig, but I don't know how to register it only once, so once this is solved it won't throw exception anymore.
I actually found the error, I'm generating a new KeySet everytime, when instead I should be storing it. Instructions on how to do that are found here https://github.com/google/tink/blob/master/docs/JAVA-HOWTO.md in the "Storing Keysets" section

Client certificates access key (encrypted)

I have a client certificate files (.perm,.csr,.pfx,.key) and these files contain hex code
The below code snippet takes a cipherText and performs some validation. This is a servlet and the cipherText is passed as a request paramter. I looked into cert files and provided all the hex code available in those files as input but nothing seem to work.
Looking at the way its decoded can anyone tell what kind of input its expecting from the certificate files:
validate(cipherText)
private static final byte[] desKeyData = {
(byte)0xA2, (byte)0x15, (byte)0x37, (byte)0x07, (byte)0xCB, (byte)0x62,
(byte)0xC1, (byte)0xD3, (byte)0xF8, (byte)0xF1, (byte)0x97, (byte)0xDF,
(byte)0xD0, (byte)0x13, (byte)0x4F, (byte)0x79, (byte)0x01, (byte)0x67,
(byte)0x7A, (byte)0x85, (byte)0x94, (byte)0x16, (byte)0x31, (byte)0x88 };
byte[] bCipherText = Base64.decode(CipherText);
Cipher oC3des = Cipher.getInstance("DESede/CBC/PKCS5Padding");
SecretKeySpec oKey = new SecretKeySpec(s_desKeyData , "DESede");
IvParameterSpec oIvSpec = new IvParameterSpec(s_baIV);
oC3des.init(Cipher.DECRYPT_MODE, oKey, oIvSpec);
byte[] plaintext = oC3des.doFinal(bCipherText );
return new String(plainText, Charset.forName("UTF-8"));

Decryption failed when storing the key inside Java key store

I've created an encryption key by the following code:
SecretKeyFactory skFactory = SecretKeyFactory.getInstance("PBEWithSHA1AndDESede");
SecretKey key = skFactory.generateSecret(new PBEKeySpec("<some password>".toCharArray()));
Then I've used the key to encrypt some text.
I've stored this key inside a java key store and saved in on FS:
KeyStore ks = KeyStore.getInstance("JCEKS");
ks.setKeyEntry(keyAlias, key ,keyPassword.toCharArray(), null);
FileOutputStream fileOutputStream = new FileOutputStream (keyStorePath);
keyStore.store(fileOutputStream , keyStorePassword.toCharArray());
fileOutputStream.close();
In a different process I open the key store and try to decrypt some text:
KeyStore ks2 = KeyStore.getInstance("JCEKS");
ks2.load(new java.io.FileInputStream(keyStorePath), ksPassword.toCharArray());
SecretKeyFactory skFactory2 = SecretKeyFactory.getInstance("PBEWithSHA1AndDESede");
String passForTheKey = ks2.getKey(keyAlias, keyPass.toCharArray()).toString();
KeySpec key = new PBEKeySpec(passForTheKey.toCharArray());
SecretKey sKey2 = skFactory.generateSecret(key);
When trying to decrypt the text I get the error:
java.security.InvalidKeyException: Given final block not properly padded
If I try to use the key without storing it in the key store immediately after creating it, the decription proccess is working great.
Any ideas?
You're storing the actual secret key in your keystore (which is normal). However, you seem to be trying to read it as a password, for a new key you're generating later.
Instead of this:
String passForTheKey = ks2.getKey(keyAlias, keyPass.toCharArray()).toString();
KeySpec key = new PBEKeySpec(passForTheKey.toCharArray());
SecretKey sKey2 = skFactory.generateSecret(key);
use this:
SecretKey sKey2 = (SecretKey) ks2.getKey(keyAlias, keyPassword.toCharArray());
What you're reading from the keystore is the key itself (as you've stored it), not some password. (generateSecret will just generate a new key.)

ASP.Net: "Invalid cryptographic message type" error when encrypting message

public byte[] DoEncrypt(string message, X509Certificate2 cryptCert)
{
byte[] signedBytes = new System.Text.UTF8Encoding().GetBytes(message);
EnvelopedCms encryptedMessage = new EnvelopedCms(new ContentInfo(signedBytes));
CmsRecipientCollection recipients = new CmsRecipientCollection();
CmsRecipient recipient = new CmsRecipient(cryptCert);
recipients.Add(recipient);
encryptedMessage.Encrypt(recipient);
return encryptedMessage.Encode();
}
When my application tries to encrypt a message it throws the exception 'encryptedMessage.RecipientInfos' threw an exception of type 'System.Security.Cryptography.CryptographicException' with the text "Invalid cryptographic message type" occurs in the line "encryptedMessage.Encrypt(recipient)"
If you are actually encrypting signed data (as the variable names suggests), you should not use the default content type for your ContentInfo. Instead you should use the alternative constructor that allows you to specify the signedData content type.

Resources