zoukankan      html  css  js  c++  java
  • 关于 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

    ---栖息之鹰(一个外表懒洋洋的内心有激情的程序员) 此博客为笔者原著,转载时请注明出处,谢谢!
  • 相关阅读:
    RHEL因为selinux设置失误,无法重启问题。(centos适用)
    Linux系统忘记管理员密码(CentOS、RHEL、Ubuntu)
    cobbler PXE 安装系统时出现的问题
    虚拟机ping 不通主机,主机可ping 虚拟机解决方法
    CentOS7系统更改网卡名为eth0
    PXE-cobbler 无人值守装机------续
    PXE-cobbler 无人值守装机
    DELL PowerEdge R410系统日志满报错
    matlab添加toolbox失败的解决办法
    vs2017+opencv3.4.0的配置方法
  • 原文地址:https://www.cnblogs.com/roostinghawk/p/8384057.html
Copyright © 2011-2022 走看看