用C#编写的数字签名不能在C ++中验证

时间:2013-04-15 12:41:24

标签: c# c++ rsa digital-signature cryptoapi

我有一个C#应用程序,它使用RSA对数据进行数字签名。代码如下:

RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportCspBlob(privateKeyBlob);

SHA1 sha1 = new SHA1CryptoServiceProvider();
sha1.ComputeHash(myData);

byte[] signature = rsa.SignHash(sha1.Hash, CryptoConfig.MapNameToOID("SHA1"));

我无法在C ++中验证签名。代码如下:

HCRYPTPROV cryptProvider;
CryptAcquireContext(&cryptProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
// PROV_RSA_SIG does not work

HCRYPTKEY publicKey;
CryptImportKey(cryptProvider, publicKeyBlob, publicKeyBlobLength, 0, 0, &publicKey);

HCRYPTHASH hash;
CryptCreateHash(cryptProvider, CALG_SHA1, 0, 0, &hash);
CryptHashData(hash, myData, myDataLength, 0);

BOOL isSigOk = CryptVerifySignature(hash, signature, signatureLength, publicKey, NULL, CRYPT_NOHASHOID);

验证返回0,GetLastError()返回2148073478“无效签名”。哈希是一样的。我在有CRYPT_NOHASHOID标志的情况下尝试了它。

我尝试用C ++签名数据(只是为了比较结果)。我删除了CRYPT_VERIFYCONTEXT标志。但导入私钥BLOB失败1008“尝试引用不存在的令牌”。生成新密钥失败并出现相同的错误。

1 个答案:

答案 0 :(得分:3)

经过逐字节检查后,我得到了它的工作。 C#应用程序中存在两个问题。

1)我使用new RSACryptoServiceProvider(RsaKeySize)生成密钥对。问题是,这会为密钥交换生成密钥对,而不是签名。 C#并不介意,但它在C ++程序中引起了麻烦。生成密钥对的正确方法是:

CspParameters parameters = new CspParameters();
parameters.KeyNumber = (int)KeyNumber.Signature;

RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(RsaKeySize, parameters);

2)RSACryptoServiceProvider反转其输出(签名,加密数据)。它在documentation中提到。因此,在保存之前,您需要Array.Reverse()计算出的签名。