查到一般的写法是 利用了 SecureRandom
private static SecretKeySpec getSecretKey(final String key) { //返回生成指定算法密钥生成器的 KeyGenerator 对象 KeyGenerator kg = null;
try {
kg = KeyGenerator.getInstance(KEY_ALGORITHM);
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(key.getBytes("utf-8"));
kg.init(256, secureRandom);
//生成一个密钥
SecretKey secretKey = kg.generateKey();
// 转换为 AES 专用密钥
return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);
} catch (NoSuchAlgorithmException | UnsupportedEncodingException ex) {
Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
不使用 SecureRandom 也能一句话默认生成 128 长度的
return new SecretKeySpec(key.getBytes("ASCII"), KEY_ALGORITHM);
1
BrettD 2020-11-09 14:50:49 +08:00 via iPhone 1
用安全随机数生成器生成的随机密钥好一些
|
2
rqxiao OP 就是想请问下
AES 256 生成秘钥的时候 不使用 SecureRandom 可以吗,写法是什么样的 还有 SecureRandom 这种写法其实用过 ,但是也不知道为什么每次加密解密都是都是利用 SecureRandom 生成的 key,但是实际上这个 key 并不是“随机的”,加密解密其实都是用同一个 key |
3
wakzz 2020-11-09 15:11:26 +08:00 1
@rqxiao
``` SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); secureRandom.setSeed(key.getBytes("utf-8")); ``` 这两行的含义是通过用户指定的种子生成一个安全秘钥,同一个种子多次调用当然生成的都是同一个安全秘钥。你也可以自己随机生成一个加密秘钥,只需要秘钥的比特长度没错就行。 |
4
GM 2020-11-09 15:25:40 +08:00 1
当然可以,秘钥就是一串随机 byte[]数组而已,用任何方法都可以生成。但是用这个很明显安全性更好啊。
|
5
jim9606 2020-11-09 15:49:49 +08:00 1
之所以要用 SecureRandom 是因为你需要避免你使用的密钥被预测出来。
常规的伪随机数生成器( PRNG ),例如线性同余 PRNG,生成的内容是可以被预测的(就是说,攻击者可以根据生成器已经生成的随机数推测之后的随机数),而你可能在其他非保密应用中使用过 PRNG 导致攻击者可以获悉以前产生的随机数。因此,密码系统生成随机数应该使用这种不可被预测的密码学安全伪随机数生成器( CSPRNG ) |
6
LLaMA2 2020-11-09 16:03:30 +08:00
可以工作,但不合规,上次有个对接的,由于他的代码和 Android 不兼容,结果没得办法,直接 secretKey.getEncoded()写死
|
7
imdong 2020-11-09 16:24:12 +08:00
记得 Win 下 Putty 的 Keygen 是在生成时要求用户随机移动鼠标或按键来获取随机数种子。
|
8
sunxiansong 2020-11-09 18:10:28 +08:00
补充个例子:生成登陆 token,一般来说主要的需求是 token 唯一,那么是不是可以用 uuid,答案是不行,因为容易被预测,降低碰撞难度。你先用正常账号登陆,拿到 token,从这个 uuid 往后碰,难度不大,碰对了就能登上其他人的账号。
|
9
Jrue0011 2020-11-10 10:20:34 +08:00
@rqxiao 第一个方法最终生成的 SecretKeySpec 相同的原因是传入了相同的参数 key(String)并使用这个 key.getBytes("utf-8")得到的相同 byte[]作为随机数种子。
直接调用 kg.init(256)的话内部会使用一个没有传入随机数种子的 SecureRandom 。 |
10
kahlkn 2020-11-10 13:54:01 +08:00
话说每次生成密钥时都要调用 “SecureRandom.getInstance("SHA1PRNG");” 来创建一个 SecureRandom 对象真的好吗?据我所知 SecureRandom 的创建应该是 比较耗费性能的,所以一般的用途也是 创建完之后静态化持有,然后 init 的时候传进去( JDK 底层就是用一个类来静态持有)。
所以由此解决了你的问题,可以不使用 SecureRandom 生成,不使用会有一个默认的 SecureRandom 来替代的。 |