Как реплицировать метод CAPICOM SignedData.Sign () в C # - PullRequest
1 голос
/ 04 июля 2019

Мне нужно написать тестовый комплект для существующего сайта Classic Asp, который использует компоненты VB6 / CAPICOM. Цель состоит в том, чтобы воссоздать результат 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.

1 Ответ

0 голосов
/ 09 июля 2019

После большой детективной работы мне удалось отправить сообщение конечной точке, которое может быть декодировано компонентом 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.

...