Пример #1
0
        public void TestBasicFunctionality()
        {
            var             dataDir = Path.Combine("..", "..", "TestData", "smime");
            var             chain = new X509CertificateChain();
            X509Certificate cert1, cert2, cert3;

            cert1 = LoadCertificate(Path.Combine(dataDir, "StartComClass1PrimaryIntermediateClientCA.crt"));
            cert2 = LoadCertificate(Path.Combine(dataDir, "StartComCertificationAuthority.crt"));
            cert3 = LoadCertificate(Path.Combine(dataDir, "certificate-authority.crt"));

            Assert.IsFalse(chain.IsReadOnly);
            Assert.AreEqual(0, chain.Count, "Initial count");

            chain.Add(cert3);

            Assert.AreEqual(1, chain.Count);
            Assert.AreEqual(cert3, chain[0]);

            chain.Insert(0, cert1);
            chain.Insert(1, cert2);

            Assert.AreEqual(3, chain.Count);
            Assert.AreEqual(cert1, chain[0]);
            Assert.AreEqual(cert2, chain[1]);
            Assert.AreEqual(cert3, chain[2]);

            Assert.IsTrue(chain.Contains(cert2), "Contains");
            Assert.AreEqual(1, chain.IndexOf(cert2), "IndexOf");

            var array = new X509Certificate[chain.Count];

            chain.CopyTo(array, 0);
            chain.Clear();

            Assert.AreEqual(0, chain.Count);

            foreach (var cert in array)
            {
                chain.Add(cert);
            }

            Assert.AreEqual(array.Length, chain.Count);

            Assert.IsTrue(chain.Remove(cert3));
            Assert.AreEqual(2, chain.Count);
            Assert.AreEqual(cert1, chain[0]);
            Assert.AreEqual(cert2, chain[1]);

            chain.RemoveAt(0);

            Assert.AreEqual(1, chain.Count);
            Assert.AreEqual(cert2, chain[0]);

            chain[0] = cert3;

            Assert.AreEqual(1, chain.Count);
            Assert.AreEqual(cert3, chain[0]);
        }
Пример #2
0
        public void TestBasicFunctionality()
        {
            var certs = SecureMimeTestsBase.LoadPkcs12CertificateChain(GetTestDataPath("smime.pfx"), "no.secret");
            var chain = new X509CertificateChain();

            Assert.IsFalse(chain.IsReadOnly);
            Assert.AreEqual(0, chain.Count, "Initial count");

            chain.Add(certs[2]);

            Assert.AreEqual(1, chain.Count);
            Assert.AreEqual(certs[2], chain[0]);

            chain.Insert(0, certs[0]);
            chain.Insert(1, certs[1]);

            Assert.AreEqual(3, chain.Count);
            Assert.AreEqual(certs[0], chain[0]);
            Assert.AreEqual(certs[1], chain[1]);
            Assert.AreEqual(certs[2], chain[2]);

            Assert.IsTrue(chain.Contains(certs[1]), "Contains");
            Assert.AreEqual(1, chain.IndexOf(certs[1]), "IndexOf");

            var array = new X509Certificate[chain.Count];

            chain.CopyTo(array, 0);
            chain.Clear();

            Assert.AreEqual(0, chain.Count);

            foreach (var cert in array)
            {
                chain.Add(cert);
            }

            Assert.AreEqual(array.Length, chain.Count);

            Assert.IsTrue(chain.Remove(certs[2]));
            Assert.AreEqual(2, chain.Count);
            Assert.AreEqual(certs[0], chain[0]);
            Assert.AreEqual(certs[1], chain[1]);

            chain.RemoveAt(0);

            Assert.AreEqual(1, chain.Count);
            Assert.AreEqual(certs[1], chain[0]);

            chain[0] = certs[2];

            Assert.AreEqual(1, chain.Count);
            Assert.AreEqual(certs[2], chain[0]);
        }
Пример #3
0
        public void TestArgumentExceptions()
        {
            var       path  = Path.Combine("..", "..", "TestData", "smime", "smime.p12");
            var       chain = new X509CertificateChain();
            CmsSigner signer;

            using (var stream = File.OpenRead(path))
                signer = new CmsSigner(stream, "no.secret");

            Assert.Throws <ArgumentNullException> (() => new X509CertificateChain(null));
            Assert.Throws <ArgumentNullException> (() => chain.Add(null));
            Assert.Throws <ArgumentNullException> (() => chain.AddRange(null));
            Assert.Throws <ArgumentNullException> (() => chain.Contains(null));
            Assert.Throws <ArgumentNullException> (() => chain.CopyTo(null, 0));
            Assert.Throws <ArgumentOutOfRangeException> (() => chain.CopyTo(new X509Certificate[0], -1));
            Assert.Throws <ArgumentNullException> (() => chain.IndexOf(null));
            Assert.Throws <ArgumentOutOfRangeException> (() => chain.Insert(-1, signer.Certificate));
            Assert.Throws <ArgumentNullException> (() => chain.Insert(0, null));
            Assert.Throws <ArgumentNullException> (() => chain[0] = null);
            Assert.Throws <ArgumentNullException> (() => chain.Remove(null));
            Assert.Throws <ArgumentOutOfRangeException> (() => chain.RemoveAt(-1));
        }
Пример #4
0
		/// <summary>
		/// Initializes a new instance of the <see cref="MimeKit.Cryptography.CmsSigner"/> class.
		/// </summary>
		/// <remarks>
		/// <para>The initial value of the <see cref="MimeKit.Cryptography.DigestAlgorithm"/> will
		/// be set to <see cref="MimeKit.Cryptography.DigestAlgorithm.Sha1"/> and both the
		/// <see cref="SignedAttributes"/> and <see cref="UnsignedAttributes"/> properties will be
		/// initialized to empty tables.</para>
		/// </remarks>
		/// <param name="certificate">The signer's certificate.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <paramref name="certificate"/> is <c>null</c>.
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// <paramref name="certificate"/> cannot be used for signing.
		/// </exception>
		public CmsSigner (X509Certificate2 certificate) : this ()
		{
			if (certificate == null)
				throw new ArgumentNullException (nameof (certificate));

			if (!certificate.HasPrivateKey)
				throw new ArgumentException ("The certificate does not contain a private key.", nameof (certificate));

			var cert = DotNetUtilities.FromX509Certificate (certificate);
			var key = DotNetUtilities.GetKeyPair (certificate.PrivateKey);

			CheckCertificateCanBeUsedForSigning (cert);

			CertificateChain = new X509CertificateChain ();
			CertificateChain.Add (cert);
			Certificate = cert;
			PrivateKey = key.Private;
		}
Пример #5
0
		void LoadPkcs12 (Stream stream, string password)
		{
			var pkcs12 = new Pkcs12Store (stream, password.ToCharArray ());

			foreach (string alias in pkcs12.Aliases) {
				if (!pkcs12.IsKeyEntry (alias))
					continue;

				var chain = pkcs12.GetCertificateChain (alias);
				var key = pkcs12.GetKey (alias);

				if (!key.Key.IsPrivate || chain.Length == 0)
					continue;

				var flags = chain[0].Certificate.GetKeyUsageFlags ();

				if (flags != X509KeyUsageFlags.None && (flags & SecureMimeContext.DigitalSignatureKeyUsageFlags) == 0)
					continue;

				CheckCertificateCanBeUsedForSigning (chain[0].Certificate);

				CertificateChain = new X509CertificateChain ();
				Certificate = chain[0].Certificate;
				PrivateKey = key.Key;

				foreach (var entry in chain)
					CertificateChain.Add (entry.Certificate);

				break;
			}

			if (PrivateKey == null)
				throw new ArgumentException ("The stream did not contain a private key.", nameof (stream));
		}
Пример #6
0
		/// <summary>
		/// Initializes a new instance of the <see cref="MimeKit.Cryptography.CmsSigner"/> class.
		/// </summary>
		/// <remarks>
		/// <para>The initial value of the <see cref="MimeKit.Cryptography.DigestAlgorithm"/> will
		/// be set to <see cref="MimeKit.Cryptography.DigestAlgorithm.Sha1"/> and both the
		/// <see cref="SignedAttributes"/> and <see cref="UnsignedAttributes"/> properties will be
		/// initialized to empty tables.</para>
		/// </remarks>
		/// <param name="certificate">The signer's certificate.</param>
		/// <param name="key">The signer's private key.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="certificate"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="key"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// <para><paramref name="certificate"/> cannot be used for signing.</para>
		/// <para>-or-</para>
		/// <para><paramref name="key"/> is not a private key.</para>
		/// </exception>
		public CmsSigner (X509Certificate certificate, AsymmetricKeyParameter key) : this ()
		{
			if (certificate == null)
				throw new ArgumentNullException (nameof (certificate));

			CheckCertificateCanBeUsedForSigning (certificate);

			if (key == null)
				throw new ArgumentNullException (nameof (key));

			if (!key.IsPrivate)
				throw new ArgumentException ("The key must be a private key.", nameof (key));

			CertificateChain = new X509CertificateChain ();
			CertificateChain.Add (certificate);
			Certificate = certificate;
			PrivateKey = key;
		}
Пример #7
0
		/// <summary>
		/// Initializes a new instance of the <see cref="MimeKit.Cryptography.CmsSigner"/> class.
		/// </summary>
		/// <remarks>
		/// <para>The initial value of the <see cref="DigestAlgorithm"/> will be set to
		/// <see cref="MimeKit.Cryptography.DigestAlgorithm.Sha1"/> and both the
		/// <see cref="SignedAttributes"/> and <see cref="UnsignedAttributes"/> properties
		/// will be initialized to empty tables.</para>
		/// </remarks>
		/// <param name="chain">The chain of certificates starting with the signer's certificate back to the root.</param>
		/// <param name="key">The signer's private key.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="chain"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="key"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// <para><paramref name="chain"/> did not contain any certificates.</para>
		/// <para>-or-</para>
		/// <para>The certificate cannot be used for signing.</para>
		/// <para>-or-</para>
		/// <para><paramref name="key"/> is not a private key.</para>
		/// </exception>
		public CmsSigner (IEnumerable<X509CertificateEntry> chain, AsymmetricKeyParameter key) : this ()
		{
			if (chain == null)
				throw new ArgumentNullException ("chain");

			if (key == null)
				throw new ArgumentNullException ("key");

			CertificateChain = new X509CertificateChain ();
			foreach (var entry in chain) {
				CertificateChain.Add (entry.Certificate);
				if (Certificate == null)
					Certificate = entry.Certificate;
			}

			if (CertificateChain.Count == 0)
				throw new ArgumentException ("The certificate chain was empty.", "chain");

			CheckCertificateCanBeUsedForSigning (Certificate);

			if (!key.IsPrivate)
				throw new ArgumentException ("The key must be a private key.", "key");

			PrivateKey = key;
		}
Пример #8
0
		/// <summary>
		/// Initializes a new instance of the <see cref="MimeKit.Cryptography.CmsSigner"/> class.
		/// </summary>
		/// <remarks>
		/// <para>The initial value of the <see cref="DigestAlgorithm"/> will be set to
		/// <see cref="MimeKit.Cryptography.DigestAlgorithm.Sha1"/> and both the
		/// <see cref="SignedAttributes"/> and <see cref="UnsignedAttributes"/> properties
		/// will be initialized to empty tables.</para>
		/// </remarks>
		/// <param name="chain">The chain of certificates starting with the signer's certificate back to the root.</param>
		/// <param name="key">The signer's private key.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="chain"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="key"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// <para><paramref name="chain"/> did not contain any certificates.</para>
		/// <para>-or-</para>
		/// <para>The certificate cannot be used for signing.</para>
		/// <para>-or-</para>
		/// <para><paramref name="key"/> is not a private key.</para>
		/// </exception>
		public CmsSigner (IEnumerable<X509CertificateEntry> chain, AsymmetricKeyParameter key) : this ()
		{
			if (chain == null)
				throw new ArgumentNullException ("chain");

			if (key == null)
				throw new ArgumentNullException ("key");

			CertificateChain = new X509CertificateChain ();
			foreach (var entry in chain) {
				CertificateChain.Add (entry.Certificate);
				if (Certificate == null)
					Certificate = entry.Certificate;
			}

			if (CertificateChain.Count == 0)
				throw new ArgumentException ("The certificate chain was empty.", "chain");

			var flags = Certificate.GetKeyUsageFlags ();
			if (flags != X509KeyUsageFlags.None && (flags & X509KeyUsageFlags.DigitalSignature) == 0)
				throw new ArgumentException ("The certificate cannot be used for signing.");

			if (!key.IsPrivate)
				throw new ArgumentException ("The key must be a private key.", "key");

			PrivateKey = key;
		}
Пример #9
0
		/// <summary>
		/// Initializes a new instance of the <see cref="MimeKit.Cryptography.CmsSigner"/> class.
		/// </summary>
		/// <remarks>
		/// <para>The initial value of the <see cref="MimeKit.Cryptography.DigestAlgorithm"/> will
		/// be set to <see cref="MimeKit.Cryptography.DigestAlgorithm.Sha1"/> and both the
		/// <see cref="SignedAttributes"/> and <see cref="UnsignedAttributes"/> properties will be
		/// initialized to empty tables.</para>
		/// </remarks>
		/// <param name="certificate">The signer's certificate.</param>
		/// <param name="key">The signer's private key.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="certificate"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="key"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// <para><paramref name="certificate"/> cannot be used for signing.</para>
		/// <para>-or-</para>
		/// <para><paramref name="key"/> is not a private key.</para>
		/// </exception>
		public CmsSigner (X509Certificate certificate, AsymmetricKeyParameter key) : this ()
		{
			if (certificate == null)
				throw new ArgumentNullException ("certificate");

			var flags = certificate.GetKeyUsageFlags ();
			if (flags != X509KeyUsageFlags.None && (flags & X509KeyUsageFlags.DigitalSignature) == 0)
				throw new ArgumentException ("The certificate cannot be used for signing.", "certificate");

			if (key == null)
				throw new ArgumentNullException ("key");

			if (!key.IsPrivate)
				throw new ArgumentException ("The key must be a private key.", "key");

			CertificateChain = new X509CertificateChain ();
			CertificateChain.Add (certificate);
			Certificate = certificate;
			PrivateKey = key;
		}