密码应用四-数字签名与抵赖难题
一、实验目标
- 理解数字签名“哈希 + 私钥加密”的技术本质,掌握“私钥签名、公钥验签”的密钥用法
- 通过完整操作流程验证数字签名的三大作用:身份认证、防篡改、不可抵赖
- 在 openEuler 24.03 环境中完成从密钥生成到签名验证的全流程实践
- 通过“赖账失败”与“篡改被抓”两个剧情化场景,体会数字签名的法律效力来源
- 实验环境
| 项目 | 说明 |
| 实验名称 | "欠条"电子签名:数字签名与抵赖难题 |
| 实验平台 | |
| 终端环境 | openEuler 24.03 LTS |
| 核心命令 | sha256sum、md5sum、sqlite3、bash 脚本 |
| 工具 | OpenSSL 3.x(openEuler 24.03 默认安装,可通过 rpm -qa openssl 确认版本) |
| 角色设定 | 借款人“小李”、出借人“老王”、想赖账的小李、捣乱的黑客 |
| 实验文件 | 电子欠条文本 iou.txt、小李的 RSA 密钥对(li_private.pem / li_public.pem) |

三、实验步骤
第一步:环境准备与欠条创建
操作:创建实验目录并写入电子欠条。
mkdir -p /home/student/signature_lab
cd /home/student/signature_lab
cat > iou.txt << 'EOF' 今借到老王5000元,2026年底归还。 借款人:小李 日期:2026年9月16日 EOF
cat iou.txt
预期输出:终端显示欠条全文。

知识点:欠条文本将成为数字签名的“原文”,后续所有签名验证操作均针对该文件的完整内容。
第二步:生成小李的 RSA 密钥对
操作:使用 OpenSSL 生成 2048 位 RSA 密钥对,并从私钥中提取公钥。
# 生成私钥(2048位,RSA算法)
Openssl genpkey -algorithm RSA -out li_private.pem -pkeyopt rsa_keygen_bits:2048
# 从私钥提取公钥
openssl rsa -in li_private.pem -pubout -out li_public.pem
参考 OpenSSL 标准用法,genpkey 指定 RSA 算法和密钥长度,rsa -pubout 从私钥中导出公钥。
验证密钥生成结果:
# 查看私钥信息(不显示私钥内容)
openssl rsa -in li_private.pem -text -noout | head -5
# 查看公钥内容
cat li_public.pem
预期输出:私钥显示 Private-Key: (2048 bit),公钥以 -----BEGIN PUBLIC KEY----- 开头。

关键理解:私钥由小李保管(不对外公开),公钥可安全地交给老王。这是“不可抵赖”的物理基础——只有小李持有私钥,因此只有小李能生成有效签名。
第三步:小李用私钥对欠条进行数字签名
操作:使用 SHA-256 哈希算法和 RSA 私钥对欠条文件进行签名。
openssl dgst -sha256 -sign li_private.pem -out iou.sig iou.txt
该命令执行了数字签名的完整过程:先对 iou.txt 计算 SHA-256 哈希值,再用 li_private.pem 中的私钥加密该哈希值,输出为二进制签名文件 iou.sig。这正是数字签名“哈希 + 私钥加密”的技术本质。
验证签名文件已生成:
ls -la iou.sig
# 查看签名文件的十六进制摘要
od -v -An -t x1 iou.sig | head -2
预期输出:iou.sig 文件存在,大小为 256 字节(2048 位 RSA 签名的输出长度)。十六进制内容为随机字节序列,不可直接阅读。

知识点——签名与加密的密钥用法对比:
| 操作 | 使用的密钥 | 目的 |
| 加密 | 公钥加密,私钥解密 | 保证保密性 |
| 签名 | 私钥签名,公钥验签 | 保证真实性、完整性和不可抵赖性 |
这是思考题①的答案核心:两者密钥用法正好相反,不会混淆,因为操作目的和密钥持有者角色不同。
第四步:老王用小李的公钥验证签名(身份确认)
操作:老王收到欠条和签名后,使用小李的公钥进行验签。
openssl dgst -sha256 -verify li_public.pem -signature iou.sig iou.txt
验证过程:OpenSSL 对 iou.txt 重新计算 SHA-256 哈希值,然后用公钥解密签名文件,比较两个哈希值是否一致。如果一致,输出 Verified OK。
预期输出:
Verified OK
验证意义:老王可以确认三件事:(1)签名确实由持有小李私钥的人生成(身份认证);(2)欠条内容与签名时完全一致(完整性);(3)小李无法否认自己签过这份欠条(不可抵赖)。
第五步:赖账失败——不可抵赖性验证
剧情:小李事后声称“这个签名不是我做的,我的私钥从来没有签过这份欠条”。
操作:模拟小李试图用其他人的私钥生成一个“假签名”,看老王能否识破。
# 模拟:生成另一对密钥(代表冒充者)
openssl genpkey -algorithm RSA -out fake_private.pem -pkeyopt rsa_keygen_bits:2048
openssl rsa -in fake_private.pem -pubout -out fake_public.pem
# 用假私钥对同一份欠条签名
openssl dgst -sha256 -sign fake_private.pem -out fake.sig iou.txt
# 老王尝试用小李的公钥验证假签名
openssl dgst -sha256 -verify li_public.pem -signature fake.sig iou.txt
预期输出:
Verification Failure
分析:假签名是用不同的私钥生成的,对应的公钥与小李的公钥不匹配,因此验证失败。这证明了不可抵赖性——只有小李的私钥才能生成通过小李公钥验证的签名,小李无法用“别人冒充我”为借口逃避责任。数字签名的可验证性和防假冒特性在此得到验证。
第六步:篡改被抓——防篡改验证
剧情:小李偷偷修改欠条金额,将“5000 元”改为“500 元”,试图减少还款金额。
操作:篡改欠条内容,然后用原有的签名文件进行验证。
# 篡改前先记录原始内容
cat iou.txt
# 小李篡改欠条金额
sed -i 's/5000元/500元/' iou.txt echo "=== 篡改后的欠条 ==="
cat iou.txt
# 老王用小李的公钥验证(使用篡改前的签名)
openssl dgst -sha256 -verify li_public.pem -signature iou.sig iou.txt
预期输出:
Verification Failure
分析:欠条内容被修改后,SHA-256 哈希值发生根本性变化。即使签名文件 iou.sig 没有被修改,公钥解密签名得到的原始哈希值与篡改后文件的哈希值不一致,验证必然失败。这就是防篡改特性——签名与原文内容严格绑定,任何改动都会导致签名失效。
第七步:使用国密 SM2 算法验证签名
openEuler 在开源版本基础上增加了对 SM2/SM3 算法的签名与验签支持。使用国密算法重复上述流程,对比 RSA 与 SM2 的差异。
# 生成SM2密钥对
openssl ecparam -genkey -name SM2 -out sm2_private.pem
# 提取SM2公钥
openssl ec -in sm2_private.pem -pubout -out sm2_public.pem
# 用SM2私钥 + SM3哈希对欠条签名
openssl dgst -sm3 -sign sm2_private.pem -out iou_sm2.sig iou.txt
# 用SM2公钥验签
openssl dgst -sm3 -verify sm2_public.pem -signature iou_sm2.sig iou.txt
预期输出:Verified OK
openEuler 官方文档确认 OpenSSL 已支持 SM2 算法的签名验证功能。SM2 基于椭圆曲线密码学,相比 RSA 在相同安全强度下密钥更短、运算更快。
四、密钥用法对比总结
本实验的两个核心操作对比如下:
| 维度 | 加密操作 | 签名操作 |
| 发送方使用 | 接收方公钥加密 | 发送方私钥签名 |
| 接收方使用 | 接收方私钥解密 | 发送方公钥验签 |
| 核心目的 | 保密性(防窃听) | 真实性 + 完整性 + 不可抵赖 |
| 密钥流向 | 公钥加密 → 私钥解密 | 私钥签名 → 公钥验签 |
通过执行上述步骤,能够从操作层面牢固掌握“私钥签名、公钥验签”的密钥用法,并通过“赖账失败”和“篡改被抓”两个剧情深刻理解数字签名的法律效力来源。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)