openssl研发随机数(random)生成(含源码)


在 OpenSSL 中,随机数生成是一个非常重要的任务,用于生成密码学中的随机数,密钥和初始化向量等。在开发应用程序时,保证随机数的质量和随机性非常关键,因为弱的随机数可能导致密码学的弱点,使得应用程序容易受到攻击。

在 OpenSSL 中,你可以使用以下函数来生成随机数:

一、RAND_bytes() 函数(推荐)

1.1 底层原理

  1. 系统随机性源: OpenSSL 首先会尝试获取系统提供的真随机数源,通常是操作系统的 /dev/random/dev/urandom(在类 UNIX 系统中),或者是 Windows 的 CryptGenRandom 函数。这些源产生的数据是由系统硬件或操作系统的事件(例如用户的鼠标移动、键盘输入、硬件噪声等)产生的,具有高度的随机性。

  2. 熵池(Entropy Pool): OpenSSL 会维护一个称为熵池的数据结构,用于存储收集到的随机性源数据。这个熵池包含了足够的随机性数据,可以供 OpenSSL 的伪随机数生成器使用。

  3. 伪随机数生成器(PRNG): OpenSSL 使用一个伪随机数生成器(通常是一个加密安全的伪随机数生成器)来从熵池中生成更多的随机数据。这个 PRNG 的输出被 RAND_bytes() 函数返回给调用者。

  4. 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() 函数来添加额外的随机性数据。请确保提供的数据是足够随机的,以确保生成的随机数具有高质量的随机性。

四、总结

请注意,虽然 RAND_pseudo_bytes() 可以用于非安全目的,但如果你的应用程序需要密码学安全的随机数,你应该使用 RAND_bytes() 函数。并且,在生产环境中,你应该避免使用自定义的随机数种子,而依赖于系统提供的随机性源来确保更高的安全性。

  • 24
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

N阶二进制

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值