Ключевое слово в защите информации
КЛЮЧЕВОЕ СЛОВО
в защите информации
Получить ГОСТ TLS-сертификат для домена (SSL-сертификат)
Добро пожаловать, Гость! Чтобы использовать все возможности Вход или Регистрация.

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline ruslanf  
#1 Оставлено : 22 сентября 2023 г. 17:37:44(UTC)
ruslanf

Статус: Новичок

Группы: Участники
Зарегистрирован: 22.09.2023(UTC)
Сообщений: 2
Российская Федерация
Откуда: Казань

Почему метод CadesMsgOpenToEncode возвращает ошибку "Объект или свойство не найдено."? В то время как CryptMsgOpenToEncode успешно создает дескриптор сообщения для создания усовершенствованной подписи.
Цитата:

[SecuritySafeCritical]
public unsafe byte[] GetCadesBesSignature(X509Certificate cert, byte[] data)
{
IntPtr hProv = IntPtr.Zero;
nint hMsg = 0;
IntPtr pMessage = IntPtr.Zero;
byte[] signMessage = null;
IntPtr pSignerCertBlob = IntPtr.Zero;
var silent = true;

try
{
uint dwKeySpec = 0;
bool mustFree = false;

var certContext = new ReadOnlySpan<CERT_CONTEXT>(cert.Handle.ToPointer(), 1);
var signerCertBlob = new CRYPT_INTEGER_BLOB
{
cbData = certContext[0].cbCertEncoded,
pbData = certContext[0].pbCertEncoded
};

#region Получаем ссылку на закрытый ключ сертификата и дестриптор криптопровайдера
var flags = (silent ? Constants.CRYPT_ACQUIRE_SILENT_FLAG : 0U) | Constants.CRYPT_ACQUIRE_COMPARE_KEY_FLAG
| Constants.CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG | Constants.CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG;
if (!Crypt32Helper.CryptAcquireCertificatePrivateKey(cert.Handle, flags, 0, out hProv, out dwKeySpec, out mustFree))
{
string error = Crypt32Helper.GetErrorDescription((uint)Kernel32Helper.GetLastError());
throw new CapiLiteCoreException($"Ошибка получения ключа для сертификата: {error}");
}
#endregion

#region задаем параметры подписи
// prepare CMSG_SIGNER_ENCODE_INFO structure
var signerInfo = new CMSG_SIGNER_ENCODE_INFO();
signerInfo.cbSize = (uint)Marshal.SizeOf(signerInfo);
signerInfo.pCertInfo = certContext[0].pCertInfo;
signerInfo.hKey = hProv;
signerInfo.dwKeySpec = dwKeySpec;
string Oid = Constants.szOID_CP_GOST_R3411;// GetHashOid(cert);//Constants.szOID_CP_GOST_R3411
var digestOidLength = Encoding.ASCII.GetByteCount(Oid);
var digestOidRaw = stackalloc byte[digestOidLength + 1];
ReadOnlySpan<char> pin = "1";
Encoding.ASCII.GetBytes(pin, new Span<byte>(digestOidRaw, digestOidLength));
signerInfo.HashAlgorithm.pszObjId = (nint)digestOidRaw;

// prepare CMSG_SIGNED_ENCODE_INFO structure
var signedInfo = new CMSG_SIGNED_ENCODE_INFO();
signedInfo.cbSize = (uint)Marshal.SizeOf(signedInfo);
signedInfo.cSigners = 1;
signedInfo.rgSigners = (nint)(&signerInfo);
signedInfo.cCertEncoded = 1;
signedInfo.rgCertEncoded = (nint)(&signerCertBlob);

var cadesInfo = new CADES_ENCODE_INFO();
cadesInfo.dwSize = (uint)Marshal.SizeOf(cadesInfo);
cadesInfo.pSignedEncodeInfo = (nint)(&signedInfo);
#endregion

// Открываем дескриптор сообщения для создания усовершенствованной подписи
//hMsg = Crypt32Helper.CryptMsgOpenToEncode(Constants.X509_ASN_ENCODING | Constants.PKCS_7_ASN_ENCODING,
// 0, Constants.CMSG_SIGNED, (nint)(&signedInfo), null, 0);//открепленная CMS
//hMsg = Crypt32Helper.CryptMsgOpenToEncode(Constants.X509_ASN_ENCODING | Constants.PKCS_7_ASN_ENCODING,
// 0, Constants.CMSG_SIGNED, (nint)(&signedInfo), null, 0); // прикрепленная CMS
hMsg = CadesHelper.CadesMsgOpenToEncode(Constants.X509_ASN_ENCODING | Constants.PKCS_7_ASN_ENCODING, 0
, (nint)(&cadesInfo), null, 0);//открепленная CADES
if (hMsg == 0)
{
//ExceptionHelper.CurrentDomain_UnhandledException();
string PInvokeError = Crypt32Helper.GetErrorDescription((uint)Marshal.GetLastPInvokeError());
string Kernel32Error = Crypt32Helper.GetErrorDescription((uint)Kernel32Helper.GetLastError());
throw new CapiLiteCoreException($"Ошибка открытия дискриптора сообщения для создания усовершенствованной подписи: {PInvokeError}; {Kernel32Error}");
}

// Формируем подпись в сообщении
fixed (byte* pData = data)
{
if (!Crypt32Helper.CryptMsgUpdate(hMsg, (nint)pData, (uint)data.Length, true))
{
string error = Crypt32Helper.GetErrorDescription((uint)Marshal.GetLastPInvokeError());
throw new CapiLiteCoreException($"Ошибка формирования подписи в сообщении: {error}");
}
}

// Получаем размер подписи
int mSize = 0;
if (!Crypt32Helper.CryptMsgGetParam(hMsg, Constants.CMSG_CONTENT_PARAM, 0, 0, ref mSize))
{
string error = Crypt32Helper.GetErrorDescription((uint)Marshal.GetLastPInvokeError());
throw new CapiLiteCoreException($"Ошибка получения размера подписи подписи: {error}");
}

// Получаем подпись
signMessage = new byte[mSize];
//pMessage = Marshal.AllocCoTaskMem(Marshal.SizeOf(signMessage[0]) * signMessage.Length);

fixed (byte* pSignature = signMessage)
{
if (!Crypt32Helper.CryptMsgGetParam(hMsg, Constants.CMSG_CONTENT_PARAM, 0, (nint)pSignature, ref mSize))
{
string error = Crypt32Helper.GetErrorDescription((uint)Marshal.GetLastPInvokeError());
throw new CapiLiteCoreException($"Ошибка получения подписи: {error}");
}
}

//Marshal.Copy(pMessage, signMessage, 0, (int)mSize);
}
catch (Exception ex){ }
finally
{
if (hProv != IntPtr.Zero) ADVAPI32Helper.CryptReleaseContext(hProv, 0);
Crypt32Helper.CertFreeCertificateContext(cert.Handle);
Crypt32Helper.CryptMsgClose(hMsg);
}

return signMessage;
}


Сертификат создал с помощью тестового УЦ Криптопро. Параметр CADES_ENCODE_INFO заполнил по примеру, взятому с проекта С++ ЭЦП SDK.
Сертификат с алгоритмом подписи - ГОСТ Р 34.11/34.10-2001, Хэш-алгоритмом подписи ГОСТ Р 34.11-94
Offline ruslanf  
#2 Оставлено : 10 октября 2023 г. 17:55:23(UTC)
ruslanf

Статус: Новичок

Группы: Участники
Зарегистрирован: 22.09.2023(UTC)
Сообщений: 2
Российская Федерация
Откуда: Казань

Нашел сам ошибку. По невнимательности передал в поле не верное значение Oid алгоритма хеширования. Исправил на:
Encoding.ASCII.GetBytes(Oid, new Span<byte>(digestOidRaw, digestOidLength));
signerInfo.HashAlgorithm.pszObjId = (nint)digestOidRaw;
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.