在java中存储/恢复用于解密字符串的加密密钥的简单方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1925104/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Easy way to store/restore encryption key for decrypting string in java
提问by dave91
For encryption I use something like this:
对于加密,我使用这样的东西:
SecretKey aesKey = KeyGenerator.getInstance("AES").generateKey();
StringEncrypter aesEncrypt = new StringEncrypter(aesKey, aesKey.getAlgorithm());
String aesEncrypted= aesEncrypt.encrypt(StringContent);
If I print out aesKey I get: "javax.crypto.spec.SecretKeySpec@1708d".
如果我打印出 aesKey,我会得到:“javax.crypto.spec.SecretKeySpec@1708d”。
So for encryption I would like to ask user for key but dont know how and what format should it be. My plan was something like this:
所以对于加密,我想向用户询问密钥,但不知道它应该是什么格式和什么格式。我的计划是这样的:
SecretKey aesKey = javax.crypto.spec.SecretKeySpec@1708d;
StringEncrypter aesEncrypt = new StringEncrypter(aesKey, aesKey.getAlgorithm());
String aesDecrypt = aesEncrypt.decrypt(aesEncrypted);
But seems its not working. Is there some easy way to print out the key after encryption to console so user can save it(or remember it) and then Use for Decryption ?
但似乎它不起作用。是否有一些简单的方法可以在加密后将密钥打印到控制台,以便用户可以保存(或记住它)然后用于解密?
Whole code is here:Cannot decrypt cyphertext from text file, symmetric key implement. in javaSo Im sorry for posting again but Im not sure If the code is even readable(I'm newbie).
完整代码在这里:无法从文本文件中解密密文,对称密钥工具。在java中所以我很抱歉再次发布但我不确定代码是否可读(我是新手)。
回答by BillMan
I've stored keys in java keystore files. Here's an article that may help you out
我已经将密钥存储在 java 密钥库文件中。这里有一篇文章可以帮到你
http://www.informit.com/articles/article.aspx?p=170967&seqNum=3
http://www.informit.com/articles/article.aspx?p=170967&seqNum=3
回答by Dan
Just for reference, the output you're seeing is the result of the default toString
method and the funny number on the end is a hash code. See here. Hash codes are by design not reversible, and toString
is not necessarily guaranteed to give you enough information to reconstruct the original object (although it does for certain classes).
仅供参考,您看到的输出是默认toString
方法的结果,最后的有趣数字是哈希码。见这里。散列码在设计上是不可逆的,并且toString
不一定保证为您提供足够的信息来重建原始对象(尽管它对某些类有作用)。
回答by erickson
Most Java Key
instances are represented as a string of bytes resulting from their getEncoded()
method. This is what needs to be stored in order to reconstruct the key later.
大多数 JavaKey
实例都表示为由它们的getEncoded()
方法产生的字节字符串。这是需要存储以便稍后重建密钥的内容。
However, to store a key safely in electronic form, it should be encrypted. Of course, encrypting the key would require another key (or password)… and so you have an infinite regress. A Java KeyStore
can be used to store SecretKey
objects in this manner, and that is useful when you have many secret keys that are all protected by a single "master" password. But for protecting a single key, it doesn't make a lot of sense.
但是,为了以电子形式安全地存储密钥,应该对其进行加密。当然,加密密钥需要另一个密钥(或密码)……所以你有一个无限的回归。JavaKeyStore
可用于以SecretKey
这种方式存储对象,当您有许多密钥都由一个“主”密码保护时,这很有用。但是对于保护单个密钥来说,它没有多大意义。
One alternative is to present the key to the user in a form that can be stored in some safe manner (in many applications, that might be on a slip of paper in their wallet). This could be as simple as displaying the bytes of the key encoded in hexadecimal, Base-64, or other text encoding, and asking the user to write it down.
一种替代方法是以可以以某种安全方式存储的形式(在许多应用程序中,可能在他们钱包中的纸条上)向用户展示密钥。这可以很简单,例如显示以十六进制、Base-64 或其他文本编码方式编码的密钥字节,并要求用户将其写下来。
Another approach is to allow the user to choose a memorable password, and generate a key with that, using an algorithm like PBKDF2. The salt (and maybe the iteration count) used for key derivation would need to be recorded somewhere though. Another drawback is that people tend to choose from a relatively limited number of passwords out of the total available. So keys derived from passwords may be easier guess than than the key size suggests.
另一种方法是允许用户选择一个令人难忘的密码,并使用 PBKDF2 之类的算法生成一个密钥。用于密钥派生的盐(可能还有迭代计数)需要记录在某处。另一个缺点是人们倾向于从可用密码总数中选择相对有限的密码。因此,从密码派生的密钥可能比密钥大小建议的更容易猜测。
Here is an illustration of the basic technique for persisting and reconstituting a secret key.
这是用于持久化和重构密钥的基本技术的说明。
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");
回答by Stu Thompson
I've had to do this myself recently. And while the other answers here led me in the right direction, it could have been easier. So here is my "share" for the day, a couple of helper methods for simple AES key manipulation. (Note the dependency on Apache Commons and Codec.)
我最近不得不自己做这件事。虽然这里的其他答案使我朝着正确的方向前进,但它本来可以更容易。所以这是我今天的“分享”,一些用于简单 AES 密钥操作的辅助方法。 (注意对 Apache Commons 和 Codec 的依赖。)
This is all in a git repo now: github.com/stuinzuri/SimpleJavaKeyStore
现在这一切都在一个 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");
}