一文详解安全随机数

这篇具有很好参考价值的文章主要介绍了一文详解安全随机数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文分享自华为云社区《【安全攻防】深入浅出实战系列专题-安全随机数》,作者: MDKing 。

随机数的使用场景

使用随机数可分类安全场景跟非安全场景。非安全场景需要生成的越快越好。安全场景使用的随机数必须足够安全,保证不能被预测到。

常见的非安全场景:

  • 数据的索引号、标识;

  • 文件的名称或目录;

  • UUID、用户ID、随机填充字节;

常见安全场景包括但不限于以下场景:

  • 用于密码算法用途,如生成IV、盐值、密钥等;

  • 会话标识(sessionId)的生成;

  • 挑战算法中的随机数生成;

  • 验证码的随机数生成;

密码学意义上的安全随机数

安全场景下使用的随机数必须是密码学意义上的安全随机数。

密码学意义上的安全随机数分为两类:
  • 真随机数产生器产生的随机数;

  • 以真随机数产生器产生的少量随机数作为种子的密码学安全的伪随机数产生器产生的大量随机数。

已知的可供产品使用的密码学安全的非物理真随机数产生器有:

  • Linux操作系统的/dev/random设备接口(存在阻塞问题)

  • Windows操作系统的 CryptGenRandom() 接口

我们可以看到,密码学意义上的安全随机数非指必须都为真随机数生成器生成,因为真随机数生成器产生随机数是需要资源(熵)消耗的,当资源不足时会阻塞。所以在业务使用随机数频次较低的时候可以考虑全部使用真随机数。在业务使用随机数的频次高、数量大时就必须使用兼顾安全跟效率的方式:使用伪随机数生成器作为主体生成器进行随机数生成,使用真随机数周期为其设置种子(seed)。

SecureRandom对象的生成随机数有两类方法:生成下一个随机数的方法,比如nextInt、nextBytes等;生成种子的方法,如generateSeed。

使用new SecureRandom()创建的对象的nextXXX、generateSeed方法在linux系统下随机数来源均为/dev/urandom,生成的随机数都是不安全随机数。

使用SecureRandom.getInstance("SHA1PRNG", "SUN")创建的对象nextXXX生成的为不安全的随机数,generateSeed生成的为安全随机数(linux下来源为/dev/random),所以使用SHA1PRNG算法合理设置好周期补种的逻辑理论上是可行的。但是根据公司密码算法相关要求,从2023年开始将禁止使用SHA1PRNG算法生成安全随机数。

常用推荐的安全随机数用法

大的原则上不建议自己实现补种、刷新熵源等逻辑,最好直接使用JDK封装好的方法。

密码学安全的随机数用法主要有3种:

1. SecureRandom.getInstance("NativePRNGBlocking")

参数要配置NativePRNGBlocking,好处是非常安全,因为nextXXX、generateSeed方法都是生成的真随机数,缺点是因为每次都是真随机数,性能较低,会有阻塞性问题。常见几个参数的对比如下:

参数取值 说明 nextXXX的随机数源 generateSeed的随机数源 随机数质量 是否阻塞(没实际验证,读者自酌)
SHA1PRNG
通过系统属性和java.security的熵收集设备完成随机数生成器的初始播种。完成初始播种后,不再依赖熵收集设备 NA NA 不安全 不阻塞
NativePRNG
完成初始播种后,仍然要从系统的熵收集设备获取随机数,这就是Native的含义。nextBytes()从/dev/urandom设备获取随机数, generateSeed()从/dev/random获取随机数。 /dev/urandom /dev/random 较安全 取随机数不阻塞,取种可能阻塞
NativePRNGBlocking
nextBytes()和generateSeed()均从/dev/random获取随机数 /dev/random /dev/random 最安全 很可能阻塞
NativePRNGNonBlocking
nextBytes()和generateSeed()均从/dev/urandom获取随机数 /dev/urandom /dev/urandom 不安全 不阻塞

2. SecureRandom.getInstanceStrong()

在JDK 8中引入,主要解决getInstance在应用某些参数时不能保证取到的随机数质量足够安全的问题,简化编程。它返回每个平台上可用的最强SecureRandom实现的实例。它会调用系统上可用的最强算法,该算法由$JAVA_HOME/jre/lib/security/java.security中的securerandom.strongAlgorithms来指定。

securerandom.strongAlgorithms的默认配置一般为NativePRNGBlocking:SUN,在这种设定下 getInstanceStrong()与getInstance("NativePRNGBlocking")等效。

3. SecureRandom.getInstance("DRBG",...)

从JDK 9开始,新增了由Sun提供的符合NIST SP 800 90-A标准的DRBG伪随机数产生器,包括HASH-DRBG、HMAC-DRBG、CTR-DRBG三种,且适用于各种OS,符合公司密码算法相关要求,在使用JDK 9
及以上版本时,推荐优先使用该方式生成安全随机数。该方式生成随机数是兼顾安全跟效率周期补种真随机数方式的封装,所以在高频生成安全随机数的场景中可以使用该方式。

推荐写法可参考编程规范:

小结一下:

低频使用安全随机数的业务场景(对性能没有要求)可以使用SecureRandom.getInstance("NativePRNGBlocking")或者SecureRandom.getInstanceStrong()方式;

高频使用安全随机数的业务场景(对性能有要求)只能使用SecureRandom.getInstance("DRBG",...)方式;

上述方式都不能满足业务场景需求时,再考虑自己实现补种、补熵等逻辑(不推荐、一般也不会有)。

实战验证

我们使用SHA1PRNG类型的随机数生成器,验证设置同样的种子seed后,是否能产生同样的随机数序列。

执行结果如下:可以看到,不管重复执行多少次,只要初始设置的种子相同,后面的序列一定是相同、且固定的。

 文章来源地址https://www.toymoban.com/news/detail-749256.html

所以如果使用了不安全的随机数生成器实现的代码逻辑,一旦攻击者掌握了一定数量的随机数序列,就有可能推测出初始种子,从而完全预测到后续生成的随机数序列的具体内容。

如果使用真随机数设置种子(当前写法仅为示例,并非推荐写法)

可以看到,每次执行都有随机性,由于设置的seed是通过真随机数生成器生成的,所以不可预测。

 

有同学肯定好奇,真随机数生成器的速度真的有那么慢吗?我们实际验证下,使用真随机数生成器、伪随机数生成器的性能对比如下:

点击关注,第一时间了解华为云新鲜技术~

 

到了这里,关于一文详解安全随机数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用java.security.SecureRandom安全生成随机数和随机字符串工具类

            在Java中,可以使用java.security.SecureRandom和java.util.Random类来生成随机数,但是它们之间有以下区别:         1、随机性强度: SecureRandom 类提供了更高的随机性强度。它使用了更安全的算法和种子生成器,以提供更高质量的随机数。这对于需要高度安全性的应用程

    2024年04月26日
    浏览(32)
  • 解决Fortify漏洞:Insecure Randomness(不安全随机数)

           Fortify漏洞:Insecure Randomness(不安全随机数)指的是代码中使用了不安全或弱随机数生成器导致的安全漏洞。随机数在密码学应用、加密和解密等领域中经常被使用,如果生成的随机数不够随机或不够复杂,则会使得攻击者可以轻易地猜出生成的随机数,从而对系统

    2024年02月10日
    浏览(40)
  • 【Java代码审计】失效认证及不安全随机数篇

    根据密码学原理,随机数生成器分为以下三类: 1、统计学伪随机数生成器(PRNG):伪随机数生成器从一个初始化的种子值开始计算得到序列,从种子开始,然后从种子中计算出后续值,当种子确定后生成的随机数也是确定的,但其输出结果很容易预测,因此容易复制数值流

    2024年01月16日
    浏览(30)
  • SM2签名算法中随机数K的随机性对算法安全的影响

            一、构造如下SM2签名算法过程1         Sig1 r1 =         F2BFC778C66127C74E3613FAA1AB6E207059740B317597A78BBFCDF58AED0A51         Sig1 s1 = 4FC719D00334CCC23098036DEEAA71DB464A076EFA79283389D3414D70659E88         私钥d = B3124DC843BB8BA61F035A7D0938251F5DD4CBFC96F5453B130D890A1CDBAE32         公钥

    2024年02月03日
    浏览(43)
  • rand()函数与srand()函数以及随机数种子详解

    初学者大部分对这两个函数的意义都不甚了解,以及不明白为什么需要srand()函数来播种,这里会对两函数的意义进行解释,让大家明白两函数搭配的作用,并对伪随机数以及真随机数进行讲解,最后会对随机数生成的原理进行一些探讨,希望对大家的学习理解有所帮助 格式

    2024年01月25日
    浏览(37)
  • Java随机数之System/Random/SecureRandom详解

    本系列为:从零开始学Java,为千锋教育资深Java教学老师独家创作 致力于为大家讲解清晰Java学习相关知识点,含有丰富的代码案例及讲解。如果感觉对大家有帮助的话,可以【点个关注】持续追更~ 文末有本文重点总结!关于技术类问题,也欢迎大家和我们沟通交流! 我们在

    2024年02月06日
    浏览(47)
  • C语言随机数生成和范围设置详解【超详细教程】

    本文详细介绍了C语言中如何使用rand函数生成随机数以及利用srand函数设置随机数的种子,同时解释了如何控制随机数的范围。适合初学者学习和实践。

    2024年02月05日
    浏览(37)
  • 【C++】详解用标准库的std::mt19937生成随机数

    2023年8月16日,周三晚上 写了1个半小时 目录 概述 英文文档 什么是mt19937 什么是状态大小 头文件 std::mt19937的常用成员函数 1. 构造函数: 2. 种子操作函数: 3. 随机数生成函数: 4. 辅助函数: 生成种子值 方法1:使用std::random_device 方法2:使用时间戳 举例说明 英文文档 std:

    2024年01月17日
    浏览(32)
  • 【安全密钥】对基尔霍夫-洛-约翰逊噪声(KLJN)安全密钥交换协议的统计随机数生成器攻击(Matlab代码实现)

    💥💥💞💞 欢迎来到本博客 ❤️❤️💥💥 🏆博主优势: 🌞🌞🌞 博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️ 座右铭: 行百里者,半于九十。 📋📋📋 本文目录如下: 🎁🎁🎁 目录 💥1 概述 📚2 运行结果 🎉3 参考文献 🌈4 Matlab代码、数据、文章

    2024年04月12日
    浏览(43)
  • 【区块链 | 预言机】从零开始使用Chainlink预言机(2)- 智能合约中使用更安全的随机数-代码实战

    Chainlink最近推出一款革命性的产品,VRF—Verifiable Random Function可验证随机数,给智能合约带来了真正安全的随机数。本文我们就来介绍一下如何在智能合约中使用VRF吧。 我们先简要介绍一下Chainlink VFR的工作流程。 首先,智能合约应用,也就是我们的Dapp,需要先发起一个获取

    2024年02月02日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包