OpenSSL SMIME如何确定micalg参数?Ruby PKCS7场景实操问询
问题描述
使用openssl smime -sign构建签名S/MIME消息时,micalg参数(如示例中的micalg="sha-256")的取值逻辑是什么?我在S/MIME文本和签名的ASN.1结构中都能看到该值,但不清楚它的来源及修改方式。
我用Ruby OpenSSL库创建PKCS7文档后,需要确定正确的micalg值来构造AS2 MDN的Content-Type头,示例代码如下:
pkcs7 = OpenSSL::PKCS7.sign certificate, pkey, message pkcs7.detached = true
最初以为该值由签名用的证书或密钥派生,但即使使用MD5算法生成证书,签名后仍得到micalg="sha-256"。比如以下OpenSSL CLI操作:
# 用MD5生成证书 openssl req -x509 -md5 -newkey rsa:2048 -nodes -keyout server_md5.key -out server_md5.crt -days 365 # 签名消息 openssl smime -sign -text -in message.txt -signer test/certificates/server_md5.crt -inkey test/certificates/server_md5.key
输出的S/MIME头中依然是:
Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----FA974EDD77D0E708FEB7C0F3E6B14F13"
将签名保存后用openssl pkcs7 -print查看ASN.1结构,发现d.sign > md_algs部分对应了摘要算法:
PKCS7: type: pkcs7-signedData (1.2.840.113549.1.7.2) d.sign: version: 1 md_algs: algorithm: sha256 (2.16.840.1.101.3.4.2.1) parameter: NULL contents: type: pkcs7-data (1.2.840.113549.1.7.1) d.data: <ABSENT>
根据S/MIME规范定义,digestAlgorithms集合列出了签名者使用的消息摘要算法,而micalg正是对应这个算法的MIME标识。
现在需要明确两个问题:
- 签名消息时如何指定
micalg值 - 如何检查生成的签名以确定
micalg值
1. 签名时如何指定micalg值
micalg的值由签名过程中使用的消息摘要算法决定,和证书生成时的摘要算法无关。要指定它,需要在签名时显式指定摘要算法:
OpenSSL CLI方式
使用-md参数指定摘要算法,比如要设置micalg="md5",命令如下:
openssl smime -sign -text -in message.txt -signer server_md5.crt -inkey server_md5.key -md md5
此时输出的Content-Type头中micalg会变为"md5"。
Ruby OpenSSL库方式
PKCS7.sign方法支持第四个参数传入摘要算法对象,示例代码:
# 指定使用MD5摘要 digest = OpenSSL::Digest::MD5.new pkcs7 = OpenSSL::PKCS7.sign(certificate, pkey, message, digest) pkcs7.detached = true
同理,若要使用SHA-256,可传入OpenSSL::Digest::SHA256.new,对应micalg="sha-256"。
2. 如何检查生成签名中的micalg值
OpenSSL CLI方式
将签名保存到文件后,用pkcs7 -print命令查看ASN.1结构中的md_algs字段,然后将算法名称映射为micalg的字符串格式:
openssl pkcs7 -in signature.p7m -print
输出中md_algs的algorithm字段,比如sha256对应micalg="sha-256",md5对应micalg="md5"。
Ruby OpenSSL库方式
通过解析PKCS7对象的签名信息获取摘要算法,再映射为micalg字符串,示例代码:
# 假设pkcs7是已生成的PKCS7对象 if pkcs7.type == OpenSSL::PKCS7::SIGNED_DATA # 获取第一个签名者的摘要算法 signer_info = pkcs7.signer_infos.first digest_alg = signer_info.digest_algorithm # 建立算法名称到micalg的映射 micalg_mapping = { "SHA256" => "sha-256", "MD5" => "md5", "SHA1" => "sha-1", "SHA384" => "sha-384", "SHA512" => "sha-512" } micalg_value = micalg_mapping[digest_alg.name] puts "对应的micalg值: #{micalg_value}" end
内容的提问来源于stack exchange,提问作者Alex

