无法使用公钥C#验证签名数据

时间:2020-09-02 18:15:08

标签: c# validation private-key x509certificate2 rsa-sha256

我有一个需要签名某些数据然后确认签名有效的应用程序。使用的算法是RSA SHA256。我在Windows证书存储区中拥有一个带有其各自私钥的证书。我搜索了几篇文章,并以此为依据this。创建签名没有问题。我的问题是,当尝试使用公用密钥确认签名是否有效时,VerifyData方法返回False。我没有使用C#和加密的丰富经验,也看不出这段代码有什么问题。不幸的是,我使用的是旧框架(4.5)

X509Store store = new X509Store(StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);

var certificates = store.Certificates.Find(X509FindType.FindBySerialNumber, "XXXXXXXXXXXXXX", false);
var certificate = certificates(0);

store.Close();

var privKey = (RSACryptoServiceProvider)certificate.PrivateKey;

var enhCsp = new RSACryptoServiceProvider().CspKeyContainerInfo;
var cspparams = new CspParameters(enhCsp.ProviderType, enhCsp.ProviderName, privKey.CspKeyContainerInfo.KeyContainerName);
privKey = new RSACryptoServiceProvider(cspparams);

byte[] sig = privKey.SignData(dataToSign, CryptoConfig.MapNameToOID("SHA256"));

bool isValid = privKey.VerifyData(dataToSign, CryptoConfig.MapNameToOID("SHA256"), sig);
string Signbase64String = Convert.ToBase64String(sig, 0, sig.Length);

if (isValid)
{
    // Print Signature just to confirm...
    // Here the signature validation WORKS! but I am using the private key 
}

var publicKey = (RSACryptoServiceProvider)certificate.PublicKey.Key;
bool isValid2 = publicKey.VerifyData(dataToSign, CryptoConfig.MapNameToOID("SHA256"), sig);
// isValid2 returns false. It not works with PUBLIC KEY

我什至以这种方式(直接加载.cer文件)并且响应是相同的

var 509 = new X509Certificate2(File.ReadAllBytes("certificate.cer"));
var publicKey = (RSACryptoServiceProvider)509.PublicKey.Key;
bool isValid2 = publicKey.VerifyData(dataToSign, CryptoConfig.MapNameToOID("SHA256"), sig);
// isValid2 returns false

非常感谢您的支持

1 个答案:

答案 0 :(得分:0)

在您提供的链接中,私钥的实现方式有所不同。我在下面进行了测试,VerifyData返回true。请注意privateKey创建中的区别。

string certPath = "C:\\testing.pfx";
string certPass = "MagicPassword";

X509Certificate2Collection collection = new X509Certificate2Collection();
collection.Import(certPath, certPass, X509KeyStorageFlags.Exportable);
X509Certificate2 cert = collection[0];


RSACryptoServiceProvider publicKey = (RSACryptoServiceProvider)cert.PublicKey.Key;
RSACryptoServiceProvider privateKey = new RSACryptoServiceProvider();
privateKey.FromXmlString(cert.PrivateKey.ToXmlString(true));

byte[] data = Encoding.UTF8.GetBytes("Hello");
byte[] signature = privateKey.SignData(data, CryptoConfig.MapNameToOID("SHA256"));
bool isValid = publicKey.VerifyData(data, CryptoConfig.MapNameToOID("SHA256"), signature);