示例#1
0
        private bool TryGetTimestamp(PackageDigitalSignature packageSignature, out Timestamp timestamp)
        {
            bool isValidTimestampSignature = false;

            if (packageSignature == null)
            {
                throw new ArgumentNullException(nameof(packageSignature));
            }

            timestamp = new Timestamp()
            {
                SignedOn = DateTime.MaxValue
            };

            XmlNamespaceManager namespaceManager = new XmlNamespaceManager(new NameTable());

            namespaceManager.AddNamespace("ds", "http://schemas.openxmlformats.org/package/2006/digital-signature");

            // Obtain timestamp from Signature Xml if there is one.
            XmlElement element         = packageSignature.Signature.GetXml();
            XmlNode    encodedTimeNode = element.SelectNodes("//ds:TimeStamp/ds:EncodedTime", namespaceManager).OfType <XmlNode>().FirstOrDefault();

            // If timestamp found, verify it.
            if (encodedTimeNode != null && encodedTimeNode.InnerText != null)
            {
                byte[] binaryTimestamp = null;

                try
                {
                    binaryTimestamp = Convert.FromBase64String(encodedTimeNode.InnerText);
                }
                catch (FormatException)
                {
                    return(false);
                }

                IntPtr TSContextPtr = IntPtr.Zero;
                IntPtr TSSignerPtr  = IntPtr.Zero;
                IntPtr StoreHandle  = IntPtr.Zero;

                // Ensure timestamp corresponds to package signature
                isValidTimestampSignature = WinCrypt.CryptVerifyTimeStampSignature(binaryTimestamp,
                                                                                   (uint)binaryTimestamp.Length,
                                                                                   packageSignature.SignatureValue,
                                                                                   (uint)packageSignature.SignatureValue.Length,
                                                                                   IntPtr.Zero,
                                                                                   out TSContextPtr,
                                                                                   out TSSignerPtr,
                                                                                   out StoreHandle);

                if (isValidTimestampSignature)
                {
                    var timestampContext = (CRYPT_TIMESTAMP_CONTEXT)Marshal.PtrToStructure(TSContextPtr, typeof(CRYPT_TIMESTAMP_CONTEXT));
                    var timestampInfo    = (CRYPT_TIMESTAMP_INFO)Marshal.PtrToStructure(timestampContext.pTimeStamp, typeof(CRYPT_TIMESTAMP_INFO));

                    unchecked
                    {
                        uint low         = (uint)timestampInfo.ftTime.dwLowDateTime;
                        long ftTimestamp = (((long)timestampInfo.ftTime.dwHighDateTime) << 32) | low;

                        timestamp.SignedOn = DateTime.FromFileTime(ftTimestamp);
                    }

                    // Get the algorithm name based on the OID.
                    timestamp.SignatureAlgorithm = Oid.FromOidValue(timestampInfo.HashAlgorithm.pszObjId, OidGroup.HashAlgorithm).FriendlyName;

                    X509Certificate2 certificate = new X509Certificate2(packageSignature.Signer);
                    timestamp.EffectiveDate = certificate.NotBefore;
                    timestamp.ExpiryDate    = certificate.NotAfter;
                }

                if (IntPtr.Zero != TSContextPtr)
                {
                    WinCrypt.CryptMemFree(TSContextPtr);
                }
                if (IntPtr.Zero != TSSignerPtr)
                {
                    WinCrypt.CertFreeCertificateContext(TSSignerPtr);
                }
                if (IntPtr.Zero != StoreHandle)
                {
                    WinCrypt.CertCloseStore(StoreHandle, 0);
                }
            }

            return(isValidTimestampSignature);
        }
示例#2
0
        public static IEnumerable <Timestamp> GetTimestamps(string path)
        {
            if (String.IsNullOrEmpty(path))
            {
                return(null);
            }

            var timestamps = new List <Timestamp>();
            int msgAndCertEncodingType;
            int msgContentType;
            int formatType;

            // NULL indicates that information is unneeded
            IntPtr certStore = IntPtr.Zero;
            IntPtr msg       = IntPtr.Zero;
            IntPtr context   = IntPtr.Zero;

            if (!WinCrypt.CryptQueryObject(
                    WinCrypt.CERT_QUERY_OBJECT_FILE,
                    Marshal.StringToHGlobalUni(path),
                    WinCrypt.CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED | WinCrypt.CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED | WinCrypt.CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
                    WinCrypt.CERT_QUERY_FORMAT_FLAG_ALL,
                    0,
                    out msgAndCertEncodingType,
                    out msgContentType,
                    out formatType,
                    ref certStore,
                    ref msg,
                    ref context))
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }

            int cbData = 0;

            // Passing in NULL to pvData retrieves the size of the encoded message
            if (!WinCrypt.CryptMsgGetParam(msg, WinCrypt.CMSG_ENCODED_MESSAGE, 0, IntPtr.Zero, ref cbData))
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }

            byte[] vData = new byte[cbData];
            if (!WinCrypt.CryptMsgGetParam(msg, WinCrypt.CMSG_ENCODED_MESSAGE, 0, vData, ref cbData))
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }

            var signedCms = new SignedCms();

            signedCms.Decode(vData);

            // Timestamp information can be stored in multiple sections.
            // A single SHA1 stores the timestamp as a counter sign in the unsigned attributes
            // Multiple authenticode signatures will store additional information as a nested signature
            // In the case of SHA2 signatures, we need to find and decode the timestamp token (RFC3161).
            // Luckily NuGet implemented a proper TST and DER parser to decode this
            foreach (SignerInfo signerInfo in signedCms.SignerInfos)
            {
                foreach (CryptographicAttributeObject unsignedAttribute in signerInfo.UnsignedAttributes)
                {
                    if (String.Equals(unsignedAttribute.Oid.Value, WinCrypt.szOID_RSA_counterSign, StringComparison.OrdinalIgnoreCase))
                    {
                        foreach (SignerInfo counterSign in signerInfo.CounterSignerInfos)
                        {
                            foreach (CryptographicAttributeObject signedAttribute in counterSign.SignedAttributes)
                            {
                                if (String.Equals(signedAttribute.Oid.Value, WinCrypt.szOID_RSA_signingTime, StringComparison.OrdinalIgnoreCase))
                                {
                                    var st = (Pkcs9SigningTime)signedAttribute.Values[0];
                                    X509Certificate2 cert = counterSign.Certificate;

                                    var timeStamp = new Timestamp
                                    {
                                        SignedOn           = st.SigningTime.ToLocalTime(),
                                        EffectiveDate      = Convert.ToDateTime(cert.GetEffectiveDateString()).ToLocalTime(),
                                        ExpiryDate         = Convert.ToDateTime(cert.GetExpirationDateString()).ToLocalTime(),
                                        SignatureAlgorithm = cert.SignatureAlgorithm.FriendlyName
                                    };

                                    timestamps.Add(timeStamp);
                                }
                            }
                        }
                    }
                    else if (String.Equals(unsignedAttribute.Oid.Value, WinCrypt.szOID_RFC3161_counterSign, StringComparison.OrdinalIgnoreCase))
                    {
                        timestamps.AddRange(GetTimestampsFromCounterSignature(unsignedAttribute.Values[0]));
                    }
                    else if (String.Equals(unsignedAttribute.Oid.Value, WinCrypt.szOID_NESTED_SIGNATURE, StringComparison.OrdinalIgnoreCase))
                    {
                        var       nestedSignature        = new Pkcs9AttributeObject(unsignedAttribute.Values[0]);
                        SignedCms nestedSignatureMessage = new SignedCms();
                        nestedSignatureMessage.Decode(nestedSignature.RawData);

                        foreach (SignerInfo nestedSignerInfo in nestedSignatureMessage.SignerInfos)
                        {
                            foreach (CryptographicAttributeObject nestedUnsignedAttribute in nestedSignerInfo.UnsignedAttributes)
                            {
                                if (String.Equals(nestedUnsignedAttribute.Oid.Value, WinCrypt.szOID_RFC3161_counterSign, StringComparison.OrdinalIgnoreCase))
                                {
                                    timestamps.AddRange(GetTimestampsFromCounterSignature(nestedUnsignedAttribute.Values[0]));
                                }
                            }
                        }
                    }
                }
            }

            return(timestamps);
        }
示例#3
0
        public static bool IsTimestamped(string filename)
        {
            try {
                int    encodingType;
                int    contentType;
                int    formatType;
                IntPtr certStore = IntPtr.Zero;
                IntPtr cryptMsg  = IntPtr.Zero;
                IntPtr context   = IntPtr.Zero;

                if (!WinCrypt.CryptQueryObject(
                        WinCrypt.CERT_QUERY_OBJECT_FILE,
                        Marshal.StringToHGlobalUni(filename),
                        WinCrypt.CERT_QUERY_CONTENT_FLAG_ALL,
                        WinCrypt.CERT_QUERY_FORMAT_FLAG_ALL,
                        0,
                        out encodingType,
                        out contentType,
                        out formatType,
                        ref certStore,
                        ref cryptMsg,
                        ref context))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                //expecting contentType=10; CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED
                //Logger.LogInfo(string.Format("Querying file '{0}':", filename));
                //Logger.LogInfo(string.Format("  Encoding Type: {0}", encodingType));
                //Logger.LogInfo(string.Format("  Content Type: {0}", contentType));
                //Logger.LogInfo(string.Format("  Format Type: {0}", formatType));
                //Logger.LogInfo(string.Format("  Cert Store: {0}", certStore.ToInt32()));
                //Logger.LogInfo(string.Format("  Crypt Msg: {0}", cryptMsg.ToInt32()));
                //Logger.LogInfo(string.Format("  Context: {0}", context.ToInt32()));

                // Get size of the encoded message.
                int cbData = 0;
                if (!WinCrypt.CryptMsgGetParam(
                        cryptMsg,
                        WinCrypt.CMSG_ENCODED_MESSAGE, //Crypt32.CMSG_SIGNER_INFO_PARAM,
                        0,
                        IntPtr.Zero,
                        ref cbData))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                var vData = new byte[cbData];

                // Get the encoded message.
                if (!WinCrypt.CryptMsgGetParam(
                        cryptMsg,
                        WinCrypt.CMSG_ENCODED_MESSAGE, //Crypt32.CMSG_SIGNER_INFO_PARAM,
                        0,
                        vData,
                        ref cbData))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                var signedCms = new SignedCms();
                signedCms.Decode(vData);

                foreach (var signerInfo in signedCms.SignerInfos)
                {
                    foreach (var unsignedAttribute in signerInfo.UnsignedAttributes)
                    {
                        if (unsignedAttribute.Oid.Value == WinCrypt.szOID_RSA_counterSign)
                        {
                            foreach (var counterSignInfo in signerInfo.CounterSignerInfos)
                            {
                                foreach (var signedAttribute in counterSignInfo.SignedAttributes)
                                {
                                    if (signedAttribute.Oid.Value == WinCrypt.szOID_RSA_signingTime)
                                    {
                                        var    fileTime     = new FILETIME();
                                        int    fileTimeSize = Marshal.SizeOf(fileTime);
                                        IntPtr fileTimePtr  = Marshal.AllocCoTaskMem(fileTimeSize);
                                        Marshal.StructureToPtr(fileTime, fileTimePtr, true);

                                        var buffdata = new byte[fileTimeSize];
                                        Marshal.Copy(fileTimePtr, buffdata, 0, fileTimeSize);

                                        var buffSize = (uint)buffdata.Length;

                                        uint encoding = WinCrypt.X509_ASN_ENCODING | WinCrypt.PKCS_7_ASN_ENCODING;

                                        var rsaSigningTime = (UIntPtr)(uint)Marshal.StringToHGlobalAnsi(WinCrypt.szOID_RSA_signingTime);

                                        byte[] pbData  = signedAttribute.Values[0].RawData;
                                        var    ucbData = (uint)pbData.Length;

                                        bool workie = WinCrypt.CryptDecodeObject(encoding, rsaSigningTime, pbData, ucbData, 0, buffdata, ref buffSize);

                                        if (workie)
                                        {
                                            IntPtr fileTimePtr2 = Marshal.AllocCoTaskMem(buffdata.Length);
                                            Marshal.Copy(buffdata, 0, fileTimePtr2, buffdata.Length);
                                            var fileTime2 = (FILETIME)Marshal.PtrToStructure(fileTimePtr2, typeof(FILETIME));

                                            long hFT2 = (((long)fileTime2.dwHighDateTime) << 32) + ((uint)fileTime2.dwLowDateTime);

                                            DateTime dte = DateTime.FromFileTime(hFT2);
                                            Console.WriteLine(dte.ToString());
                                        }
                                        else
                                        {
                                            throw new Win32Exception(Marshal.GetLastWin32Error());
                                        }
                                    }
                                }
                            }

                            return(true);
                        }
                    }
                }
            } catch (Exception) {
                // no logging
            }

            return(false);
        }