Мне нужно написать тестовую обвязку для существующего веб-сайта 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 здесь в качестве руководства.
Эквивалент С#
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.
Можете ли вы отредактировать свой вопрос и включить образец вывода для версий VB6 и C#?
@DaveInCaz знаковый метод, см. документы здесь: docs.microsoft.com/en-us/windows/win32/seccrypto/…





После большой детективной работы мне удалось отправить сообщение на конечную точку, которая может быть декодирована компонентом 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.
Вместо переключателя AppContext для сброса настроек по умолчанию можно просто вручную назначить signer.DigestAlgorithm = new Oid("1.3.14.3.2.26");
@bartonjs спасибо за это. Я как невнимательный. Есть ли список допустимых значений? Почему «1.3.14.3.2.26» = SHA1?
Вы написали «воссоздать результат SignedData.Sign()», но я предполагаю, что вместо этого вы имели в виду «SignedData.SignContent()»?