AES Gingerbread - android

This is my code for AES.
Under Gingerbread I get following error after encrypting the data on 2.2 then trying to decrypt on 2.3:
Caused by: javax.crypto.BadPaddingException: pad block corrupted
at org.bouncycastle.jce.provider.JCEBlockCipher.engineDoFinal(JCEBlockCipher.java:715)
at javax.crypto.Cipher.doFinal(Cipher.java:1090)
at com.citc.wallet.util.security.SimpleCrypto.decrypt(SimpleCrypto.java:63)
... 21 more
I have found some posts saying that SecureRandom is producing different results under different systems:
BouncyCastle AES error when upgrading to 1.45
How do I avoid this problem on 2.3?
Can I somehow force 2.3 to use the same SecureRandom class?
Do I need to use some portable encryption method and if so what?

The answer is that you shouldn't really be doing what you are doing at all. Here is the culprit:
sr.setSeed(seed);
kgen.init(128, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
You should never pad your key with some un-predictable random value because you will need to recreate this same exact key later on. Here are some key lines from the android docs
"Seeding SecureRandom may be insecure"
Although it is common practice to seed
Random with the current time, that is
dangerous with SecureRandom since that
value is predictable to an attacker
and not appropriate for secure use.
Anyway, I know your argument will be that you are just "padding" the key and the security of what you are doing is not a big deal.
If you are going to accept keys of 128 bits for 192 or 256 bit implementations, then you must implement a repeatable method of expanding the key to 192 or 256 bits. You can even add all 0's to the key if you wanted to, but the key really is that it must be done in some way that you can repeat it on every system.
In any case, you may also want to consider that what you are doing may be used on systems other than Android. In those cases, using a more "portable" method to expand a key should be chosen.

Related

Get AES-GCM to work also on older android versions

I am implementing the AES encryption algorithm in GCM operating mode in an android application.
My IDE (Intellij Idea) tells me that to use javax.crypto.spec.GCMParameterSpec the condition android.os.Build.VERSION.SDK_INT> = android.os.Build.VERSION_CODES.KITKAT is required.
I tried when the condition is not verified to use a javax.crypto.spec.GCMParameterSpec of which I downloaded the source file and included it in my project, but with it the encryption operations do not work correctly (the decrypted data does not match to original data or java.security.InvalidAlgorithmParameterException: IV must be specified in GCM mode).
Do you have any ideas to suggest on how I can also support previous versions of Android KITKAT?
Thanks in advance.
Initial versions of Android based on Java 6 did not give you GCMParameterSpec, but they would use IvParameterSpec instead. Besides the (usually 12 byte) IV, the GCMParameterSpec will give you two additional operations: the support for additional data and the tag size.
Now the tag size is not too much of a problem: first of all, usually the full 128 bits / 16 bytes are used. Furthermore you can just remove those bytes from the end of the ciphertext until you reach the required tag size, e.g. remove 4 bytes / 32 bits to get a tag size of 96 bits.
The additional data is a problem, as far as I know there is no way to specify those, at least not if you require a Cipher instance. You could of course use GCMBlockCipher instead, but then you'd not use Cipher and any possible acceleration provided by the platform (as Bouncy is software only).
And yes, as indicated, it is perfectly possible to implement GCM mode yourself for Android, as you don't need to sign any providers. Of course, you'd have to use a different GCMParameterSpec implementation, and it would be a good idea only to use the provider for the older platform, so some runtime switching seems to be required.

What is the difference between cipher algorithms AES and AES_128

According to documentation for app developers AES_128 and AES_256 are supported from api 26. https://developer.android.com/reference/javax/crypto/Cipher. For example now I'm using AES(GCM mode) with 128 bit key. What is the difference between AES with 128 bit key and AES_128 ?
There is no difference between AES with a 128-bit key and AES_128.
As you can see in the docs you linked, previous to API 26 there existed one primitive for AES, with various padding options/modes of operation.
To make things simpler, in API 26+ there is now two primitives to disambiguate the usage of AES with either a definitive 128-bit or 256-bit key.
If you are using AES, you should opt for AES-256 GCM as it provides a authenticated encryption, ensuring that the ciphertext cannot be tampered with, without the recipients knowledge.
AES-GCM operates with a 32-bit counter, so unfortunately with the same key, nonce (IV) pair you can only safely encrypt ~ 64GB of data (2^39-256 bits).
If you want to move to an even safer cipher, I recommend XSalsa20 or XChaCha20, which provide a 192-bit nonce size, effectively allowing a practically "unlimited" amount of data to be encrypted with the same key, nonce pair.
AES_128 doesn't exists. However, constants in Java don't generally use the hyphen (-) character, so the underscore is used to indicate AES-128 (still a strange choice for a String if you ask me).
AES-128 is just AES configured to use a 128 bit key. Internally it uses a specific sub-key derivation and 10 rounds. AES-256 has a different sub-key derivation and uses 14 rounds. AES-192 (12 rounds) isn't used much, as it has an awkward key size and it doesn't fully protect against attacks that may be applicable to AES-128.
Practically speaking there may be two differences when it comes to general usage. First of all, the API may be able to select an implementation of 128 or 256 bits of AES before the init methods are called. Secondly, I presume that the init method only accepts 128 bit keys when you configure AES-128.

AES 256 Encryption implementation in android

I know this question is So popular in StackOverflow that How AES 256 implemented in Android, but the main problem is No any solution gives the exact encryption and decryption of AES 256. All codes are explained through Key Length of 128 and 256 which is not correct.
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(seed);
kgen.init(256, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
But I need different from this, which AES 256 implementation not as the 256 key length. Please suggest me the right solution regarding the same.
Thanks in advance.
If the keying material you have is a password, you should use PBKDF2. If not, it's probably sufficient just to take the SHA-256 hash of the keying material, which will be 256-bits. For a 128-bit key, just use half the hash.
Note that using keying material that is less than 100 bits is extremely inadvisable.
AES256 always uses a 256 bit key. If your key material has a different length, you can use the output of a hash function, such as SHA-256 to get a 256 bit key.
But if your key material has an entropy of less then 256 bits, that obviously means that you won't get 256 bits of security. Practical security suffers once you get significantly below 128 bits of security.
If your key material is a password, use a key-derivation-function such as PBKDF2 to get the key. It's deliberately slow, in order to increase the security with relatively low entropy passwords.

Encryption system in android

I'd like to leave the user the possibility to choice the encryption method, but for now I implemented just AES with SHA1PRNG. With AES/CBC/PKCS5Padding it doesn't work.
What does other encryption method work with android?
I have to encrypt data to store them in a db and then decrypt for show them.
The error returned:
java.security.NoSuchAlgorithmException: SecureRandom AES/CBC/PKCS5Padding implementation not found
here:
SecureRandom.getInstance( "AES/CBC/PKCS5Padding" );
Do you want to use a random number generator (which is what SecureRandom is for), or do you want to use an encryption algorithm (which is what AES is for)?
If you want an encryption algorithm (and its implementation), use the javax.crypto.Cipher class, which should support your AES/CBC/PKCS5Padding algorithm.
In principle you can use AES to build an RNG, too, but then you would not use CBC/PKCS5Padding, but something like ANSI X9.31. I don't think this is implemented in any Java and/or Android API for SecureRandom.
According to the reference it only supports SHA1PRNG, unless you install other providers.
See: http://developer.android.com/reference/java/security/SecureRandom.html

Unlimited Strength Jce and Android

I'm using SpongyCastle (full implementation of BouncyCastle's crypto functions for Android) and I have a bks that contains a key of size 384. I'm trying to extract that key using the method KeyStore.getKey(alias, password) as you would any key in a keystore. But what I'm running into is the error
java.security.UnrecoverableKeyException: no match.
Doing a little bit of research indicates that it might be because the key size is too big for Android to handle which makes sense as my program gets the other keys of sizes 128 and 256 no problem. Normally in Java, this would be resolved by importing the "Unlimited Strength" JCE into the Java security folder but what about android? Can I import the unlimited strength JCE into android (my gut instinct is no) If not, are there any suggestions as to how to extract the key? SpongyCastle has solved a lot of my other issues, I'm hoping there's a SpongyCastle solution here too.
Thanks!
So after much wrestling with it, I figured out the problem.
I wasn't specifying a provider so my program defaulted to the default Android BouncyCastle. The minute I did
KeyStore ks = new KeyStore("BKS","SC");
as opposed to
KeyStore ks = new KeyStore("BKS");
it worked just fine and did not complain.

Categories

Resources