将密钥转换为string和副本

我正在生成一个密钥,需要将它存储在数据库中,所以我把它转换成一个string,但要从string中取回密钥。 完成这个的可能方法是什么?

我的代码是,

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

我怎样才能从string中取回密钥?

您可以将SecretKey转换为一个字节数组( byte[] ),然后Base64将其编码为一个String 。 要转换回SecretKey ,Base64将解码string,并在SecretKeySpec使用它来重build原始的SecretKey

对于Java 8

SecretKeystring:

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

string到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"); 

对于Java 7和以前版本(包括Android):

注意I:你可以跳过Base64编码/解码部分,只是将byte[]存储在SQLite中。 这就是说,执行Base64编码/解码不是一个昂贵的操作,你可以将string存储在几乎任何数据库中,而没有问题。

注2:早期的Java版本在java.langjava.util包之一中不包含Base64。 然而,可以使用来自Apache Commons Codec , Bouncy Castle或Guava的 编解码器 。

SecretKeystring:

 // 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到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"); 

为了显示创build一些function失败的快感,我写了以下3个函数。

一个创build一个AES密钥,一个编码,一个解码回来。 这三个方法可以与Java 8一起使用(不依赖于内部类或外部依赖):

 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; } 

你不想使用.toString()

注意,SecretKeyinheritance自java.security.Key,它本身从Serializableinheritance。 所以这里的关键(没有双关语意图)是序列化到ByteArrayOutputStream的密钥,获取byte []数组,并将其存储到数据库。 相反的过程是从数据库中获取byte []数组,创buildbyte []数组的ByteArrayInputStream,并将SecretKey反序列化…

…甚至更简单,只需使用inheritance自java.security.Key(这是SecretKey的父接口.getEncoded().getEncoded()方法。 此方法返回编码的byte []数组,可以从数据库中存储或检索Key / SecretKey。

这一切都假设你的SecretKey实现支持编码。 否则, getEncoded()将返回null。

编辑:

你应该看看Key / SecretKey javadocs(可以在google页面的开头find):

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

或从CodeRanch(也发现有相同的谷歌search):

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

实际上路易斯提出的不适合我。 我必须找出另一种方式。 这是对我的帮助。 也可以帮助你。 链接:

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

  2. 编码器信息: https : //docs.oracle.com/javase/8/docs/api/java/util/Base64.Encoder.html

  3. 解码器信息: https : //docs.oracle.com/javase/8/docs/api/java/util/Base64.Decoder.html

代码片段:对于编码:

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

解码:

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

将SecretKeySpec转换为String,反之亦然:您可以在SecretKeySpec使用getEncoded()方法给出byteArray ,您可以使用encodeToString()来获取Base64对象中SecretKeySpec string值。

在将SecretKeySpec转换为String :在Base64使用decode()会给出byteArray ,从中可以创buildSecretKeySpec实例,以params作为byteArray来重现您的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"); 

试试这个,没有Base64(只包含在JDK 1.8中),这个代码也运行在以前的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; }