AES 256 生成秘钥的时候 可以不使用 SecureRandom 的生成的写法吗

2020-11-09 14:38:11 +08:00
 rqxiao

查到一般的写法是 利用了 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);
2512 次点击
所在节点    Java
11 条回复
BrettD
2020-11-09 14:50:49 +08:00
用安全随机数生成器生成的随机密钥好一些
rqxiao
2020-11-09 14:54:24 +08:00
就是想请问下
AES 256 生成秘钥的时候 不使用 SecureRandom 可以吗,写法是什么样的

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

所以由此解决了你的问题,可以不使用 SecureRandom 生成,不使用会有一个默认的 SecureRandom 来替代的。
rqxiao
2020-11-10 14:51:35 +08:00
@Jrue0011 KeyGenerator.init ( 256 )的确是有个默认的 SecureRandom 的,我百度出的一些 aes 加密网站 ,验证下来 128 的时候他们是没有用 SecureRandom,所以就想试下 256 的写法 。不过大家都说 SecureRandom 的确更安全,256 这个也没必要试了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/723205

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX