Converting Secret Key into a String and Vice Versa Converting Secret Key into a String and Vice Versa java java

Converting Secret Key into a String and Vice Versa


You can convert the SecretKey to a byte array (byte[]), then Base64 encode that to a String. To convert back to a SecretKey, Base64 decode the String and use it in a SecretKeySpec to rebuild your original SecretKey.

For Java 8

SecretKey to String:

// create new keySecretKey secretKey = KeyGenerator.getInstance("AES").generateKey();// get base64 encoded version of the keyString encodedKey = Base64.getEncoder().encodeToString(secretKey.getEncoded());

String to SecretKey:

// decode the base64 encoded stringbyte[] decodedKey = Base64.getDecoder().decode(encodedKey);// rebuild key using SecretKeySpecSecretKey originalKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES"); 

For Java 7 and before (including Android):

NOTE I: you can skip the Base64 encoding/decoding part and just store the byte[] in SQLite. That said, performing Base64 encoding/decoding is not an expensive operation and you can store strings in almost any DB without issues.

NOTE II: Earlier Java versions do not include a Base64 in one of the java.lang or java.util packages. It is however possible to use codecs from Apache Commons Codec, Bouncy Castle or Guava.

SecretKey to String:

// CREATE NEW KEY// GET ENCODED VERSION OF KEY (THIS CAN BE STORED IN A DB)    SecretKey secretKey;    String stringKey;    try {secretKey = KeyGenerator.getInstance("AES").generateKey();}    catch (NoSuchAlgorithmException e) {/* LOG YOUR EXCEPTION */}    if (secretKey != null) {stringKey = Base64.encodeToString(secretKey.getEncoded(), Base64.DEFAULT)}

String to SecretKey:

// DECODE YOUR BASE64 STRING// REBUILD KEY USING SecretKeySpec    byte[] encodedKey     = Base64.decode(stringKey, Base64.DEFAULT);    SecretKey originalKey = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");


To show how much fun it is to create some functions that are fail fast I've written the following 3 functions.

One creates an AES key, one encodes it and one decodes it back. These three methods can be used with Java 8 (without dependence of internal classes or outside dependencies):

public static SecretKey generateAESKey(int keysize)        throws InvalidParameterException {    try {        if (Cipher.getMaxAllowedKeyLength("AES") < keysize) {            // this may be an issue if unlimited crypto is not installed            throw new InvalidParameterException("Key size of " + keysize                    + " not supported in this runtime");        }        final KeyGenerator keyGen = KeyGenerator.getInstance("AES");        keyGen.init(keysize);        return keyGen.generateKey();    } catch (final NoSuchAlgorithmException e) {        // AES functionality is a requirement for any Java SE runtime        throw new IllegalStateException(                "AES should always be present in a Java SE runtime", e);    }}public static SecretKey decodeBase64ToAESKey(final String encodedKey)        throws IllegalArgumentException {    try {        // throws IllegalArgumentException - if src is not in valid Base64        // scheme        final byte[] keyData = Base64.getDecoder().decode(encodedKey);        final int keysize = keyData.length * Byte.SIZE;        // this should be checked by a SecretKeyFactory, but that doesn't exist for AES        switch (keysize) {        case 128:        case 192:        case 256:            break;        default:            throw new IllegalArgumentException("Invalid key size for AES: " + keysize);        }        if (Cipher.getMaxAllowedKeyLength("AES") < keysize) {            // this may be an issue if unlimited crypto is not installed            throw new IllegalArgumentException("Key size of " + keysize                    + " not supported in this runtime");        }        // throws IllegalArgumentException - if key is empty        final SecretKeySpec aesKey = new SecretKeySpec(keyData, "AES");        return aesKey;    } catch (final NoSuchAlgorithmException e) {        // AES functionality is a requirement for any Java SE runtime        throw new IllegalStateException(                "AES should always be present in a Java SE runtime", e);    }}public static String encodeAESKeyToBase64(final SecretKey aesKey)        throws IllegalArgumentException {    if (!aesKey.getAlgorithm().equalsIgnoreCase("AES")) {        throw new IllegalArgumentException("Not an AES key");    }    final byte[] keyData = aesKey.getEncoded();    final String encodedKey = Base64.getEncoder().encodeToString(keyData);    return encodedKey;}


Actually what Luis proposed did not work for me. I had to figure out another way. This is what helped me. Might help you too. Links:

  1. *.getEncoded(): https://docs.oracle.com/javase/7/docs/api/java/security/Key.html

  2. Encoder information: https://docs.oracle.com/javase/8/docs/api/java/util/Base64.Encoder.html

  3. Decoder information: https://docs.oracle.com/javase/8/docs/api/java/util/Base64.Decoder.html

Code snippets:For encoding:

String temp = new String(Base64.getEncoder().encode(key.getEncoded()));

For decoding:

byte[] encodedKey = Base64.getDecoder().decode(temp);SecretKey originalKey = new SecretKeySpec(encodedKey, 0, encodedKey.length, "DES");