简体   繁体   English

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

[英]Easy way to store/restore encryption key for decrypting string in java

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 java So Im sorry for posting again but Im not sure If the code is even readable(I'm newbie). 在java所以我很抱歉再次发布但我不确定如果代码甚至可读(我是新手)。

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. 所以这是我今天的“份额”,一些简单的AES键操作的辅助方法。 (Note the dependency on Apache Commons and Codec.) (注意对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");
}

Most Java Key instances are represented as a string of bytes resulting from their getEncoded() method. 大多数Java Key实例表示为由其getEncoded()方法产生的字节字符串。 This is what needs to be stored in order to reconstruct the key later. 这是需要存储以便稍后重建密钥的内容。

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. Java KeyStore可用于以这种方式存储SecretKey对象,当您拥有许多受单个“主”密码保护的密钥时,这很有用。 But for protecting a single key, it doesn't make a lot of sense. 但是为了保护单个密钥,它没有多大意义。

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. 另一种方法是允许用户选择令人难忘的密码,并使用像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. 因此,密码派生的密钥可能比密钥大小所暗示的更容易猜测。


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

I've stored keys in java keystore files. 我已经将密钥存储在java密钥库文件中。 Here's an article that may help you out 这篇文章可以帮到你

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

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. 仅供参考,您看到的输出是默认的toString方法的结果,最后的有趣数字是哈希码。 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不一定能保证为您提供足够的信息来重建原始对象(尽管它适用于某些类)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM