Android password text encryption

Posted by admin on February 20, 2012

Hello again, Android fans.  In this article I will explain how to use the javax.crypto classes to encrypt strings of text.  It also uses the Base64 class from http://iharder.net/base64.

There are some very simple steps to making password-encryption work.

First, you need to come up with a string to use as your secret password.  You can easily grab this from a textBox with the line:

String superSecretPassword = textBox.getText().toString();

Second, you need to convert your secret password into a byte[ ].  This is necessary so that you can make your secret key for encryption.  I use the Base64 class from http://iharder.net/base64

 The class from the above website is great for converting from String to byte[ ], and from byte[ ] back to String. You can't just to string.getBytes(), because you will lose data in the conversion from String to byte[ ], and the data is not regained when you go from byte[ ] to String.

In order to make the encryption work, you have to convert the string into base64 encoded bytes.

To convert to byte[ ] from String, do

byte[ ] superSecretKeyBytes = Base64.decode(string);

To convert from byte[ ] to String, do

String superSecretKey = Base64.encodeBytes(superSecretKey);

 

In order to use the Base64 class in your Android app, just download the class and copy / paste it into the /src/appName folder in your Eclipse workspace.  Refresh the folder (right click on it and say 'refresh') and it will show up, ready for use.

Now, on to the encryption.

Here's where things can start to get complicated really fast.  Most online tutorials I have found won't work, so I floundered around for two days before stumbling on a good tutorial and then I modified it for my purposes.

When you specify a password for encryption, it will not always come out to be the right number of bytes.  You need a 16 byte password, but that's not possible to make in any length of string.  Therefore, you will need to make a 16 byte array and then fill it with up to 16 bytes of your password.

Here's how I did this:
1:  First, make the byte[16] and fill it with random numbers.  Use a random number generator or something.  Put this array into persistent storage (sharedPreferences or a file or something).  DO NOT lose this array, because you will be needing it every time you encrypt or decrypt something.  If you lose it, you will have to crack your encryption key to get your data back.

2: Next, convert your password into bytes using the Base64.decode() function.  Store that byte[ ] array in a variable.

3: Use a for loop to put all of the bytes from your password into the random byte[ ] array you made earlier.  DO NOT put this modified array into persistent storage.  This array is what will be used to encrypt your text.  If you store this, someone else could grab it and have free access to your secret key.

 

          byte[ ] userInput = Base64.decode(passwordBox.getText().toString());
          byte[ ] sKey = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6};
          //Pad the key to 16 or 32 bytes.  Likely 16, because not all devices support more than 128 bits
          for(int i = 0; i < userInput.length; i++){
              //Copy the bytes from the string into the sKey array,
              //Leaving the rest of the array (the padding) intact
              sKey[i] = userInput[i];
           }

Now that the sKey array contains the actual secret key, we can use this to encrypt stuff.

Steps to encryption:

1: Make a 'SecretKeySpec' object using your secret key, and specifying the type of encryption you want.  In this example, I use AES encryption.

2: Create a Cipher object (this is what does the encryption), and initialize it to use AES.

3: Tell the Cipher to encrypt, using your SecretKeySpec you just made

4: Use your Cipher to get an encrypted byte[ ]

5: Turn the byte[ ] into a string using Base64.encodeBytes()

6: Do whatever you want with the string.  Store it, transmit it, whatever.  It's encrypted.

Below is the code I use to encrypt Strings.  It takes in the String to be encrypted, and the byte[ ] that is your secret key.  It returns an encrypted String.

public static String encrypt(String toEncrypt, byte[ ] key) throws Exception {
        //Create your Secret Key Spec, which defines the key transformations
        SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
       

        //Get the cipher
        Cipher cipher = Cipher.getInstance("AES");

        //Initialize the cipher
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);

        //Encrypt the string into bytes
        byte[ ] encryptedBytes = cipher.doFinal(toEncrypt.getBytes());

        //Convert the encrypted bytes back into a string
        String encrypted = Base64.encodeBytes(encryptedBytes);

        return encrypted;
}

Decrypting what you just encrypted:

Now that you encrypted that string, let's decrypt it.  What use is an encryption tutorial if it doesn't tell you how to decrypt what you just encrypted?

This is why I told you to keep that random byte[ ] array.  Without it, you'll have to try and crack your password.

Essentially, you'll do what you did above, but your set the Cipher to DECRYPT_MODE.

Pull in the String that is your password, convert it with the Base64.encode() method, put it into the random byte[ ] array, and you have your Secret Key back.

To decrypt:
1: Take in your encrypted text string and the Secret Key byte[ ].

2: Make your SecretKeySpec using the key byte[ ] and specify AES as the encryption type.

3: Initialize the cipher to use AES, and tell it to be DECRYPT_MODE and use your SecretKeySpec.

4: Turn your encrypted text string into a byte[ ] array with Base64.decode()

5: Decrypt your encrypted text byte[ ] array into a decrypted byte[ ] array.

6: Turn the decrypted byte[ ] back into a string.

7: Do as you please with your decrypted string.

public static String decrypt(String encryptedText, byte[ ] key) throws Exception {
        SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
     
        Cipher cipher = Cipher.getInstance("AES");

        cipher.init(Cipher.DECRYPT_MODE, skeySpec);

        byte[] toDecrypt = Base64.decode(encryptedText);
        
        byte[] encrypted = cipher.doFinal(toDecrypt);

        return new String(encrypted);
}