存储/恢复加密密钥以便在java中解密字符串的简便方法

对于加密我使用这样的东西:

SecretKey aesKey = KeyGenerator.getInstance("AES").generateKey(); StringEncrypter aesEncrypt = new StringEncrypter(aesKey, aesKey.getAlgorithm()); String aesEncrypted= aesEncrypt.encrypt(StringContent); 

如果我打印出aesKey,我会得到:“javax.crypto.spec.SecretKeySpec@1708d”。

因此,对于加密,我想问用户密钥,但不知道它应该是什么格式。 我的计划是这样的:

 SecretKey aesKey = javax.crypto.spec.SecretKeySpec@1708d; StringEncrypter aesEncrypt = new StringEncrypter(aesKey, aesKey.getAlgorithm()); String aesDecrypt = aesEncrypt.decrypt(aesEncrypted); 

但似乎它不起作用。 是否有一些简单的方法可以在加密后将密钥打印到控制台,以便用户可以保存(或记住它)然后用于解密?

整个代码在这里: 无法解密来自文本文件,对称密钥工具的密文。 在java所以我很抱歉再次发布但我不确定如果代码甚至可读(我是新手)。

我最近自己必须这样做。 虽然这里的其他答案让我朝着正确的方向前进,但它可能会更容易。 所以这是我今天的“份额”,一些简单的AES键操作的辅助方法。 (注意对Apache Commons和Codec的依赖。)

现在全部都在git repo中: github.com/stuinzuri/SimpleJavaKeyStore

 import static org.apache.commons.codec.binary.Hex.*; import static org.apache.commons.io.FileUtils.*; import java.io.*; import java.security.NoSuchAlgorithmException; import javax.crypto.*; import org.apache.commons.codec.DecoderException; public static SecretKey generateKey() throws NoSuchAlgorithmException { KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); keyGenerator.init(256); // 128 default; 192 and 256 also possible return keyGenerator.generateKey(); } public static void saveKey(SecretKey key, File file) throws IOException { char[] hex = encodeHex(key.getEncoded()); writeStringToFile(file, String.valueOf(hex)); } public static SecretKey loadKey(File file) throws IOException { String data = new String(readFileToByteArray(file)); byte[] encoded; try { encoded = decodeHex(data.toCharArray()); } catch (DecoderException e) { e.printStackTrace(); return null; } return new SecretKeySpec(encoded, "AES"); } 

大多数Java Key实例表示为由其getEncoded()方法产生的字节字符串。 这是需要存储以便稍后重建密钥的内容。

但是,要以电子forms安全地存储密钥,应加密。 当然,加密密钥需要另一个密钥(或密码)……所以你有一个无限的回归。 Java KeyStore可用于以这种方式存储SecretKey对象,当您有许多受单个“主”密码保护的密钥时,这很有用。 但是为了保护单个密钥,它没有多大意义。

一种替代方案是以可以以某种安全方式存储的forms向用户呈现密钥(在许多应用中,可能在其钱包中的纸上)。 这可以像显示以hex,Base-64或其他文本编码编码的密钥的字节一样简单,并要求用户将其写下来。

另一种方法是允许用户选择令人难忘的密码,并使用像PBKDF2这样的算法生成密钥。 用于密钥推导的salt(可能是迭代计数)需要在某处记录。 另一个缺点是人们倾向于从总数中选择相对有限数量的密码。 因此,密码派生的密钥可能比密钥大小所暗示的更容易猜测。


以下是持久化和重构密钥的基本技术的说明。

 byte[] encoded = aesKey.getEncoded(); /* Now store "encoded" somewhere. For example, display the key and ask the user to write it down. */ String output = Base64.getEncoder().withoutPadding().encodeToString(encoded); System.out.println("Keep it secret, keep it safe! " + output); ... /* At some point, you need to reconstitute the key. Let's say the user enters it as a base-64 number that you convert to bytes. */ String input = ... ; byte[] encoded = Base64.getDecoder().decode(input); SecretKey aesKey = new SecretKeySpec(encoded, "AES"); 

我已经将密钥存储在java密钥库文件中。 这篇文章可以帮到你

http://www.informit.com/articles/article.aspx?p=170967&seqNum=3

仅供参考,您看到的输出是默认的toString方法的结果,最后的有趣数字是哈希码。 看到这里 。 哈希代码在设计上是不可逆的,并且toString不一定能保证为您提供足够的信息来重建原始对象(尽管它适用于某些类)。