在 OpenSSL 中,随机数生成是一个非常重要的任务,用于生成密码学中的随机数,密钥和初始化向量等。在开发应用程序时,保证随机数的质量和随机性非常关键,因为弱的随机数可能导致密码学的弱点,使得应用程序容易受到攻击。
在 OpenSSL 中,你可以使用以下函数来生成随机数:
一、RAND_bytes() 函数(推荐)
1.1 底层原理
-
系统随机性源: OpenSSL 首先会尝试获取系统提供的真随机数源,通常是操作系统的
/dev/random
或/dev/urandom
(在类 UNIX 系统中),或者是 Windows 的 CryptGenRandom 函数。这些源产生的数据是由系统硬件或操作系统的事件(例如用户的鼠标移动、键盘输入、硬件噪声等)产生的,具有高度的随机性。 -
熵池(Entropy Pool): OpenSSL 会维护一个称为熵池的数据结构,用于存储收集到的随机性源数据。这个熵池包含了足够的随机性数据,可以供 OpenSSL 的伪随机数生成器使用。
-
伪随机数生成器(PRNG): OpenSSL 使用一个伪随机数生成器(通常是一个加密安全的伪随机数生成器)来从熵池中生成更多的随机数据。这个 PRNG 的输出被
RAND_bytes()
函数返回给调用者。 -
Re-seeding: 如果熵池中的随机性数据用尽,或者达到一定的使用次数,OpenSSL 会重新从系统的随机性源获取新的随机性数据,然后再将它们混合到熵池中,以维持熵池的随机性。
这个函数用于生成随机字节。它需要一个缓冲区和要生成的字节数作为参数。示例用法如下:
1.2 RAND_bytes函数说明
该函数的目的是填充指定长度的缓冲区 buf(以字节为单位),并返回一个表示操作成功与否的值。如果函数成功,它返回 1;如果函数失败,它返回 0。
- **buf:**用于存储生成的随机字节序列的缓冲区的指针。
- **num:**要生成的随机字节数。
unsigned char buffer[16]; // 16字节的缓冲区
RAND_bytes(buffer, sizeof(buffer));
这个函数会生成16个随机字节并存储在 buffer
中。注意!!在使用 RAND_bytes() 函数之前,你应该确保 OpenSSL 库已经被正确初始化。通常,你需要在你的程序开始时调用 RAND_poll() 函数来初始化 OpenSSL 的随机数发生器。
1.3 RAND_bytes代码实例
需要注意的是我们随机数的生成有可能生成\0作为数据,因此如果想使用string进行存储有可能出错,因为string的结束符号以\0进行判断。
- 代码
#include <iostream>
#include <openssl/rand.h>
int main() {
const int numBytes = 16; // 要生成的随机字节数
unsigned char buffer[numBytes];
// 初始化 OpenSSL 的随机数发生器
RAND_poll();
// 生成随机数
int success = RAND_bytes(buffer, numBytes);
if (success == 1) {
// 打印生成的随机字节序列
std::cout << "Random Bytes: ";
for (int i = 0; i < numBytes; ++i) {
std::cout << std::hex << static_cast<int>(buffer[i]);
}
std::cout << std::endl;
} else {
std::cerr << "Error generating random bytes." << std::endl;
}
return 0;
}
- 编译
g++ -o random_generator random_generator.cpp -lssl -lcrypto
- 运行
./random_generator
二、RAND_pseudo_bytes()`函数
2.1 RAND_pseudo_bytes()函数说明
RAND_pseudo_bytes()
函数是 OpenSSL 库中的一个函数,用于生成伪随机字节序列。与 RAND_bytes()
函数不同,RAND_pseudo_bytes()
并不保证生成的字节序列具有密码学安全性。它使用伪随机数生成器(PRNG)生成随机数据,通常用于不需要密码学安全性的场景。
RAND_pseudo_bytes()
函数的声明如下:
int RAND_pseudo_bytes(unsigned char *buf, int num);
-
buf
:用于存储生成的随机字节序列的缓冲区的指针。 -
num
:要生成的随机字节数。
函数返回值为 1 表示生成成功,为 0 表示失败。
2.2 RAND_pseudo_bytes()代码实例
与 RAND_bytes()
函数不同,RAND_pseudo_bytes()
不依赖于系统提供的真随机数源,而是仅依赖 OpenSSL 内部的伪随机数生成器。因此,它生成的随机数不适用于需要密码学安全性的场景。如果你的应用需要密码学安全的随机数,应该使用 RAND_bytes()
函数。
以下是一个使用 RAND_pseudo_bytes()
函数生成伪随机字节序列的示例代码:
#include <iostream>
#include <openssl/rand.h>
int main() {
const int numBytes = 16; // 要生成的随机字节数
unsigned char buffer[numBytes];
// 生成伪随机数
int success = RAND_pseudo_bytes(buffer, numBytes);
if (success == 1) {
// 打印生成的随机字节序列
std::cout << "Pseudo-Random Bytes: ";
for (int i = 0; i < numBytes; ++i) {
std::cout << std::hex << static_cast<int>(buffer[i]);
}
std::cout << std::endl;
} else {
std::cerr << "Error generating pseudo-random bytes." << std::endl;
}
return 0;
}
g++ -o RAND_pseudo_bytes RAND_pseudo_bytes.cc -lssl -lcrypto
运行
在这个示例中,RAND_pseudo_bytes()
函数用于生成伪随机字节序列,结果存储在 buffer
中。请注意,生成的随机数是以十六进制形式显示的。
三、RAND_seed() 函数
3.1 RAND_seed() 函数说明
RAND_seed()
函数是 OpenSSL 库中的一个函数,用于增加 OpenSSL 随机数发生器的熵(entropy),提高随机性。熵是随机性的度量,可以看作是计算机系统中的随机性源。通过添加额外的随机性数据到 OpenSSL 的随机数发生器,可以增加生成的随机数的质量。
RAND_seed()
函数的声明如下:
void RAND_seed(const void *buf, int num);
-
buf
:包含随机性数据的缓冲区的指针。 -
num
:要添加的随机性数据的字节数。
3.2 RAND_seed() 代码实例
使用 RAND_seed()
函数,你可以提供自定义的随机性数据来增加 OpenSSL 的随机数发生器的熵。这通常用于增加系统随机性源不足的情况,或者在启动时向 OpenSSL 的随机数发生器注入额外的随机性。
以下是一个简单的示例,演示如何使用 RAND_seed()
函数:
#include <openssl/rand.h>
int main() {
unsigned char entropy_data[32]; // 32 字节的自定义随机性数据
// 填充 entropy_data 缓冲区,可以使用系统的随机性源或其他安全随机方法
// ...
// 添加自定义的随机性数据到 OpenSSL 的随机数发生器
RAND_seed(entropy_data, sizeof(entropy_data));
// 现在 OpenSSL 的随机数发生器被增加了额外的随机性数据
return 0;
}
在实际应用中,当系统提供的随机性源不足时,或者为了提高随机数质量,你可以使用 RAND_seed()
函数来添加额外的随机性数据。请确保提供的数据是足够随机的,以确保生成的随机数具有高质量的随机性。文章来源:https://www.toymoban.com/news/detail-715532.html
四、总结
请注意,虽然 RAND_pseudo_bytes()
可以用于非安全目的,但如果你的应用程序需要密码学安全的随机数,你应该使用 RAND_bytes()
函数。并且,在生产环境中,你应该避免使用自定义的随机数种子,而依赖于系统提供的随机性源来确保更高的安全性。文章来源地址https://www.toymoban.com/news/detail-715532.html
到了这里,关于openssl研发随机数(random)生成(含源码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!