早些时候,我们的Application-A使用C ++编写,并在使用C ++中的加密API函数将其发送到Application-B之前签署了一条消息,与http://msdn.microsoft.com/en-us/library/windows/desktop/aa382372%28v=vs.85%29.aspx中描述的示例完全相似。
Application-B再次使用C ++中的Crypto API函数验证了此消息(上面的示例再次讨论了如何验证已签名的消息)。
现在我们正在将旧的C ++ Application-A转换/迁移到C#。 我已经找到了一种在C#中使用P-Invoke 对消息进行签名的方法,并且当Application-B(使用C ++ CryptVerifySignatureMessage)验证签名消息时,一切正常。 示例可在 - http://blogs.msdn.com/b/alejacma/archive/2008/02/21/how-to-sign-a-message-and-verify-a-message-signature-c.aspx。
中找到正如 @CodeInChaos 在他的评论中提到的,我希望将互操作留给框架(不使用P-Invoke或其他第三方实现,如BountyCastle)
所以想知道.net是否提供任何API来签署消息(作为学习视角),如果是,我该如何实现它。
注意:
我已经尝试过.Net提供的加密包装API RSACryptoServiceProvider 。
private byte[] SignData(byte[] data, string certThumbPrint)
{
X509Certificate2 cert = GetCertificate(); // finds the certificate with thumbprint
RSACryptoServiceProvider rsaCryptoServiceProvider = (RSACryptoServiceProvider)cert.PrivateKey;
return rsaCryptoServiceProvider.SignData(data, new SHA1CryptoServiceProvider());
}
但是发现C ++的CryptSignMessage和C#的RSACryptoServiceProvider.SignData()方法的返回值(字节数组)存在很大差异。
•CryptSignMessage:CryptSignMessage函数创建指定内容的散列,对散列进行签名,然后对原始消息内容和签名散列进行编码。
•RSA.SignData:使用指定的哈希算法计算指定字节数组的哈希值,并对结果哈希值进行签名。
由于存在这种差异,应用程序B在验证邮件时会抛出错误,说“无效签名”。
所以我不能使用.net提供的这种RSACryptoServiceProvider类型。 有没有其他方法可以使用任何.NET API实现相同的功能? (当使用.net API时,输出字节数组应与使用上面提到的PInvoke示例时的输出字节数组类似),以便Application-B可以正常工作。
感谢任何帮助。
答案 0 :(得分:1)
经过一番长时间的研究,我发现了一种方法。如果其他人正在寻找如何使用C#中的证书使用PKCS7格式签名消息,那么就在这里,
public byte[] SignMsg(
Byte[] msg,
X509Certificate2 signerCert)
{
// Place message in a ContentInfo object.
// This is required to build a SignedCms object.
ContentInfo contentInfo = new ContentInfo(msg);
// Instantiate SignedCms object with the ContentInfo above.
// Has default SubjectIdentifierType IssuerAndSerialNumber.
// Has default Detached property value false, so message is
// included in the encoded SignedCms.
SignedCms signedCms = new SignedCms(contentInfo);
// Formulate a CmsSigner object, which has all the needed
// characteristics of the signer.
CmsSigner cmsSigner = new CmsSigner(signerCert);
// Sign the PKCS #7 message.
Console.Write("Computing signature with signer subject " +
"name {0} ... ", signerCert.SubjectName.Name);
signedCms.ComputeSignature(cmsSigner);
Console.WriteLine("Done.");
// Encode the PKCS #7 message.
return signedCms.Encode();
}
从链接http://msdn.microsoft.com/en-us/library/ms180961%28v=vs.85%29.aspx中找到信息。