1.参考相关内容,在Ubuntu或openEuler中(推荐openEuler)中使用OpenSSL库编程实现调用SM2(加密解密,签名验签),SM3(摘要计算,HMAC 计算),SM4(加密解密)算法,使用Markdown记录详细记录实践过程,每完成一项gitcommit一次。(5')
(一)SM3的实践
qzz@qzz-virtual-machine:~/bestidiocs4stu/ch03/sm3/sm3openssl$ gcc -Wall -O2 -o test test.c sm3hash.c -lssl -lcrypto
qzz@qzz-virtual-machine:~/bestidiocs4stu/ch03/sm3/sm3openssl$ ./test
Raw data (sample1): abc
Hash length: 32 bytes.
Hash value:
66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0Raw data (sample2):
0x61 0x62 0x63 0x64 0x61 0x62 0x63 0x64 0x61 0x62 0x63 0x64 0x61 0x62 0x63 0x64 0x61 0x62 0x63 0x64 0x61 0x62 0x63 0x64 0x61 0x62 0x63 0x64 0x61 0x62 0x63 0x64 0x61 0x62 0x63 0x64 0x61 0x62 0x63 0x64 0x61 0x62 0x63 0x64 0x61 0x62 0x63 0x64 0x61 0x62 0x63 0x64 0x61 0x62 0x63 0x64 0x61 0x62 0x63 0x64 0x61 0x62 0x63 0x64
Hash length: 32 bytes.
Hash value:
debe9ff92275b8a138604889c18e5a4d6fdb70e5387e5765293dcba39c0c5732
qzz@qzz-virtual-machine:~/bestidiocs4stu/ch03/sm3/sm3openssl$ cd hmac-sm3
bash: cd: hmac-sm3: No such file or directory
qzz@qzz-virtual-machine:~/bestidiocs4stu/ch03/sm3/sm3openssl$ cd ..
qzz@qzz-virtual-machine:~/bestidiocs4stu/ch03/sm3$ cd hmac-sm3
qzz@qzz-virtual-machine:~/bestidiocs4stu/ch03/sm3/hmac-sm3$ make
gcc -Wall -O2 -o test test.c sm3.c
qzz@qzz-virtual-machine:~/bestidiocs4stu/ch03/sm3/hmac-sm3$ ./test
Message: abc
HMAC: ec76c401 b2ddceb3 916bdffa 0469b85f 90536ffc f4ecac77 539f3d8b 8bbe046c
(二)SM4的实践
qzz@qzz-virtual-machine:~/bestidiocs4stu/ch03/sm4/sm4openssl$ ./test
===== SM4-CBC Encryption and Decryption =====
sm4-cbc encryption successful. Ciphertext length: 16 bytes
Ciphertext:
0000: 45 E9 16 3A 1C 88 36 4D DD 64 1D 63 18 94 4A F4
sm4-cbc decryption: Read ciphertext length: 16 bytes
sm4-cbc decryption result:
Helloworld
Decrypted plaintext (hex):
0000: 48 65 6C 6C 6F 77 6F 72 6C 64
遇到的问题
在sm3实践中,make命令执行后遇到以下问题:
qzz@qzz-virtual-machine:~/bestidiocs4stu/ch03/sm3/sm3openssl$ gcc -Wall -O2 -I/usr/include -o test test.c sm3hash.c -lssl -lcrypto
test.c:4:10: fatal error: openssl/evp.h: No such file or directory4 | #include <openssl/evp.h>| ^~~~~~~~~~~~~~~
compilation terminated.
sm3hash.c:2:10: fatal error: openssl/evp.h: No such file or directory2 | #include <openssl/evp.h>| ^~~~~~~~~~~~~~~
compilation terminated.
qzz@qzz-virtual-machine:~/bestidiocs4stu/ch03/sm3/sm3openssl$ gcc -Wall -O2 -o test test.c sm3hash.c -lssl -lcrypto
test.c:4:10: fatal error: openssl/evp.h: No such file or directory4 | #include <openssl/evp.h>| ^~~~~~~~~~~~~~~
compilation terminated.
sm3hash.c:2:10: fatal error: openssl/evp.h: No such file or directory2 | #include <openssl/evp.h>| ^~~~~~~~~~~~~~~
compilation terminated.
查询csdn,发现是由于未安装开发库libssl.so
,链接:https://blog.csdn.net/poiiuytree233/article/details/134817152
在执行命令sudo apt install libssl-dev
后代码正常编译运行
二、参考相关内容,在Ubuntu或openEuler中(推荐openEuler)中使用GmSSL库编程实现调用SM2(加密解密,签名验签),SM3(摘要计算,HMAC 计算),SM4(加密解密)算法,使用Markdown记录详细记录实践过程,每完成一项gitcommit一次。
(一)SM2的实践
qzz@qzz-virtual-machine:~/bestidiocs4stu/ch03/sm2/sm2gmssl$ ./sm2gmssl
生成 SM2 密钥对...
SM2 密钥生成成功。
明文: Hello, SM2!
加密明文...
加密成功。
密文: 307402205848071A1F8A976C4BA6E0BB4D0095CCEDFF687E3B5557C5DC967847D105D3D2022100EF19835660CDDE19E93082CEAE3B4D4200FA8239F63E3217D312EDAFE8331FA904202565479C198998E326DB6D9D0D3B10B1DB6756B1DA8714DA5473C391ED7CEA3C040B92843E63BA16825093D458
解密密文...
解密成功。
解密后的明文: Hello, SM2!
要签名的消息: This is a message to be signed.
签名成功。
签名: 3046022100EB0FA25B684A368B75A1901E08B10016E97E776C6F1F14A530A6974605ED95AD0221009D2F5080F14B7B9FEF7FBDDB6FE841B41CA0D25C03B5EE3EE1FDCB7B8728F798
签名验证成功。
(二)SM3的实践
qzz@qzz-virtual-machine:~/bestidiocs4stu/ch03/sm3/sm3gmssl$ gcc -o testsm3 testsm3.c -lgmssl
qzz@qzz-virtual-machine:~/bestidiocs4stu/ch03/sm3/sm3gmssl$ ./testsm3
SM3 hash: 8b3145130a678ef0049952d0c3d78f878b3c825bd3e73a0fb2319b34cabea9e0
(三)SM4的实践
qzz@qzz-virtual-machine:~/bestidiocs4stu/ch03/sm4/sm4gmssl$ ./sm4gmssl
随机生成的密钥: 88 80 72 76 5C 09 94 B9 29 E1 2E 14 42 90 6A AD
随机生成的IV: 41 5F 3F 7E E1 D8 0D E7 95 3F 66 29 D6 96 8C 9F
明文 (130 字节): 9B BA DF 2E 80 89 CC 30 05 E7 92 6C D6 EF 9E 68 A7 7B D5 05 05 EA 02 3F CF 66 75 BA 34 8D 99 87 A9 A4 C2 3E E7 2B CC F9 8F 01 14 86 C5 FC B5 FB 83 07 A9 D6 F5 FD BF F0 A2 40 21 A0 DA 83 6A 35 DE 5B 81 6D 81 78 49 E4 A8 BB 7F BB E5 5B 6E A2 37 12 EC 88 02 DB E7 FC 99 60 BE 79 FE 05 72 4B 7F 0D 9B A5 1E 62 87 92 87 16 2A 96 A0 03 93 E9 EB 19 C8 B8 19 14 40 F0 55 9E D9 22 D5 DA A9 77 36 AD
密文 (144 字节): A4 E5 8A 20 2C 4F 38 BE F4 8C 1D 6D AD FE F6 2D 88 68 1E C4 97 DE 08 02 13 9B A5 D0 AC 33 1B 67 15 78 C1 7F B5 73 D1 3A C0 2D 8C 91 98 A9 42 A8 F0 FA FB F8 F6 D4 CE 1E 3F AC CE 19 02 5B B7 98 7C 90 4A DB C9 85 84 A0 43 3F 76 B9 E3 39 3C 2B B5 AC E5 BB 46 A2 88 18 EF 05 20 CF B2 2B E8 2F B4 A1 EB 4E 58 A7 51 D4 5E 7A 99 72 79 B4 EB 93 5C 3D C2 A1 D4 AE 42 5F 30 94 EE 76 B0 08 F4 D2 C2 6B 51 15 0B C5 39 6B 6C DF 28 38 39 8D 5E D3
解密后的明文 (130 字节): 9B BA DF 2E 80 89 CC 30 05 E7 92 6C D6 EF 9E 68 A7 7B D5 05 05 EA 02 3F CF 66 75 BA 34 8D 99 87 A9 A4 C2 3E E7 2B CC F9 8F 01 14 86 C5 FC B5 FB 83 07 A9 D6 F5 FD BF F0 A2 40 21 A0 DA 83 6A 35 DE 5B 81 6D 81 78 49 E4 A8 BB 7F BB E5 5B 6E A2 37 12 EC 88 02 DB E7 FC 99 60 BE 79 FE 05 72 4B 7F 0D 9B A5 1E 62 87 92 87 16 2A 96 A0 03 93 E9 EB 19 C8 B8 19 14 40 F0 55 9E D9 22 D5 DA A9 77 36 AD
解密验证成功:解密后的明文与原始明文一致。
qzz@qzz-virtual-machine:~/bestidiocs4stu/ch03/sm4/sm4gmsslcbc$ ./sm4gmssl
原文(ASCII):
Hello, SM4!AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA原文(十六进制):
0000: 48 65 6C 6C 6F 2C 20 53 4D 34 21 41 41 41 41 41
0010: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0020: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0030: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0040: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0050: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0060: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0070: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0080: 41 41 密文(十六进制):密文:
0000: 82 08 EF BF 25 BA 27 5B 63 87 7D CD 97 A4 92 5C
0010: 3A 35 94 7F F8 20 1B 54 70 34 48 5D 0E 93 58 43
0020: C0 71 95 D4 09 E4 27 29 F6 63 2D 57 A3 E0 50 EE
0030: EF 62 ED 24 3B 55 3D 43 D1 94 CD 9B 77 7E A9 E6
0040: 77 1E AB 1C 49 CF 0F 87 F2 35 4D 13 00 51 C3 6F
0050: C5 FB 3A 97 8B E8 E7 49 29 37 24 DD CB 68 9B 1F
0060: 71 91 7B B5 B5 9C 93 70 CE 01 78 9F A7 39 33 E5
0070: DC 76 D1 D7 DF 2A 4B D9 8D 05 A2 47 7F 00 02 41
0080: 6C 2A FF CA 25 44 37 FC C2 23 06 C5 49 44 23 2C 解密后的明文(ASCII):
Hello, SM4!AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA解密后的明文(十六进制):
0000: 48 65 6C 6C 6F 2C 20 53 4D 34 21 41 41 41 41 41
0010: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0020: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0030: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0040: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0050: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0060: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0070: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0080: 41 41 解密成功,明文与原文一致。
3.两人一组,在Ubuntu或openEuler中(推荐openEuler)中使用OpenSSL编程实现带签名的数字信封协议。使用OpenSSL库时,Alice发送,Bob接收。Ailice,Bob在实验中要替换为自己的8位学号+姓名。使用Markdown记录详细记录实践过程,每完成一项gitcommit一次。(5分)
- 本次实验里我是发送方20231302qzz,操作如下
qzz@qzz-virtual-machine:~/Desktop$ chmod +x build.sh
qzz@qzz-virtual-machine:~/Desktop$ ./build.sh
编译数字信封程序...
sender 编译成功
receiver 编译成功
所有程序编译完成!使用方法:
1. 首先确保双方已交换公钥
2. 发送方执行: ./sender receiver_public.pem sender_private.pem 输入文件 输出信封文件
3. 接收方执行: ./receiver sender_public.pem receiver_private.pem 信封文件 签名文件 输出文件
qzz@qzz-virtual-machine:~/Desktop$ gcc -o generate_keys generate_keys.c -lssl -lcrypto
qzz@qzz-virtual-machine:~/Desktop$ ./generate_keys sender
生成RSA 2048位密钥对...
密钥对生成成功:公钥: sender_public.pem私钥: sender_private.pem
qzz@qzz-virtual-machine:~/Desktop$ ./generate_keys receiver
生成RSA 2048位密钥对...
密钥对生成成功:公钥: receiver_public.pem私钥: receiver_private.pem
qzz@qzz-virtual-machine:~/Desktop$ echo "20231302qzz" > message.txt
qzz@qzz-virtual-machine:~/Desktop$ ./sender receiver_public.pem sender_private.pem message.txt envelope.bin
读取原始数据: 12 字节
开始创建数字信封...
生成AES密钥和IV成功
RSA加密AES密钥成功,加密后长度: 256
AES加密数据成功,密文长度: 16
生成签名成功,签名长度: 256
数字信封创建完成,总长度: 288=== 发送方任务完成 ===
数字信封已保存到: envelope.bin
数字签名已保存到: envelope.bin.sig
信封数据大小: 288 字节
签名大小: 256 字节
请将以上两个文件发送给接收方
收方同学20231322cjl操作如下:
[cjl@localhost openEuler共享文件夹]$ ./sender receiver_public.pem sender_private.pem message.txt envelope.bin
读取原始数据: 12 字节
开始创建数字信封...
生成AES密钥和IV成功
RSA加密AES密钥成功,加密后长度: 256
AES加密数据成功,密文长度: 16
生成签名成功,签名长度: 256
数字信封创建完成,总长度: 288=== 发送方任务完成 ===
数字信封已保存到: envelope.bin
数字签名已保存到: envelope.bin.sig
信封数据大小: 288 字节
签名大小: 256 字节
请将以上两个文件发送给接收方
[cjl@localhost openEuler共享文件夹]$ ./receiver sender_public.pem receiver_private.pem envelope.bin envelope.bin.sig decrypted_message.txt
读取信封数据: 288 字节
读取签名数据: 256 字节
开始解析数字信封...
信封总长度: 288 字节
IV大小: 16 字节
加密密钥大小: 256 字节
密文大小: 16 字节
开始解密AES密钥...
AES密钥解密成功
开始解密数据...
数据解密成功: 12 字节
开始验证签名...
签名验证成功!数据完整性和来源可信=== 接收方任务完成 ===
解密成功!数据已保存到: decrypted_message.txt
解密数据大小: 12 字节解密内容预览:
----------------------------------------
20231302qzz----------------------------------------
以下是运行的截图:
4.两人一组,在Ubuntu或openEuler中(推荐openEuler)中使用OpenSSL编程实现带签名的数字信封协议。使用GmSSL库时,Alice发送,Bob接收。Ailice,Bob在实验中要替换为自己的8位学号+姓名。使用Markdown记录详细记录实践过程,每完成一项gitcommit一次。(5分)
以下是运行的截图:
发方同学(bob)20231322cjl:
收方同学(Alice)20231302qzz:
可以看到运行成功
5.使用Rust完成带签名的数字信封协议(选做,10分)
首先是Cargo.toml
文件:
[package]
name = "digital-envelope"
version = "0.1.0"
edition = "2021"[dependencies]
aes-gcm = "0.10"
rsa = "0.9"
rand = "0.8"
anyhow = "1.0"
hex = "0.4"
base64 = "0.21"
sha2 = "0.10" # 添加这个
bincode = "1.3" # 可选,用于序列化
在src/main.rs
添加代码:
use aes_gcm::{aead::{Aead, AeadCore, KeyInit, OsRng},Aes256Gcm, Key, Nonce
};
use rsa::{RsaPrivateKey, RsaPublicKey, Oaep};
use rsa::pkcs8::{EncodePublicKey, DecodePublicKey}; // 修正导入
use rand::RngCore;
use std::fs;// 数字信封结构
pub struct DigitalEnvelope {pub encrypted_data: Vec<u8>, // 加密的数据pub encrypted_key: Vec<u8>, // 加密的对称密钥pub nonce: Vec<u8>, // 初始化向量
}impl DigitalEnvelope {// 创建数字信封pub fn seal(data: &[u8], public_key: &RsaPublicKey) -> anyhow::Result<Self> {// 1. 生成随机对称密钥let mut symmetric_key = [0u8; 32]; // AES-256OsRng.fill_bytes(&mut symmetric_key);// 2. 使用对称密钥加密数据let cipher = Aes256Gcm::new(Key::<Aes256Gcm>::from_slice(&symmetric_key));let nonce = Aes256Gcm::generate_nonce(&mut OsRng);let encrypted_data = cipher.encrypt(&nonce, data).map_err(|e| anyhow::anyhow!("加密数据失败: {}", e))?;// 3. 使用公钥加密对称密钥let mut rng = rand::thread_rng();let padding = Oaep::new::<sha2::Sha256>(); // 现在 sha2 可用let encrypted_key = public_key.encrypt(&mut rng, padding, &symmetric_key).map_err(|e| anyhow::anyhow!("加密对称密钥失败: {}", e))?;Ok(DigitalEnvelope {encrypted_data,encrypted_key,nonce: nonce.to_vec(),})}// 打开数字信封pub fn open(&self, private_key: &RsaPrivateKey) -> anyhow::Result<Vec<u8>> {// 1. 使用私钥解密对称密钥let padding = Oaep::new::<sha2::Sha256>();let symmetric_key = private_key.decrypt(padding, &self.encrypted_key).map_err(|e| anyhow::anyhow!("解密对称密钥失败: {}", e))?;// 2. 使用对称密钥解密数据let cipher = Aes256Gcm::new(Key::<Aes256Gcm>::from_slice(&symmetric_key));let nonce = Nonce::from_slice(&self.nonce);let decrypted_data = cipher.decrypt(nonce, self.encrypted_data.as_ref()).map_err(|e| anyhow::anyhow!("解密数据失败: {}", e))?;Ok(decrypted_data)}
}// 密钥管理
pub struct KeyManager;impl KeyManager {// 生成RSA密钥对pub fn generate_keypair(bits: usize) -> anyhow::Result<(RsaPrivateKey, RsaPublicKey)> {let mut rng = rand::thread_rng();let private_key = RsaPrivateKey::new(&mut rng, bits).map_err(|e| anyhow::anyhow!("生成密钥对失败: {}", e))?;let public_key = RsaPublicKey::from(&private_key);Ok((private_key, public_key))}// 保存公钥到文件 - 修正这个方法pub fn save_public_key(public_key: &RsaPublicKey, filename: &str) -> anyhow::Result<()> {let pem = public_key.to_public_key_pem(rsa::pkcs8::LineEnding::LF).map_err(|e| anyhow::anyhow!("序列化公钥失败: {}", e))?;fs::write(filename, pem)?;Ok(())}// 从文件加载公钥pub fn load_public_key(filename: &str) -> anyhow::Result<RsaPublicKey> {let pem = fs::read_to_string(filename)?;let public_key = RsaPublicKey::from_public_key_pem(&pem).map_err(|e| anyhow::anyhow!("加载公钥失败: {}", e))?;Ok(public_key)}
}fn main() -> anyhow::Result<()> {println!("Digital Envelope Demo");// 1. 生成密钥对println!("1. Generating RSA keypair...");let (private_key, public_key) = KeyManager::generate_keypair(2048)?;// 2. 要加密的原始数据 - 使用英文避免编码问题let original_data = b"This is a secret message that needs to be encrypted!";println!("Original data: {}", String::from_utf8_lossy(original_data));// 3. 创建数字信封println!("2. Creating digital envelope...");let envelope = DigitalEnvelope::seal(original_data, &public_key)?;println!("Encrypted data length: {} bytes", envelope.encrypted_data.len());println!("Encrypted key length: {} bytes", envelope.encrypted_key.len());println!("Nonce length: {} bytes", envelope.nonce.len());// 4. 打开数字信封println!("3. Opening digital envelope...");let decrypted_data = envelope.open(&private_key)?;let decrypted_text = String::from_utf8(decrypted_data).map_err(|e| anyhow::anyhow!("UTF-8 decoding failed: {}", e))?;println!("Decrypted data: {}", decrypted_text);// 5. 验证数据完整性if original_data == decrypted_text.as_bytes() {println!("Digital envelope operation successful! Data integrity and confidentiality protected.");} else {println!("Data mismatch!");}Ok(())
}#[cfg(test)]
mod tests {use super::*;#[test]fn test_digital_envelope() -> anyhow::Result<()> {let (private_key, public_key) = KeyManager::generate_keypair(2048)?;let test_data = b"test data"; // 使用英文避免编码问题// 加密let envelope = DigitalEnvelope::seal(test_data, &public_key)?;// 解密let decrypted = envelope.open(&private_key)?;assert_eq!(test_data, decrypted.as_slice());Ok(())}
}
最后cargo run
,如下图示,成功运行数字信封:
代码,文档托管到gitee或github等,推荐gitclone
https://gitee.com/q9z2z2/922.git