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));
            }
        }
Beispiel #2
0
        internal unsafe Signature(AsnEncodedData data, SignatureKind kind)
        {
            Kind = kind;
            fixed(byte *pin = data.RawData)
            {
                EncodingType          encodingType;
                CryptQueryContentType contentType;
                CryptQueryFormatType  formatType;
                CryptMsgSafeHandle    msgHandle;
                var blob = new CRYPTOAPI_BLOB
                {
                    cbData = (uint)data.RawData.Length,
                    pbData = new IntPtr(pin)
                };
                var result = Crypt32.CryptQueryObject(
                    CryptQueryObjectType.CERT_QUERY_OBJECT_BLOB,
                    ref blob,
                    CryptQueryContentFlagType.CERT_QUERY_CONTENT_FLAG_ALL,
                    CryptQueryFormatFlagType.CERT_QUERY_FORMAT_FLAG_BINARY,
                    CryptQueryObjectFlags.NONE,
                    out encodingType,
                    out contentType,
                    out formatType,
                    IntPtr.Zero,
                    out msgHandle,
                    IntPtr.Zero);

                if (!result)
                {
                    msgHandle.Dispose();
                    throw new InvalidOperationException("Unable to read signature.");
                }
                var signerSize = 0u;

                if (!Crypt32.CryptMsgGetParam(msgHandle, CryptMsgParamType.CMSG_SIGNER_INFO_PARAM, 0, LocalBufferSafeHandle.Zero, ref signerSize))
                {
                    throw new InvalidOperationException();
                }
                using (var signerHandle = LocalBufferSafeHandle.Alloc(signerSize))
                {
                    if (!Crypt32.CryptMsgGetParam(msgHandle, CryptMsgParamType.CMSG_SIGNER_INFO_PARAM, 0, signerHandle, ref signerSize))
                    {
                        throw new InvalidOperationException();
                    }
                    InitFromHandles(msgHandle, signerHandle);
                }
            }
        }
        /// <summary>
        /// Gets PKCS#7 signature object of signed file. If file is not signed using authenticode signature, the method return null.
        /// </summary>
        /// <param name="fileInfo">An instance of file object.</param>
        /// <returns>Detached signature object.</returns>
        public static DefaultSignedPkcs7 GetSignatureObject(this FileInfo fileInfo)
        {
            if (!fileInfo.Exists)
            {
                return(null);
            }
            const Int32 CMSG_ENCODED_MESSAGE       = 29;
            const Int32 dwExpectedContentTypeFlags = Wincrypt.CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
                                                     | Wincrypt.CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED;

            if (!Crypt32.CryptQueryObject(
                    Wincrypt.CERT_QUERY_OBJECT_FILE,
                    fileInfo.FullName,
                    dwExpectedContentTypeFlags,
                    Wincrypt.CERT_QUERY_FORMAT_FLAG_ALL,
                    0,
                    out Int32 _,
                    out Int32 pdwContentType,
                    out Int32 _,
                    out IntPtr phCertStore,
                    out IntPtr phMsg,
                    out IntPtr ppvContext
                    ))
            {
                return(null);
            }

            if (!Crypt32.CryptMsgGetParam(phMsg, CMSG_ENCODED_MESSAGE, 0, null, out Int32 pcbData))
            {
                return(null);
            }

            var pvData = new Byte[pcbData];

            Crypt32.CryptMsgGetParam(phMsg, CMSG_ENCODED_MESSAGE, 0, pvData, out pcbData);
            Crypt32.CryptMsgClose(phMsg);
            Crypt32.CertCloseStore(phCertStore, 0);
            switch (pdwContentType)
            {
            case Wincrypt.CERT_QUERY_CONTENT_FLAG_CERT:
            case Wincrypt.CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT:
                Crypt32.CertFreeCertificateContext(ppvContext);
                break;
            }
            return(new DefaultSignedPkcs7(pvData));
        }