第4章:使用OpenSSL进行签名验签操作
4.1 OpenSSL基础与密码算法选择
OpenSSL,说白了就是一把瑞士军刀。做安全的人基本人手一份。我个人习惯把它当作HSM的"前置练习器"——在接入硬件设备之前,先用OpenSSL把流程跑通。
你可能会问:为什么不用更高级的工具?嗯,因为OpenSSL是底层工具,它能让你看清楚每一步到底在干什么。
4.2 支持的签名算法对比
先看一张表。这里是我这些年常用的签名算法对比。你想想看,选错了算法,后面全白干。
| 算法 | 密钥长度 | 签名长度 | 性能 | 适用场景 |
|---|---|---|---|---|
| RSA | 2048/4096 | 256/512字节 | 较慢 | 兼容性要求高 |
| ECDSA | 256/384 | 64/96字节 | 快 | 移动端/IoT |
| EdDSA | 256 | 64字节 | 极快 | 高性能场景 |
| SM2 | 256 | 64字节 | 较快 | 国密合规 |
我在项目中遇到过最头疼的事,就是客户拿着RSA-512的旧证书要求继续用。大哥,512位的RSA已经被破解了,你不换算法我就不接单。
4.3 数字签名核心流程
签名验签,说白了就是两件事:你用私钥签,别人用公钥验。下面这张图是我给团队培训时画的,后来成了我们的标准流程图。
4.4 实操:生成密钥对
第一步,先生成私钥。我习惯用以下命令:
# 生成RSA私钥
openssl genrsa -out private_key.pem 2048
# 或者生成ECDSA私钥
openssl ecparam -genkey -name prime256v1 -out ec_private_key.pem
# 提取公钥
openssl rsa -in private_key.pem -pubout -out public_key.pem
私钥文件的权限必须设为600。我曾经看到新同事把私钥设成644,吓得我赶紧叫他改回来。你想想看,私钥泄露等于你家大门钥匙被别人配了一把。
4.5 实操:签名
有了密钥对,签名就简单了。完整的签名命令是这样:
# 对消息文件进行签名
openssl dgst -sha256 -sign private_key.pem -out signature.bin message.txt
# 查看签名的十六进制内容
xxd signature.bin | head -10
这里要注意:dgst命令会自动对消息做一次SHA-256哈希,然后才用私钥加密。你不用手动算哈希。为什么?因为OpenSSL替你做了,省得你犯错。
签名不要用PKCS#1 v1.5填充模式直接加密哈希。这不是标准签名流程,很多验证工具不认。我一直用dgst命令,省事又标准。
4.6 实操:验签
验签,说白了就是验证签名是否匹配。命令如下:
# 验签
openssl dgst -sha256 -verify public_key.pem \
-signature signature.bin message.txt
# 输出示例
# Verified OK
# 如果消息被篡改
# Verification Failure
只有两种结果:"Verified OK"或"Verification Failure"。没有中间状态。
4.7 常见陷阱
我这些年踩过的坑,挑几个说说:
- 文件编码问题:Windows和Linux的换行符不同。你在Windows上签名,在Linux上验签,结果可能不匹配。我建议始终统一使用二进制模式读写文件。
- 摘要算法不匹配:签名用了SHA-256,验签却用了SHA-1。OpenSSL不会告诉你这个,只会给你一个"Verification Failure",你查半天都查不出来。
- 密钥格式:PEM和DER格式互不兼容。我见过有人把PEM格式的私钥丢给要求DER格式的程序,然后说"OpenSSL有问题"。
记住一个原则:签名方和验签方必须使用完全相同的算法参数。密钥算法、曲线名称、摘要算法、编码格式,一个都不能错。
4.8 性能优化
如果你要批量签名,比如每秒几千次,裸用OpenSSL命令肯定不行。我建议:
- 使用OpenSSL的引擎接口,能加快RSA运算
- 考虑用ECDSA代替RSA,性能能提升3-5倍
- 如果追求极致性能,用EdDSA,实测比ECDSA还快一倍
我曾经为一个支付系统做优化,把签名时间从15ms降到了2ms。怎么做到的?就是把RSA-4096换成了ECDSA P-384,同时用OpenSSL引擎调用了硬件加速模块。说白了,算法和硬件都得选对。
嗯,OpenSSL这部分就先到这儿。用到的时候打开这个笔记,照着命令敲就行了。核心就三个动作:生成密钥对、签名、验签。记住算法要匹配,格式要一致,私钥要看死。