OpenSSL生成签名时如何指定填充方式?解决与.NET签名不一致问题
问题描述
我们的服务器团队使用以下.NET代码为给定校验和生成签名:
Convert.ToBase64String(rsap.SignHash(SHA256.HashData(Convert.FromHexString(strHash)), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
该代码采用RSA签名填充方式Pkcs1。我通过以下命令生成SHA256校验和:
sha256sum v.tgz | awk '{printf $1}' > chksum
但客户端使用Shell执行以下OpenSSL命令生成签名时,即使使用相同私钥,生成的签名与服务器端完全不同:
openssl dgst -sha256 -sign ipdvr-private-key.pem chksum | openssl base64 -A
我怀疑是因为OpenSSL命令未指定RSA签名填充方式导致的,请问是否确实如此?需给OpenSSL命令添加哪些参数才能生成与服务器端一致的签名?
解决方案
- 差异根源:填充方式不是问题,
openssl dgst -sign默认使用PKCS#1 v1.5填充,和.NET代码的RSASignaturePadding.Pkcs1完全一致。真正的问题是数据处理流程不同:- .NET逻辑:对校验和的十六进制字符串做Hex解码→对解码后的二进制数据做SHA256哈希→签名该哈希值
- 原OpenSSL命令逻辑:直接对
chksum文件里的十六进制字符串原文做SHA256哈希→签名,相当于处理的原始数据和.NET完全不同
- 修正后的OpenSSL命令:需要先把十六进制字符串转成二进制数据,再执行签名,命令如下:
若要显式指定填充方式(避免环境默认值差异),可以添加参数明确声明:xxd -r -p chksum | openssl dgst -sha256 -sign ipdvr-private-key.pem | openssl base64 -Axxd -r -p chksum | openssl dgst -sha256 -sign ipdvr-private-key.pem -sigopt rsa_padding_mode:pkcs1 | openssl base64 -A - 关键命令解释:
xxd -r -p:将十六进制字符串转换为原始二进制数据,对应.NET中的Convert.FromHexString(strHash)openssl dgst -sha256 -sign:自动对输入的二进制数据做SHA256哈希,再用指定私钥签名,和.NET中SHA256.HashData(...)+SignHash(...)的逻辑完全对齐
内容的提问来源于stack exchange,提问作者kadina
相关产品推荐
相关产品推荐

