Crypto Library for Android
Android applications are developed in Java programming language. The basic functionality for using cryptographic techniques in Java is provided by the Java Cryptography Architecture (JCA) and the Java Cryptography Extension (JCE).
The normal JDK download ships with a set of policy files that place certain restrictions on the key sizes that can be used. Key sizes are limited in general to a maximum 128 bits (except for the symmetric cipher Triple-DES) and RSA key generation is limited to 2048bits. The easiest way to deal with this restriction is to download the unrestricted policy files.
The cryptographic service classes have a distinct structure to facilitate independence from algorithm and implementation. Every provider implements those services. As default, Java uses five bundled providers and their names are: SUN, SunJSSE, SunRsaSign, SunJCE and SunJGSS. In Android apps, the most frequently used cryptographic provider is BouncyCastle. To install BouncyCastle it is necessary to download bcprov-jdk-xxx.jar and copy it to jre/lib/ext directory of Java installation, and then install provider.
When we want to specify to use the Bouncy Castle provider to create the object, we might say, in the case of a Cipher object:
Cipher.getInstance("Blowfish/ECB/NoPadding", "BC");Or if we do not care which provider is used to create the object we might say:
Cipher.getInstance("Blowfish/ECB/NoPadding");
According to this post, it will be shown how cryptographic primitives are often incorrectly used in making Android applications, and how they are fixed.
First rule prohibits the use of Electronic Codebook mode. An application will use ECB block cipher if the developer explicitly specifies that he wants ECB mode or if the developer only specifies transformation, BouncyCastle or SUN will choose ECB as default.
Incorrect code:
First rule prohibits the use of Electronic Codebook mode. An application will use ECB block cipher if the developer explicitly specifies that he wants ECB mode or if the developer only specifies transformation, BouncyCastle or SUN will choose ECB as default.
Incorrect code:
Cipher.getInstance("AES/ECB/PKCS7Padding");
Cipher.getInstance("AES");
Correct code (for block cipher):
Cipher.getInstance("AES/CBC/PKCS7Padding");Correct code for stream ciphers (CBC, CFB, OFB):
Cipher.getInstance("AES/CTR/NoPadding");
Cipher.getInstance("AES/CFB/NoPadding");
Cipher.getInstance("AES/OFB/NoPadding");
Second rule recommends not to use Cipher Block Chaining mode (CBC) with non-random initialization vector (IV). Java API allows the developer to override this random selection and specify an IV himself. If the developer does not specify an IV, the BouncyCastle implementation of CBC will follow the CBC algorithm and generate an IV at random using the SecureRandom API.
Incorrect code:
Third rule prohibits the use of constant encryption keys. Very often, developers hard-code key when they Incorrect code:
Cipher.getInstance("AES/CBC/PKCS7Padding");
byte[] ivBytes = new byte[] { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);Correct code:
Cipher.getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
IvParameterSpec ivSpec = new IvParameterSpec(cipher.getIV());
develop app which is extremely insecure. It is mostly recommended to use random keys obtained with class KeyGenerator.
Incorrect code:
SecretKey secretkey = new SecretKeySpec(new byte[] { 0x00, 0x01, 0x02,0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,0x17 }, "AES");
Correct code:
KeyGenerator generator = KeyGenerator.getInstance("AES", "BC");
generator.init(192);
SecretKey secretKey = generator.generateKey();
Fourth and fifth rules are about password based encryption (PBE). It is strongly recommended to use random salts made from KeyGenerator and, according to PKCS#5 standard, it is recommended to use at least 1000 iterations for PBE.
Correct code:
Correct code:
int iterationCount = 1000;
PBEKeySpec pbeSpec = new PBEKeySpec(password);
SecretKeyFactory keyFact = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1", "BC");
Cipher cDec = Cipher.getInstancef ("PBEWithSHAAnd3KeyTripleDES", "BC");
Key sKey = keyFact.generateSecret(pbeSpec);
cipher.init(Cipher.DECRYPT_MODE, sKey, new PBEParameterSpec(salt, iterationCount));
Sixth rule prohibits seeding SecureRandom() functions with static value. This can be done in two ways. First is to generate some random value and then seed SecureRandom() with that value, or second, better way is to use power of SecureRandom() function and let the function to generate random value by itself.
First example:
SecureRandom sr = new SecureRandom();
sr.setSeed(RANDOM_VALUE);
sr.nextBytes(output);Second example:
SecureRandom sr = new SecureRandom();
sr.nextBytes(output);
First example is faster but requires truly random value to seed SecrueRandom(). Second example is a bit slower, but easier to use.
download file now