Статус: Новичок
Группы: Участники
Зарегистрирован: 24.11.2023(UTC) Сообщений: 8 Сказал(а) «Спасибо»: 1 раз
|
Добрый день, уважаемые форумчане! Помогите, пожалуйста, разобраться. Задача: требуется "подпись запроса в формате PKCS#7 detached signature в формате urlSafeBase64 в кодировке UTF-8 – подписанный не ранее, чем за 24 часа (86400 с) параметр UUID сертификатом организации, на сотрудника которой был выдан (сформирован) идентификационный ключ". Я установила КриптоПро .NET и КриптоПро .NET SDK. Нашла примеры - .NET SDK\Examples\simple.zip\CMS\cs\DetachedSignature.cs Полностью взяла код из этого файла, но у меня ничего не работает. Код:
public static byte[] MainMethod(string[] args, String msg)
{
try
{
ClearLog();
// Проверка корректности переданных параметров.
if (args.Length < 1)
{
Log(string.Format("CMS.DetachedSignature <cert-subject>"));
return Array.Empty<byte>();
}
String signerName = args[0];
// Исходное сообщение.
//const String msg = "Это сообщение, которое будет подписано.";
Log(string.Format("{0}Исходное сообщение (длина {1}): {2} ",
Environment.NewLine, msg.Length, msg));
// Переводим исходное сообщение в массив байтов.
Encoding unicode = Encoding.UTF8;
byte[] msgBytes = unicode.GetBytes(msg);
Log(string.Format("{0}{0}------------------------------",
Environment.NewLine));
Log(string.Format(" Поиск сертификата "));
Log(string.Format("------------------------------{0}",
Environment.NewLine));
// Получаем сертификат ключа подписи;
// он будет использоваться для получения
// секретного ключа подписи.
X509Certificate2 signerCert = GetSignerCert(signerName);
Log(string.Format("{0}{0}------------------------------",
Environment.NewLine));
Log(string.Format(" На стороне отправителя"));
Log(string.Format("------------------------------{0}",
Environment.NewLine));
byte[] encodedSignature = SignMsg(msgBytes, signerCert);
File.WriteAllBytes("signature.bin", encodedSignature);
Log(string.Format("{0}{0}------------------------------",
Environment.NewLine));
Log(string.Format(" На стороне получателя "));
Log(string.Format("------------------------------{0}",
Environment.NewLine));
// При проверка detached подписи передаем и само сообщение
if (VerifyMsg(msgBytes, encodedSignature))
{
Log(string.Format("{0}Сообщение проверено.",
Environment.NewLine));
}
else
{
Log(string.Format("{0}Ошибка при проверке сообщения.",
Environment.NewLine));
}
return encodedSignature;
}
catch (Exception)
{
return new byte[0];
}
}
// Открываем хранилище 'My' и ищем сертификат
// для подписи сообщения.
private static X509Certificate2 GetSignerCert(string signerName)
{
// Открываем хранилище My.
X509Store storeMy = new X509Store(StoreName.My,
StoreLocation.CurrentUser);
storeMy.Open(OpenFlags.ReadOnly);
// Отображаем сертификаты для удобства работы
// с примером.
Log(string.Format("Найдены сертификаты следующих субъектов " +
"в хранилище {0}:", storeMy.Name));
foreach (X509Certificate2 cert in storeMy.Certificates)
{
Log(string.Format("\t{0}", cert.SubjectName.Name));
}
// Ищем сертификат для подписи.
X509Certificate2Collection certColl =
storeMy.Certificates.Find(X509FindType.FindBySubjectName,
signerName, false);
Log(string.Format(
"Найдено {0} сертификат(ов) в хранилище {1} для субъекта {2}",
certColl.Count, storeMy.Name, signerName));
// Проверяем, что нашли требуемый сертификат
if (certColl.Count == 0)
{
Log(string.Format(
"Сертификат для данного примера не найден " +
"в хранилище. Выберите другой сертификат для подписи. "));
return null;
}
storeMy.Close();
// Если найдено более одного сертификата,
// возвращаем первый попавщийся.
return certColl[0];
}
// Подписываем сообщение секретным ключем.
private static byte[] SignMsg(
Byte[] msg,
X509Certificate2 signerCert)
{
// Создаем объект ContentInfo по сообщению.
// Это необходимо для создания объекта SignedCms.
ContentInfo contentInfo = new ContentInfo(msg);
// Создаем объект SignedCms по только что созданному
// объекту ContentInfo.
// SubjectIdentifierType установлен по умолчанию в
// IssuerAndSerialNumber.
// Свойство Detached устанавливаем явно в true, таким
// образом сообщение будет отделено от подписи.
SignedCms signedCms = new SignedCms(contentInfo, true);
// Определяем подписывающего, объектом CmsSigner.
CmsSigner cmsSigner = new CmsSigner(signerCert);
// Подписываем CMS/PKCS #7 сообение.
Log(string.Format("Вычисляем подпись сообщения для субъекта " +
"{0} ... ", signerCert.SubjectName.Name));
signedCms.ComputeSignature(cmsSigner);
Log(string.Format("Успешно."));
// Кодируем CMS/PKCS #7 подпись сообщения.
return signedCms.Encode();
}
// Проверяем SignedCms сообщение и возвращаем Boolean
// значение определяющее результат проверки.
private static bool VerifyMsg(Byte[] msg,
byte[] encodedSignature)
{
// Создаем объект ContentInfo по сообщению.
// Это необходимо для создания объекта SignedCms.
ContentInfo contentInfo = new ContentInfo(msg);
// Создаем SignedCms для декодирования и проверки.
SignedCms signedCms = new SignedCms(contentInfo, true);
// Декодируем подпись
signedCms.Decode(encodedSignature);
// Перехватываем криптографические исключения, для
// возврата о false значения при некорректности подписи.
try
{
// Проверяем подпись. В данном примере не
// проверяется корректность сертификата подписавшего.
// В рабочем коде, скорее всего потребуется построение
// и проверка корректности цепочки сертификата.
Log(string.Format("Проверка подписи сообщения ... "));
signedCms.CheckSignature(true);
Log(string.Format("Успешно."));
}
catch (System.Security.Cryptography.CryptographicException e)
{
Log(string.Format("Функция VerifyMsg возбудила исключение: {0}",
e.Message));
Log(string.Format("Проверка PKCS #7 сообщения завершилась " +
"неудачно. Возможно сообщене, подпись, или " +
"соподписи модифицированы в процессе передачи или хранения. " +
"Подписавший или соподписавшие возможно не те " +
"за кого себя выдают. Достоверность и/или целостность " +
"сообщения не гарантируется. "));
return false;
}
return true;
}
Ошибка падает в методе SignMsg на строчке Код:signedCms.ComputeSignature(cmsSigner);
Текст ошибки: Цитата: System.Security.Cryptography.CryptographicException: 'Could not determine signature algorithm for the signer certificate.'
This exception was originally thrown at this call stack: System.Security.Cryptography.Pkcs.CmsSigner.Sign(System.ReadOnlyMemory<byte>, string, bool, out System.Security.Cryptography.X509Certificates.X509Certificate2Collection) System.Security.Cryptography.Pkcs.SignedCms.ComputeSignature(System.Security.Cryptography.Pkcs.CmsSigner, bool) System.Security.Cryptography.Pkcs.SignedCms.ComputeSignature(System.Security.Cryptography.Pkcs.CmsSigner) Samples.CMS.DetachedSignature.SignMsg(byte[], System.Security.Cryptography.X509Certificates.X509Certificate2) in DetachedSignature.cs Samples.CMS.DetachedSignature.MainMethod(string[], string) in DetachedSignature.cs
Помогите, пожалуйста, разобраться. Может ли проблема быть связана сертификатом? Если для этого могут потребоваться характеристики сертификата, то я скину их. И вообще, соответствует ли мой код задаче? К сожалению, пока что я дилетант в криптографии, пытаюсь во всем разобраться, но пока без особых успехов. Помогите, пожалуйста
|