public IReadOnlyList <ISignature> Extract(string filePath) { EncodingType encodingType; CryptQueryContentType contentType; CryptQueryFormatType formatType; CryptMsgSafeHandle message = CryptMsgSafeHandle.InvalidHandle; var result = Crypt32.CryptQueryObject(CryptQueryObjectType.CERT_QUERY_OBJECT_FILE, filePath, CryptQueryContentFlagType.CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, CryptQueryFormatFlagType.CERT_QUERY_FORMAT_FLAG_BINARY, CryptQueryObjectFlags.NONE, out encodingType, out contentType, out formatType, IntPtr.Zero, out message, IntPtr.Zero); if (!result) { var resultCode = Marshal.GetLastWin32Error(); switch (unchecked ((uint)resultCode)) { case 0x80092009: //Cannot find request object. There's no signature. return(Array.Empty <ISignature>()); default: throw new Win32Exception(resultCode, "Failed to extract signature."); } } using (message) { if (message.IsInvalid || message.IsClosed) { return(Array.Empty <ISignature>()); } return(GetSignatures(message)); } }
private static unsafe IReadOnlyList <ICmsSignature> GetSignatures(CryptMsgSafeHandle messageHandle) { var countSize = 0u; if (!Crypt32.CryptMsgGetParam(messageHandle, CryptMsgParamType.CMSG_SIGNER_COUNT_PARAM, 0, LocalBufferSafeHandle.Zero, ref countSize)) { return(Array.Empty <ICmsSignature>()); } uint signerCount; using (var countHandle = LocalBufferSafeHandle.Alloc(countSize)) { if (!Crypt32.CryptMsgGetParam(messageHandle, CryptMsgParamType.CMSG_SIGNER_COUNT_PARAM, 0, countHandle, ref countSize)) { return(Array.Empty <ICmsSignature>()); } signerCount = (uint)Marshal.ReadInt32(countHandle.DangerousGetHandle()); } var signatures = new List <ICmsSignature>(); var contentSize = 0u; byte[] content = null; if (Crypt32.CryptMsgGetParam(messageHandle, CryptMsgParamType.CMSG_CONTENT_PARAM, 0, LocalBufferSafeHandle.Zero, ref contentSize)) { using (var contentHandle = LocalBufferSafeHandle.Alloc(contentSize)) { if (Crypt32.CryptMsgGetParam(messageHandle, CryptMsgParamType.CMSG_CONTENT_PARAM, 0, contentHandle, ref contentSize)) { content = new byte[contentSize]; Marshal.Copy(contentHandle.DangerousGetHandle(), content, 0, (int)contentSize); } } } for (var i = 0u; i < signerCount; i++) { var signerSize = 0u; if (!Crypt32.CryptMsgGetParam(messageHandle, CryptMsgParamType.CMSG_SIGNER_INFO_PARAM, i, LocalBufferSafeHandle.Zero, ref signerSize)) { continue; } using (var signerHandle = LocalBufferSafeHandle.Alloc(signerSize)) { if (!Crypt32.CryptMsgGetParam(messageHandle, CryptMsgParamType.CMSG_SIGNER_INFO_PARAM, i, signerHandle, ref signerSize)) { continue; } var signature = new CmsSignature(SignatureKind.Signature, messageHandle, signerHandle, content); signatures.Add(signature); } } return(signatures.AsReadOnly()); }
private void InitFromHandles(CryptMsgSafeHandle messageHandle, LocalBufferSafeHandle signerHandle) { var signerInfo = Marshal.PtrToStructure <CMSG_SIGNER_INFO>(signerHandle.DangerousGetHandle()); var subjectId = new UniversalSubjectIdentifier(signerInfo.Issuer, signerInfo.SerialNumber); var certs = GetCertificatesFromMessage(messageHandle); if (subjectId.Type == SubjectIdentifierType.SubjectKeyIdentifier) { Certificate = FindCertificate((string)subjectId.Value, certs); } else if (subjectId.Type == SubjectIdentifierType.IssuerAndSerialNumber) { Certificate = FindCertificate((X509IssuerSerial)subjectId.Value, certs); } AdditionalCertificates = certs; DigestAlgorithm = new Oid(signerInfo.HashAlgorithm.pszObjId); HashEncryptionAlgorithm = new Oid(signerInfo.HashEncryptionAlgorithm.pszObjId); SerialNumber = ReadBlob(signerInfo.SerialNumber); UnsignedAttributes = ReadAttributes(signerInfo.UnauthAttrs); SignedAttributes = ReadAttributes(signerInfo.AuthAttrs); }
internal X509Certificate2Collection GetCertificatesFromMessage(CryptMsgSafeHandle handle) { var size = (uint)Marshal.SizeOf <uint>(); var certs = new X509Certificate2Collection(); uint certCount; using (var certCountLocalBuffer = LocalBufferSafeHandle.Alloc(size)) { if (!Crypt32.CryptMsgGetParam(handle, CryptMsgParamType.CMSG_CERT_COUNT_PARAM, 0, certCountLocalBuffer, ref size)) { return(certs); } certCount = unchecked ((uint)Marshal.ReadInt32(certCountLocalBuffer.DangerousGetHandle(), 0)); } if (certCount == 0) { return(certs); } for (var i = 0u; i < certCount; i++) { uint certSize = 0; if (!Crypt32.CryptMsgGetParam(handle, CryptMsgParamType.CMSG_CERT_PARAM, i, LocalBufferSafeHandle.Zero, ref certSize)) { continue; } using (var certLocalBuffer = LocalBufferSafeHandle.Alloc(certSize)) { if (!Crypt32.CryptMsgGetParam(handle, CryptMsgParamType.CMSG_CERT_PARAM, i, certLocalBuffer, ref certSize)) { continue; } var data = new byte[certSize]; Marshal.Copy(certLocalBuffer.DangerousGetHandle(), data, 0, data.Length); var cert = new X509Certificate2(data); certs.Add(cert); } } return(certs); }
static CryptMsgSafeHandle() { InvalidHandle = new CryptMsgSafeHandle(true); InvalidHandle.SetHandleAsInvalid(); }
internal Signature(SignatureKind kind, CryptMsgSafeHandle messageHandle, LocalBufferSafeHandle signerHandle) { Kind = kind; InitFromHandles(messageHandle, signerHandle); }