【问题标题】:How to recreate SecureRandom instances and compare them?如何重新创建 SecureRandom 实例并进行比较?
【发布时间】:2014-01-02 11:52:27
【问题描述】:

我正在创建一个像这样的安全随机数:

SecureRandom challange = new SecureRandom();
final byte[] number = new byte[32];
challange.nextBytes(number);

然后像这样将其转换为 Base64(不确定 generateSeed 是否搞砸了):

byte[] secureBytes = challange.generateSeed(32);
byte[] base64secure = Base64.encode(secureBytes);

之后我通过 TCP 套接字发送它并在另一端读取它。

如何从收到的字节中创建一个新的 SecureRandom 实例? 如果它们是相同的数字,我如何比较两个 SecureRandom 实例? (例如,从字节数组中创建的新实例开始时创建的数字)

【问题讨论】:

    标签: java security cryptography


    【解决方案1】:

    我只是对此进行了更多研究,但没有办法做到这一点。 SecureRandom 的重点在于它通过加密安全和播种值来防止它:

    import java.security.SecureRandom;
    
    public class Main{
        public static void main(String[] args){
    
          SecureRandom seedMaker = new SecureRandom();  
          byte[] seed = seedMaker.generateSeed(20);
          SecureRandom r1 = new SecureRandom(seed);
          SecureRandom r2 = new SecureRandom(seed);
    
          byte[] b1 = new byte[4];
          byte[] b2 = new byte[4];
          for (int i=0;i<10;i++) {
            r1.nextBytes(b1);
            r2.nextBytes(b2);
    
            System.out.println(java.util.Arrays.toString(b1)+" == "+java.util.Arrays.toString(b2));
          }
        }
    }
    

    在这里试试:http://www.tryjava8.com/app/snippets/52c56f1de4b00bdc99e8a99c

    您可以立即看到结果不匹配。

    要获得您想要的行为,您只能使用标准的 Random 数字生成器和种子来实现,而使用 SecureRandom 则无法实现。

    【讨论】:

    • 我想这将是依赖于提供者的行为,因为 Javadocs 不要求忽略种子或两个相同的种子不应该产生不一致的输出。另请注意,如果您以System.out.println(java.util.Arrays.equals(b1, b2)); 结尾,您的示例可能更易于阅读。
    • 是的,我想直观地看到差异,但 Arrays.equals 也是一个不错的选择。
    • 您应该使用流密码而不是带有种子的SecureRandom。您的代码将在不同的 java 版本/实现之间中断。我相信甚至有一些实现会忽略种子或只是将其添加到熵池中。我建议在 CTR 模式下使用 AES。
    • 上面的答案是正确的。对于我的问题,使用 IvParameterSpec 而不是 SecureRandom 作为 AES IV 参数对我有用,因为您可以使用字节数组对其进行初始化。
    猜你喜欢
    • 1970-01-01
    • 2021-12-09
    • 2021-09-30
    • 1970-01-01
    • 1970-01-01
    • 2011-05-27
    • 2015-12-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多