OpenSSL 文件数字签名

发布时间: 更新时间: 总字数:1727 阅读时间:4m 作者: IP上海 分享 网址

OpenSSL 数字签名

区别

私钥公钥
公钥私钥(如HTTPS实现)接收者解密时使用发送者加密时使用
数字签名签名者生成签名时使用验证者验证签名时使用
谁持有密钥?个人持有只要需要,任何人都可以持有

信息摘要

  • 信息摘要:对数据进行处理,得到一段固定长度的结果,特点如下:
    • 输出长度固定:即输出长度和输入长度无关
    • 不可逆:输出数据理论上不能推导出输入数据
    • 对输入数据敏感:当输入数据变化极小时,输出数据也会发生明显的变化
    • 防碰撞:不同的数据数据得到相同输出数据的可能性极低
  • 场景:网络等传输后,通过摘要值,确定文件本身有没有发生变化
  • openssl 支持摘要算法(即 openssl --help 输出的 Message Digest commands (see the dgst' command for more details) 信息):
-md4            to use the md4 message digest algorithm
-md5            to use the md5 message digest algorithm
-ripemd160      to use the ripemd160 message digest algorithm
-sha            to use the sha message digest algorithm
-sha1           to use the sha1 message digest algorithm
-sha224         to use the sha224 message digest algorithm
-sha256         to use the sha256 message digest algorithm
-sha384         to use the sha384 message digest algorithm
-sha512         to use the sha512 message digest algorithm
-whirlpool      to use the whirlpool message digest algorithm
  • 以下命令的作用相同
$ openssl dgst -sha1 /etc/hosts
SHA1(/etc/hosts)= 0024556bbcb1584640ab4fb906a50e5ee4f88ddb
$ openssl sha1 /etc/hosts
SHA1(/etc/hosts)= 0024556bbcb1584640ab4fb906a50e5ee4f88ddb
$ sha1sum /etc/hosts
0024556bbcb1584640ab4fb906a50e5ee4f88ddb  /etc/hosts

# debug 信息
$ openssl dgst -sha1 -d /etc/hosts
BIO[0x55e66ce720c0]: ctrl(6) - FILE pointer
BIO[0x55e66ce720c0]: ctrl return 0
BIO[0x55e66ce720c0]: ctrl(108) - FILE pointer
BIO[0x55e66ce720c0]: ctrl return 1
BIO[0x55e66ce720c0]: ctrl(10) - FILE pointer
BIO[0x55e66ce720c0]: ctrl return 0
BIO[0x55e66ce720c0]: ctrl(2) - FILE pointer
BIO[0x55e66ce720c0]: ctrl return 0
BIO[0x55e66ce720c0]: read(0,8192) - FILE pointer
BIO[0x55e66ce720c0]: read return 257
BIO[0x55e66ce720c0]: ctrl(10) - FILE pointer
BIO[0x55e66ce720c0]: ctrl return 0
BIO[0x55e66ce720c0]: ctrl(2) - FILE pointer
BIO[0x55e66ce720c0]: ctrl return 1
SHA1(/etc/hosts)= 0024556bbcb1584640ab4fb906a50e5ee4f88ddb
BIO[0x55e66ce720c0]: ctrl(1) - FILE pointer
BIO[0x55e66ce720c0]: ctrl return 0
BIO[0x55e66ce720c0]: Free - FILE pointer

# 输出二进制
$ openssl dgst -sha1 -binary /etc/hosts

# 输出十六进制
$ openssl dgst -sha1 -c -hex /etc/hosts
SHA1(/etc/hosts)= 00:24:55:6b:bc:b1:58:46:40:ab:4f:b9:06:a5:0e:5e:e4:f8:8d:db

数字签名

  • 数字签名 分成两步:

    • 首先对原始文件进行摘要运算,得到摘要值
    • 然后使用公开密钥算法中的 私钥 对摘要值进行加密
    • 用户通过 公钥 验证文件和签名是否匹配
  • 在数字签名中,有 2 种行为:

    • 生成消息签名的行为,两种生成和验证数字签名的方法:
      • 直接对消息签名的方法(推荐)
      • 对消息的散列值签名的方法
    • 验证消息签名的行为
  • 使用 openssl dgst 管理数字签名

$ openssl dgst --help
Usage: dgst [options] [file...]
  file... files to digest (default is stdin)
 -help               Display this summary
 -list               List digests
 -c                  Print the digest with separating colons
 -r                  Print the digest in coreutils format
 -out outfile        Output to filename rather than stdout
 -passin val         Input file pass phrase source
 -sign val           Sign digest using private key
 -verify val         Verify a signature using public key
 -prverify val       Verify a signature using private key
 -signature infile   File with signature to verify
 -keyform format     Key file format (PEM or ENGINE)
 -hex                Print as hex dump
 -binary             Print in binary form
 -d                  Print debug info
 -debug              Print debug info
 -fips-fingerprint   Compute HMAC with the key used in OpenSSL-FIPS fingerprint
 -hmac val           Create hashed MAC with key
 -mac val            Create MAC (not necessarily HMAC)
 -sigopt val         Signature parameter in n:v form
 -macopt val         MAC algorithm parameters in n:v form or key
 -*                  Any supported digest
 -rand val           Load the file(s) into the random number generator
 -writerand outfile  Write random data to the specified file
 -engine val         Use engine e, possibly a hardware device
 -engine_impl        Also use engine given by -engine for digest operations

RSA 签名

  • RSA 算法是一种非对称加密算法,与对称加密算法不同的是,RSA算法有两个不同的密钥
    • 一个是公钥
    • 一个是私钥
  • 在公开密钥密码体制中,加密密钥(即公开密钥)PK是公开信息,而解密密钥(即秘密密钥)SK是需要保密的
  • 加密算法E和解密算法D也都是公开的
  • 虽然解密密钥SK是由公开密钥PK决定的,但却不能根据PK计算出SK
# 1. Create private/public key pair
openssl genrsa -out private.key 1024

# 2. Extracting Public key
openssl rsa -in private.key -out public.pem -outform PEM -pubout

# 3. Create hash of the data.
echo 'data to sign' > example.txt
openssl dgst -sha256 < example.txt > hash

# 4. Sign the hash using Private key to a file called hash.sign
openssl dgst -sha256 -sign private.key -out hash.sign hash

# 5. Verify the file (example.txt)and the digital signature (hash.sign)
openssl dgst -sha256 -verify public.pem -signature hash.sign hash

# 6. Verify the file (example.txt) by private key
openssl dgst -sha256 -prverify private.key -signature hash.sign hash
  • 指定 RSASSA-PSS 标准
# 签名
openssl dgst -sha256 -sign private.key -sigopt rsa_padding_mode:pss -out signature.txt hash

# 验证
openssl dgst -sha256 -verify public.pem -sigopt rsa_padding_mode:pss -signature signature.txt hash

DSA 签名

  • DSA(Digital Signature Algorithm)是一种数字签名的算法
    • 是由 NIST(National Institute of Standards and Technology,美国国家标准技术研究所) 于 1991 年制定的 数字签名规范(Digital Signature Standard,DSS)
    • DSA 是 Schnorr 算法和 ElGamal 方式的变体,只能用于数字签名,不能进行加密解密
# 生成参数文件,类似于 DH 参数文件
$ openssl dsaparam -out dsaparam.pem 1024

# 生成密钥对,通过参数文件生成密钥对 dsaprivatekey.pem
$ openssl gendsa -out dsaprivatekey.pem dsaparam.pem

# 通过密钥对文件拆分出公钥
$ openssl dsa -in dsaprivatekey.pem -pubout -out dsapublickey.pem

# 查看私钥文件的信息,三个公共参数、公钥、私钥
$ openssl dsa -in dsaprivatekey.pem -text

# 查看公钥和文件的信息
$ openssl dsa -pubin -in dsapublickey.pem -text

# DSA 进行签名
$ openssl dgst -sha256 -sign dsaprivatekey.pem -out signature.txt hash

# 验证签名
$ openssl dgst -sha256 -verify dsapublickey.pem -signature signature.txt hash

ECDSA 签名

  • ECDSA(Elliptic Curve Digital Signature Algorithm) 是一种利用 椭圆曲线密码 来实现的数字签名算法
  • 相比 DSA 算法,ECDSA 算法安全性更高
  • 在 ECDSA 中,有三个参数很重要:
    • ECDSA 算法选择的命名曲线
    • G,椭圆曲线的基点
    • n,相当于 G 基点的打点操作,n * G = 0
# 直接生成 ECDSA 私钥,不用预先生成 ECC 参数文件
$ openssl ecparam -name secp256k1 -genkey -out ecdsa_priv.pem

# 显示私钥信息
$ openssl ec -in ecdsa_priv.pem -text -noout

# 提取公钥
$ openssl ec -in ecdsa_priv.pem -pubout -out ecdsa_pub.pem

# 显示公钥
$ openssl ec -in ecdsa_pub.pem -pubin -text -noout

# 选择 sha256 作为 HASH 算法
$ openssl dgst -sha256 -sign ecdsa_priv.pem -out signature.txt example.txt

# 校验签名
$ openssl dgst -sha256 -verify ecdsa_pub.pem -signature signature.txt example.txt

Rabin

  • Rabin 方式是由 M.O.Rabin 设计的公钥算法,利用了在 mod N 中求平方根的困难度。Rabin 方式可以被用于公钥密码和数字签名

总结

  • DSA 签名算法运算比 RSA 签名运算慢很多,但是 ECDSA 签名算法比 RSA 签名生成快的多,ECDSA 签名验证却比 RSA 签名验证相对慢
  • 从安全和速度综合考虑,在 DSA 和 ECDSA 中选一个,优先选择 ECDSA

扩展

参考

  1. https://opensource.com/article/19/6/cryptography-basics-openssl-part-2
  2. https://github.com/halfrost/Halfrost-Field/blob/master/contents/Protocol/HTTPS-digital-signature.md
Home Archives Categories Tags Statistics
本文总阅读量 次 本站总访问量 次 本站总访客数