1

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

VB6 CAPICOM 供参考

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# 等价物

public string Sign(string dataToSign)
{    
    ContentInfo contentInfo = new ContentInfo(Encoding.UTF8.GetBytes(dataToSign));

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

    // get cert from store by Serial Number
    X509Certificate2 cert = GetCertificateBy("my-cert-serial-number");
    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);
}

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

4

1 回答 1

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 不再被认为是安全的。来源

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

从编码 UTF8 更改为 Unicode。

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

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

于 2019-07-09T11:19:21.523 回答