20231302邱之釗密碼系統設計實驗一第二
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:
66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0
Raw 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 directory
4 | #include <openssl/evp.h>
| ^~~~~~~~~~~~~~~
compilation terminated.
sm3hash.c:2:10: fatal error: openssl/evp.h: No such file or directory
2 | #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 directory
4 | #include <openssl/evp.h>
| ^~~~~~~~~~~~~~~
compilation terminated.
sm3hash.c:2:10: fatal error: openssl/evp.h: No such file or directory
2 | #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-256
OsRng.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,如下圖示,成功運行數字信封:


浙公網安備 33010602011771號