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.
Related
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.
We are using Android 4.0.4 ICS in an enterprise context, and i am trying to understand how Android protects the Key Store, specifically the Certificates Private Key.
What Hashing Algorithm does it use?
Are there any good reference materials out there that i can present to my Security Architect?
Take a look at Nikolay Elenkov's articles on ICS KeyChain if you want to see how that API is implemented inside. There are three articles in the series, but the article on ICS Credential Storage Implementation tells you how the files are stored on disk.
keytool is a standard Java tool for managing a keystore and associated X.509 certificates.
See the documentation for more information; more specifically the section on supported algorithms:
The default key pair generation algorithm is "DSA". The signature
algorithm is derived from the algorithm of the underlying private key:
If the underlying private key is of type "DSA", the default signature
algorithm is "SHA1withDSA", and if the underlying private key is of
type "RSA", the default signature algorithm is "MD5withRSA". When
generating a DSA key pair, the key size must be in the range from 512
to 1024 bits, and must be a multiple of 64. The default key size for
any algorithm is 1024 bits.
I am using a 128-bit AES cipher algorithm. But the program takes a long time, since the files to encrypt are big.
I was wondering if there is a more light cipher algorithm to use in Android. I can't find a list of supported ciphers in Android.
Have you tried to use shorter keys with AES instead? You can try OpenSSL build as native code, but I guess dalvik already uses optimized libraries, I don't think it will help. There are good reasons AES takes some time, by choosing something faster, you will have to lower real security.
I suggest you should not encrypt whole file if you need speed. Instead, encrypt only header or parts of file, without which rest of file is not useful. However it depends on what data you are encrypting and will not work for generic data files.
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
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.