我在互联网上找到了这个:http://www.code2learn.com/2011/06/encryption-and-decryption-of-data-using.html
基本上,我想做的不是像
那样设置密钥 new byte[] { 'T', 'h', 'e', 'B', 'e', 's', 't',
'S', 'e', 'c', 'r','e', 't', 'K', 'e', 'y' };
我希望它是随机的(但必须是16个字节),并且可以访问它(在屏幕上打印)。还有,有没有办法将其设置为字符串,而不是字节类型?
答案 0 :(得分:6)
强AES密钥长度为16,24或32 字节。如果将键限制为映射到可打印US-ASCII字符的字节,则键将弱于预期,因为其范围有限(大约100位,而不是128倍数百倍)。最好使用十六进制,base-64或base-85等编码将密钥表示为文本;当然,这些陈述会更长。
要创建安全密钥,请使用基于正确播种的加密随机数生成器的KeyGenerator
;如果您没有指定RNG,提供商将选择自己的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);
如果需要,可以使用首选算法和提供程序实例化自己的SecureRandom
实例,并通过init()
方法的重载将其传递给密钥生成器。
有一些关键的派生方法试图减轻基于密码的密钥的弱点,但基于密码的密钥总是更容易预测。
答案 1 :(得分:1)
基本上,我想做的不是像
那样设置密钥
new byte[] { 'T', 'h', 'e', 'B', 'e', 's', 't', 'S', 'e', 'c', 'r','e', 't', 'K', 'e', 'y' };
很好,因为这很糟糕且不安全。这是最糟糕的秘密密钥。密码不是密钥,不应该这样使用。
我希望它是随机的(但必须是16个字节)
您希望它是安全随机的:
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();
}
并可以访问它(在屏幕上打印)。
见上文。
另外,有没有办法将其设置为字符串,而不是字节类型?
嗯,是的,你可以解码上面的十六进制字符串。但最终AES算法需要二进制密钥,二进制明文并将生成二进制输出。 SecretKey
类只不过是字节数组的包装器。
要与字符串进行更多转化,请了解character-encoding和encoding ...