Статус: Новичок
Группы: Участники
Зарегистрирован: 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
|