0

早些时候,我们的 Application-A 使用 C++,并且在将消息发送到 Application-B 之前使用 C++ 中的加密 API 函数对消息进行了签名,与http://msdn.microsoft.com/en-us/library/中描述的示例完全相同windows/桌面/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 或其他 3rd 方实现,如 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:使用指定的散列算法计算指定字节数组的散列值,并对生成的散列值进行签名。

由于这种差异,Application-B 在验证消息时会抛出错误,说“无效签名”。

所以我不能使用.net 提供的这个 RSACryptoServiceProvider 类型。有没有其他方法可以使用任何 .NET API 来实现相同的目标?(使用 .net API 时,输出字节数组应与使用上述 PInvoke 示例时的输出字节数组相似),以便 Application-B 可以正常工作。

任何帮助表示赞赏。

4

1 回答 1

2

经过长时间的研究,我找到了一种方法。如果其他人正在寻找如何使用 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找到信息。

于 2014-04-28T05:23:12.097 回答