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)); } }
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)); }