对于加密,我使用这样的东西:
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);
但似乎不起作用。是否有一些简单的方法可以在加密后将密钥打印到控制台,以便用户可以保存(或记住它)然后用于解密?
整个代码在这里:Cannot decrypt cyphertext from text file, symmetric key implement. in java 所以我很抱歉再次发布,但我不确定如果代码是可读的(我是新手)。
答案 0 :(得分:21)
我最近自己必须这样做。虽然这里的其他答案让我朝着正确的方向前进,但它可能会更容易。所以这是我今天的“份额”,一些简单的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");
}
答案 1 :(得分:14)
大多数Java Key
实例表示为由getEncoded()
方法生成的字节字符串。这是需要存储的内容,以便稍后重建密钥。
但是,要以电子形式安全存储密钥,应加密。当然,加密密钥需要另一个密钥(或密码)......所以你有一个无限的回归。 Java KeyStore
可用于以这种方式存储SecretKey
对象,当您有许多密钥全部受单个“主”密码保护时,这很有用。但是为了保护单个密钥,它没有多大意义。
一种替代方案是以可以某种安全方式存储的形式向用户呈现密钥(在许多应用程序中,可能在其钱包中的纸上)。这可以像显示以十六进制,Base-64或其他文本编码编码的键的字节一样简单,并要求用户将其写下来。
另一种方法是允许用户选择一个令人难忘的密码,并使用像PBKDF2这样的算法生成一个密钥。用于密钥推导的盐(可能是迭代计数)需要在某处记录。另一个缺点是人们倾向于从总数中选择相对有限数量的密码。所以从密码中获得的密钥可能比密钥大小所暗示的更容易猜测。
以下是持久化和重构密钥的基本技术说明。
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");
答案 2 :(得分:4)
我已将密钥存储在java密钥库文件中。这是一篇可以帮助你的文章
http://www.informit.com/articles/article.aspx?p=170967&seqNum=3
答案 3 :(得分:0)
仅供参考,您看到的输出是默认toString
方法的结果,最后的有趣数字是哈希码。见here。哈希代码在设计上是不可逆的,并且toString
不一定能保证为您提供足够的信息来重建原始对象(尽管它适用于某些类)。