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