public void T1_ValidSignature ()
		{
			byte[] data = GetData ("SignedValidSignaturesTest1.eml");
			SignedCms cms = new SignedCms ();
			cms.Decode (data);
			Assert.IsTrue (CheckHash (cms), "CheckHash");
			Assert.IsTrue (CheckSignature (cms), "CheckSignature");

			X509Certificate2 ee = GetCertificate ("ValidCertificatePathTest1EE.crt");
			// certificates aren't in any particuliar order
			Assert.IsTrue (cms.Certificates.Contains (ee), "EE");
			Assert.IsTrue (cms.Certificates.Contains (GoodCACert), "GoodCACert");
			Assert.IsFalse (cms.Detached, "Detached");
			Assert.AreEqual (1, cms.Version, "Version");
			Assert.AreEqual ("1.2.840.113549.1.7.1", cms.ContentInfo.ContentType.Value, "ContentInfo.Oid");
			Assert.AreEqual ("43-6F-6E-74-65-6E-74-2D-54-79-70-65-3A-20-74-65-78-74-2F-70-6C-61-69-6E-3B-20-63-68-61-72-73-65-74-3D-69-73-6F-2D-38-38-35-39-2D-31-0D-0A-43-6F-6E-74-65-6E-74-2D-54-72-61-6E-73-66-65-72-2D-45-6E-63-6F-64-69-6E-67-3A-20-37-62-69-74-0D-0A-0D-0A-54-68-69-73-20-69-73-20-61-20-73-61-6D-70-6C-65-20-73-69-67-6E-65-64-20-6D-65-73-73-61-67-65-2E", BitConverter.ToString (cms.ContentInfo.Content), "ContentInfo.Content");
			Assert.AreEqual (1, cms.SignerInfos.Count, "SignerInfos.Count");
			Assert.AreEqual (ee, cms.SignerInfos[0].Certificate, "SignerInfos[0].Certificate");
			Assert.AreEqual (0, cms.SignerInfos[0].CounterSignerInfos.Count, "SignerInfos[0].CounterSignerInfos.Count");
			Assert.AreEqual ("1.3.14.3.2.26", cms.SignerInfos[0].DigestAlgorithm.Value, "cms.SignerInfos[0].DigestAlgorithm");
			Assert.AreEqual (0, cms.SignerInfos[0].SignedAttributes.Count, "SignerInfos[0].SignedAttributes.Count");
			Assert.AreEqual (SubjectIdentifierType.IssuerAndSerialNumber, cms.SignerInfos[0].SignerIdentifier.Type, "SignerInfos[0].SignerIdentifier.Type");
			X509IssuerSerial xis = (X509IssuerSerial) cms.SignerInfos[0].SignerIdentifier.Value;
			Assert.AreEqual ("CN=Good CA, O=Test Certificates, C=US", xis.IssuerName, "SignerInfos[0].SignerIdentifier.Value.IssuerName");
			Assert.AreEqual ("01", xis.SerialNumber, "SignerInfos[0].SignerIdentifier.Value.SerialNumber");
			Assert.AreEqual (0, cms.SignerInfos[0].UnsignedAttributes.Count, "SignerInfos[0].UnsignedAttributes.Count");
			Assert.AreEqual (1, cms.SignerInfos[0].Version, "SignerInfos[0].Version");
		}
示例#2
1
        protected string CheckSig()
        {
            var formData = Request.Form;
            var text = formData["txtSign"];
            var sig = formData["txtSig"];

            string output = "INVALID!";

            if (!string.IsNullOrEmpty(sig))
            {
                try
                {
                    ContentInfo contentInfo = new ContentInfo(Encoding.UTF8.GetBytes(text));

                    SignedCms signedCms = new SignedCms(contentInfo, true);

                    signedCms.Decode(Convert.FromBase64String(sig));

                    // This checks if the signature is valid, but doensn't actually verify the cert (TODO)
                    signedCms.CheckSignature(true);

                    output = "Signature valid.";

                    signedCms.CheckSignature(false);

                    output += "<br>Cert valid";
                }
                catch (Exception e)
                {
                    output += "<br>" + e.ToString();
                }
            }

            return output;
        }
示例#3
1
        public bool ValidateToken(byte[] token, byte[] nonce, byte[] certificate, byte[] signature)
        {
            SignedCms cms = new SignedCms();
            cms.Decode(certificate);

            var certificates = cms.Certificates.Cast<X509Certificate2>().ToArray();

            var leaf = certificates.Single(cert => cert.Extensions.Cast<X509Extension>().Any(usage =>
            {
                var eku = usage as X509EnhancedKeyUsageExtension;
                if (eku != null)
                {
                    return eku.EnhancedKeyUsages.Cast<Oid>().Any(oid => oid.Value == "1.3.6.1.4.1.311.10.5.40");
                }
                return false;
            }));

            var signedData = nonce.Concat(token).ToArray();

            var publicKeyProvider = leaf.PublicKey.Key as System.Security.Cryptography.RSACryptoServiceProvider;

            return publicKeyProvider.VerifyData(signedData, CryptoConfig.MapNameToOID("SHA1"), signature);

            // not working either (same results)
            //
            //SHA1Managed hash = new SHA1Managed();
            //byte[] hashedData;
            //hashedData = hash.ComputeHash(signedData);

            //if (!publicKeyProvider.VerifyHash(hashedData, CryptoConfig.MapNameToOID("SHA1"), signature))
            //    throw new Exception("Invalid or Corrupted HardwareToken");
        }
        /// <summary>
        /// Gets certificates contained in pkcs 7.
        /// </summary>
        /// <returns>Returns certificates contained in pkcs 7. Returns null if no certificates.</returns>
        public X509Certificate2Collection GetCertificates()
        {
            if(this.Data == null){
                return null;
            }

            SignedCms signedCms = new SignedCms();
            signedCms.Decode(this.Data);

            return signedCms.Certificates;
        }
示例#5
0
        public static void CheckSig(byte[] sig, byte[] data)
        {
            ContentInfo contentInfo = new ContentInfo(data);

            SignedCms signedCms = new SignedCms(contentInfo, true);

            signedCms.Decode(sig);

            // This checks if the signature is valid, but doensn't actually verify the cert (TODO)
            signedCms.CheckSignature(true);

            signedCms.CheckSignature(false);
        }
 public static bool VerifySign(byte[] data)
 {
     try
     {
         SignedCms signed = new SignedCms();
         signed.Decode(data);
     }
     catch
     {
         return false; // Arquivo não assinado
     }
     return true;
 }
示例#7
0
 public bool Verify(byte[] data, byte[] signature)
 {
     var signedCms = new SignedCms();
     signedCms.Decode(signature);
     try
     {
         signedCms.CheckSignature(_certificate2Collection, false);
     }
     catch(Exception e)
     {
         return false;
     }
     return signedCms.ContentInfo.Content.SequenceEqual(_md5.ComputeHash(data));
 }
        /// <summary>
        /// Gets signed mime content. Value null means no content.
        /// </summary>
        /// <returns>Returns signed mime content. Value null means no content.</returns>
        /// <remarks>This method is valid only if <b>Content-Type</b> parameter <b>smime-type=signed-data</b>.</remarks>
        /// <exception cref="InvalidOperationException">Is raised when <b>smime-type != signed-data</b>.</exception>
        public MIME_Message GetSignedMime()
        {
            if(!string.Equals(this.Entity.ContentType.Parameters["smime-type"],"signed-data",StringComparison.InvariantCultureIgnoreCase)){
                throw new InvalidOperationException("The VerifySignature method is only valid if Content-Type parameter smime-type=signed-data.");
            }

            if(this.Data != null){
                SignedCms signedCms = new SignedCms();
                signedCms.Decode(this.Data);

                return MIME_Message.ParseFromStream(new MemoryStream(signedCms.ContentInfo.Content));
            }
            else{
                return null;
            }
        }
示例#9
0
        public static String CheckFileSignature(ContentInfo content, byte[] signature)
        {
            var verifyCms = new SignedCms(content, true);
            verifyCms.Decode(signature);

            var cert = verifyCms.SignerInfos[0].Certificate;

            try
            {
                verifyCms.CheckSignature(new X509Certificate2Collection(cert), false);
                return @"Signature is valid";
            }
            catch (CryptographicException)
            {
                return @"Signature is not valid for content";
            }
        }
        public static bool IsSignedBy(this X509Certificate thisCertificate, X509Certificate signerCertificate)
        {
            X509Certificate2 c = new X509Certificate2(thisCertificate.GetTbsCertificate());
            X509Certificate2 i = new X509Certificate2(signerCertificate.GetTbsCertificate());
            X509Certificate2 c2 = new X509Certificate2(@"c:\temp\der.cer");
            X509Certificate2 i2 = new X509Certificate2(@"c:\temp\cader.cer");
            /*byte[] pvSubject = thisCertificate.GetTbsCertificate();
            byte[] pvIssuer = signerCertificate.GetTbsCertificate();
            */
            System.Text.Encoding.ASCII.GetString(c.RawData);
            IntPtr pvSubject = c.Handle;
            IntPtr pvIssuer = i.Handle;
            int res = SspiProvider.CryptVerifyCertificateSignatureEx(IntPtr.Zero, X509_ASN_ENCODING,
                                                           CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT, pvSubject,
                                                           CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT, pvIssuer, 0,
                                                           IntPtr.Zero);
            Marshal.GetLastWin32Error();
            CmsSigner signer = new CmsSigner(i);
            SignedCms signedMessage = new SignedCms();
            // deserialize PKCS #7 byte array

            signedMessage.Decode(thisCertificate.GetTbsCertificate());
            Log.Write("Veryfy old");
            Log.Write("EndVeryfy old");
            Log.Write("Get signer's public key");
            var publicKey = signerCertificate.GetPublicKey();
            Log.Write("Got signer's public key");
            try
            {
                Log.Write("Veryfy signature");
                //TODO: log errors
                thisCertificate.Verify(publicKey);
                Log.Write("Verified");
            }
            catch (CertificateException)
            {
                return false;
            }
            catch (InvalidKeyException)
            {
                return false;
            }
            return true;
        }
示例#11
0
        public static SignatureResponse Sign(byte[] data)
        {
            // TODO:
            // padding configuration
            // algorithm configuration
            // encoding configuration
            /*
            SHA1Managed sha1 = new SHA1Managed();
            byte[] hash = sha1.ComputeHash(data);

            var sig = csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA1"));
            //sig = csp.SignData(Encoding.UTF8.GetBytes(text), CryptoConfig.MapNameToOID("SHA1"));

            MessageBox.Show("SignData");
            */

            var content = new ContentInfo(data);
            var cms = new SignedCms(content, true); // TODO detached config
            var signer = new CmsSigner();
            signer.IncludeOption = X509IncludeOption.EndCertOnly;

            cms.ComputeSignature(signer, false);
            var sig = cms.Encode();

            //ensure my signature is correct before continuing.
            cms.CheckSignature(true);

            var newCMS = new SignedCms(content, false);
            newCMS.Decode(sig);
            newCMS.CheckSignature(true);

            var cert = cms.Certificates[0];
            CheckSig(sig, data);
            return new SignatureResponse
            {
                publicKey = Convert.ToBase64String(cert.PublicKey.EncodedKeyValue.RawData),
                signature = Convert.ToBase64String(sig),
                fullSig = null // TODO
            };
        }
示例#12
0
        internal static SignedCms RequestTimestamp(byte[] data, string hashAlgorithmOid, Uri timestampingAuthorityUrl)
        {
            var para = new CRYPT_TIMESTAMP_PARA()
            {
                fRequestCerts = true
            };

            IntPtr unmanagedContext = IntPtr.Zero;
            byte[] encodedResponse;
            try
            {
                NativeUtils.ThrowIfFailed(NativeMethods.CryptRetrieveTimeStamp(
                    wszUrl: timestampingAuthorityUrl.ToString(),
                    dwRetrievalFlags: NativeMethods.TIMESTAMP_VERIFY_CONTEXT_SIGNATURE,
                    dwTimeout: 5 * 1000 /* 5 second timeout */,
                    pszHashId: hashAlgorithmOid,
                    pPara: ref para,
                    pbData: data,
                    cbData: (uint)data.Length,
                    ppTsContext: out unmanagedContext,
                    ppTsSigner: IntPtr.Zero,
                    phStore: IntPtr.Zero));

                // Copy the encoded response out
                var context = (CRYPT_TIMESTAMP_CONTEXT)Marshal.PtrToStructure(unmanagedContext, typeof(CRYPT_TIMESTAMP_CONTEXT));
                encodedResponse = new byte[context.cbEncoded];
                Marshal.Copy(context.pbEncoded, encodedResponse, 0, (int)context.cbEncoded);
            }
            finally
            {
                if (unmanagedContext != IntPtr.Zero)
                {
                    NativeMethods.CryptMemFree(unmanagedContext);
                }
            }

            SignedCms cms = new SignedCms();
            cms.Decode(encodedResponse);
            return cms;
        }
        public static byte[] SignFile(X509Certificate2 cert, byte[] data)
        {
            try
            {
                ContentInfo content = new ContentInfo(data);
                SignedCms signedCms = new SignedCms(content, false);
                if (VerifySign(data))
                {
                    signedCms.Decode(data);
                }

                CmsSigner signer = new CmsSigner(cert);
                signer.IncludeOption = X509IncludeOption.WholeChain;
                signedCms.ComputeSignature(signer);

                return signedCms.Encode();
            }
            catch (Exception ex)
            {
                throw new Exception("Erro ao assinar arquivo. A mensagem retornada foi: " + ex.Message);
            }
        }
示例#14
0
        public void Timestamp(Uri timestampingAuthority, string requestedDigestAlgorithmName)
        {
            var digestAlgorithmOid = CryptoConfig.MapNameToOID(requestedDigestAlgorithmName);
            if (digestAlgorithmOid == null)
            {
                throw new InvalidOperationException("Unknown digest algorithm: " + requestedDigestAlgorithmName);
            }

            // Get the encrypted digest to timestamp
            byte[] digest;
            using (var cms = NativeCms.Decode(_signature.Encode(), detached: false))
            {
                digest = cms.GetEncryptedDigest();
            }

            // Request a timestamp and add it to the signature as an unsigned attribute
            var timestamp = RFC3161.RequestTimestamp(digest, digestAlgorithmOid, timestampingAuthority);

            // Build the certificate chain locally to ensure we store the whole thing
            var chain = new X509Chain();
            if (!chain.Build(timestamp.SignerInfos[0].Certificate))
            {
                throw new InvalidOperationException("Unable to build certificate chain for timestamp!");
            }

            // Reopen the timestamp as a native cms so we can modify it
            byte[] rawTimestamp;
            using (var cms = NativeCms.Decode(timestamp.Encode(), detached: false))
            {
                cms.AddCertificates(chain.ChainElements
                    .Cast<X509ChainElement>()
                    .Where(c => !timestamp.Certificates.Contains(c.Certificate))
                    .Select(c => c.Certificate.Export(X509ContentType.Cert)));
                rawTimestamp = cms.Encode();
            }

            // Reopen the signature as a native cms so we can modify it
            SignedCms newSignature = new SignedCms();
            using (var cms = NativeCms.Decode(_signature.Encode(), detached: false))
            {
                cms.AddTimestamp(rawTimestamp);
                var newSig = cms.Encode();
                newSignature.Decode(newSig);
            }

            // Reset the signature
            SetSignature(newSignature);
        }
示例#15
0
        public override bool VerifyFile(string filePath, ref List<KeyValuePair<X509Certificate2, bool>> verifiedCMS)
        {
            byte[] DataDigest = new byte[0];
            byte[] BlockDigest = new byte[0];
            signatureBlock = new Elements(ExtractBlocks(filePath), false);

            //digest of the data without the signature(s)
            DataDigest = Hash(filePath);
            //signatures found in the file
            Dictionary<string, string> Signatures = ExtractAllSignatures(filePath);
            if (Signatures.Count < 1) throw new NoSignatureFoundException(filePath);

            List<KeyValuePair<X509Certificate2, bool>> UsedCertificates = new List<KeyValuePair<X509Certificate2, bool>>();

            bool Validation = true;

            foreach (String Signature in Signatures.Keys)
            {
                BlockDigest = HashFunction.ComputeHash(new MemoryStream(System.Text.Encoding.UTF8.GetBytes(Signatures[Signature])));
                byte[] merkleHash = new byte[DataDigest.Length + BlockDigest.Length];
                Array.Copy(DataDigest, merkleHash, DataDigest.Length);
                Array.Copy(BlockDigest, 0, merkleHash, DataDigest.Length, BlockDigest.Length);

                //Content information created from the data digest
                ContentInfo StepContent = new ContentInfo(merkleHash);

                SignedCms SignedCMS = new SignedCms(StepContent, true);
                SignedCMS.Decode(Convert.FromBase64String(Signature));
                SignerInfoEnumerator Enumerator = SignedCMS.SignerInfos.GetEnumerator();
                if (!Enumerator.MoveNext()) throw new InvalidSignerInformationException(Signature);

                try
                {
                    //after decoding the signed cms, we check the signature
                    SignedCMS.CheckSignature(true);
                    UsedCertificates.Add(new KeyValuePair<X509Certificate2, bool>(Enumerator.Current.Certificate, true));

                }
                catch (System.Security.Cryptography.CryptographicException e)
                {
                    //signature can't be verified
                    UsedCertificates.Add(new KeyValuePair<X509Certificate2, bool>(Enumerator.Current.Certificate, false));
                    Validation = false;
                }

            }
            verifiedCMS = UsedCertificates;
            return Validation;
        }
示例#16
0
        void FurtherWork()
        {
            usNumSigs = tDSIG.usNumSigs;
            if ( tDSIG.usNumSigs > 1 )
                throw new NotImplementedException("usNumSigs=" + tDSIG.usNumSigs + " > 1" );
            for ( uint v = 0; v < tDSIG.usNumSigs ; v++ )
            {
                Table_DSIG.SignatureBlock sgb;
                try {
                    sgb = tDSIG.GetSignatureBlock(v);
                } catch (IndexOutOfRangeException)
                {
                    Warn_MalformedSIG = true;
                    break;
                }

                SignedCms cms = new SignedCms();
                cms.Decode(sgb.bSignature);

                signer_count = cms.SignerInfos.Count;
                if ( signer_count > 1 )
                    throw new NotImplementedException("SignerInfos.Count=" + signer_count + " > 1" );
                foreach ( var si in cms.SignerInfos )
                {
                    signer = si.Certificate.Subject;
                };

                ASN1 spc = new ASN1(cms.ContentInfo.Content);

                ASN1 playload_oid = null;
                ASN1 oid = null;
                ASN1 digest = null;
                ASN1 obsolete = null;
                if ( Type.GetType("Mono.Runtime") == null )
                {
                    // DotNet is much saner!
                    playload_oid = spc[0][0];
                    obsolete = spc[0][1][0];
                    oid = spc[1][0][0];
                    digest = spc[1][1];
                }
                else
                {
                    playload_oid = spc[0];
                    obsolete = spc[1][0];
                    oid = spc[2][0][0];
                    digest = spc[2][1];
                }

                string algo = ASN1Convert.ToOid (oid);
                algoname = (new Oid(algo)).FriendlyName;
                signed_hash = digest.Value;

                switch ( algoname )
                {
                    case "md5":
                        hash = HashAlgorithm.Create ("MD5");
                        break;
                    case "sha1":
                        hash = HashAlgorithm.Create ("SHA1");
                        break;
                    default:
                        throw new NotImplementedException("Unknown HashAlgorithm: " + algoname );
                }

                if ( fontfile.IsCollection() )
                {
                    calc_hash = get_TTC_digest();
                }
                else
                {
                    calc_hash = get_TTF_digest();
                }
            }
        }
示例#17
0
        static int Main( string[] args )
        {
            if (args.Length == 0) {
                Console.WriteLine("DSIGInfo [-v] [-v] [-v] fontfile");
                return 0;
            }

            OTFile f = new OTFile();
            Table_DSIG tDSIG = null;
            string filename = null;
            verbose = 0;

            for ( int i = 0; i < args.Length; i++ ) {
                if ( "-v" == args[i] )
                    verbose++;
                else
                    filename = args[i];
            }

            if ( !f.open(filename) )
            {
                    Console.WriteLine("Error: Cannot open {0} as font file", filename);
                    return 0;
            }

            TTCHeader ttc = null;
            if ( f.IsCollection() )
            {
                ttc = f.GetTTCHeader();
                if ( f.GetTableManager().GetUnaliasedTableName(ttc.DsigTag) == "DSIG" )
                {
                MBOBuffer buf = f.ReadPaddedBuffer(ttc.DsigOffset, ttc.DsigLength);
                tDSIG = (Table_DSIG) f.GetTableManager().CreateTableObject(ttc.DsigTag, buf);
                }
                for (uint i = 0; i < f.GetNumFonts() ; i++)
                {
                    OTFont fn = f.GetFont(i);
                    Table_DSIG memDSIG = (Table_DSIG) fn.GetTable("DSIG");
                    if (memDSIG != null)
                    {
                        Console.WriteLine("Warning: DSIG in member font");
                        break;
                    }
                }
            }
            else
            {
                OTFont fn = f.GetFont(0);
                tDSIG = (Table_DSIG) fn.GetTable("DSIG");
            }

            Console.WriteLine("{0} DSIG table: {1}", filename,
                              ( tDSIG == null ) ? "Absent" : "Present" );
            if (tDSIG == null)
                return 0;
            if ( f.IsCollection() && ttc.version != 0x00020000 )
                Console.WriteLine("Warning: TTC has DSIG but header version is 0x{0}, != 0x00020000", ttc.version.ToString("X8"));

            if ( tDSIG.usNumSigs != 1 )
            Console.WriteLine("NumSigs = {0}", tDSIG.usNumSigs);
            for ( uint v = 0; v < tDSIG.usNumSigs ; v++ )
            {
                Table_DSIG.SignatureBlock sgb;
                try {
                    sgb = tDSIG.GetSignatureBlock(v);
                } catch (IndexOutOfRangeException)
                {
                    Console.WriteLine("Error: Out of Range SignatureBlock {0}", v);
                    break;
                }

                SignedCms cms = new SignedCms();
                cms.Decode(sgb.bSignature);

                if ( cms.SignerInfos.Count > 1 )
                Console.WriteLine( "#SignerInfos: {0}", cms.SignerInfos.Count );
                foreach ( var si in cms.SignerInfos )
                {
                    Console.WriteLine(si.Certificate);
                    if ( Type.GetType("Mono.Runtime") == null )
                        foreach ( var ua in si.UnsignedAttributes )
                        {
                            foreach ( var asnd in ua.Values )
                            {
                                try
                                {
                                    ASN1 vv = new ASN1(asnd.RawData);
                                    ASN1 t = new ASN1(vv[3][1][1].Value);
                                    Console.WriteLine("Decoded Signing Time: {0}", ASN1Convert.ToDateTime (t) );
                                }
                                catch (Exception e)
                                {/* Nothing to do */ }
                            }
                        }
                }
                Console.WriteLine( "#Certificates: {0}", cms.Certificates.Count );
            #if HAVE_MONO_X509
                certs =  new Mono.Security.X509.X509CertificateCollection ();
                //Mono.Security.X509.X509Chain signerChain = new Mono.Security.X509.X509Chain ();
            #endif
                foreach ( var x509 in cms.Certificates )
                {
            #if HAVE_MONO_X509
                    certs.Add(new Mono.Security.X509.X509Certificate(x509.RawData));
            #endif
                if ( verbose > 0 )
                {
                    Console.WriteLine(x509);
                }
                else
                {
                    Console.WriteLine(x509.Subject);
                }
                };
            #if HAVE_MONO_X509
                Mono.Security.X509.X509Certificate x = new Mono.Security.X509.X509Certificate(cms.SignerInfos[0].Certificate.RawData);
                Mono.Security.X509.X509Certificate parent = x;
                while (x != null) { // Self-signed is fine - the font bundled CA is self-signed.
                    parent = x; // last valid
                    x = FindCertificateParent (x);
                    if (x != null && x.Equals(parent))
                        break;
                }
            #endif
                ASN1 spc = new ASN1(cms.ContentInfo.Content);

                ASN1 playload_oid = null;
                ASN1 oid = null;
                ASN1 digest = null;
                ASN1 obsolete = null;
                if ( Type.GetType("Mono.Runtime") == null )
                {
                    // DotNet is much saner!
                    playload_oid = spc[0][0];
                    obsolete = spc[0][1][0];
                    oid = spc[1][0][0];
                    digest = spc[1][1];
                }
                else
                {
                    playload_oid = spc[0];
                    obsolete = spc[1][0];
                    oid = spc[2][0][0];
                    digest = spc[2][1];
                }
                string algo = ASN1Convert.ToOid (oid);
                string algoname = (new Oid(algo)).FriendlyName;
                Console.WriteLine("Digest Algorithm: {0}", algoname);
                byte[] Value = digest.Value;
                StringBuilder hexLine_sig = new StringBuilder ();
                for (int i = 0; i < Value.Length; i++) {
                    hexLine_sig.AppendFormat ("{0} ", Value [i].ToString ("X2"));
                }
                hexLine_sig.AppendFormat (Environment.NewLine);

                switch ( algoname )
                {
                    case "md5":
                        hash = HashAlgorithm.Create ("MD5");
                        break;
                    case "sha1":
                        hash = HashAlgorithm.Create ("SHA1");
                        break;
                    default:
                        throw new NotImplementedException("Unknown HashAlgorithm: " + algoname );
                }

                byte[] cdigest;
                if ( f.IsCollection() )
                {
                    cdigest = get_TTC_digest( f );

                }
                else
                {
                    cdigest = get_TTF_digest( f );
                }
                StringBuilder hexLine = new StringBuilder ();
                for (int i = 0; i < cdigest.Length; i++) {
                    hexLine.AppendFormat ("{0} ", cdigest [i].ToString ("X2"));
                }
                hexLine.AppendFormat (Environment.NewLine);
                Console.WriteLine("{0} Signed Digest:\t{1}", algoname.ToUpper(), hexLine_sig);
                Console.WriteLine("Calculated Digest:\t{0}", hexLine);
                string root_thumb = "";
            #if HAVE_MONO_X509
                root_thumb =
                    (new System.Security.Cryptography.X509Certificates.X509Certificate2(parent.RawData)).Thumbprint;
                Console.WriteLine("ChainEnd Name: {0}", parent.SubjectName);
                Console.WriteLine("ChainEnd Self-Signed: {0}", parent.IsSelfSigned);
            #endif
                Console.WriteLine("ChainEnd: {0}", root_thumb);
                bool trusted = false;
                try
                {
                    string root_id = trusted_roots[root_thumb];
                    Console.WriteLine("RootID: {0}", root_id);
                    trusted = true;
                }
                catch (KeyNotFoundException)
                {}
                Console.WriteLine("Trusted: {0}", trusted);
            }

            return 0;
        }
        //  Verify the encoded SignedCms message and return a Boolean
        //  value that specifies whether the verification was successful.
        //  Also return the original message that was signed, which is
        //  available as part of the SignedCms message after it
        //  is decoded.
        public static bool VerifyMsg(byte[] encodedSignedCms,
            out byte[] origMsg)
        {
            //  Prepare a SignedCms object in which to decode
            //  and verify.
            SignedCms signedCms = new SignedCms();

            signedCms.Decode(encodedSignedCms);

            //  Catch a verification exception in the event you want to
            //  advise the message recipient that security actions
            //  might be appropriate.
            try
            {
                //  Verify signature. Do not validate signer
                //  certificate for the purposes of this example.
                //  Note that in a production environment, validating
                //  the signer certificate chain will probably be
                //  necessary.
                Console.Write("Checking signature on message ... ");
                signedCms.CheckSignature(true);
                Console.WriteLine("Done.");
            }
            catch (System.Security.Cryptography.CryptographicException e)
            {
                Console.WriteLine("VerifyMsg caught exception:  {0}",
                    e.Message);
                Console.WriteLine("The message may have been modified " +
                    "in transit or storage. Authenticity of the " +
                    "message is not guaranteed.");
                origMsg = null;
                return false;
            }

            origMsg = signedCms.ContentInfo.Content;

            return true;
        }
示例#19
0
        private void GetSignature()
        {
            if (_vbaPart == null) return;
            var rel = _vbaPart.GetRelationshipsByType(schemaRelVbaSignature).FirstOrDefault();
            if (rel != null)
            {
                Uri = PackUriHelper.ResolvePartUri(rel.SourceUri, rel.TargetUri);
                Part = _vbaPart.Package.GetPart(Uri);

                var stream = Part.GetStream();
                BinaryReader br = new BinaryReader(stream);
                uint cbSignature = br.ReadUInt32();
                uint signatureOffset = br.ReadUInt32();     //44 ??
                uint cbSigningCertStore = br.ReadUInt32();
                uint certStoreOffset = br.ReadUInt32();
                uint cbProjectName = br.ReadUInt32();
                uint projectNameOffset = br.ReadUInt32();
                uint fTimestamp = br.ReadUInt32();
                uint cbTimestampUrl = br.ReadUInt32();
                uint timestampUrlOffset = br.ReadUInt32();
                byte[] signature = br.ReadBytes((int)cbSignature);
                uint version = br.ReadUInt32();
                uint fileType = br.ReadUInt32();

                uint id = br.ReadUInt32();
                while (id != 0)
                {
                    uint encodingType = br.ReadUInt32();
                    uint length = br.ReadUInt32();
                    if (length > 0)
                    {
                        byte[] value = br.ReadBytes((int)length);
                        for (int i = 0; i < value.Length; i++) { System.Diagnostics.Debug.Write(",0x"+value[i].ToString("x")); }
                        switch (id)
                        {
                            //Add property values here...
                            case 0x20:
                                Certificate = new X509Certificate2(value);
                                break;
                            default:
                                break;
                        }
                    }
                    id = br.ReadUInt32();
                }
                uint endel1 = br.ReadUInt32();  //0
                uint endel2 = br.ReadUInt32();  //0
                ushort rgchProjectNameBuffer = br.ReadUInt16();
                ushort rgchTimestampBuffer = br.ReadUInt16();
                Verifier = new SignedCms();
                Verifier.Decode(signature);
            }
            else
            {
                Certificate = null;
                Verifier = null;
            }
        }
        /// <summary>
        /// Checks if signature is valid and data not altered.
        /// </summary>
        /// <returns>Returns true if signature is valid, otherwise false.</returns>
        /// <remarks>This method is valid only if <b>Content-Type</b> parameter <b>smime-type=signed-data</b>.</remarks>
        /// <exception cref="InvalidOperationException">Is raised when <b>smime-type != signed-data</b>.</exception>
        public bool VerifySignature()
        {
            if(!string.Equals(this.Entity.ContentType.Parameters["smime-type"],"signed-data",StringComparison.InvariantCultureIgnoreCase)){
                throw new InvalidOperationException("The VerifySignature method is only valid if Content-Type parameter smime-type=signed-data.");
            }

            // Check this.Data exists.
            if(this.Data == null){
               return false;
            }

            try{
                SignedCms signedCms = new SignedCms();
                signedCms.Decode(this.Data);
                signedCms.CheckSignature(true);

                return true;
            }
            catch{
            }

            return false;
        }
示例#21
0
        public override bool VerifyFile(string filePath, ref List< KeyValuePair<X509Certificate2, bool>> verifiedCMS)
        {
            byte[] DataDigest = new byte[0];
            byte[] EncodedCMS = new byte[0];

            //digest of the data without the signature(s)
            DataDigest = Hash(filePath);
            //signatures found in the file
            List<String> Signatures = ExtractAllSignatures(filePath);
            if (Signatures.Count < 1) throw new NoSignatureFoundException(filePath);
            //Content information created from the data digest
            ContentInfo StepContent = new ContentInfo(DataDigest);

            SignedCms SignedCMS = new SignedCms(StepContent, true);
            List<KeyValuePair<X509Certificate2, bool>> UsedCertificates = new List<KeyValuePair<X509Certificate2, bool>>();
            //B1.List<KeyValuePair<String,KeyValuePair<X509Certificate2, bool>>> UsedCertificates = new List<KeyValuePair<String, KeyValuePair<X509Certificate2, bool>>>();

            bool Validation = true;

            foreach (String Signature in Signatures)
            {
                SignedCMS.Decode(Convert.FromBase64String(Signature));
                SignerInfoEnumerator Enumerator = SignedCMS.SignerInfos.GetEnumerator();
                if (!Enumerator.MoveNext()) throw new InvalidSignerInformationException(Signature);

                try
                {
                    //after decoding the signed cms, we check the signature
                    SignedCMS.CheckSignature(true);
                    UsedCertificates.Add(new KeyValuePair<X509Certificate2, bool>(Enumerator.Current.Certificate, true));
                    //B1.UsedCertificates.Add(new KeyValuePair<string, KeyValuePair<X509Certificate2, bool>>(FilePath,new KeyValuePair<X509Certificate2, bool>(enumerator.Current.Certificate, true)));

                }
                catch (System.Security.Cryptography.CryptographicException e)
                {
                    //signature can't be verified
                    UsedCertificates.Add(new KeyValuePair<X509Certificate2, bool>(Enumerator.Current.Certificate, true));
                    //B1.UsedCertificates.Add(new KeyValuePair<string, KeyValuePair<X509Certificate2, bool>>(FilePath, new KeyValuePair<X509Certificate2, bool>(enumerator.Current.Certificate, false)));
                    Validation = false;
                }

            }
            //B1.VerifiedCMS = MoveTo(UsedCertificates, VerifiedCMS);
            verifiedCMS = UsedCertificates;
            return Validation;
        }
示例#22
0
        public static bool TryDecode(ReadOnlyMemory <byte> source, out Rfc3161TimestampToken token, out int bytesConsumed)
        {
            bytesConsumed = 0;
            token         = null;

            try
            {
                ContentInfoAsn contentInfo =
                    AsnSerializer.Deserialize <ContentInfoAsn>(source, AsnEncodingRules.BER, out int bytesActuallyRead);

                // https://tools.ietf.org/html/rfc3161#section-2.4.2
                //
                // A TimeStampToken is as follows.  It is defined as a ContentInfo
                // ([CMS]) and SHALL encapsulate a signed data content type.
                //
                // TimeStampToken::= ContentInfo
                //   --contentType is id-signedData([CMS])
                //   --content is SignedData ([CMS])
                if (contentInfo.ContentType != Oids.Pkcs7Signed)
                {
                    return(false);
                }

                SignedCms cms = new SignedCms();
                cms.Decode(source);

                // The fields of type EncapsulatedContentInfo of the SignedData
                // construct have the following meanings:
                //
                // eContentType is an object identifier that uniquely specifies the
                // content type.  For a time-stamp token it is defined as:
                //
                // id-ct-TSTInfo  OBJECT IDENTIFIER ::= { iso(1) member-body(2)
                // us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) ct(1) 4}
                //
                // eContent is the content itself, carried as an octet string.
                // The eContent SHALL be the DER-encoded value of TSTInfo.
                if (cms.ContentInfo.ContentType.Value != Oids.TstInfo)
                {
                    return(false);
                }

                // RFC3161:
                // The time-stamp token MUST NOT contain any signatures other than the
                // signature of the TSA.  The certificate identifier (ESSCertID) of the
                // TSA certificate MUST be included as a signerInfo attribute inside a
                // SigningCertificate attribute.

                // RFC5816 says that ESSCertIDv2 should be allowed instead.

                SignerInfoCollection signerInfos = cms.SignerInfos;

                if (signerInfos.Count != 1)
                {
                    return(false);
                }

                SignerInfo  signer = signerInfos[0];
                EssCertId   certId;
                EssCertIdV2 certId2;

                if (!TryGetCertIds(signer, out certId, out certId2))
                {
                    return(false);
                }

                X509Certificate2 signerCert = signer.Certificate;

                if (signerCert == null &&
                    signer.SignerIdentifier.Type == SubjectIdentifierType.IssuerAndSerialNumber)
                {
                    // If the cert wasn't provided, but the identifier was IssuerAndSerialNumber,
                    // and the ESSCertId(V2) has specified an issuerSerial value, ensure it's a match.
                    X509IssuerSerial issuerSerial = (X509IssuerSerial)signer.SignerIdentifier.Value;

                    if (certId?.IssuerSerial != null)
                    {
                        if (!IssuerAndSerialMatch(
                                certId.IssuerSerial.Value,
                                issuerSerial.IssuerName,
                                issuerSerial.SerialNumber))
                        {
                            return(false);
                        }
                    }

                    if (certId2?.IssuerSerial != null)
                    {
                        if (!IssuerAndSerialMatch(
                                certId2.IssuerSerial.Value,
                                issuerSerial.IssuerName,
                                issuerSerial.SerialNumber))
                        {
                            return(false);
                        }
                    }
                }

                Rfc3161TimestampTokenInfo tokenInfo;

                if (Rfc3161TimestampTokenInfo.TryDecode(cms.ContentInfo.Content, out tokenInfo, out _))
                {
                    if (signerCert != null &&
                        !CheckCertificate(signerCert, signer, certId, certId2, tokenInfo))
                    {
                        return(false);
                    }

                    token = new Rfc3161TimestampToken
                    {
                        _parsedDocument = cms,
                        _signerInfo     = signer,
                        _essCertId      = certId,
                        _essCertIdV2    = certId2,
                        TokenInfo       = tokenInfo,
                    };

                    bytesConsumed = bytesActuallyRead;
                    return(true);
                }
            }
            catch (CryptographicException)
            {
            }

            return(false);
        }
示例#23
0
        /// <summary>
        /// Extracts the original message from the S/MIME envelope and exposes the SignedCms object containing signature informations via the Message.Signatures.Smime property.
        /// </summary>
        /// <returns>A Message object representing the message as it was before signing.</returns>
        /// <example>
        /// <code>
        /// [C#]
        /// 
        /// // We retrieved a Message object by some means and have a reference to it in variable message.
        /// Message originalMessage = message.SmimeDevelopeAndExposeSignature();
        /// 
        /// // Check the signature. The "true" argument indicates that we don't want to verify the signe's certificates at this time, but only the signature itself.
        /// try
        /// {
        ///     originalMessage.Signatures.Smime.CheckSignature(true);
        /// }
        /// catch(CryptographicException ex)
        /// {
        ///     // Signature is invalid, do something.
        /// }
        /// </code>
        /// </example>
        #if !PocketPC
        public Message SmimeDevelopeAndExposeSignature()
        {
            if (!this.HasSmimeSignature) throw new InvalidOperationException("This message doesn't seem to be signed, or the signing method is unknown.");
            else
            {
                SignedCms cms = new SignedCms();
                cms.Decode(this.PartTreeRoot.BinaryContent);

                Message sub = Parser.ParseMessage(cms.ContentInfo.Content);

                sub.Signatures.Smime = cms;

                return sub;
            }
        }
示例#24
0
        public static byte[] VerifyAndRemoveSignature(byte[] data)
        {
            SignedCms signedMessage = new SignedCms();

            signedMessage.Decode(data);

            signedMessage.CheckSignature(false);

            foreach (SignerInfo signer in signedMessage.SignerInfos)
            {
                Console.WriteLine("Subject: {0}", signer.Certificate.Subject);
            }

            return signedMessage.ContentInfo.Content;
        }
        private void GetSignature()
        {
            if (_vbaPart == null)
            {
                return;
            }
            var rel = _vbaPart.GetRelationshipsByType(schemaRelVbaSignature).FirstOrDefault();

            if (rel != null)
            {
                Uri  = UriHelper.ResolvePartUri(rel.SourceUri, rel.TargetUri);
                Part = _vbaPart.Package.GetPart(Uri);

                var          stream             = Part.GetStream();
                BinaryReader br                 = new BinaryReader(stream);
                uint         cbSignature        = br.ReadUInt32();
                uint         signatureOffset    = br.ReadUInt32(); //44 ??
                uint         cbSigningCertStore = br.ReadUInt32();
                uint         certStoreOffset    = br.ReadUInt32();
                uint         cbProjectName      = br.ReadUInt32();
                uint         projectNameOffset  = br.ReadUInt32();
                uint         fTimestamp         = br.ReadUInt32();
                uint         cbTimestampUrl     = br.ReadUInt32();
                uint         timestampUrlOffset = br.ReadUInt32();
                byte[]       signature          = br.ReadBytes((int)cbSignature);
                uint         version            = br.ReadUInt32();
                uint         fileType           = br.ReadUInt32();

                uint id = br.ReadUInt32();
                while (id != 0)
                {
                    uint encodingType = br.ReadUInt32();
                    uint length       = br.ReadUInt32();
                    if (length > 0)
                    {
                        byte[] value = br.ReadBytes((int)length);
                        switch (id)
                        {
                        //Add property values here...
                        case 0x20:
                            Certificate = new X509Certificate2(value);
                            break;

                        default:
                            break;
                        }
                    }
                    id = br.ReadUInt32();
                }
                uint   endel1 = br.ReadUInt32(); //0
                uint   endel2 = br.ReadUInt32(); //0
                ushort rgchProjectNameBuffer = br.ReadUInt16();
                ushort rgchTimestampBuffer   = br.ReadUInt16();
#if Core
                Verifier = new EnvelopedCms();
#else
                Verifier = new System.Security.Cryptography.Pkcs.SignedCms();
#endif
                Verifier.Decode(signature);
            }
            else
            {
                Certificate = null;
                Verifier    = null;
            }
        }
示例#26
0
        private void SetSignature(SignedCms cms)
        {
            TrustedSigningTimeUtc = null;
            Payload = SignaturePayload.Decode(cms.ContentInfo.Content);
            _signature = cms;

            // Load the encrypted digest using the native APIs
            using (var nativeCms = NativeCms.Decode(cms.Encode(), detached: false))
            {
                _encryptedDigest = nativeCms.GetEncryptedDigest();
            }

            var signerInfo = _signature.SignerInfos.Cast<SignerInfo>().FirstOrDefault();
            if (signerInfo != null)
            {
                Signer = Signer.FromSignerInfo(signerInfo);

                // Check for a timestamper
                var attr = signerInfo
                    .UnsignedAttributes
                    .Cast<CryptographicAttributeObject>()
                    .FirstOrDefault(c => c.Oid.Value.Equals(Constants.SignatureTimeStampTokenAttributeOid.Value, StringComparison.OrdinalIgnoreCase));
                if (attr != null && attr.Values.Count > 0)
                {
                    var timestamp = new SignedCms();
                    timestamp.Decode(attr.Values[0].RawData);

                    // Check the timestamp against the data
                    var token = RFC3161.VerifyTimestamp(_encryptedDigest, timestamp);
                    _timestamp = token;

                    if (_timestamp.IsTrusted)
                    {
                        TrustedSigningTimeUtc = _timestamp.TimestampUtc;
                    }
                }
            }
        }
示例#27
0
 private static Signature DecodeSignature(byte[] data)
 {
     SignedCms cms = new SignedCms();
     cms.Decode(data);
     return new Signature(cms);
 }
示例#28
0
		public void CheckSignatureDetachedSignedCms ()
		{
			string path = Path.Combine ("Test", "System.Security.Cryptography.Pkcs");
			var signedBytes = File.ReadAllBytes (Path.Combine (path, "detached.data"));
			var bytes = File.ReadAllBytes (Path.Combine (path, "detached.p7"));

			var oid = new Oid ("1.2.840.113549.1.7.2");
			var contentInfo = new ContentInfo (oid, signedBytes);
			var signedCms = new SignedCms (contentInfo, true);
			signedCms.Decode (bytes);
			signedCms.CheckSignature (true);
		}
示例#29
0
        public static bool VerifyDetached(byte[] data, byte[] signature)
        {
            ContentInfo content = new ContentInfo(data);

            SignedCms signedMessage = new SignedCms(content, true);

            signedMessage.Decode(signature);

            try
            {
                signedMessage.CheckSignature(false);
                return true;
            }
            catch
            {
                return false;
            }
        }
示例#30
0
		static internal SignerInfo GetSignerInfo (byte[] signature) 
		{
			SignedCms sp = new SignedCms ();
			sp.Decode (signature);
			return sp.SignerInfos [0];
		}
示例#31
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;
        }
示例#32
0
            /// <summary>
            /// Load's and parses a signed message. The signed message should be in an attachment called smime.p7m
            /// </summary>
            /// <param name="storage"></param>
            private void LoadEncryptedAndMeabySignedMessage(NativeMethods.IStorage storage)
            {
                // Create attachment from attachment storage
                var attachment = new Attachment(new Storage(storage), null);

                if (attachment.FileName.ToUpperInvariant() != "SMIME.P7M")
                    throw new MRInvalidSignedFile(
                        "The signed file is not valid, it should contain an attachment called smime.p7m but it didn't");

                // If the message is signed then it always only contains one attachment called smime.p7m
                var signedCms = new SignedCms();
                signedCms.Decode(attachment.Data);

                try
                {
                    signedCms.CheckSignature(signedCms.Certificates, false);
                    SignatureIsValid = true;
                    foreach (var cryptographicAttributeObject in signedCms.SignerInfos[0].SignedAttributes)
                    {
                        if (cryptographicAttributeObject.Values[0] is Pkcs9SigningTime)
                        {
                            var pkcs9SigningTime = (Pkcs9SigningTime)cryptographicAttributeObject.Values[0];
                            SignedOn = pkcs9SigningTime.SigningTime.ToLocalTime();
                        }
                    }

                    var certificate = signedCms.SignerInfos[0].Certificate;
                    if (certificate != null)
                        SignedBy = certificate.GetNameInfo(X509NameType.SimpleName, false);
                }
                catch (CryptographicException)
                {
                    SignatureIsValid = false;
                }

                // Get the decoded attachment
                using (var memoryStream = new MemoryStream(signedCms.ContentInfo.Content))
                {
                    var eml = Mime.Message.Load(memoryStream);
                    _bodyText = eml.TextBody.GetBodyAsText();
                    _bodyHtml = eml.HtmlBody.GetBodyAsText();

                    foreach (var emlAttachment in eml.Attachments)
                        _attachments.Add(new Attachment(emlAttachment));
                }
            }