openssl使用哈希算法生成随机密钥

文章目录

  • 一、openssl中随机数函数
      • **OpenSSL 随机数函数概览**
        • 1. **核心随机数函数**
      • **常用函数详解**
        • 1. `RAND_bytes`
        • 2. `RAND_priv_bytes`
        • 3. `RAND_seed` 和 `RAND_add`
        • 4. `RAND_status`
      • **随机数生成器的熵池**
      • **常见用例**
      • **注意事项**
  • 二、使用哈希算法生成随机的密钥


一、openssl中随机数函数

OpenSSL 提供了一套功能强大的随机数生成函数,用于生成高质量的伪随机数。随机数在密码学中至关重要,广泛用于密钥生成、盐值生成、初始化向量 (IV) 等安全操作。


OpenSSL 随机数函数概览

1. 核心随机数函数
函数名称描述
RAND_bytes生成高质量的伪随机字节。
RAND_priv_bytes生成高质量伪随机字节,推荐用于对安全性要求更高的密钥生成。
RAND_pseudo_bytes生成伪随机字节(不保证是加密级别安全,已被弃用)。
RAND_seed手动为伪随机数生成器添加种子值。
RAND_add添加额外的熵(种子数据)到伪随机数生成器的池中。
RAND_status检查随机数生成器是否被正确初始化。
RAND_poll自动收集熵以初始化随机数生成器(由内部调用)。

常用函数详解

1. RAND_bytes
  • 作用:生成高质量的加密级别伪随机字节。

  • 函数原型

    int RAND_bytes(unsigned char *buf, int num);
    
    • buf:指向用于存储随机字节的缓冲区。
    • num:要生成的随机字节数。
    • 返回值
      • 成功返回 1
      • 如果随机数生成器未正确初始化,返回 0
  • 示例

    unsigned char random_bytes[16];
    if (RAND_bytes(random_bytes, sizeof(random_bytes)) == 1) {
        printf("生成的随机数:");
        for (int i = 0; i < sizeof(random_bytes); i++) {
            printf("%02x", random_bytes[i]);
        }
        printf("\n");
    } else {
        fprintf(stderr, "随机数生成失败!\n");
    }
    

2. RAND_priv_bytes
  • 作用:与 RAND_bytes 类似,但专为高安全性应用设计(如密钥生成)。可能在实现中增加额外的保护。
  • 函数原型
    int RAND_priv_bytes(unsigned char *buf, int num);
    
  • 使用方法与 RAND_bytes 一致。

3. RAND_seedRAND_add
  • 作用:为随机数生成器添加种子值或熵,增强其随机性。
    OpenSSL 的随机数生成器依赖熵池,通常会自动初始化,但可以通过这些函数手动添加种子数据。

  • 函数原型

    void RAND_seed(const void *buf, int num);
    void RAND_add(const void *buf, int num, double entropy);
    
    • buf:种子数据。
    • num:种子数据的字节数。
    • entropy:种子中估计的熵(单位是比特,范围 0 到 8*num)。
  • 示例

    unsigned char seed_data[] = {0x12, 0x34, 0x56, 0x78};
    RAND_seed(seed_data, sizeof(seed_data));
    

4. RAND_status
  • 作用:检查随机数生成器是否被正确初始化。

  • 函数原型

    int RAND_status(void);
    
    • 返回值
      • 如果熵池已初始化且可用随机性足够,返回 1
      • 否则返回 0
  • 示例

    if (RAND_status() == 1) {
        printf("随机数生成器已初始化!\n");
    } else {
        printf("随机数生成器未初始化!\n");
    }
    

随机数生成器的熵池

OpenSSL 的随机数生成器使用熵池作为随机性的来源,依赖于系统提供的随机性(如 /dev/random/dev/urandom)。在大多数情况下,OpenSSL 会自动处理熵池的初始化,但开发者可以通过 RAND_seedRAND_add 提供额外的种子数据。


常见用例

  1. 生成随机密钥

    unsigned char key[32]; // 256 位密钥
    if (RAND_bytes(key, sizeof(key)) == 1) {
        printf("密钥生成成功!\n");
    }
    
  2. 生成随机初始化向量 (IV)

    unsigned char iv[16]; // 128 位 IV
    if (RAND_bytes(iv, sizeof(iv)) == 1) {
        printf("IV 生成成功!\n");
    }
    
  3. 增强随机数生成器熵

    unsigned char extra_entropy[] = {0xde, 0xad, 0xbe, 0xef};
    RAND_add(extra_entropy, sizeof(extra_entropy), 4.0); // 添加 4 比特熵
    

注意事项

  1. 使用 RAND_bytesRAND_priv_bytes

    • 推荐使用这两个函数生成随机数,因为它们提供加密级别的安全性。
    • 不建议使用 RAND_pseudo_bytes,因为它已被弃用。
  2. 熵的重要性

    • 高质量的熵是随机数生成的核心。如果熵不足,生成的随机数可能会被预测,降低安全性。
  3. 平台依赖

    • OpenSSL 的随机数生成器在不同平台上依赖系统的熵源,例如 /dev/urandom 或 Windows 的 CryptGenRandom。

OpenSSL 的随机数生成函数设计灵活,满足了从简单随机需求到高安全性应用的各种场景。如果需要更高安全性的随机数生成,推荐使用 RAND_priv_bytes

二、使用哈希算法生成随机的密钥

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/rand.h>
#include <openssl/evp.h>

#define SEED_LENGTH 32  // 随机种子长度(32 字节 = 256 位)
#define KEY_LENGTH 32   // 密钥长度(32 字节 = 256 位)

// 使用随机种子和哈希算法生成密钥
void generate_hashed_key(unsigned char *key, size_t key_length) {
    unsigned char seed[SEED_LENGTH]; // 随机种子

    // 生成随机种子
    if (!RAND_bytes(seed, sizeof(seed))) {
        fprintf(stderr, "随机种子生成失败!\n");
        exit(EXIT_FAILURE);
    }

    // 打印随机种子(调试用)
    printf("随机种子: ");
    for (size_t i = 0; i < sizeof(seed); i++) {
        printf("%02x", seed[i]);
    }
    printf("\n");

    // 使用 SHA-256 哈希函数对种子进行散列
    EVP_MD_CTX *mdctx = EVP_MD_CTX_new(); // 创建哈希上下文
    if (!mdctx) {
        fprintf(stderr, "创建哈希上下文失败!\n");
        exit(EXIT_FAILURE);
    }

    // 初始化哈希计算(使用 SHA-256)
    if (EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL) != 1) {
        fprintf(stderr, "哈希初始化失败!\n");
        EVP_MD_CTX_free(mdctx);
        exit(EXIT_FAILURE);
    }

    // 提供数据进行哈希计算
    if (EVP_DigestUpdate(mdctx, seed, sizeof(seed)) != 1) {
        fprintf(stderr, "哈希更新失败!\n");
        EVP_MD_CTX_free(mdctx);
        exit(EXIT_FAILURE);
    }

    // 获取哈希结果
    unsigned char hash[EVP_MAX_MD_SIZE];
    unsigned int hash_len;
    if (EVP_DigestFinal_ex(mdctx, hash, &hash_len) != 1) {
        fprintf(stderr, "哈希计算失败!\n");
        EVP_MD_CTX_free(mdctx);
        exit(EXIT_FAILURE);
    }

    // 释放哈希上下文
    EVP_MD_CTX_free(mdctx);

    // 取哈希结果的前 key_length 字节作为密钥
    if (key_length > hash_len) {
        fprintf(stderr, "密钥长度超出哈希值长度!\n");
        exit(EXIT_FAILURE);
    }
    memcpy(key, hash, key_length);

    // 打印生成的密钥(调试用)
    printf("生成的密钥: ");
    for (size_t i = 0; i < key_length; i++) {
        printf("%02x", key[i]);
    }
    printf("\n");
}

int main() {
    unsigned char key[KEY_LENGTH]; // 存储生成的密钥

    // 调用密钥生成函数
    generate_hashed_key(key, KEY_LENGTH);

    return 0;
}

运行两次的结果:

这里可以看到每次运行后生成的密钥都是不一样的,这样就保证了密钥的不一致性。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/929048.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【PlantUML系列】序列图(二)

目录 一、参与者 二、消息交互顺序 三、其他技巧 3.1 改变参与者的顺序 3.2 使用 as 重命名参与者 3.3 注释 3.4 页眉和页脚 一、参与者 使用 participant、actor、boundary、control、entity 和 database 等关键字来定义不同类型的参与者。例如&#xff1a; Actor&…

从excel数据导入到sqlsever遇到的问题

1、格式问题时间格式&#xff0c;excel中将日期列改为日期未生效&#xff0c;改完后&#xff0c;必须手动单击这个单元格才能生效&#xff0c;那不可能一个一个去双击。解决方案如下 2、导入之后表字段格式问题&#xff0c;数据类型的用navicat导入之后默认是nvarchar类型的&a…

On-Chip-Network之router微架构的物理实现

Low-Power Microarchitecture 自20世纪90年代以来&#xff0c;功耗一直是嵌入式芯片和高性能芯片面临的一个挑战。自2000年代中期以来&#xff0c;它已经成为大多数设计的主要约束。多核解决了功耗问题&#xff0c;由此产生的communication substrate&#xff0c;namely the on…

路径规划之启发式算法之四:蚁群算法(Ant Colony Optimization,ACO)

蚁群算法&#xff08;Ant Colony Optimization&#xff0c;ACO&#xff09;是一种模拟蚂蚁觅食行为的启发式搜索算法&#xff0c;由Marco Dorigo于1992年在他的博士论文中提出。该算法适用于解决组合优化问题&#xff0c;如旅行商问题&#xff08;TSP&#xff09;、车辆路径问题…

LabVIEW密码保护与反编译的安全性分析

在LabVIEW中&#xff0c;密码保护是一种常见的源代码保护手段&#xff0c;但其安全性并不高&#xff0c;尤其是在面对专业反编译工具时。理论上&#xff0c;所有软件的反编译都是可能的&#xff0c;尽管反编译不一定恢复完全的源代码&#xff0c;但足以提取程序的核心功能和算法…

RabbitMQ消息可靠性保证机制6--可靠性分析

在使用消息中间件的过程中&#xff0c;难免会出现消息错误或者消息丢失等异常情况。这个时候就需要有一个良好的机制来跟踪记录消息的过程&#xff08;轨迹溯源&#xff09;&#xff0c;帮助我们排查问题。 在RabbitMQ中可以使用Firehose实现消息的跟踪&#xff0c;Firehose可…

工业—使用Flink处理Kafka中的数据_ProduceRecord1

1 、 使用 Flink 消费 Kafka 中 ProduceRecord 主题的数据,统计在已经检验的产品中,各设备每 5 分钟 生产产品总数,将结果存入Redis 中, key 值为

前端上传后端接收参数为null

记录一下工作中的问题 前端明明把文件传到后台了&#xff0c;但是后台接收参数为null 原因&#xff1a; 前端上传文件的name和后端接收参数名称不匹配 前端 后端 把前端上传的name由upfile改为file即可 本来是很基本的小问题&#xff0c;但因为自己钻了牛角尖一直没搞定&…

CSS3 布局样式及其应用

深入探讨 CSS3 布局样式及其应用 引言 在现代网页设计中&#xff0c;CSS&#xff08;层叠样式表&#xff09;不仅是设计视觉样式的工具&#xff0c;也是布局的核心技术。CSS3引入了新的布局模型&#xff0c;其中Flexbox与Grid布局在满足复杂布局需求方面表现尤为出色。本文将…

spark sql 环境安装,java 默认路径和 安装配置!

yum安装java 查看默认路径 update-alternatives --config java # Java 环境变量 export JAVA_HOME/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.412.b08-1.el7_9.x86_64/jreexport PATH$JAVA_HOME/bin:$PATH# Spark 环境变量 export SPARK_HOME/home/vagrant/soft/sparkexport PATH…

第32天:安全开发-JavaEE应用Servlet路由技术JDBCMybatis数据库生命周期

时间轴&#xff1a; 32天主要学习内容&#xff1a; 1、JavaEE-HTTP-Servlet技术 2、JavaEE-数据库-JDBC&Mybatis java技术使用历史&#xff08;2023 &#xff09;&#xff1a; JavaEE-HTTP-Servlet&路由&周期: java学习范围&#xff1a; 3、Java: 功能:数据…

Android渗透环境配置教程

工具 模拟器 ADB brew install android-platform-tools set import cert # cer 证书转为 pem 证书 openssl x509 -inform DER -in cacert.der -out cacert.pem# 获取证书的 hash 值 hash$(openssl x509 -inform PEM -subject_hash_old -in cacert.pem | head -n 1)# 将 pem…

基于遗传优化SVM的电机参数预测matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 数据收集与预处理 4.2模型构建与训练 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 输入&#xff1a;电机结构参数x1 x2 x3 x4 x5(分别是铁心高度 铁心厚度 绕组…

【开源代码】图像水印移除-依赖python-tensorflow

下载源码 git clone https://github.com/zuruoke/watermark-removal创建conda环境 conda create -n tensorflow_gpu python=3.7 conda activate tensorflow_gpu conda install tensorflow-gpu==1.15

汇编语言学习-二

好吧&#xff0c;已经隔了两天&#xff0c;下完班看了两天&#xff0c;在电脑上装了虚拟机版的MS_DOS,主要是怕折腾坏我的电脑系统&#xff1b; 这个第二天应该是称为第二章更为合适&#xff0c;目前第二章已经看完&#xff0c;基本的命令也是敲了敲&#xff1b; 下面就进行一…

开源即时通讯与闭源即时通讯该怎么选择,其优势是什么?

在选择即时通讯软件时&#xff0c;应根据企业的经营领域来选择适合自身需求的开源或闭源方案。不同领域对开源和闭源即时通讯的理念存在差异&#xff0c;因此总结两个点简要分析这两种选择&#xff0c;有助于做出更明智的决策。 一、开源与闭源的根本区别在于软件的源代码是否…

【算法】图论——树的重心

目录 题目解析 算法原理 图的存储 算法实现 题目解析 题目解析 给定一颗树&#xff0c;树中包含n个结点&#xff08;编号&#xff09;和n-1条无向边。请找到树的重心&#xff0c;并输出将重心删除后&#xff0c;剩余各个连通块中点数的最大值。 什么是重心&#xff1f; 重…

【Vue3 ElementUI开发环境搭建】

VUE搭建关系系统 1. 安装vue脚手架工具2. 使用脚手架创建项目2.1 选择VUE版本2.2 启动demo2.3 vue工程搭建完的目录 3. 安装Element UI3.1 测试ElementUI3.1.1 更换Demo页面的内容3.1.2 引入ElementUI的样式表 1. 安装vue脚手架工具 npm install -g vue/cli执行命令后等他跑一…

Redis常见问题总结

Redis常见问题总结 1.Redis分布式存储方案 分布式存储核心特点主从&#xff08;Master/Slave&#xff09;模式一主多从&#xff0c;故障时手动切换。哨兵&#xff08;Sentinel&#xff09;模式有哨兵的一主多从&#xff0c;主节点故障自动选择新的主节点。集群&#xff08;Cl…

Yeeco成长型一体化数智赋能平台:科技矩阵重塑企业数字生态

随着科技的飞速发展&#xff0c;我们正在步入一个被称为“数智化时代”的新时代。在这个时代中&#xff0c;数据处理和分析的能力被提升到一个前所未有的高度&#xff0c;而这种变化背后的重要推动力量就是各种新兴的技术趋势。 为了在激烈的市场竞争中脱颖而出&#xff0c;Yee…