当前位置: 首页 > news >正文

密钥自己生成的方法

两人一组,在Ubuntu或openEuler中(推荐openEuler)中使用OpenSSL编程实现带签名的数字信封协议。使用OpenSSL库时,Alice发送,Bob接收。Ailice,Bob在实验中要替换为自己的8位学号+姓名。使用Markdown记录详细记录实践过程,每完成一项gitcommit一次。

一、实验环境准备

  1. 安装 OpenSSL 开发库
  2. 创建实验目录与 Git 仓库

二、生成密钥与证书(模拟 Alice、Bob 身份)

数字信封需要非对称加密(RSA)保护对称密钥,哈希与签名保证完整性。需为 Alice、Bob 生成 RSA 密钥对和自签名证书。

1. 生成 Alice 的 RSA 密钥对与证书

# 生成 RSA 私钥(2048 位)
openssl genrsa -out alice_private.key 2048# 从私钥提取公钥
openssl rsa -in alice_private.key -pubout -out alice_public.key# 生成自签名证书(需填写信息,如 Common Name 填“20231313zjy+alice”)
openssl req -new -x509 -key alice_private.key -out alice_cert.pem -days 365

alt text

2. 生成 Bob 的 RSA 密钥对与证书

# 生成 RSA 私钥
openssl genrsa -out bob_private.key 2048# 提取公钥
openssl rsa -in bob_private.key -pubout -out bob_public.key# 生成自签名证书(Common Name 填“学号+Bob”)
openssl req -new -x509 -key bob_private.key -out bob_cert.pem -days 365

三、代码编写(C 语言,依赖 OpenSSL 库)

数字信封流程:

  1. Alice:

    • 生成随机对称密钥(AES),用其加密明文 → 得到“密文”。
    • 用 Bob 的公钥加密对称密钥 → 得到“数字信封”。
    • 用 Alice 的私钥对明文哈希值签名 → 得到“签名”。
    • 将「密文 + 数字信封 + 签名」发送给 Bob。
  2. Bob:

    • 用 Bob 的私钥解密“数字信封” → 得到对称密钥。
    • 用对称密钥解密密文 → 得到明文。
    • 用 Alice 的公钥验证“签名” → 确保数据来自 Alice 且未被篡改。

1. Alice 发送端代码(alice.c

#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rand.h>
#include <openssl/err.h>#define AES_KEY_SIZE 256    // AES-256
#define AES_IV_SIZE 16      // CBC模式IV长度
#define BUFFER_SIZE 1024void print_openssl_error(const char *msg) {fprintf(stderr, "%s\n", msg);ERR_print_errors_fp(stderr);
}int main() {ERR_load_crypto_strings();// 1. 明文数据unsigned char plaintext[] = "Hello Bob! This is a secret from Alice.";printf("Alice: 原始明文: %s\n", plaintext);// 2. 生成AES密钥和IVunsigned char aes_key[AES_KEY_SIZE / 8];unsigned char aes_iv[AES_IV_SIZE];if (RAND_bytes(aes_key, sizeof(aes_key)) != 1 || RAND_bytes(aes_iv, sizeof(aes_iv)) != 1) {print_openssl_error("Alice: 生成AES密钥/IV失败");return 1;}// 3. AES-CBC加密明文unsigned char ciphertext[BUFFER_SIZE];int ciphertext_len = 0;EVP_CIPHER_CTX *aes_ctx = EVP_CIPHER_CTX_new();if (!aes_ctx) { print_openssl_error("Alice: 创建AES ctx失败"); return 1; }if (EVP_EncryptInit_ex(aes_ctx, EVP_aes_256_cbc(), NULL, aes_key, aes_iv) != 1) {print_openssl_error("Alice: EVP_EncryptInit_ex 失败");return 1;}if (EVP_EncryptUpdate(aes_ctx, ciphertext, &ciphertext_len, plaintext, (int)strlen((char*)plaintext)) != 1) {print_openssl_error("Alice: EVP_EncryptUpdate 失败");return 1;}int temp_len = 0;if (EVP_EncryptFinal_ex(aes_ctx, ciphertext + ciphertext_len, &temp_len) != 1) {print_openssl_error("Alice: EVP_EncryptFinal_ex 失败");return 1;}ciphertext_len += temp_len;EVP_CIPHER_CTX_free(aes_ctx);// 4. 用Bob公钥加密AES密钥(数字信封)FILE *bob_pub_file = fopen("bob_public.key", "r");if (!bob_pub_file) { printf("Alice: 找不到bob_public.key\n"); return 1; }EVP_PKEY *bob_pubkey = PEM_read_PUBKEY(bob_pub_file, NULL, NULL, NULL);fclose(bob_pub_file);if (!bob_pubkey) { print_openssl_error("Alice: 读取Bob公钥失败"); return 1; }unsigned char envelope[BUFFER_SIZE];size_t envelope_len = sizeof(envelope); // **重要:初始化为缓冲区最大长度**EVP_PKEY_CTX *rsa_ctx = EVP_PKEY_CTX_new(bob_pubkey, NULL);if (!rsa_ctx) { print_openssl_error("Alice: 创建RSA ctx失败"); EVP_PKEY_free(bob_pubkey); return 1; }if (EVP_PKEY_encrypt_init(rsa_ctx) <= 0) { print_openssl_error("Alice: EVP_PKEY_encrypt_init 失败"); EVP_PKEY_free(bob_pubkey); EVP_PKEY_CTX_free(rsa_ctx); return 1; }if (EVP_PKEY_CTX_set_rsa_padding(rsa_ctx, RSA_PKCS1_PADDING) <= 0) { print_openssl_error("Alice: 设置RSA填充失败"); }if (EVP_PKEY_encrypt(rsa_ctx, envelope, &envelope_len, aes_key, sizeof(aes_key)) <= 0) {print_openssl_error("Alice: EVP_PKEY_encrypt 失败");EVP_PKEY_CTX_free(rsa_ctx);EVP_PKEY_free(bob_pubkey);return 1;}EVP_PKEY_CTX_free(rsa_ctx);EVP_PKEY_free(bob_pubkey);// 5. 用Alice私钥签名明文FILE *alice_priv_file = fopen("alice_private.key", "r");if (!alice_priv_file) { printf("Alice: 找不到alice_private.key\n"); return 1; }EVP_PKEY *alice_privkey = PEM_read_PrivateKey(alice_priv_file, NULL, NULL, NULL);fclose(alice_priv_file);if (!alice_privkey) { print_openssl_error("Alice: 读取Alice私钥失败"); return 1; }unsigned char signature[BUFFER_SIZE];size_t signature_len = sizeof(signature); // **重要:初始化为缓冲区最大长度**EVP_MD_CTX *sign_ctx = EVP_MD_CTX_new();if (!sign_ctx) { print_openssl_error("Alice: 创建签名ctx失败"); EVP_PKEY_free(alice_privkey); return 1; }if (EVP_DigestSignInit(sign_ctx, NULL, EVP_sha256(), NULL, alice_privkey) != 1) {print_openssl_error("Alice: EVP_DigestSignInit 失败");EVP_MD_CTX_free(sign_ctx); EVP_PKEY_free(alice_privkey); return 1;}if (EVP_DigestSignUpdate(sign_ctx, plaintext, strlen((char*)plaintext)) != 1) {print_openssl_error("Alice: EVP_DigestSignUpdate 失败");EVP_MD_CTX_free(sign_ctx); EVP_PKEY_free(alice_privkey); return 1;}if (EVP_DigestSignFinal(sign_ctx, signature, &signature_len) != 1) {print_openssl_error("Alice: EVP_DigestSignFinal 失败");EVP_MD_CTX_free(sign_ctx); EVP_PKEY_free(alice_privkey); return 1;}EVP_MD_CTX_free(sign_ctx);EVP_PKEY_free(alice_privkey);// 6. 写入消息文件(带长度信息,确保Bob正确解析)FILE *out = fopen("message_to_bob", "wb");if (!out) { perror("Alice: 打开输出文件失败"); return 1; }// 写入IV长度+IVint iv_len = AES_IV_SIZE;fwrite(&iv_len, sizeof(int), 1, out);fwrite(aes_iv, 1, iv_len, out);// 写入密文长度+密文fwrite(&ciphertext_len, sizeof(int), 1, out);fwrite(ciphertext, 1, ciphertext_len, out);// 写入信封长度+信封fwrite(&envelope_len, sizeof(size_t), 1, out);fwrite(envelope, 1, envelope_len, out);// 写入签名长度+签名fwrite(&signature_len, sizeof(size_t), 1, out);fwrite(signature, 1, signature_len, out);fclose(out);printf("Alice: 消息已生成(message_to_bob)\n");ERR_free_strings();return 0;
}

保存为 alice.c

2. Bob 接收端代码(bob.c

#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/pem.h>#define BUFFER_SIZE 1024int main() {FILE *in = fopen("message_to_bob", "rb");if (!in) { printf("Bob: 找不到 message_to_bob\n"); return 1; }int iv_len;fread(&iv_len, sizeof(int), 1, in);unsigned char aes_iv[iv_len];fread(aes_iv, 1, iv_len, in);int ciphertext_len;fread(&ciphertext_len, sizeof(int), 1, in);unsigned char ciphertext[ciphertext_len];fread(ciphertext, 1, ciphertext_len, in);size_t envelope_len;fread(&envelope_len, sizeof(size_t), 1, in);unsigned char envelope[envelope_len];fread(envelope, 1, envelope_len, in);size_t signature_len;fread(&signature_len, sizeof(size_t), 1, in);unsigned char signature[signature_len];fread(signature, 1, signature_len, in);fclose(in);// 1. Bob 用私钥解密 AES 密钥FILE *bob_priv_file = fopen("bob_private.key", "r");if (!bob_priv_file) { printf("Bob: 找不到 bob_private.key\n"); return 1; }EVP_PKEY *bob_privkey = PEM_read_PrivateKey(bob_priv_file, NULL, NULL, NULL);fclose(bob_priv_file);EVP_PKEY_CTX *rsa_ctx = EVP_PKEY_CTX_new(bob_privkey, NULL);EVP_PKEY_decrypt_init(rsa_ctx);EVP_PKEY_CTX_set_rsa_padding(rsa_ctx, RSA_PKCS1_PADDING);size_t aes_key_len = 0;EVP_PKEY_decrypt(rsa_ctx, NULL, &aes_key_len, envelope, envelope_len);unsigned char aes_key[aes_key_len];if (EVP_PKEY_decrypt(rsa_ctx, aes_key, &aes_key_len, envelope, envelope_len) != 1) {printf("Bob: RSA解密失败(密钥不匹配或数据损坏)\n");return 1;}EVP_PKEY_CTX_free(rsa_ctx);EVP_PKEY_free(bob_privkey);// 2. AES 解密密文unsigned char plaintext[BUFFER_SIZE] = {0};int plaintext_len = 0, len;EVP_CIPHER_CTX *aes_ctx = EVP_CIPHER_CTX_new();EVP_DecryptInit_ex(aes_ctx, EVP_aes_256_cbc(), NULL, aes_key, aes_iv);EVP_DecryptUpdate(aes_ctx, plaintext, &plaintext_len, ciphertext, ciphertext_len);EVP_DecryptFinal_ex(aes_ctx, plaintext + plaintext_len, &len);plaintext_len += len;EVP_CIPHER_CTX_free(aes_ctx);plaintext[plaintext_len] = '\0';// 3. 验证签名FILE *alice_pub_file = fopen("alice_public.key", "r");if (!alice_pub_file) { printf("Bob: 找不到 alice_public.key\n"); return 1; }EVP_PKEY *alice_pubkey = PEM_read_PUBKEY(alice_pub_file, NULL, NULL, NULL);fclose(alice_pub_file);EVP_MD_CTX *verify_ctx = EVP_MD_CTX_new();EVP_DigestVerifyInit(verify_ctx, NULL, EVP_sha256(), NULL, alice_pubkey);EVP_DigestVerifyUpdate(verify_ctx, plaintext, plaintext_len);int verify_result = EVP_DigestVerifyFinal(verify_ctx, signature, signature_len);EVP_MD_CTX_free(verify_ctx);EVP_PKEY_free(alice_pubkey);printf("Bob: 解密明文: %s\n", plaintext);if (verify_result == 1)printf("Bob: 签名验证成功(数据完整且来自 Alice)\n");elseprintf("Bob: 签名验证失败\n");return 0;
}

保存为 bob.c

四、编译与运行

1. 编译 Alice 代码

gcc -o alice alice.c -lcrypto

2. 运行 Alice 生成“数字信封”

./alice

3. 编译 Bob 代码

gcc -o bob bob.c -lcrypto

4. 运行 Bob 解密与验证

./bob

五、实验结果验证

运行 ./bob 后,终端应输出:

  • 解密后的明文:Hello Bob! This is a secret message from 20231313zjy.已经更改为学号和姓名
  • 签名验证结果:成功(数据完整且来自Alice)
http://www.hskmm.com/?act=detail&tid=34289

相关文章:

  • 2025机床维修厂家推荐:永华鑫数控设备,专业服务保障生产!
  • ubuntu 24.04虚拟机安装vgpu显卡驱动
  • 2025棋牌室加盟推荐麻友社,自主自助模式引领行业新风尚!
  • 计算机硬件-网络
  • 2025TYPE-C母座优质厂家推荐,创粤科技TID认证高速传输首选!
  • 2025年医药冷链运输厂家推荐排行榜,药品/临床样本/CAR-T/蛋白/诊断试剂/生物/血液/细胞/芯片运输,冷藏车/冷藏箱/保温箱/干冰/液氮/温控/国际冷链公司推荐!
  • Ubuntu 桌面美化
  • 题解:CF1336E2 Chiori and Doll Picking (hard version)
  • Apollo自动驾驶平台:开源、高性能的自动驾驶解决方案
  • 三八皇后、8线程、MMX
  • MantisBT vs Kanass,开源项目管理工具一文全面对比分析 - 详解
  • 2025工作服厂家推荐:深圳市贵格服饰,专业定制各类高品质工作服!
  • 2025年陶瓷过滤机厂家推荐排行榜,陶瓷真空过滤机/盘式陶瓷过滤机/矿用陶瓷过滤机/全自动陶瓷过滤机/固液分离设备公司精选
  • 2019年机器学习研究奖项获奖名单公布
  • 2025不锈钢清洗钝化液推荐:隆彦商贸环保高效,品质卓越!
  • 2025年棋牌室加盟推荐排行榜,自主棋牌室加盟,自助棋牌室加盟,优选品牌与服务指南
  • 2025年轻钢龙骨厂家,铝方通厂家,铝单板厂家,石膏板厂家推荐排行榜:专业品质与服务口碑之选!
  • 013的加密世界权威指南_第一部分
  • 卸载安装JDK
  • 2025年给汤机厂家最新权威推荐榜:诚信价格与卓越性能的完美结合,优质给汤机公司精选
  • 2025年给汤机厂家最新权威推荐榜:靠谱给汤机源头厂家精选,高效稳定与售后服务深度解析
  • DOS命令
  • windows防火墙开放某个端口的配置方法
  • 2025铝单板厂家推荐杰兰斯装饰,专业定制异形双曲等多款铝单板!
  • 条件运算符的中间表达式省略扩展
  • 2025年网络营销推广服务商权威推荐榜单,网络推广,网络营销,专业服务与效果保障之选!
  • day18-课程介绍+环境适配
  • 动态规划做题记录
  • 高级语言程序设计低第一次作业
  • 2025年棒球帽,卫衣,羽绒服生产厂家推荐排行榜,时尚舒适与品质保证的首选!