public static extern bool CryptVerifyMessageSignature( ref CRYPT_VERIFY_MESSAGE_PARA pVerifyPara, int dwSignerIndex, byte[] pbSignedBlob, int cbSignedBlob, byte[] pbDecoded, ref int pcbDecoded, IntPtr ppSignerCert );
public static extern Boolean CryptVerifyMessageSignature( ref CRYPT_VERIFY_MESSAGE_PARA pVerifyPara, Int32 dwSignerIndex, Byte[] pbSignedBlob, Int32 cbSignedBlob, Byte[] pbDecoded, ref Int32 pcbDecoded, IntPtr ppSignerCert );
static internal extern bool CryptVerifyDetachedMessageSignature( ref CRYPT_VERIFY_MESSAGE_PARA pVerifyPara, int dwSignerIndex, byte[] pbDetachedSignBlob, int cbDetachedSignBlob, int cToBeSigned, IntPtr[] rgpbToBeSigned, int[] rgcbToBeSigned, IntPtr ppSignerCert );
/// <summary> /// Метод проверки открепленной подписи /// </summary> /// <param name="signatureData"></param> /// <param name="messageData"></param> /// <returns></returns> internal static bool VerifySignDetachedMessage(byte[] signatureData, byte[] messageData) { IntPtr messagePtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(byte)) * messageData.Length); Marshal.Copy(messageData, 0, messagePtr, messageData.Length); IntPtr[] rgpbToBeSigned = new IntPtr[1] { messagePtr }; int[] rgcbToBeSigned = new int[1] { messageData.Length }; GCHandle pCertContext = GCHandle.Alloc(IntPtr.Zero, GCHandleType.Pinned); CRYPT_VERIFY_MESSAGE_PARA verifyParams = new CRYPT_VERIFY_MESSAGE_PARA() { cbSize = (int)Marshal.SizeOf(typeof(CRYPT_VERIFY_MESSAGE_PARA)), dwMsgAndCertEncodingType = PKCS_7_OR_X509_ASN_ENCODING, hCryptProv = 0, pfnGetSignerCertificate = IntPtr.Zero, pvGetArg = IntPtr.Zero }; try { bool result = CApiExtWin.CryptVerifyDetachedMessageSignature( ref verifyParams, // Verify parameters. 0, // Signer index. signatureData, // Buffer for decoded message. signatureData.Length, // Size of buffer. 1, rgpbToBeSigned, // Pointer to signed BLOB. rgcbToBeSigned, // Size of signed BLOB. pCertContext.AddrOfPinnedObject() ); return(result); } catch (Exception ex) { throw new CryptographicException($"Ошибка при попытке выполнить проверку открепленной подписи. {ex.Message}."); } finally { pCertContext.Free(); } }
/// <summary> /// Функция проверки открепленной подписи /// </summary> /// <param name="pVerifyPara"></param> /// <param name="dwSignerIndex"></param> /// <param name="pbDetachedSignBlob"></param> /// <param name="cbDetachedSignBlob"></param> /// <param name="cToBeSigned"></param> /// <param name="rgpbToBeSigned"></param> /// <param name="rgcbToBeSigned"></param> /// <param name="ppSignerCert"></param> /// <returns></returns> static internal bool CryptVerifyDetachedMessageSignature( ref CRYPT_VERIFY_MESSAGE_PARA pVerifyPara, int dwSignerIndex, byte[] pbDetachedSignBlob, int cbDetachedSignBlob, int cToBeSigned, IntPtr[] rgpbToBeSigned, int[] rgcbToBeSigned, IntPtr ppSignerCert ) { if (SignServiceProvider.Csp == CspType.CryptoPro) { return(CApiExtUnixCryptoPro.CryptVerifyDetachedMessageSignature(ref pVerifyPara, dwSignerIndex, pbDetachedSignBlob, cbDetachedSignBlob, cToBeSigned, rgpbToBeSigned, rgcbToBeSigned, ppSignerCert)); } else if (SignServiceProvider.Csp == CspType.VipNet) { return(CApiExtUnixVipNet.CryptVerifyDetachedMessageSignature(ref pVerifyPara, dwSignerIndex, pbDetachedSignBlob, cbDetachedSignBlob, cToBeSigned, rgpbToBeSigned, rgcbToBeSigned, ppSignerCert)); } else { throw new Exception($"CryptVerifyDetachedMessageSignature. Указан неподдерживаемый тип криптопровайдера {SignServiceProvider.Csp}."); } }
public static extern bool CryptVerifyDetachedMessageSignature(ref CRYPT_VERIFY_MESSAGE_PARA parameters, Int32 signerIndex, Byte[] signature, Int32 signatureSize, Int32 contentsCount, IntPtr[] contents, Int32[] contentsSizes, [Out] out IntPtr certificate);
internal bool VerifyDetachedMessage(byte[] signatureData, byte[] messageData, bool isCheckTrusted, ref X509Certificate2 certFromSign) { log.LogDebug("Запущен метод проверки открепленной подписи под Windows платформой."); // Заполняем буфер с информацией о данных на основе которых получена подпись IntPtr messagePtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(byte)) * messageData.Length); Marshal.Copy(messageData, 0, messagePtr, messageData.Length); IntPtr[] rgpbToBeSigned = new IntPtr[1] { messagePtr }; int[] rgcbToBeSigned = new int[1] { messageData.Length }; GCHandle pCertContext = GCHandle.Alloc(IntPtr.Zero, GCHandleType.Pinned); CRYPT_VERIFY_MESSAGE_PARA verifyParams = new CRYPT_VERIFY_MESSAGE_PARA() { cbSize = (int)Marshal.SizeOf(typeof(CRYPT_VERIFY_MESSAGE_PARA)), dwMsgAndCertEncodingType = PKCS_7_OR_X509_ASN_ENCODING, hCryptProv = 0, pfnGetSignerCertificate = IntPtr.Zero, pvGetArg = IntPtr.Zero }; try { log.LogDebug("Выполняем проверку открепленной подписи используя метод CryptVerifyDetachedMessageSignature."); bool result = CApiExtWin.CryptVerifyDetachedMessageSignature( ref verifyParams, // Verify parameters. 0, // Signer index. signatureData, // Buffer for decoded message. signatureData.Length, // Size of buffer. 1, rgpbToBeSigned, // Pointer to signed BLOB. rgcbToBeSigned, // Size of signed BLOB. pCertContext.AddrOfPinnedObject() ); if (!result) { log.LogError($"Метод проверки подписи CryptVerifyDetachedMessageSignature вернул ошибку. Статус код ошибки: {Marshal.GetLastWin32Error()}."); return(result); } log.LogDebug($"Метод CryptVerifyDetachedMessageSignature вернул true. Пытаемся получить сертификат из подписи."); try { log.LogDebug($"Флаг проверки сертификата в списке доверенных издателей {(isCheckTrusted ? "установлен" : "не установлен")}"); // Информацию о сертификате из подписи можно получить только если проверка вернула true, иначе возникнет исключение certFromSign = new X509Certificate2((IntPtr)pCertContext.Target); if (isCheckTrusted) { log.LogDebug("Сертификат из подписи успешно получен. Проверяем наличие сертификата в списке доверенных издателей."); var trustedCerts = GetTrustedCertificates(); if (trustedCerts.Count <= 0) { log.LogError("Список доверенных издателей пуст. Отсутствует доверие к сертификату."); return(false); } if (!trustedCerts.Contains(certFromSign)) { log.LogError("Сертификат указанный в подписи не найден среди доверенных издателей."); return(false); } } } catch (Exception ex) { log.LogError($"Необработанная ошибка при попытке проверить сертификат из подписи на наличие в списке доверенных. {ex.Message}."); return(false); } finally { CApiExtWin.CertFreeCertificateContext((IntPtr)pCertContext.Target); } log.LogDebug("Проверка выполнена. Подпись корректна."); return(result); } finally { pCertContext.Free(); } }