• 关于 java中的SecureRandom在linux中每次生成不同结果


    使用AES算法的时候,会发现下面的代码在windows每次产生确定的结果,但Linux就不同,导致无法正确解密

    public static String encrypt(String content, String password) {
        try {
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            kgen.init(128, new SecureRandom(password.getBytes()));
            SecretKey secretKey = kgen.generateKey();
            byte[] enCodeFormat = secretKey.getEncoded();
            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
            Cipher cipher = Cipher.getInstance("AES");// 创建密码器
            byte[] byteContent = content.getBytes("utf-8");
            cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
            byte[] result = cipher.doFinal(byteContent);
    
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            random.setSeed(password.getBytes());
            kgen.init(128, random);
    
            return parseByte2HexStr(result); // 加密
        } catch (Exception e) {
            System.out.print(e);
        }
        return null;
    }

    原因在于加红的部分SecureRaom的生成,Linux下默认的算法是“NativePRNG”, 而windows下默认是“SHA1PRNG”(sun提供的算法)

    对于这两种算法

    相同点:
      1. 都是伪随即算法,
      2. 默认都是阻塞式
    
    不同点:
      1. SHA1PRNG使用的seed是在系统启动时就指定的,而NativePRNG会在内核中随机取得(这也是Linux下每次结果不同的原因)
      2. 正是因为每次随机取,NativePRNG开销要更大些

     虽然Linux认为最佳随机算法是NativePRNG(安全因素),但使用每次都变化的radom是无法正确解密的,所以并不适用于此种场合。

    解决办法

    SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG" );
    secureRandom.setSeed(password.getBytes());
    kgen.init(128, secureRandom);

    另外,这两种算法都是阻塞式算法,会读取/var/random,如果想非阻塞,启动时加上下面参数

    Djava.security=file:/dev/urandom

    参考:

    http://www.cjsdn.net/Doc/JDK50/java/security/SecureRandom.html

    https://docs.oracle.com/javase/7/docs/api/java/security/SecureRandom.html

    http://calvin1978.blogcn.com/articles/securerandom.html

    https://stackoverflow.com/questions/27622625/securerandom-with-nativeprng-vs-sha1prng

    ---栖息之鹰(一个外表懒洋洋的内心有激情的程序员) 此博客为笔者原著,转载时请注明出处,谢谢!
  • 相关阅读:
    《老男孩》
    java中四种阶乘的计算
    DataOutputStream的乱码问题
    java中飞clone方法
    类反射的简单例子
    PHP: 如何连接oracle数据库进行数据读取
    .NET : 如何读取图片中的元数据信息
    重新审视REST
    PHP 的历史
    Image File Format Specifications {转载}
  • 原文地址:https://www.cnblogs.com/roostinghawk/p/8384057.html
Copyright © 2020-2023  润新知