I am generating a key and need to store it in DB, so I convert it into a String, but to get back the key from the String. What are the possible ways of accomplishing this?
My code is,
SecretKey key = KeyGenerator.getInstance("AES").generateKey();
String stringKey=key.toString();
System.out.println(stringKey);
How can I get the key back from the String?
You can convert the
SecretKey
to a byte array (byte[]
), then Base64 encode that to aString
. To convert back to aSecretKey
, Base64 decode the String and use it in aSecretKeySpec
to rebuild your originalSecretKey
.For Java 8
SecretKey to String:
String to SecretKey:
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
orjava.util
packages. It is however possible to use codecs from Apache Commons Codec, Bouncy Castle or Guava.SecretKey to String:
String to SecretKey:
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:
*.getEncoded(): https://docs.oracle.com/javase/7/docs/api/java/security/Key.html
Encoder information: https://docs.oracle.com/javase/8/docs/api/java/util/Base64.Encoder.html
Decoder information: https://docs.oracle.com/javase/8/docs/api/java/util/Base64.Decoder.html
Code snippets: For encoding:
For decoding:
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):
try this, it's work without Base64 ( that is included only in JDK 1.8 ), this code run also in the previous java version :)
You don't want to use
.toString()
.Notice that SecretKey inherits from java.security.Key, which itself inherits from Serializable. So the key here (no pun intended) is to serialize the key into a ByteArrayOutputStream, get the byte[] array and store it into the db. The reverse process would be to get the byte[] array off the db, create a ByteArrayInputStream offf the byte[] array, and deserialize the SecretKey off it...
... or even simpler, just use the
.getEncoded()
method inherited from java.security.Key (which is a parent interface of SecretKey). This method returns the encoded byte[] array off Key/SecretKey, which you can store or retrieve from the database.This is all assuming your SecretKey implementation supports encoding. Otherwise,
getEncoded()
will return null.edit:
You should look at the Key/SecretKey javadocs (available right at the start of a google page):
http://download.oracle.com/javase/6/docs/api/java/security/Key.html
Or this from CodeRanch (also found with the same google search):
http://www.coderanch.com/t/429127/java/java/Convertion-between-SecretKey-String-or
Converting SecretKeySpec to String and vice-versa: you can use
getEncoded()
method inSecretKeySpec
which will givebyteArray
, from that you can useencodeToString()
to getstring
value ofSecretKeySpec
inBase64
object.While converting
SecretKeySpec
toString
: usedecode()
inBase64
will givebyteArray
, from that you can create instance forSecretKeySpec
with the params as thebyteArray
to reproduce yourSecretKeySpec
.