How to generate a javax.crypto.SecretKey from a String - android

The follow line allow me to generate a SecretKey
SecretKey key = KeyGenerator.getInstance("DES").generateKey();
But I want to generate a SecretKey related to a specific String.
For example
String myKeyStr="abcde";
SecretKey mykey2=keyGeneratedFrom(myKeyStr);
Obviously the SecretKey generation should have a 1:1 link to avoid issue during the decryption.
I have no idea of how to solve this problem.
Could you help me?

Passwords are not keys. You have to use something like PBKDF2 to derive a key from a password. Even then, it pays to have secure passwords. There is a lot of information about PBKDF2 when used in Java, and the Bouncy Castle library can help too.
PBKDF2 function in Android
Java - PBKDF2 with HMACSHA256 as the PRF
PBKDF2 with bouncycastle in Java
Etcetera.
Don't forget to use a random salt.

Related

"Your app contains unsafe cryptographic encryption patterns" - How I can get rid of this warning?

Few days ago, In "Pre-launch report for APK" in Google Play Console, it start to flag me
Unsafe encryption
Detected in APK ???
Your app contains unsafe cryptographic encryption patterns. Please see this Google Help Centre article for details.
Vulnerable classes:
c.j.a.s.J.b
However, since the early day of APK, I do not change anything in encryption code/ description code. Hence, I'm not sure why Google starts to warn me on recent APK?
Any idea how to resolve? As, the information for vulnerable classes c.j.a.s.J.b is not helpful.
I try to use Proguard + mapping.txt to retrace c.j.a.s.J.b but able to figure what class is that.
Any idea how I can get rid of Google security warning?
The google play suggests with vulnerable classes with the function name, you can see in the dialog.
Review your app for statically computed keys, initialization vectors, and/or salts that are used in cryptographic encryption operations and ensure that these values are constructed safely
For example :
public byte[] encryptionUtil(String key, String iv, byte[] plainText) {
Cipher cipher = Cipher.getInstance(“AES/GCM/NoPadding”);
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), “AES”);
GCMParameterSpec paramSpec = new GCMParameterSpec(256, iv.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, keySpec, paramSpec);
return cipher.doFinal(plainText);
}
And you are calling a function as:
byte[] cipherText = encryptionUtil(“abcdef...”, “010203040506”, plainText);
Here your encryption key “abcdef...” is provides as a static string. A statically computed value is a value that is the same on every execution of your app. Statically computed cryptographic values can be extracted from your app and used to attack your app’s encrypted data.
So you can use EncryptedSharedPreferences to store locally data
Reference link https://developer.android.com/reference/androidx/security/crypto/EncryptedSharedPreferences
OR
Jetpack Security
For more details:
Remediation for Unsafe Cryptographic Encryption
I think you are using some encryption/decryption code with statically stored key.
A statically computed value is a value that is the same on every execution of your app. Statically computed cryptographic values can be extracted from your app and used to attack your app’s encrypted data.
So Google give this warning to change that stored key with dynamically generated key.
For that you can generate different key on every launch.
To solve this problem generate dynamic encryption/decryption key on every launch.
For that you can find more info here https://developer.android.com/jetpack/androidx/releases/security

How to encrypt and decrypt data in Android using the elliptic curve key pair of type secp256r1?

I need to use NIST P-256 elliptic curves to encrypt and decrypt data. Now that I have generated the key pair, but how do I use them to encrypt and decrypt?
The official website only says how to use this ec key pair to sign/verify, but I want to know how to use this ec key pair to encrypt/decrypt.
website: https://developer.android.com/reference/android/security/keystore/KeyGenParameterSpec#example:-nist-p-256-ec-key-pair-for-signingverification-using-ecdsa
generate NIST P-256 key pair code:
val kpg: KeyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore")
val parameterSpec =
KeyGenParameterSpec.Builder("container", KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
.setAlgorithmParameterSpec(ECGenParameterSpec("secp256r1"))
.setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA384, KeyProperties.DIGEST_SHA512)
.build()
kpg.initialize(parameterSpec)
val keyPair = kpg.generateKeyPair()
val ecPublicKey = keyPair.public as ECPublicKey
val ecPrivateKey = keyPair.private as ECPrivateKey
AndroidKeyStore does not currently support encryption or decryption with EC keys, only with RSA keys.
To use EC keys for encryption, you need to either use ECDH plus a key derivation function (KDF) to compute a shared symmetric key which you can use for your data, or to use ECIES which does that internally. But AndroidKeyStore doesn't support either mode of operation as of Android 10. Maybe in Android 11.
For now, you can either use RSA with an appropriate padding mode (OAEP recommended) to encrypt your symmetric key, or you can use the native Java cryto provider. This, unfortunately, will not use secure hardware to generate, store or use the key, and will instead do all of these things in your app's process space. There's an example here.
(For what it's worth, I'm the Google engineer who owns AndroidKeyStore. I've been planning to add ECDH support for a few years now, but it's always been pre-empted by other features that were considered higher priority. I will get to it, though.)
Public key encryption is not recommended to use for encryption. The general practice is hybrid-encryption where a block cipher key is exchanged then symmetric encryption is performed.
After the key exchange the most common issues Authentication and Integrity. The modern practice is using an authenticated encryption mode as AES-GCM. GCM mode gives you authentication and integrity. You can see an implementation here

Android KeyStore Initialization

First off I am new to android Programming, though I am not new to programming itself. What I am, essentially, trying to do is to save my encryption Keys into the Android Keystore. There seems to be a phenomenal lack of such information on GOOGLE, itself. Since there is not much how-to available on the topic I am assuming that it isn't fairly standard knowledge. So can someone please give me a sample code to
Initialize the KeyStore(Will be using AES-256).
Save multiple keys in a KeyStore(Please tell me the max number of keys I can store in 1 KeyStore, since i plan on saving nothing short of a 100).
Get Keys from KeyStore.
Edit Keys
Delete Keys
Delete Entire KeyStore
So in essence a code for all basic functions of a keystore.
Thank you in advance for your assistance.
If you set your minSdkVersion to 23 or higher Android M makes it easy to generate and manage symmetric keys as of this month.
Check out the 4th example listed here.
https://developer.android.com/reference/android/security/keystore/KeyGenParameterSpec.html
KeyGenerator keyGenerator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
keyGenerator.init(
new KeyGenParameterSpec.Builder("key2",
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.build());
SecretKey key = keyGenerator.generateKey();
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key);
...
// The key can also be obtained from the Android Keystore any time as follows:
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
key = (SecretKey) keyStore.getKey("key2", null);
This example also was helpful.
https://github.com/googlesamples/android-ConfirmCredential/blob/master/Application/src/main/java/com/example/android/confirmcredential/MainActivity.java
I think Android Key Store does not support symmetric keys like AES keys. Please refer to here. BTW, why does the app need so many symmetric keys? I suggest that you store one master asymmetric key in key store, and use this key to encrypt many other symmetric keys in your app.
Hope you solve your problem soon.

Create custom key for DES encryption and decryption - Android

I'm looking to encrypt a string using DES in one app and then decrypt it in another app. Currently I think its not working because the key to encrypt is generated randomly and so in the second app, the key generated when attempting to decrypt is different.
I need to be able to set my own key for when I am encrypting and then set the same key in the second app when decrypting but cannot find an explicit method on how to do so
Currently my key is being generated as follows:
KeyGenerator keygenerator = KeyGenerator.getInstance("DES");
SecretKey myDesKey = keygenerator.generateKey();
How can I create a dummy key to use (e.g. 12345678)
Thanks
see this article, perhaps it can help you:
http://examples.javacodegeeks.com/core-java/crypto/encrypt-decrypt-with-des-using-pass-phrase/

how to encrypt and decrypt a message by using RSA with signature in android

no key distribution, public and private keys will be known by users (random key generator will not be used). I have to encrypt hashed message with private key in order to provide signature
message will only 10-20 characters, so system can be as simple as it is possible
For generating a digital signature, you don't need to encrypt the hash. Signing is a separate crypto primitive; the hash is not encrypted raw anyway, there's some padding. That said, the code is:
Signature Signer = Signature.getInstance("SHA1withRSA");
Signer.initSign(MyKey, new SecureRandom()); //Where do you get the key?
byte []Message = MyMessage(); //Initialize somehow
Signer.update(Message, 0, Message.length);
byte [] Signature = Sign.sign();
Okay, back up and tell us what you want. Are you trying to get privacy by protecting the contents of the message, or guarantee authenticity by showing that the message really came from the originator?
If you're looking for privacy, RSA isn't the way to go: use RSA to generate a private/public pair, and then use them to excahnge keys -- or exchange keys out of band. Use a streaming algorithm like AES to encrypt the message.
If you just want signature to show the message was originated by who you think it was, then have a look at the Wiki article on digital signature -- it's reasonably straightforward.

Categories

Resources