1. 什么是安全的随机数?

在安全应用场景,随机数应该使用安全的随机数。密码学意义上的安全随机数,要求必须保证其不可预测性

2. 怎么得到安全的随机数

可以直接使用真随机数产生器产生的随机数。或者使用真随机数产生器产生的随机数做种子,输入密码学安全的伪随机数产生器产生密码学安全随机数。

非物理真随机数产生器有:

  1. Linux操作系统的/dev/random设备接口
  2. Windows操作系统的CryptGenRandom接口

密码学安全的伪随机数产生器,包括JDK的java.security.SecureRandom等。

本文主要讨论SecureRandom

3. SecureRandom最佳实践

3.1 基本用法

java.security.SecureRandom基本用法:

byte[] values = new byte[128];
SecureRandom random = new SecureRandom();
random.nextBytes(values);

3.2 关于种子的设置

要保证得到安全的随机数,需要使用真随机数产生器产生的随机数做种子。

可能的不当用法

 byte[] salt = new byte[128];
SecureRandom secureRandom = new SecureRandom();
secureRandom.setSeed(System.currentTimeMillis()); //使用系统时间作为种子
secureRandom.nextBytes(salt);

此处指定了当前系统时间作为种子,替代系统默认随机源。如果同一毫秒连续调用,则得到的随机数则是相同的。

小结:不要自己指定种子。应当使用系统随机源。

系统默认的随机源是什么?

这取决于$JAVA_HOME/jre/lib/security/java.security配置中的securerandom.source属性。例如jdk1.8中该配置为:

securerandom.source=file:/dev/random

使用无参构造函数实例化SecureRandom,在大多数系统中,默认的算法是“nativePRNG”,从/dev/random获取随机数。

3.3 熵源不足时阻塞问题

概念回顾

  • "熵值":即是随机值的不确定性度量值。

    "熵源":即是随机数的来源。

    "熵输入":是伪随机数产生器描述从熵源获取的bit串,用来产生种子。

    "种子":即是输入到伪随机数产生器用于初始化的bit串。

问题描述

在Linux系统中,/dev/random是系统提供的安全随机数接口。当通过/dev/random读取随机数的速度可以为产品所接受时,可以直接使用/dev/random读取的随机数。

有时无法满足产品对随机数的使用要求,熵源不足时存在阻塞,会导致得到随机数的速度太慢。

在读取时,/dev/random设备会返回小于熵池噪声总数的随机字节。/dev/random可生成高随机性的公钥或一次性密码本。若熵池空了,对/dev/random的读操作将会被阻塞,直到收集到了足够的环境噪声为止。

解决方法

提高系统随机数产生器产生随机数速度的一种方法:

  • 采用haveged守护进程增加系统熵池熵值以提高/dev/random读取随机数的速度。

4. 小结

  1. SecureRandom的使用可以采用无参构造方法实例化,无需手动设置种子。
  2. 如果出现了熵源不足获取随机数阻塞的问题,再进一步优化即可。
  3. 不是安全场景的随机数,使用Random就好。

SecureRandom的正确使用的更多相关文章

  1. [转]加盐hash保存密码的正确方式

    0x00 背景 大多数的web开发者都会遇到设计用户账号系统的需求.账号系统最重要的一个方面就是如何保护用户的密码.一些大公司的用户数据库泄露事件也时有发生,所以我们必须采取一些措施来保护用户的密码, ...

  2. 如何正确对用户密码进行加密?转自https://blog.csdn.net/zhouyan8603/article/details/80473083

    本文介绍了对密码哈希加密的基础知识,以及什么是正确的加密方式.还介绍了常见的密码破解方法,给出了如何避免密码被破解的思路.相信读者阅读本文后,就会对密码的加密有一个正确的认识,并对密码正确进行加密措施 ...

  3. [No0000132]正确使用密码加盐散列[译]

    如果你是一个 web 开发工程师,可能你已经建立了一个用户账户系统.一个用户账户系统最重要的部分是如何保护密码.用户账户数据库经常被黑,如果你的网站曾经被攻击过,你绝对必须做点什么来保护你的用户的密码 ...

  4. 我的Android进阶之旅------>Android关于HttpsURLConnection一个忽略Https证书是否正确的Https请求工具类

    下面是一个Android HttpsURLConnection忽略Https证书是否正确的Https请求工具类,不需要验证服务器端证书是否正确,也不需要验证服务器证书中的域名是否有效. (PS:建议下 ...

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

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

  6. Git 在团队中的最佳实践--如何正确使用Git Flow

    我们已经从SVN 切换到Git很多年了,现在几乎所有的项目都在使用Github管理, 本篇文章讲一下为什么使用Git, 以及如何在团队中正确使用. Git的优点 Git的优点很多,但是这里只列出我认为 ...

  7. 如何正确使用日志Log

    title: 如何正确使用日志Log date: 2015-01-08 12:54:46 categories: [Python] tags: [Python,log] --- 文章首发地址:http ...

  8. WebAPi之SelfHost自创建证书启动Https疑难解惑及无法正确返回结果

    前言 话说又来需求了,之前对于在SelfHost中需要嵌套页面并操作为非正常需求,这回来正常需求了,客户端现在加了https,老大过来说WebAPi访问不了了,这是什么情况,我去试了试,还真是这个情况 ...

  9. javascript匹配各种括号书写是否正确

    今天在codewars上做了一道题,如下 看上去就是验证三种括号各种嵌套是否正确书写,本来一头雾水,一种括号很容易判断, 但是三种怎么判断! 本人只是个前端菜鸟,,不会什么高深的正则之类的. 于是,在 ...

随机推荐

  1. Django Shell 如何对数据库进行测试

    Django 如何对数据库进行测试 Python manager.py shell Import django django.setup() from my_app.models import * 开 ...

  2. HTTPS 加密原理探究

    由于之前项目中IOS系统建议将http协议换成https协议所以查看相关资料在此记录 HTTPS 通讯过程的基本原理 问:Https是什么? 答: HTTP 协议定义了一套规范,让客户端或浏览器可以和 ...

  3. node.js是用来做什么的

    Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效.(事件驱动:事件触发过程中,进行决策的一种策略,简单说就是跟随当前时间点上出现的事物,调用可用的资源进行解决该事物,使得不 ...

  4. Java学习之集合(Collection接口)

    集合类的由来: 对象用于封装特有数据,对象多了需要存储,如果对象的个数不确定,就使用集合容器进行存储 集合特点: 1.用于存储对象的容器 2.集合长度可变 3.不可以存储基本数据类型 集合体系的顶层C ...

  5. git分布式版本控制系统权威指南学习笔记(四):git reset

    文章目录 git reset目录树重写 git reset 重置 git reset目录树重写 git reset --soft 暂存区工作区不变 git reset --hard git reset ...

  6. 11、testng.xml文件解析

    我们可以从以下几种方式调用testng 用testng.xml ant 命令行 我们本次重点介绍testng.xml,testng.xml 文件来配置测试用例的执行 ,testng.xml 文件可以很 ...

  7. Maven Optional & Exclusions使用区别

    Optional和Exclusions都是用来排除jar包依赖使用的,两者在使用上却是相反. Optional定义后,该依赖只能在本项目中传递,不会传递到引用该项目的父项目中,父项目需要主动引用该依赖 ...

  8. PS--工具类

    1.移动工具 快捷点Vctrl + 点击想要移动的图层.选中后,就可以移动了. 2.选取工具 快捷键M2.1选取后填充颜色:新建图层 选取 右键填充 添加前景色 2.2两块选区选择一个选区后,属性面板 ...

  9. forEach方法

    *forEach() * -这个方法只支持ie8以上的浏览器 * -forEach方法需要一个函数作为参数 * -像这种函数,由我们创建但是不由我们调用,我们称为回调函数 * 数组中由几个元素函数就会 ...

  10. docker一键部署zookeeper

    version: '3.1' services: zoo1: image: zookeeper:3.4.11 restart: always hostname: zoo1 container_name ...