如何将 openssl_pkey_get_public 和 openssl_verify 转换为 C# .NET
PHP 代码验证来自银行的 iPizza 签名:
$key = openssl_pkey_get_public (file_get_contents ($preferences['bank_certificate']));
if (!openssl_verify ($data, $signature, $key)) {
trigger_error ("Invalid signature", E_USER_ERROR);
}
我尝试使用
SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
X509Certificate2 cert = new X509Certificate2(HttpContext.Current.Request.MapPath("~/App_Data/bankert.crt"), "");
RSACryptoServiceProvider rsaCryptoIPT = new RSACryptoServiceProvider();
rsaCryptoIPT.ImportCspBlob(cert.RawData);
if (!rsaCryptoIPT.VerifyData(data, CryptoConfig.MapNameToOID("SHA1"), signature))
throw new InvalidOperationException("Invalid signature from bank ");
rsaCryptoIPT.ImportCspBlob(cert.RawData) 行将其转换为 ASP .NET,但导致 Cryptography.CryptographyException 提供程序版本无效:
StackTrace:
at System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
at System.Security.Cryptography.Utils._ImportCspBlob(Byte[] keyBlob, SafeProvHandle hProv, CspProviderFlags flags, SafeKeyHandle& hKey)
at System.Security.Cryptography.Utils.ImportCspBlobHelper(CspAlgorithmType keyType, Byte[] keyBlob, Boolean publicOnly, CspParameters& parameters, Boolean randomKeyContainer, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle)
at System.Security.Cryptography.RSACryptoServiceProvider.ImportCspBlob(Byte[] keyBlob)
...
如何修复?
银行_证书文件包含
-----开始证书----- MIIDRTCCAq6gAwIBAgIBADANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJFRTEO .... C82uR/wUZJDw9kj+R1O46/byG8yA+S9FVw== -----证书结束-----
更新:我根据
var cert = new X509Certificate2(HttpContext.Current.Request.MapPath("~/App_Data/banksert.crt"), "");
var rsaCryptoIPT = (RSACryptoServiceProvider)cert.PublicKey.Key;
var sha1 = new SHA1CryptoServiceProvider();
if (!rsaCryptoIPT.VerifyData(data, sha1, signature))
throw new InvalidOperationException("Invalid signature from bank ");
对此代码的暴虐回答更改了代码,导致银行异常签名无效。检查中的证书对象显示证书数据。 如何解决这个问题以使签名得到验证? 调试器显示银行证书有效日期已过期。也许这会导致错误或VerifyDate第二个参数错误。
我可以成功地签署数据,并且银行使用代码接受签名
SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
X509Certificate2 cert = new X509Certificate2(HttpContext.Current.Request.MapPath("~/App_Data/P12File.p12"), "");
RSACryptoServiceProvider rsaCryptoIPT = (RSACryptoServiceProvider)cert.PrivateKey;
byte[] binSignature = rsaCryptoIPT.SignData(binData, sha1);
验证银行签名应该与此过程相反,使用相同的算法。如何验证签名?
PHP code verifies iPizza signature from bank:
$key = openssl_pkey_get_public (file_get_contents ($preferences['bank_certificate']));
if (!openssl_verify ($data, $signature, $key)) {
trigger_error ("Invalid signature", E_USER_ERROR);
}
I tried to convert it to ASP .NET using
SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
X509Certificate2 cert = new X509Certificate2(HttpContext.Current.Request.MapPath("~/App_Data/bankert.crt"), "");
RSACryptoServiceProvider rsaCryptoIPT = new RSACryptoServiceProvider();
rsaCryptoIPT.ImportCspBlob(cert.RawData);
if (!rsaCryptoIPT.VerifyData(data, CryptoConfig.MapNameToOID("SHA1"), signature))
throw new InvalidOperationException("Invalid signature from bank ");
but line rsaCryptoIPT.ImportCspBlob(cert.RawData) causes Cryptography.CryptographicException invalid provider version:
StackTrace:
at System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
at System.Security.Cryptography.Utils._ImportCspBlob(Byte[] keyBlob, SafeProvHandle hProv, CspProviderFlags flags, SafeKeyHandle& hKey)
at System.Security.Cryptography.Utils.ImportCspBlobHelper(CspAlgorithmType keyType, Byte[] keyBlob, Boolean publicOnly, CspParameters& parameters, Boolean randomKeyContainer, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle)
at System.Security.Cryptography.RSACryptoServiceProvider.ImportCspBlob(Byte[] keyBlob)
...
How to fix ?
bank_certificate file contains
-----BEGIN CERTIFICATE----- MIIDRTCCAq6gAwIBAgIBADANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJFRTEO
....
C82uR/wUZJDw9kj+R1O46/byG8yA+S9FVw==
-----END CERTIFICATE-----
UPDATE: I changed code according to tyranid answer to
var cert = new X509Certificate2(HttpContext.Current.Request.MapPath("~/App_Data/banksert.crt"), "");
var rsaCryptoIPT = (RSACryptoServiceProvider)cert.PublicKey.Key;
var sha1 = new SHA1CryptoServiceProvider();
if (!rsaCryptoIPT.VerifyData(data, sha1, signature))
throw new InvalidOperationException("Invalid signature from bank ");
This code causes Invalid signature from bank exception. Inspecting cert object in shows cert data.
How to fix this so that signature is validated?
Debugger shows that bank cert valid date has expired. Maybe this causes error or VerifyDate second parameter is wrong.
I can successfully sign the data and bank accepts signature using code
SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
X509Certificate2 cert = new X509Certificate2(HttpContext.Current.Request.MapPath("~/App_Data/P12File.p12"), "");
RSACryptoServiceProvider rsaCryptoIPT = (RSACryptoServiceProvider)cert.PrivateKey;
byte[] binSignature = rsaCryptoIPT.SignData(binData, sha1);
Verifying bank signature should be reverse to this process, same algorithms are used. How to verify signature ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您是否安装了增强型加密提供程序?
实际上,为了不依赖加密提供者,您可以使用其他库,它们以本机代码实现所有加密内容。我知道 EldoS SecureBlackbox(商业版)和 Bouncy Castle(免费版),但是市场上可能还有其他库。
Do you have Enhanced crypto provider installed?
Actually, to not depend on crypto providers, you can use other libraries, which implements all the cryptography stuff in native code. I know about EldoS SecureBlackbox (which is commercial), and Bouncy Castle (free one), however there can be other libraries on market.
如果 X509Certificate2 已成功导入证书文件,则您可以从 PublicKey.Key 参数中获取证书的公钥。
If the X509Certificate2 has successfully imported the cert file then you get the public key of the cert from the PublicKey.Key parameter.