Convert secret key to string and vice versa

I create a key and must store it in the database, so I convert it to a string, but return the key from the string. What are the possible ways to achieve this?

My code

SecretKey key = KeyGenerator.getInstance("AES").generateKey(); String stringKey=key.toString(); System.out.println(stringKey); 

How can I return a key from a string?

+59
java string encryption
Mar 18 2018-11-18T00:
source share
6 answers

You can convert SecretKey to an array of bytes ( byte[] ), and Base64 to String . To convert back to SecretKey , Base64 decodes the string and uses it in SecretKeySpec to restore the original SecretKey .

For Java 8

SecretKey to String:

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

String in SecretKey:

 // decode the base64 encoded string byte[] decodedKey = Base64.getDecoder().decode(encodedKey); // rebuild key using SecretKeySpec SecretKey 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 save the byte[] in SQLite. However, performing Base64 encoding / decoding is not an expensive operation, and you can store strings in almost any database without any problems.

NOTE II: Early versions of Java do not include Base64 in one of the java.lang or java.util packages. However, you can 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 in 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"); 
+167
Aug 20 2018-12-12T00:
source share

To show how interesting it is to create some functions that quickly crash, I wrote the following 3 functions.

One creates an AES key, one encodes it and one decodes. These three methods can be used with Java 8 (regardless of internal classes or external 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; } 
+4
Dec 21 '14 at 23:07
source share

You do not want to use .toString() .

Note that SecretKey inherits from java.security.Key, which itself inherits Serializable. So, the key here (not a pun) is to serialize the key in ByteArrayOutputStream, get the byte [] array and save it in db. The reverse process would be to get the byte [] array from db, create a ByteArrayInputStream from the byte [] array, and deserialize the SecretKey from it ...

... or even simpler, just use the .getEncoded() method inherited from java.security.Key (which is the SecretKey parent interface). This method returns a byte [] encoded array from Key / SecretKey, which you can save or retrieve from the database.

All of this suggests that the SecretKey implementation supports coding. Otherwise, getEncoded() will return null.

Edit

You should look at javadocs Key / SecretKey (available right at the top of google page):

http://download.oracle.com/javase/6/docs/api/java/security/Key.html

Or this is from CodeRanch (also found with the same google search):

http://www.coderanch.com/t/429127/java/java/Convertion-between-SecretKey-String-or

+1
Mar 18 '11 at 17:19
source share

In fact, what Louis suggested did not help me. I had to figure out another way. It helped me. I can help you. References:

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"); 
0
Nov 30 '14 at 7:17
source share

Converting SecretKeySpec to string and vice versa: you can use the getEncoded() method in SecretKeySpec , which will give a byteArray from which you can use encodeToString() to get the string value of SecretKeySpec in a Base64 object.

When converting SecretKeySpec to string : using decode() in Base64 will give a byteArray from which you can create an instance for SecretKeySpec with parameters like byteArray to play SecretKeySpec .

 String mAesKey_string; SecretKeySpec mAesKey= new SecretKeySpec(secretKey.getEncoded(), "AES"); //SecretKeySpec to String byte[] byteaes=mAesKey.getEncoded(); mAesKey_string=Base64.encodeToString(byteaes,Base64.NO_WRAP); //String to SecretKeySpec byte[] aesByte = Base64.decode(mAesKey_string, Base64.NO_WRAP); mAesKey= new SecretKeySpec(aesByte, "AES"); 
0
Apr 01 '16 at 13:36
source share

try this, it works without Base64 (which is only included in JDK 1.8), this code also runs in a previous version of java :)

 private static String SK = "Secret Key in HEX"; // To Encrupt public static String encrypt( String Message ) throws Exception{ byte[] KeyByte = hexStringToByteArray( SK); SecretKey k = new SecretKeySpec(KeyByte, 0, KeyByte.length, "DES"); Cipher c = Cipher.getInstance("DES","SunJCE"); c.init(1, k); byte mes_encrypted[] = cipher.doFinal(Message.getBytes()); String MessageEncrypted = byteArrayToHexString(mes_encrypted); return MessageEncrypted; } // To Decrypt public static String decrypt( String MessageEncrypted )throws Exception{ byte[] KeyByte = hexStringToByteArray( SK ); SecretKey k = new SecretKeySpec(KeyByte, 0, KeyByte.length, "DES"); Cipher dcr = Cipher.getInstance("DES","SunJCE"); dc.init(Cipher.DECRYPT_MODE, k); byte[] MesByte = hexStringToByteArray( MessageEncrypted ); byte mes_decrypted[] = dcipher.doFinal( MesByte ); String MessageDecrypeted = new String(mes_decrypted); return MessageDecrypeted; } public static String byteArrayToHexString(byte bytes[]){ StringBuffer hexDump = new StringBuffer(); for(int i = 0; i < bytes.length; i++){ if(bytes[i] < 0) { hexDump.append(getDoubleHexValue(Integer.toHexString(256 - Math.abs(bytes[i]))).toUpperCase()); }else { hexDump.append(getDoubleHexValue(Integer.toHexString(bytes[i])).toUpperCase()); } return hexDump.toString(); } public static byte[] hexStringToByteArray(String s) { int len = s.length(); byte[] data = new byte[len / 2]; for (int i = 0; i < len; i += 2) { data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16)); } return data; } 
-one
Mar 17 '17 at 16:14
source share



All Articles