草庐IT

java - java.util.Random 和 java.security.SecureRandom 之间的区别

coder 2023-04-26 原文

我的团队收到了一些生成随机 token 的服务器端代码(Java 中),我对此有疑问 -

这些 token 的用途相当敏感 - 用于 session ID、密码重置链接等。因此它们确实需要加密随机以避免有人猜测它们或暴力破解它们是可行的。 token 是“长”的,所以它是 64 位长。

代码当前使用 java.util.Random 类来生成这些标记。 documentation对于 java.util.Random 明确指出以下内容:

Instances of java.util.Random are not cryptographically secure. Consider instead using SecureRandom to get a cryptographically secure pseudo-random number generator for use by security-sensitive applications.

但是,代码当前使用 java.util.Random 的方式是这样的 - 它实例化 java.security.SecureRandom 类,然后使用 SecureRandom.nextLong() 方法获取用于实例化 java.util.Random 类的种子。然后它使用 java.util.Random.nextLong() 方法生成 token 。

所以我现在的问题 - 考虑到 java.util.Random 正在使用 java.security.SecureRandom 播种,它仍然不安全吗?我是否需要修改代码以便它专门使用 java.security.SecureRandom 来生成 token ?

目前代码种子是 Random 在启动时一次

最佳答案

标准的 Oracle JDK 7 实现使用所谓的线性同余生成器在 java.util.Random 中生成随机值。

取自 java.util.Random 源代码 (JDK 7u2),来自对方法 protected int next(int bits) 的注释,该方法是生成随机值:

This is a linear congruential pseudorandom number generator, as defined by D. H. Lehmer and described by Donald E. Knuth in The Art of Computer Programming, Volume 3: Seminumerical Algorithms, section 3.2.1.

线性同余生成器的可预测性

Hugo Krawczyk 写了一篇关于如何预测这些 LCG 的非常好的论文(“如何预测同余生成器”)。如果您幸运且感兴趣,您仍然可以在网络上找到它的免费、可下载版本。还有大量研究清楚地表明,您应该永远不要将 LCG 用于安全关键目的。这也意味着您的随机数现在可预测的,这是您不希望 session ID 等的东西。

如何破坏线性同余生成器

攻击者必须等待 LCG 在一个完整周期后重复的假设是错误的。即使使用最佳循环(其递推关系中的模数 m),也很容易在比完整循环更短的时间内预测 future 值。毕竟,这只是一堆需要求解的模方程,只要你观察到足够多的 LCG 输出值,就变得容易了。

“更好”的种子不会提高安全性。如果您使用 SecureRandom 生成的随机值作为种子,或者甚至通过掷骰子数次来产生该值,这根本无关紧要。

攻击者将简单地根据观察到的输出值计算种子。在 java.util.Random 的情况下,这比 2^48 花费的时间明显少。不信的人可以试试这个experiment ,其中表明您可以预测 future 的 Random 输出,在大约 2^16 的时间内仅观察两个(!)输出值。现在,在现代计算机上预测随机数的输出甚至不需要一秒钟。

结论

替换您当前的代码。仅使用 SecureRandom。那么至少你会有一点保证,结果是很难预测的。如果您想要加密安全 PRNG 的属性(在您的情况下,这就是您想要的),那么您只需要使用 SecureRandom。聪明地改变它应该使用的方式几乎总是会导致一些不太安全的东西......

关于java - java.util.Random 和 java.security.SecureRandom 之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11051205/

有关java - java.util.Random 和 java.security.SecureRandom 之间的区别的更多相关文章

  1. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  2. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  3. ruby - 为什么 SecureRandom.uuid 创建一个唯一的字符串? - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?

  4. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  5. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  6. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  7. ruby-on-rails - `a ||= b` 和 `a = b if a.nil 之间的区别? - 2

    我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行

  8. ruby - 这两个 Ruby 类初始化定义有什么区别? - 2

    我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是

  9. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  10. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

随机推荐