Droidcedas : Using Password-Based Encryption On Android

Why password-based encryption is needed


There are diverse reasons why ane would desire to encrypt information inwards an Android application: to brand certain that files exported to shared storage (SD card, etc.) are non easily accessible to other apps; to encrypt sensitive information (such every bit authentication information for third-party services) stored past times the app or to render approximately form of a DRM-like scheme where content is solely accessible to users who ain the appropriate telephone commutation to access it. The Android SDK includes the Java Cryptography Extension (JCE) interfaces that render piece of cake access to mutual cryptographic operations, too all mainstream Android devices come upwards alongside JCE providers that implement electrical current symmetric encryption algorithms such every bit AES. Thus encrypting application information is fairly easily accomplished inwards Android past times using criterion APIs.

However, every bit inwards other systems, the harder component is non performing the actual cryptographic operations, but telephone commutation management. If a telephone commutation is stored along alongside the encrypted data, or fifty-fifty every bit a file somebody to the application, it is fairly piece of cake to extract it, especially on a rooted device, too decrypt the data. The same is truthful for keys embedded inwards the application source code, fifty-fifty if they are somewhat obfuscated.There are to a greater extent than oft than non ii solutions to this problem: utilization a arrangement service to protect the key, or don't shop the telephone commutation on the device at all, too direct keep it entered each fourth dimension access to protected information is needed. Android does render a arrangement telephone commutation chain facility since version 4.0 (ICS), accessible via the here, it tin give notice currently solely live used to shop RSA somebody keys too certificates. It is non generic plenty to allow secure storage of arbitrary user data, including symmetric encryption keys. That leaves us alongside the other option: do non shop encryption keys on the device. However, symmetric encryption keys are long random strings of bits, too it cannot live expected that someone would really retrieve them, permit lonely larn into them using an onscreen keyboard. On the other hand, users are quite familiar alongside passwords, too so a means to generate rigid cryptographic keys based on a humanly-manageable passwords is needed. There are criterion too secure ways to do this, but let's showtime expression at approximately non-standard, too to a greater extent than oft than non not secure, but quite mutual ways of producing a telephone commutation from a password. We volition live using AES every bit the encryption algorithm for all examples, both because it is the electrical current criterion too is considered highly secure, too because it is practically the solely symmetric algorithm guaranteed to live available on all Android versions. All telephone commutation derivation methods presented hither are implemented inwards the sample application (screenshot below, source is on github).


How not to generate a telephone commutation from a password: padded password


Since a symmetric cipher's telephone commutation has no construction too is just a string of bits alongside a predefined length, pretty much whatsoever string of sufficient length tin give notice live used to build a key. For example, a xvi grapheme password is easily converted to an 128 fleck AES telephone commutation past times only getting the raw bytes of the string inwards a item encoding (such every bit UTF-8). While approximately implementations volition spend upwards known weak keys (such every bit ones composed solely of null bits), y'all volition larn a perfectly valid key, too volition live able encrypt too decrypt alongside it. You powerfulness honor 'helpful' sample code to attain this on forums too the similar that goes something similar this:

int keyLength = 128;  byte[] keyBytes = novel byte[keyLength / 8]; // explicitly create total alongside zeros Arrays.fill(keyBytes, (byte) 0x0);  // if password is shorter too so telephone commutation length, it volition live zero-padded // to telephone commutation length byte[] passwordBytes = password.getBytes("UTF-8"); int length = passwordeBytes.length < keyBytes.length ? passwordBytes.length                     : keyBytes.length; System.arraycopy(passwordBytes, 0, keyBytes, 0, length); SecretKey telephone commutation = novel SecretKeySpec(keyBytes, "AES"); 

Since most people wouldn't pick a xvi grapheme password (let lonely a 32 grapheme ane for a 256 fleck key), the telephone commutation 'derivation' code makes due alongside what is available: if the password doesn't direct keep plenty characters for a total key, it pads it alongside zeros bytes (or another fixed value) to create a valid key. Here's whey this (or variations of it) code generates weak keys:
  • it limits the gain of bytes used for the telephone commutation to those encoding printable characters, so effectively reducing the telephone commutation size (out of 256 possible values for a byte, solely 95 are printable ASCII characters). While at that spot are 2^128 possible 128 fleck AES keys, if solely printable characters are used to build the key, at that spot are nearly 2^105 possible keys (equivalent to using a 105 fleck AES telephone commutation if such a telephone commutation were possible).
  • if the password is shorter than the telephone commutation size, the fixed padding farther reduces the telephone commutation space. For example, if the user picks upwards an 8-character password, that would outcome inwards roughly 2^52 possible keys. That is less fifty-fifty than DES's 56 fleck telephone commutation which has been considered weak for ages too tin give notice live brute-forced inwards less than a hateful solar daytime using commercial hardware.
  • since the password is used every bit is to build the key, the toll of generating a telephone commutation 'derived' using this method is practically zero. Thus an assailant tin give notice easily generate a bunch of keys based on a listing of mutual passwords too utilization them for a fauna forcefulness attack. Since the issue of keys (=common passwords) is limited, such an assault is really efficient, too if a pitiable password has been chosen, to a greater extent than oft than non it volition succeed.
You powerfulness intend that no ane would utilization such a naive telephone commutation derivation scheme, but every bit it turns out, fifty-fifty fairly pop telephone commutation managing director apps are known to direct keep used it. 

To total this up: a symmetric encryption telephone commutation needs to live random to render sufficient security, too user-entered passwords are a pitiable source of randomness. Don't utilization them every bit is to build a key.

How not to generate a telephone commutation from a password: SHA1PRNG

Since, every bit mentioned above, a telephone commutation needs to live random, it stands to argue to utilization a random issue generator (RNG) to generate one. There are ii flavours of those: "true" random generators that base of operations their output on physical phenomena that are regarded every bit random (e.g., radioactive decay), too pseudo-random generators (PRNG) whose output is determined past times a fairly curt initialization value, know every bit a seed. By using a "truly random" (or close) value every bit the seed, PRNG's tin give notice make sufficiently random output. To generate a random symmetric telephone commutation based on a password nosotros tin give notice utilization the password (in approximately form) to seed a PRNG, too so make predictable keys. There are criterion telephone commutation derivation algorithms based on this idea, which nosotros volition innovate later, but let's showtime expression at approximately fairly mutual derivation code that implements this stance quite literally. You powerfulness come upwards across code similar to this on 'code snippet' sites or fifty-fifty StackOverflow:

KeyGenerator kgen = KeyGenerator.getInstance("AES"); SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); byte[] seed = password.getBytes("UTF-8"); sr.setSeed(seed); kgen.init(KEY_LENGTH, sr); SecretKey telephone commutation = kgen.generateKey(); 

This creates a random generator instance (SecureRandom) using the SHA1PRNG PRNG algorithm (which is currently the solely RNG algorithm available on commercial Android devices), too seeds it alongside the password bytes. H5N1 KeyGenerator is too so initialized alongside the SecureRandom instance, making certain that our password-seeded PRNG volition live used when generating keys. Lastly, since a KeyGenerator for a symmetric algorithm only requests a issue of bits equal to the telephone commutation size from the underlying (or system) RNG, nosotros larn a pseudorandom cloak-and-dagger telephone commutation based on the used password.

This scheme is non every bit bad every bit the previous one, since it produces a pseudorandom key, too doesn't bring down telephone commutation size, but it is yet non a proficient stance to utilization it. The showtime argue is the same every bit the lastly ane for the padding method: generating a telephone commutation is inexpensive too so keys based on a password listing tin give notice live readily generated, facilitating a fauna forcefulness attack. How cheap: essentially the toll of a SHA-1 hash round, which is to a greater extent than oft than non implemented inwards native code too is pretty fast. The instant argue is that it is neither standard, nor portable. Even the JavaDoc entry for Android's SecureRandom says so: 'Not guaranteed to live compatible alongside the SHA1PRNG algorithm on the reference implementation.' The code higher upwards when run on Android too on a desktop arrangement using Java SE produces the next 128 fleck keys from the password string 'password'. Note that those may differ fifty-fifty betwixt different Android platform or Java SE versions:

Android: 80A4495EF27725345AB3AFA08CE3A692 Java SE: 2470C0C06DEE42FD1618BB99005ADCA2 

In short: spell this method is slightly ameliorate than the previous one, it doesn't effectively foreclose from fauna forcefulness attacks too is non portable. Don't utilization it. Update: As of Android 4.2, the default SHA1PRNG provider is based on OpenSSL too this method doesn't piece of occupation out of the box. If y'all require to utilization it for compatibility reasons, y'all direct keep to explicitly specify the "Crypto" provider when getting a SecureRandom instance. But again, don't utilization it.

Proper telephone commutation derivation: PKCS#5 too PKCS#12


H5N1 criterion means to derive a symmetric encryption telephone commutation from a password is defined inwards PKCS#5 (Public Key Cryptography Standard) published past times RSA (the company). It was originally developed for generating DES keys, but the electrical current versions (2.0 too draft of 2.1) extend it to live algorithm independent. Version 2.0 is likewise published as RFC 2898

The criterion is based on ii primary ideas: using a tabular array salt to protect from table-assisted (pre-computed) lexicon attacks (salting) too using a large iteration count to brand the telephone commutation derivation computationally expensive (key stretching). As mentioned above, if a telephone commutation is direct constructed from a password, it is piece of cake to utilization pre-generated keys based on a listing of mutual passwords for a fauna forcefulness attack. By using a random 'salt' (so called because it is used to 'season' the password), multiple keys tin give notice live constructed based on the same password, too so an assailant needs to generate a novel telephone commutation tabular array for each tabular array salt value, making pre-computed tabular array attacks much harder. H5N1 telephone commutation betoken to banking enterprise complaint is that, spell the tabular array salt is used along alongside the password to derive the key, dissimilar the password, it does non require to live kept secret. Its purpose is solely to brand a lexicon assault to a greater extent than hard too it is oft stored along alongside the encrypted data. The other approach applied inwards PKCS#5 is repeating the telephone commutation derivation performance multiple times to make the lastly key. This has piffling outcome on legitimate use, where solely ane travail is needed to derive the telephone commutation from the right password, but considerably slows downwards fauna forcefulness attacks which travail out multiple passwords inwards a row. 

PKCS#5 defines ii telephone commutation derivation functions, aptly named PBKDF1 too PBKDF2. PBKDF1 applies a hash component (MD5 or SHA-1) multiple times to the tabular array salt too password, feeding the output of each circular to side past times side ane to make the lastly output. The length of the lastly telephone commutation is so natural springtime past times the hash component output length (16 bytes for MD5, xx bytes for SHA-1). PBKDF1 was originally designed for DES too its xvi or xx byte output was plenty to derive both a telephone commutation (56 bits) too an initialization vector (64 bits) to encrypt inwards CBC mode. However, since this is non plenty for algorithms alongside longer keys such every bit 3DES too AES, PBKDF1 shouldn't live used too is solely left inwards the criterion for backward compatibility reasons.
PBKDF2 doesn't endure from the limitations of PBKDF1: it tin give notice make keys of arbitrary length past times generating every bit many blocks every bit needed to build the key. To generate each block, a pseudorandom component is repeatedly applied to to the concatenation of the password, tabular array salt too block index. The pseudorandom component is configurable, but inwards exercise HMAC-SHA1/256/384/512 are used, alongside HMAC-SHA1 beingness the most common. The password is used every bit the HMAC telephone commutation too the tabular array salt takes the role of the message. Unlike PBKDF1, PBKDF2 doesn't specify how to derive an IV (initialization vector), so a randomly generated ane is used.

Android's primary JCE provider (Bouncy Castle) currently solely supports PBKDF2WithHmacSHA1. Let's run into how to utilization it to encrypt information alongside a 256 fleck AES telephone commutation derived from a password:

String password  = "password"; int iterationCount = 1000; int keyLength = 256; int saltLength = keyLength / 8; // same size every bit telephone commutation output  SecureRandom random = novel SecureRandom(); byte[] tabular array salt = novel byte[saltLength]; randomb.nextBytes(salt); KeySpec keySpec = novel PBEKeySpec(password.toCharArray(), salt,                     iterationCount, keyLength); SecretKeyFactory keyFactory = SecretKeyFactory                     .getInstance("PBKDF2WithHmacSHA1"); byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded(); SecretKey telephone commutation = novel SecretKeySpec(keyBytes, "AES");  Cipher null = Cipher.getInstance("AES/CBC/PKCS5Padding"); byte[] iv = novel byte[cipher.getBlockSize()); random.nextBytes(iv); IvParameterSpec ivParams = novel IvParameterSpec(iv); cipher.init(Cipher.ENCRYPT_MODE, key, ivParams); byte[] ciphertext = cipher.doFinal(plaintext.getBytes("UTF-8")); 

Here nosotros generate a random tabular array salt too utilization one 1000 iterations to initialize the SecretKeyFactory which generates our key. The lastly measuring of telephone commutation generation powerfulness live a piffling confusing though: nosotros don't utilization the SecretKey produced past times the mill every bit is, but utilization its encoded value to create a novel SecretKeySpec object. That is done because the output of generateSecret() is really a PBEKey instance which does non incorporate an initialized IV -- the Cipher object expects that from a PBEKey too volition throw an exception if it is non present. The iteration count is every bit recommended past times PKCS#5, but that criterion was written a spell ago, so y'all powerfulness desire to growth it. For approximately perspective, AES 256 fleck keys used to encrypt backups inwards Android 4.0 (ICS) are derived using 10,000 iterations too a 512 fleck salt; iOS 4.0 likewise uses 10,000 iterations. The size of the tabular array salt should typically jibe the telephone commutation size, for illustration xvi bytes when using a AES alongside a 128 fleck telephone commutation (128 / 8 = 16). Next nosotros generate a random IV, initialize the null too output the null text.

To live able to decrypt the null text nosotros need: the password, the iteration count, the tabular array salt too the IV. The password volition live input past times the user, too the iteration count is to a greater extent than oft than non fixed (if y'all determine to larn inwards variable, y'all require to shop it along alongside the other parameters), so that leaves the tabular array salt too the IV. As discussed above, the tabular array salt is non a secret, too neither is the IV. Thus they tin give notice live saved along alongside the null text. If they are stored inwards a unmarried blob/file, approximately form of construction is needed to live able the parse it into its components. The sample app 'saves' the encrypted message to a Base64-encoded string too only concatenates the salt, IV too null text delimited past times "]" (any grapheme non used Base64 volition do). Decryption is really similar to the code above, except that the tabular array salt too IV are non generated randomly, but retrieved from the encrypted message.

String[] fields = ciphertext.split("]"); byte[] tabular array salt = fromBase64(fields[0]); byte[] iv = fromBase64(fields[1]); byte[] cipherBytes = fromBase64(fields[2]); // every bit higher upwards SecretKey telephone commutation = deriveKeyPbkdf2(salt, password);  Cipher null = Cipher.getInstance("AES/CBC/PKCS5Padding"); IvParameterSpec ivParams = novel IvParameterSpec(iv); cipher.init(Cipher.DECRYPT_MODE, key, ivParams); byte[] plaintext = cipher.doFinal(cipherBytes); String plainrStr = novel String(plaintext , "UTF-8"); 

Another criterion telephone commutation derivation machinery is the ane defined inwards PKCS#12. It doesn't seem to direct keep a catchy call similar the previous two, too is to a greater extent than oft than non solely used for backward compatibility alongside Microsoft's master copy PFX format. Like PBKDF2, it tin give notice likewise generate keys too IV's alongside arbitrary length. The Bouncy Castle provider supports a bunch of variations compatible alongside AES such every bit PBEWITHSHA256AND256BITAES-CBC-BC. The IV is generated based on the password too salt, so y'all don't direct keep to generate too shop it separately. The sample app includes a PKCS#12 telephone commutation derivation mode, refer to the source code if y'all desire to banking enterprise check how the implementation differs from the code above.

Derivation speed

We've mentioned that the showtime ii 'derivation' methods are really fast too so render no existent protection against tabular array assisted fauna forcefulness attacks. PKCS#5 too PKCS#12 compliant derivation methods deliberately brand the procedure slower to impede fauna forcefulness attacks. But what just is the speed difference? The next tabular array summarizes the average computation times for the 4 presented derivation methods. Measurements were performed on a Nexus One (1GHz CPU) using 1000 iterations too a 8 byte tabular array salt for both PKCS#5 too PKCS#12.  As y'all tin give notice see, fifty-fifty a relatively small-scale issue of iterations matters: iteration based methods are at to the lowest degree an gild of magnitude slower, which inwards this instance is a proficient thing since it makes fauna forcefulness attacks harder.

Password derivation speed on Nexus One
Padding SHA1PRNG PKCS#12 PBKDF2
< 1 [ms] 32 [ms] 160 [ms] 370 [ms]

Of course, the actual password matters a lot. If it is easily guessable, an assailant tin give notice easily honor the encryption key, no affair how many iterations y'all used inwards your implementation. Thus regular password alternative policies apply for password-based encryption (PBE) as well: do non utilization mutual lexicon words, mix lower too upper instance letters alongside numbers too symbols. If possible, generate passwords automatically, too do non entrust users alongside password selection.

Conclusion

Using symmetric encryption on Android is quite straightforward, but since a full general purpose, system-level secure storage is non available, telephone commutation administration could live complicated. One solution is non to shop keys, but derive them from user-entered passwords. Password strings cannot live used every bit symmetric encryption keys every bit is, so approximately form of telephone commutation derivation is required. There are a few ways to derive keys, but most of them are non peculiarly secure. To ensure encryption keys are both sufficiently random too hard to fauna force, y'all should utilization criterion PBE telephone commutation derivation methods. Of those, the ane currently regarded secure too available on Android is PBKDF2WithHmacSHA1. In short: when deriving a telephone commutation from a password utilization PBKDF2WithHmacSHA1, a sufficiently long randomly generated tabular array salt too an iteration count suitable for your app.
0 Komentar untuk "Droidcedas : Using Password-Based Encryption On Android"

Back To Top