如何在C#中复制CAPICOM SignedData.Sign()方法

时间:2019-07-04 10:24:07

标签: c# .net vb6 certificate capicom

我需要为使用VB6 / CAPICOM组件的现有Classic Asp网站编写一个测试工具。目的是重新创建SignedData.Sign()的结果,以便我可以将其发布到Classic Asp网站,在该网站上它将使用CAPICOM解码有效负载。

VB6 CAPICOM供参考

StoreWins

我一直在使用CAPICOM文档here作为指南

等效于C#

Function SignContent(ByVal strXmlToSign As String) As String
    Dim strSignedString As String
    Dim objSign As SignedData ‘ From CAPICOM library
    Set objSign = New SignedData
    objSign.Content = strXmlToSign
    strSignedString = objSign.Sign
    Set objSign = Nothing
    SignContent = strSignedString
End Function

到目前为止,CAPICOM组件无法解码C#生成的签名。

1 个答案:

答案 0 :(得分:0)

经过大量侦探工作,我设法将一条消息发送到可以解码为CAPICOM组件的端点。有效的解决方案如下:

public string Sign(string dataToSign)
{
    // Default to SHA1; required if targeting .Net Framework 4.7.1 or above
    AppContext.SetSwitch("Switch.System.Security.Cryptography.Pkcs.UseInsecureHashAlgorithms", true);

    // The dataToSign byte array holds the data to be signed.
    ContentInfo contentInfo = new ContentInfo(Encoding.Unicode.GetBytes(dataToSign));

    // Create a new, nondetached SignedCms message.
    SignedCms signedCms = new SignedCms(contentInfo, false);

    X509Certificate2 cert = GetCertificate();

    CmsSigner signer = new CmsSigner(cert);

    // Sign the message.
    signedCms.ComputeSignature(signer);

    // Encode the message.
    var encoded = signedCms.Encode();

    // mimic default EncodingType; CAPICOM_ENCODE_BASE64 Data is saved as a base64 - encoded string.
    return Convert.ToBase64String(encoded, Base64FormattingOptions.InsertLineBreaks);
}

更改摘要:

AppContext.SetSwitch("Switch.System.Security.Cryptography.Pkcs.UseInsecureHashAlgorithms", true);

如果以.NET Framework 4.7.1+为目标(我的应用程序以.NET 4.7.1为目标),则默认情况下为这些操作启用SHA256。因为SHA1不再被认为是安全的,所以此更改是必需的。 Source

ContentInfo contentInfo = new ContentInfo(Encoding.Unicode.GetBytes(dataToSign));

从“编码UTF8”更改为“ Unicode”。

return Convert.ToBase64String(encoded, Base64FormattingOptions.InsertLineBreaks);

使用换行选项匹配Capicom输出。