如何在各种编程语言中生成安全的随机数

简介:

生成安全的随机数据指什么?为什么要生成安全的随机数据?之前一些文献中这并没有很好得说明如何生成“安全”的随机数。所以,这里将介绍如何在下面的编程语言中安全地生成随机数。

复制代码
    C/C++

    Java

    .NET

    Node.js

    PHP

    Python

    Ruby
复制代码

需要包含的一般条件

这篇文章的所有方案都必须只从内核的CSPRNG(Cryptographically Secure Pseudo-Random Number Generator,密码安全的伪随机数生成器)中读取,并且失败后立即关闭。用户空间的RNG以及回退到不安全的RNG都是不允许的。所以,根据平台的不同,使用下面的熵源:

复制代码
  Windows:
        RtlGenRandom
Linux: getrandom (如何可用的话) 它的方法是正确的,在播种之前会阻塞,之后不再播种。
/dev/urandom (老的Linux内核) 对于在Linux启动时运行的软件,查询/dev/random,直到它可用。这意味着那时/dev/urandom已经播种了,你可以安全地从/dev/urandom中读取内容了,可以用到你的密码中。不要从/dev/random中读取。 OpenBSD: getentropy() arc4random_buf() 使用ChaCha20加密算法 (不是RC4) 其它类Unix系统 (包括OS X): /dev/urandom
复制代码

这里不考虑依赖于haveged,egd等程序的解决方案。

C/C++中的密码安全随机

最简单和安全的方法是,把libsodium库添加到工程的依赖库中,使用randombytes_buf()函数。

这里查看libsodium是怎样实现这些函数的。PHP团队在其内部的random_bytes函数实现中采用了与此类似的方法。

复制代码
#include "sodium.h"

int foo() {

    char myString[32];

    int myInt;

    

    randombytes_buf(myString, 32);

    /* myString will be a string of 32 random bytes */

    myInt = randombytes_uniform(10);

    /* myInt will be a random number between 0 and 9 */

}
复制代码

如果可以的话就使用libsodium,下面的其它语言也是如此。

 

Java中的密码安全随机

除了使用libsodium(推荐),也可以直接使用Java的SecureRandom类:

SecureRandom csprng = new SecureRandom();

byte[] randomBytes = new byte[32];

csprng.nextBytes(randombytes);

注意:不要在Linux上使用SecureRandom.getInstanceStrong(),不要被名称误导,它等同于读取/dev/random,这个是不安全的。Java8中new SecureRandom()默认读取/dev/urandom,这才是你需要的。

 

.NET(C#)中的密码安全随机

普遍采用的方案是使用System.Security.Cryptography.RNGCryptoServiceProvider,比如:

RandomNumberGenerator csprng = new RNGCryptoServiceProvider();

byte[] rawByteArray = new byte[32];

csprng.getBytes(rawByteArray);

如果你需要生成密码上安全的整数,查看Inferno(一个Stan Drapkin写的.NET密码库)中的CryptoRandom类的实现方法。

 

Node.js中的密码安全随机

不要使用crypto.randomBytes()

var csprng = require("sodium").Random;

var bytes = csprng.randombytes_buf(32);

 

PHP中的密码安全随机

如果你运行的是PHP 7,有一个内置的函数:

$string = random_bytes(32);

$integer = random_int(0, PHP_INT_MAX);

如何你用的还是PHP 5, 获取random_compat,然后同PHP 7一样使用相同的API。

composer require paragonie/random_compat:^2

请使用版本2。版本1会回退到OpenSSL,如果没有其它可用的熵源,它会导致安全问题。然而,一些人为了兼容性,会明确地使用版本1。

如果你在写一个供别人在他们的工程中使用的PHP 5库,将你的composer.json条件字符串设置为^1|^2。相反,如果你在写一个应用程序,将条件字符串设置为^2。

 

Python中的密码安全随机

如果你没有使用libsodium: 如果你需要随机字节,使用os.urandom().

如果你需要其它格式的随机数据,你需要使用random.SystemRandom(),而不是random。

复制代码
import sys

import random

# Random bytes

bytes = os.urandom(32)

csprng = random.SystemRandom()

# Random (probably large) integer

int = csprng.randint(0, sys.maxint)
复制代码

 

Ruby中的密码安全随机

不要使用Ruby的SecureRandom!

与名称无关,它不是最好的CSPRNG。幸运的是,Tony Arcieri(密码专家,Cryptosphere 的设计者,全面的密码应用工程师)给Ruby community提供了一个安全的选择,将libsodium的sysrandom接口移植到了Ruby gem中。

建议:使用Sysrandom代理SecureRandom。

安装sysrandom:

gem install sysrandom

Sysrandom与SecureRandom API兼容。可以通过打补丁来代替SecureRandom。


本文转自 K1two2 博客园博客,原文链接:http://www.cnblogs.com/k1two2/p/5567794.html  ,如需转载请自行联系原作者

相关文章
|
算法 编译器 C语言
C语言学习系列-->【关于随机数的实现】
C语言学习系列-->【关于随机数的实现】
81 0
|
7月前
|
算法 编译器 C语言
你知道C语言中随机数是如何生成的吗~?
你知道C语言中随机数是如何生成的吗~?
|
6月前
|
Python
python之数值计算、math库、随机数
python之数值计算、math库、随机数
|
7月前
|
Python
【Python进阶(六)】——随机数与数组
【Python进阶(六)】——随机数与数组
|
7月前
|
Rust 数据安全/隐私保护
rust每日一库 rand 生成随机数
rust每日一库 rand 生成随机数
179 0
|
存储 算法 编译器
产生一个随机数(伪随机)的一种方法(c语言)
计算机并不能产生真正的随机数,而是将已经编写好的一些无规则排列的数字存储在电脑里,把这些数字划分为若干相等的N份,并为每份加上一个编号,用srand()函数获取这个编号,然后rand()就按顺序获取这些数字,当srand()的参数值固定的时候,rand()获得的数也是固定的,所以一般srand的参数用time(NULL),因为系统的时间一直在变,所以rand()获得的数,也就一直在变,相当于是随机数了。只要用户或第三方不设置随机种子,那么在默认情况下随机种子来自系统时钟。如果想在一个程序中生成随机数序列,需要至多在生成随机数之前设置一次随机种子。
186 0
|
C语言 C++
C语言生成随机数问题
rand()函数是专门用来生成随机数的 rand()返回的是0~RAND_MAX(32767)之间的随机数 rand()函数在头文件stdlib.h中,使用前要导入这个头文件 因为rand默认生成随机数范围是0~32767,这是一段很大的范围,所以我们需要限制随机数范围:rand()%100+1 范围:1~ 100 因为任何一个数字,模100,得到结果的范围是0~99,在加1,范围就是1 ~ 100
10680 0
|
编解码 安全 算法
随机数探秘|如果python不用random怎样生成随机数?
随机数探秘|如果python不用random怎样生成随机数?
534 0
|
Go
Go语言 rand(随机数)包
Go语言 rand(随机数)包
160 0
|
Python
零基础Python教程034期 random随机数开发猜数字游戏
零基础Python教程034期 random随机数开发猜数字游戏
298 0