Java 为 AES 生成密钥
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20204491/
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
Generate a key for AES
提问by
I found this on the internet: http://www.code2learn.com/2011/06/encryption-and-decryption-of-data-using.html
我在互联网上找到了这个:http: //www.code2learn.com/2011/06/encryption-and-decryption-of-data-using.html
Basicly, what I want to do is instead of having the key set like
基本上,我想要做的是而不是像这样设置键
new byte[] { 'T', 'h', 'e', 'B', 'e', 's', 't',
'S', 'e', 'c', 'r','e', 't', 'K', 'e', 'y' };
I want it to be random(but must be 16 bytes), and to have access to it(print it on the screen). Also, is there a way to set it as a string, instead of byte type?
我希望它是随机的(但必须是 16 个字节),并且可以访问它(在屏幕上打印)。另外,有没有办法将其设置为字符串,而不是字节类型?
采纳答案by erickson
A strong AES key will be 16, 24, or 32 byteslong. If you restrict the key to bytes that map to printable US-ASCII characters, the key will be weaker than expected, because its range is limited (to about 100 bits, rather than 128—many millions of times weaker). It would be better to use an encoding like hexadecimal, base-64 or base-85 to represent the key as text; of course, these representations will be longer.
强 AES 密钥的长度为16、24或 32个字节。如果将密钥限制为映射到可打印 US-ASCII 字符的字节,则密钥将比预期的要弱,因为它的范围是有限的(大约 100 位,而不是 128 位——弱数百万倍)。最好使用十六进制、base-64 或 base-85 等编码将密钥表示为文本;当然,这些表示会更长。
To create a secure key, use a KeyGenerator
that is based on a properly seeded cryptographic random number generator; providers will choose their own RNG if you don't specify one:
要创建安全密钥,请使用KeyGenerator
基于正确种子加密随机数生成器的密钥;如果您不指定,提供者将选择他们自己的 RNG:
KeyGenerator gen = KeyGenerator.getInstance("AES");
gen.init(128); /* 128-bit AES */
SecretKey secret = gen.generateKey();
byte[] binary = secret.getEncoded();
String text = String.format("%032X", new BigInteger(+1, binary));
System.out.println(text);
If you want, you can instantiate your own SecureRandom
instance, using your preferred algorithm and provider, and pass it to the key generator via an overload of the init()
method.
如果需要,您可以SecureRandom
使用首选算法和提供程序实例化您自己的实例,并通过init()
方法的重载将其传递给密钥生成器。
There are key derivation methods that attempt to mitigate the weaknesses of password-based keys, but a password-based key will always be more predictable.
有一些密钥派生方法试图减轻基于密码的密钥的弱点,但基于密码的密钥总是更容易预测。
回答by Maarten Bodewes
Basicly, what I want to do is instead of having the key set like
基本上,我想要做的是而不是像这样设置键
new byte[] { 'T', 'h', 'e', 'B', 'e', 's', 't', 'S', 'e', 'c', 'r','e', 't', 'K', 'e', 'y' };
Good because that is terrible and unsafe. It's the worst secret key. Passwords are not keys and should not be used as such.
很好,因为那很可怕而且不安全。这是最糟糕的秘钥。密码不是密钥,不应如此使用。
I want it to be random(but must be 16 bytes)
我希望它是随机的(但必须是 16 个字节)
You want it to be secure random:
你希望它是安全的随机:
public static void main(final String ... args) throws Exception {
final SecureRandom prng = new SecureRandom();
final byte[] aes128KeyData = new byte[128 / Byte.SIZE];
prng.nextBytes(aes128KeyData);
final SecretKey aesKey = new SecretKeySpec(aes128KeyData, "AES");
System.out.println(toHex(aesKey.getEncoded()));
}
private static String toHex(final byte[] data) {
final StringBuilder sb = new StringBuilder(data.length * 2);
for (final byte b : data) {
sb.append(String.format("%02X", b));
}
return sb.toString();
}
and to have access to it(print it on the screen).
并有权访问它(将其打印在屏幕上)。
See above.
看上面。
Also, is there a way to set it as a string, instead of byte type?
另外,有没有办法将其设置为字符串,而不是字节类型?
Well, yes, you can decode the above hexadecimal string. But in the end the AES algorithm requires a binary key, binary plaintext and will generate binary output. The SecretKey
class is little more than a wrapper around the byte array.
嗯,是的,你可以解码上面的十六进制字符串。但最终 AES 算法需要一个二进制密钥,二进制明文,并将生成二进制输出。该SecretKey
班是多一点的字节数组周围的包装。
To do more conversions to and from strings, learn about character-encodingand encoding...