Example #1
0
        public static void TestDecodeFormats(X500DistinguishedNameFlags format)
        {
            // The Issuer field from the Microsoft.com test cert.
            byte[] encoding = (
                "3077310B3009060355040613025553311D301B060355040A131453796D616E74" +
                "656320436F72706F726174696F6E311F301D060355040B131653796D616E7465" +
                "63205472757374204E6574776F726B312830260603550403131F53796D616E74" +
                "656320436C61737320332045562053534C204341202D204733").HexToByteArray();

            X500DistinguishedName name = new X500DistinguishedName(encoding);
            string delimiter;

            switch (format)
            {
                case X500DistinguishedNameFlags.UseCommas:
                    delimiter = ", ";
                    break;
                case X500DistinguishedNameFlags.UseSemicolons:
                    delimiter = "; ";
                    break;
                case X500DistinguishedNameFlags.UseNewLines:
                    delimiter = Environment.NewLine;
                    break;
                default:
                    throw new InvalidOperationException("No handler for format: " + format);
            }

            string expected = string.Format(
                "C=US{0}O=Symantec Corporation{0}OU=Symantec Trust Network{0}CN=Symantec Class 3 EV SSL CA - G3",
                delimiter);

            string actual = name.Decode(format);

            Assert.Equal(expected, actual);
        }
        public static void NoQuoteWhitespaceAfter(string expectedQuoted, string hexEncoded)
        {
            string expected = expectedQuoted.Replace("\"", "");
            byte[] encoded = hexEncoded.HexToByteArray();

            X500DistinguishedName dn = new X500DistinguishedName(encoded);
            Assert.Equal(expected, dn.Decode(X500DistinguishedNameFlags.DoNotUseQuotes));
        }
        public static void PrintUnknownOidRdn()
        {
            byte[] encoded = (
                "30183116301406052901020203130B496E76616C6964204F6964").HexToByteArray();

            X500DistinguishedName dn = new X500DistinguishedName(encoded);
            Assert.Equal("OID.1.1.1.2.2.3=Invalid Oid", dn.Decode(X500DistinguishedNameFlags.None));
        }
        public static void PrintInvalidEncoding()
        {
            // One byte has been removed from the payload here.  Since DER is length-prepended
            // this will run out of data too soon, and report as invalid.
            byte[] encoded = "3017311530130603550403130C436F6D6D6F6E204E616D65".HexToByteArray();

            X500DistinguishedName dn = new X500DistinguishedName(encoded);
            Assert.Equal("", dn.Decode(X500DistinguishedNameFlags.None));
        }
Example #5
0
        public static void TestDecode()
        {
            byte[] encoding = "300e310c300a06035504031303466f6f".HexToByteArray();

            X500DistinguishedName n = new X500DistinguishedName(encoding);
            String s = n.Name;
            Assert.Equal("CN=Foo", s);
            byte[] rawData = n.RawData;
            Assert.Equal(encoding, rawData);
        }
Example #6
0
        public static void TestFormat()
        {
            byte[] encoding = "300e310c300a06035504031303466f6f".HexToByteArray();
            String s;

            X500DistinguishedName n = new X500DistinguishedName(encoding);

            s = n.Format(multiLine: false);
            Assert.Equal("CN=Foo", s);

            s = n.Format(multiLine: true);
            Assert.Equal("CN=Foo\r\n", s);
        }
        public static void PrintMultiComponentRdn()
        {
            byte[] encoded = (
                "30223120300C060355040313054A616D65733010060355040A13094D6963726F" +
                "736F6674").HexToByteArray();

            const string expected = "CN=James + O=Microsoft";
            X500DistinguishedName dn = new X500DistinguishedName(encoded);

            Assert.Equal(expected, dn.Decode(X500DistinguishedNameFlags.None));

            // It should not change ordering when reversed, since the two are one unit.
            Assert.Equal(expected, dn.Decode(X500DistinguishedNameFlags.Reversed));
        }
        public static void PrintComplexReversed()
        {
            byte[] encoded = MicrosoftDotComSubject.HexToByteArray();
            X500DistinguishedName dn = new X500DistinguishedName(encoded);

            const string expected =
                "CN=www.microsoft.com, OU=MSCOM, O=Microsoft Corporation, STREET=1 Microsoft Way, " +
                "L=Redmond, S=Washington, PostalCode=98052, C=US, SERIALNUMBER=600413485, ";

            // Windows 8.1 would continue the string with some unknown OIDs, but OpenSSL 1.0.1 can decode
            // at least businessCategory (2.5.4.15), and other Windows versions may do so in the future.
            //    "OID.2.5.4.15=Private Organization, OID.1.3.6.1.4.1.311.60.2.1.2=Washington, " +
            //    "OID.1.3.6.1.4.1.311.60.2.1.3=US";

            Assert.StartsWith(expected, dn.Decode(X500DistinguishedNameFlags.Reversed), StringComparison.Ordinal);
        }
Example #9
0
        public string GetNameInfo(X509NameType nameType, bool forIssuer)
        {
            // Algorithm behaviors (pseudocode).  When forIssuer is true, replace "Subject" with "Issuer" and
            // SAN (Subject Alternative Names) with IAN (Issuer Alternative Names).
            //
            // SimpleName: Subject[CN] ?? Subject[OU] ?? Subject[O] ?? Subject[E] ?? Subject.Rdns.FirstOrDefault() ??
            // SAN.Entries.FirstOrDefault(type == GEN_EMAIL);
            // EmailName: SAN.Entries.FirstOrDefault(type == GEN_EMAIL) ?? Subject[E];
            // UpnName: SAN.Entries.FirsOrDefaultt(type == GEN_OTHER && entry.AsOther().OID == szOidUpn).AsOther().Value;
            // DnsName: SAN.Entries.FirstOrDefault(type == GEN_DNS) ?? Subject[CN];
            // DnsFromAlternativeName: SAN.Entries.FirstOrDefault(type == GEN_DNS);
            // UrlName: SAN.Entries.FirstOrDefault(type == GEN_URI);

            EnsureCertData();

            if (nameType == X509NameType.SimpleName)
            {
                X500DistinguishedName name = forIssuer ? _certData.Issuer : _certData.Subject;
                string candidate           = GetSimpleNameInfo(name);

                if (candidate != null)
                {
                    return(candidate);
                }
            }

            // Check the Subject Alternative Name (or Issuer Alternative Name) for the right value;
            {
                string          extensionId = forIssuer ? Oids.IssuerAltName : Oids.SubjectAltName;
                GeneralNameType?matchType   = null;
                string          otherOid    = null;

                // Currently all X509NameType types have a path where they look at the SAN/IAN,
                // but we need to figure out which kind they want.
                switch (nameType)
                {
                case X509NameType.DnsName:
                case X509NameType.DnsFromAlternativeName:
                    matchType = GeneralNameType.DnsName;
                    break;

                case X509NameType.SimpleName:
                case X509NameType.EmailName:
                    matchType = GeneralNameType.Email;
                    break;

                case X509NameType.UpnName:
                    matchType = GeneralNameType.OtherName;
                    otherOid  = Oids.UserPrincipalName;
                    break;

                case X509NameType.UrlName:
                    matchType = GeneralNameType.UniformResourceIdentifier;
                    break;
                }

                if (matchType.HasValue)
                {
                    foreach (X509Extension extension in _certData.Extensions)
                    {
                        if (extension.Oid.Value == extensionId)
                        {
                            string candidate = FindAltNameMatch(extension.RawData, matchType.Value, otherOid);

                            if (candidate != null)
                            {
                                return(candidate);
                            }
                        }
                    }
                }
                else
                {
                    Debug.Fail($"Unresolved matchType for X509NameType.{nameType}");
                }
            }

            // Subject-based fallback
            {
                string expectedKey = null;

                switch (nameType)
                {
                case X509NameType.EmailName:
                    expectedKey = Oids.EmailAddress;
                    break;

                case X509NameType.DnsName:
                    // Note: This does not include DnsFromAlternativeName, since
                    // the subject (or issuer) is not the Alternative Name.
                    expectedKey = Oids.CommonName;
                    break;
                }

                if (expectedKey != null)
                {
                    X500DistinguishedName name = forIssuer ? _certData.Issuer : _certData.Subject;

                    foreach (var kvp in ReadReverseRdns(name))
                    {
                        if (kvp.Key == expectedKey)
                        {
                            return(kvp.Value);
                        }
                    }
                }
            }

            return("");
        }
Example #10
0
 public X509Identity(X500DistinguishedName x500DistinguishedName)
     : base(X509, X509)
 {
     _x500DistinguishedName = x500DistinguishedName;
 }
Example #11
0
        /// <summary>建立自签名证书</summary>
        /// <param name="distName"></param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public static byte[] CreateSelfSignCertificatePfx(X500DistinguishedName distName, DateTime startTime, DateTime endTime, SecureString password)
        {
            byte[] pfxData;

            SystemTime startSystemTime = ToSystemTime(startTime);
            SystemTime endSystemTime   = ToSystemTime(endTime);
            string     containerName   = Guid.NewGuid().ToString();

            GCHandle dataHandle       = new GCHandle();
            IntPtr   providerContext  = IntPtr.Zero;
            IntPtr   cryptKey         = IntPtr.Zero;
            IntPtr   certContext      = IntPtr.Zero;
            IntPtr   certStore        = IntPtr.Zero;
            IntPtr   storeCertContext = IntPtr.Zero;
            IntPtr   passwordPtr      = IntPtr.Zero;

            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                Check(NativeMethods.CryptAcquireContextW(
                          out providerContext,
                          containerName,
                          null,
                          1,   // PROV_RSA_FULL
                          8)); // CRYPT_NEWKEYSET

                Check(NativeMethods.CryptGenKey(
                          providerContext,
                          1, // AT_KEYEXCHANGE
                          1, // CRYPT_EXPORTABLE
                          out cryptKey));

                byte[] nameData = distName.RawData;

                dataHandle = GCHandle.Alloc(nameData, GCHandleType.Pinned);
                CryptoApiBlob nameBlob = new CryptoApiBlob(
                    nameData.Length,
                    dataHandle.AddrOfPinnedObject());

                CryptKeyProviderInformation kpi = new CryptKeyProviderInformation();
                kpi.ContainerName = containerName;
                kpi.ProviderType  = 1; // PROV_RSA_FULL
                kpi.KeySpec       = 1; // AT_KEYEXCHANGE

                certContext = NativeMethods.CertCreateSelfSignCertificate(
                    providerContext,
                    ref nameBlob,
                    0,
                    ref kpi,
                    IntPtr.Zero, // default = SHA1RSA
                    ref startSystemTime,
                    ref endSystemTime,
                    IntPtr.Zero);
                Check(certContext != IntPtr.Zero);
                dataHandle.Free();

                certStore = NativeMethods.CertOpenStore(
                    "Memory", // sz_CERT_STORE_PROV_MEMORY
                    0,
                    IntPtr.Zero,
                    0x2000, // CERT_STORE_CREATE_NEW_FLAG
                    IntPtr.Zero);
                Check(certStore != IntPtr.Zero);

                Check(NativeMethods.CertAddCertificateContextToStore(
                          certStore,
                          certContext,
                          1, // CERT_STORE_ADD_NEW
                          out storeCertContext));

                NativeMethods.CertSetCertificateContextProperty(
                    storeCertContext,
                    2, // CERT_KEY_PROV_INFO_PROP_ID
                    0,
                    ref kpi);

                if (password != null)
                {
                    passwordPtr = Marshal.SecureStringToCoTaskMemUnicode(password);
                }

                CryptoApiBlob pfxBlob = new CryptoApiBlob();
                Check(NativeMethods.PFXExportCertStoreEx(
                          certStore,
                          ref pfxBlob,
                          passwordPtr,
                          IntPtr.Zero,
                          7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY

                pfxData      = new byte[pfxBlob.DataLength];
                dataHandle   = GCHandle.Alloc(pfxData, GCHandleType.Pinned);
                pfxBlob.Data = dataHandle.AddrOfPinnedObject();
                Check(NativeMethods.PFXExportCertStoreEx(
                          certStore,
                          ref pfxBlob,
                          passwordPtr,
                          IntPtr.Zero,
                          7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY
                dataHandle.Free();
            }
            finally
            {
                if (passwordPtr != IntPtr.Zero)
                {
                    Marshal.ZeroFreeCoTaskMemUnicode(passwordPtr);
                }

                if (dataHandle.IsAllocated)
                {
                    dataHandle.Free();
                }

                if (certContext != IntPtr.Zero)
                {
                    NativeMethods.CertFreeCertificateContext(certContext);
                }

                if (storeCertContext != IntPtr.Zero)
                {
                    NativeMethods.CertFreeCertificateContext(storeCertContext);
                }

                if (certStore != IntPtr.Zero)
                {
                    NativeMethods.CertCloseStore(certStore, 0);
                }

                if (cryptKey != IntPtr.Zero)
                {
                    NativeMethods.CryptDestroyKey(cryptKey);
                }

                if (providerContext != IntPtr.Zero)
                {
                    NativeMethods.CryptReleaseContext(providerContext, 0);
                    NativeMethods.CryptAcquireContextW(
                        out providerContext,
                        containerName,
                        null,
                        1,     // PROV_RSA_FULL
                        0x10); // CRYPT_DELETEKEYSET
                }
            }

            return(pfxData);
        }
Example #12
0
        internal bool verify(NativeConnectionInfo info, string desc)
        {
            List <List <List <RFC2253.RDNPair> > > reject = new List <List <List <RFC2253.RDNPair> > >(),
                                                   accept = new List <List <List <RFC2253.RDNPair> > >();

            if (rejectAll_.Count != 0)
            {
                reject.Add(rejectAll_);
            }
            if (info.incoming)
            {
                if (rejectAllServer_.Count != 0)
                {
                    reject.Add(rejectAllServer_);
                }
                if (info.adapterName.Length > 0)
                {
                    List <List <RFC2253.RDNPair> > p = null;
                    if (rejectServer_.TryGetValue(info.adapterName, out p))
                    {
                        reject.Add(p);
                    }
                }
            }
            else
            {
                if (rejectClient_.Count != 0)
                {
                    reject.Add(rejectClient_);
                }
            }

            if (acceptAll_.Count != 0)
            {
                accept.Add(acceptAll_);
            }
            if (info.incoming)
            {
                if (acceptAllServer_.Count != 0)
                {
                    accept.Add(acceptAllServer_);
                }
                if (info.adapterName.Length > 0)
                {
                    List <List <RFC2253.RDNPair> > p = null;
                    if (acceptServer_.TryGetValue(info.adapterName, out p))
                    {
                        accept.Add(p);
                    }
                }
            }
            else
            {
                if (acceptClient_.Count != 0)
                {
                    accept.Add(acceptClient_);
                }
            }

            //
            // If there is nothing to match against, then we accept the cert.
            //
            if (reject.Count == 0 && accept.Count == 0)
            {
                return(true);
            }

            //
            // If there is no certificate then we match false.
            //
            if (info.nativeCerts != null && info.nativeCerts.Length > 0)
            {
                X500DistinguishedName subjectDN = info.nativeCerts[0].SubjectName;
                string subjectName = subjectDN.Name;
                Debug.Assert(subjectName != null);
                try
                {
                    //
                    // Decompose the subject DN into the RDNs.
                    //
                    if (traceLevel_ > 0)
                    {
                        if (info.incoming)
                        {
                            communicator_.getLogger().trace("Security", "trust manager evaluating client:\n" +
                                                            "subject = " + subjectName + "\n" + "adapter = " + info.adapterName + "\n" + desc);
                        }
                        else
                        {
                            communicator_.getLogger().trace("Security", "trust manager evaluating server:\n" +
                                                            "subject = " + subjectName + "\n" + desc);
                        }
                    }

                    List <RFC2253.RDNPair> dn = RFC2253.parseStrict(subjectName);

                    //
                    // Unescape the DN. Note that this isn't done in
                    // the parser in order to keep the various RFC2253
                    // implementations as close as possible.
                    //
                    for (int i = 0; i < dn.Count; ++i)
                    {
                        RFC2253.RDNPair p = dn[i];
                        p.value = RFC2253.unescape(p.value);
                        dn[i]   = p;
                    }

                    //
                    // Fail if we match anything in the reject set.
                    //
                    foreach (List <List <RFC2253.RDNPair> > matchSet in reject)
                    {
                        if (traceLevel_ > 0)
                        {
                            StringBuilder s = new StringBuilder("trust manager rejecting PDNs:\n");
                            stringify(matchSet, s);
                            communicator_.getLogger().trace("Security", s.ToString());
                        }
                        if (match(matchSet, dn))
                        {
                            return(false);
                        }
                    }

                    //
                    // Succeed if we match anything in the accept set.
                    //
                    foreach (List <List <RFC2253.RDNPair> > matchSet in accept)
                    {
                        if (traceLevel_ > 0)
                        {
                            StringBuilder s = new StringBuilder("trust manager accepting PDNs:\n");
                            stringify(matchSet, s);
                            communicator_.getLogger().trace("Security", s.ToString());
                        }
                        if (match(matchSet, dn))
                        {
                            return(true);
                        }
                    }
                }
                catch (RFC2253.ParseException e)
                {
                    communicator_.getLogger().warning(
                        "IceSSL: unable to parse certificate DN `" + subjectName + "'\nreason: " + e.reason);
                }

                //
                // At this point we accept the connection if there are no explicit accept rules.
                //
                return(accept.Count == 0);
            }

            return(false);
        }
Example #13
0
 /// <summary>
 /// Create a new certificate
 /// </summary>
 /// <param name="issuer">Issuer certificate, if null then self-sign</param>
 /// <param name="subjectName">Subject name</param>
 /// <param name="serialNumber">Serial number of certificate, if null then will generate a new one</param>
 /// <param name="signature">If true create an AT_SIGNATURE key, otherwise AT_EXCHANGE</param>
 /// <param name="keySize">Size of RSA key</param>
 /// <param name="hashAlgorithm">The hash algorithm for the certificate</param>
 /// <param name="notBefore">Start date of certificate</param>
 /// <param name="notAfter">End date of certificate</param>
 /// <param name="extensions">Array of extensions, if null then no extensions</param>
 /// <returns>The created X509 certificate</returns>
 public static X509Certificate2 CreateCert(X509Certificate2 issuer, X500DistinguishedName subjectName,
                                           byte[] serialNumber, bool signature, int keySize, CertificateHashAlgorithm hashAlgorithm, DateTime notBefore, DateTime notAfter, X509ExtensionCollection extensions)
 {
     return(builder.CreateCert(issuer, subjectName, serialNumber, signature, keySize, hashAlgorithm, notBefore, notAfter, extensions));
 }
Example #14
0
        public static void EncodeWithFlags(FlagControlledEncoderTestCase testCase)
        {
            X500DistinguishedName dn = new X500DistinguishedName(testCase.Input, testCase.Flags);

            ProcessTestCase(testCase, dn);
        }
Example #15
0
        public static void EncodeSingleRdn(SimpleEncoderTestCase testCase)
        {
            X500DistinguishedName dn = new X500DistinguishedName(testCase.Input, X500DistinguishedNameFlags.None);

            ProcessTestCase(testCase, dn);
        }
Example #16
0
        public static void CheckParserBoundaryCases(SimpleEncoderTestCase testCase)
        {
            X500DistinguishedName dn = new X500DistinguishedName(testCase.Input, X500DistinguishedNameFlags.None);

            ProcessTestCase(testCase, dn);
        }
Example #17
0
        /// <summary>
        /// Generates a new pairing record.
        /// </summary>
        /// <param name="devicePublicKey">
        /// A <see cref="byte"/> array which represents the public key of the device with which to pair.
        /// </param>
        /// <param name="udid">
        /// The UDID of the device. This will be included in the subjectName of the root certificate.
        /// This can be used to match the child certificates with the parent certificate based on the
        /// issuer name / subject name.
        /// This is not the default behavior of the canoncial implementation and should be needed on
        /// Windows for testing purposes only.
        /// </param>
        /// <param name="systemBuid">
        /// A <see cref="string"/> which uniquely identifies the host.
        /// </param>
        /// <returns>
        /// A new <see cref="PairingRecord"/> which can be used to pair the host with the device.
        /// </returns>
        public virtual PairingRecord Generate(byte[] devicePublicKey, string udid, string systemBuid)
        {
            if (devicePublicKey == null)
            {
                throw new ArgumentNullException(nameof(devicePublicKey));
            }

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

            RSA rootKeyPair = RSA.Create(KeySize);
            RSA hostKeyPair = RSA.Create(KeySize);

            DateTimeOffset notBefore = DateTimeOffset.Now;
            DateTimeOffset notAfter  = notBefore.AddDays(365 * 10);

            X500DistinguishedName caName = Name;

            if (udid != null)
            {
                caName = new X500DistinguishedName($"CN=Root Certification Authority,OU={udid}");
            }

            var generator = new RSASha1Pkcs1SignatureGenerator(rootKeyPair);
            CertificateRequest rootRequest = new CertificateRequest(
                caName,
                rootKeyPair,
                HashAlgorithmName.SHA1,
                RSASignaturePadding.Pkcs1);

            rootRequest.CertificateExtensions.Add(new X509BasicConstraintsExtension(certificateAuthority: true, hasPathLengthConstraint: false, pathLengthConstraint: -1, critical: true));
            rootRequest.CertificateExtensions.Add(new X509SubjectKeyIdentifierExtension(rootRequest.PublicKey, critical: false));

            var rootCert = rootRequest.Create(
                issuerName: caName,
                generator,
                notBefore: notBefore,
                notAfter: notAfter,
                serialNumber: new byte[] { 0 });

            CertificateRequest hostRequest = new CertificateRequest(
                Name,
                hostKeyPair,
                HashAlgorithmName.SHA1,
                RSASignaturePadding.Pkcs1);

            hostRequest.CertificateExtensions.Add(new X509BasicConstraintsExtension(certificateAuthority: false, hasPathLengthConstraint: false, pathLengthConstraint: -1, critical: true));
            hostRequest.CertificateExtensions.Add(new X509SubjectKeyIdentifierExtension(hostRequest.PublicKey, critical: false));
            hostRequest.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.KeyEncipherment, critical: true));

            var hostCert = hostRequest.Create(
                issuerName: caName,
                generator,
                notBefore: notBefore,
                notAfter: notAfter,
                serialNumber: new byte[] { 0 });

            var device = RSA.Create();

            device.ImportFromPem(Encoding.UTF8.GetString(devicePublicKey));
            var deviceRequest = new CertificateRequest(
                Name,
                device,
                HashAlgorithmName.SHA1,
                RSASignaturePadding.Pkcs1);

            deviceRequest.CertificateExtensions.Add(new X509BasicConstraintsExtension(certificateAuthority: false, hasPathLengthConstraint: false, pathLengthConstraint: -1, critical: true));
            deviceRequest.CertificateExtensions.Add(new X509SubjectKeyIdentifierExtension("hash", critical: false));
            deviceRequest.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.KeyEncipherment, critical: true));

            var deviceCertificate = deviceRequest.Create(
                issuerName: caName,
                generator,
                notBefore: notBefore,
                notAfter: notAfter,
                serialNumber: new byte[] { 0 });

            var hostId = Guid.NewGuid();

            return(new PairingRecord()
            {
                DeviceCertificate = deviceCertificate,
                HostPrivateKey = hostKeyPair,
                HostCertificate = hostCert,
                RootPrivateKey = rootKeyPair,
                RootCertificate = rootCert,
                SystemBUID = systemBuid,
                HostId = hostId.ToString("D").ToUpperInvariant(),
            });
        }
Example #18
0
 public X509Certificate2 CreateMutualAuthenticationX509(X500DistinguishedName fullSubject, DateTimeOffset validFrom, DateTimeOffset expires)
 {
     return CreateMutualAuthenticationX509(fullSubject.Format(false), validFrom, expires);
 }
Example #19
0
        internal static void MakeTestChain(
            ReadOnlySpan <RSA> keys,
            Span <X509Certificate2> certs,
            IEnumerable <X509Extension> endEntityExtensions,
            IEnumerable <X509Extension> intermediateExtensions,
            IEnumerable <X509Extension> rootExtensions)
        {
            if (keys.Length < 2)
            {
                throw new ArgumentException(nameof(keys));
            }
            if (keys.Length != certs.Length)
            {
                throw new ArgumentException(nameof(certs));
            }

            rootExtensions ??= new X509Extension[] {
                new X509BasicConstraintsExtension(true, false, 0, true),
                new X509KeyUsageExtension(
                    X509KeyUsageFlags.CrlSign |
                    X509KeyUsageFlags.KeyCertSign |
                    X509KeyUsageFlags.DigitalSignature,
                    false)
            };

            intermediateExtensions ??= new X509Extension[] {
                new X509BasicConstraintsExtension(true, false, 0, true),
                new X509KeyUsageExtension(
                    X509KeyUsageFlags.CrlSign |
                    X509KeyUsageFlags.KeyCertSign |
                    X509KeyUsageFlags.DigitalSignature,
                    false)
            };

            endEntityExtensions ??= new X509Extension[] {
                new X509BasicConstraintsExtension(false, false, 0, true),
                new X509KeyUsageExtension(
                    X509KeyUsageFlags.DigitalSignature |
                    X509KeyUsageFlags.NonRepudiation |
                    X509KeyUsageFlags.KeyEncipherment,
                    false)
            };

            TimeSpan       notBeforeInterval = TimeSpan.FromDays(30);
            TimeSpan       notAfterInterval  = TimeSpan.FromDays(90);
            DateTimeOffset eeStart           = DateTimeOffset.UtcNow.AddDays(-7);
            DateTimeOffset eeEnd             = eeStart.AddDays(45);

            byte[] serialBuf = new byte[16];

            int rootIndex = keys.Length - 1;

            HashAlgorithmName   hashAlgorithm    = HashAlgorithmName.SHA256;
            RSASignaturePadding signaturePadding = RSASignaturePadding.Pkcs1;

            CertificateRequest rootReq = new CertificateRequest(
                "CN=Test Root",
                keys[rootIndex],
                hashAlgorithm,
                signaturePadding);

            foreach (X509Extension extension in rootExtensions)
            {
                rootReq.CertificateExtensions.Add(extension);
            }

            X509SignatureGenerator lastGenerator = X509SignatureGenerator.CreateForRSA(keys[rootIndex], RSASignaturePadding.Pkcs1);
            X500DistinguishedName  lastSubject   = rootReq.SubjectName;

            certs[rootIndex] = rootReq.Create(
                lastSubject,
                lastGenerator,
                eeStart - (notBeforeInterval * rootIndex),
                eeEnd + (notAfterInterval * rootIndex),
                CreateSerial());

            int presentationNumber = 0;

            for (int i = rootIndex - 1; i > 0; i--)
            {
                presentationNumber++;

                CertificateRequest intermediateReq = new CertificateRequest(
                    $"CN=Intermediate Layer {presentationNumber}",
                    keys[i],
                    hashAlgorithm,
                    signaturePadding);

                foreach (X509Extension extension in intermediateExtensions)
                {
                    intermediateReq.CertificateExtensions.Add(extension);
                }

                certs[i] = intermediateReq.Create(
                    lastSubject,
                    lastGenerator,
                    eeStart - (notBeforeInterval * i),
                    eeEnd + (notAfterInterval * i),
                    CreateSerial());

                lastSubject   = intermediateReq.SubjectName;
                lastGenerator = X509SignatureGenerator.CreateForRSA(keys[i], RSASignaturePadding.Pkcs1);
            }

            CertificateRequest eeReq = new CertificateRequest(
                "CN=End-Entity",
                keys[0],
                hashAlgorithm,
                signaturePadding);

            foreach (X509Extension extension in endEntityExtensions)
            {
                eeReq.CertificateExtensions.Add(extension);
            }

            certs[0] = eeReq.Create(lastSubject, lastGenerator, eeStart, eeEnd, CreateSerial());
        }
Example #20
0
        // CTL == Certificate Trust List / NOT SUPPORTED
        // TODO - check for X509ChainStatusFlags.CtlNotTimeValid
        // TODO - check for X509ChainStatusFlags.CtlNotSignatureValid
        // TODO - check for X509ChainStatusFlags.CtlNotValidForUsage

        private void PrepareForNextCertificate(int n)
        {
            X509ChainElement   element     = elements[n];
            BCX509Certificate2 certificate = element.BCCertificate;

            // TODO 6.1.4.a-b

            // 6.1.4.c
            working_issuer_name = certificate.SubjectDN;
            // 6.1.4.d-e - our key includes both the public key and it's parameters
            working_public_key = certificate.GetPublicKey();
            // 6.1.4.f
//			working_public_key_algorithm = certificate.PublicKey.Oid.Value;

            // TODO 6.1.4.g-j

            // 6.1.4.k - Verify that the certificate is a CA certificate
            //BasicConstraints bce = (certificate.Extensions["2.5.29.19"] as BasicConstraints);
            BasicConstraints bce = BasicConstraints.GetInstance(certificate.CertificateStructure.TbsCertificate.Extensions.GetExtension(X509Extensions.BasicConstraints));

            if (bce != null)
            {
                if (!bce.IsCA())
                {
                    element.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints;
                }
            }
            else if (certificate.Version >= 3)
            {
                // recent (v3+) CA certificates must include BCE
                element.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints;
            }

            // 6.1.4.l - if the certificate isn't self-issued...
            if (!IsSelfIssued(certificate))
            {
                // ... verify that max_path_length > 0
                if (max_path_length > 0)
                {
                    max_path_length--;
                }
                else
                {
                    // to match MS the reported status must be against the certificate
                    // with the BCE and not where the path is too long. It also means
                    // that this condition has to be reported only once
                    if (bce_restriction != null)
                    {
                        bce_restriction.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints;
                    }
                }
            }

            // 6.1.4.m - if pathLengthConstraint is present...
            if ((bce != null) && (bce.PathLenConstraint != null))
            {
                // ... and is less that max_path_length, set max_path_length to it's value
                if (bce.PathLenConstraint.IntValue < max_path_length)
                {
                    max_path_length = bce.PathLenConstraint.IntValue;
                    bce_restriction = element;
                }
            }

            // 6.1.4.n - if key usage extension is present...
            //X509KeyUsage kue = (certificate.Extensions["2.5.29.15"] as X509KeyUsage);
            KeyUsage kue = KeyUsage.GetInstance(certificate.CertificateStructure.TbsCertificate.Extensions.GetExtension(X509Extensions.KeyUsage));

            if (kue != null)
            {
                // ... verify keyCertSign is set
                //KeyUsage success = new KeyUsage(KeyUsage.KeyCertSign);
                //if ((kue.KeyUsages & success) != success)
                if ((kue.IntValue & KeyUsage.KeyCertSign) != KeyUsage.KeyCertSign)
                {
                    element.StatusFlags |= X509ChainStatusFlags.NotValidForUsage;
                }
            }

            // 6.1.4.o - recognize and process other critical extension present in the certificate
            ProcessCertificateExtensions(element);
        }
Example #21
0
        internal CertificateData(byte[] rawData)
        {
#if DEBUG
            try
            {
#endif
            DerSequenceReader reader = new DerSequenceReader(rawData);

            DerSequenceReader tbsCertificate = reader.ReadSequence();

            if (tbsCertificate.PeekTag() == DerSequenceReader.ContextSpecificConstructedTag0)
            {
                DerSequenceReader version = tbsCertificate.ReadSequence();
                Version = version.ReadInteger();
            }
            else if (tbsCertificate.PeekTag() != (byte)DerSequenceReader.DerTag.Integer)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }
            else
            {
                Version = 0;
            }

            if (Version < 0 || Version > 2)
            {
                throw new CryptographicException();
            }

            SerialNumber = tbsCertificate.ReadIntegerBytes();

            DerSequenceReader tbsSignature = tbsCertificate.ReadSequence();
            TbsSignature.AlgorithmId = tbsSignature.ReadOidAsString();
            TbsSignature.Parameters  = tbsSignature.HasData ? tbsSignature.ReadNextEncodedValue() : Array.Empty <byte>();

            if (tbsSignature.HasData)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }

            Issuer = new X500DistinguishedName(tbsCertificate.ReadNextEncodedValue());

            DerSequenceReader validity = tbsCertificate.ReadSequence();
            NotBefore = validity.ReadX509Date();
            NotAfter  = validity.ReadX509Date();

            if (validity.HasData)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }

            Subject = new X500DistinguishedName(tbsCertificate.ReadNextEncodedValue());

            SubjectPublicKeyInfo = tbsCertificate.ReadNextEncodedValue();
            DerSequenceReader subjectPublicKeyInfo = new DerSequenceReader(SubjectPublicKeyInfo);
            DerSequenceReader subjectKeyAlgorithm  = subjectPublicKeyInfo.ReadSequence();
            PublicKeyAlgorithm.AlgorithmId = subjectKeyAlgorithm.ReadOidAsString();
            PublicKeyAlgorithm.Parameters  = subjectKeyAlgorithm.HasData ? subjectKeyAlgorithm.ReadNextEncodedValue() : Array.Empty <byte>();

            if (subjectKeyAlgorithm.HasData)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }

            PublicKey = subjectPublicKeyInfo.ReadBitString();

            if (subjectPublicKeyInfo.HasData)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }

            if (Version > 0 &&
                tbsCertificate.HasData &&
                tbsCertificate.PeekTag() == DerSequenceReader.ContextSpecificConstructedTag1)
            {
                IssuerUniqueId = tbsCertificate.ReadBitString();
            }
            else
            {
                IssuerUniqueId = null;
            }

            if (Version > 0 &&
                tbsCertificate.HasData &&
                tbsCertificate.PeekTag() == DerSequenceReader.ContextSpecificConstructedTag2)
            {
                SubjectUniqueId = tbsCertificate.ReadBitString();
            }
            else
            {
                SubjectUniqueId = null;
            }

            Extensions = new List <X509Extension>();

            if (Version > 1 &&
                tbsCertificate.HasData &&
                tbsCertificate.PeekTag() == DerSequenceReader.ContextSpecificConstructedTag3)
            {
                DerSequenceReader extensions = tbsCertificate.ReadSequence();
                extensions = extensions.ReadSequence();

                while (extensions.HasData)
                {
                    DerSequenceReader extensionReader = extensions.ReadSequence();
                    string            oid             = extensionReader.ReadOidAsString();
                    bool critical = false;

                    if (extensionReader.PeekTag() == (byte)DerSequenceReader.DerTag.Boolean)
                    {
                        critical = extensionReader.ReadBoolean();
                    }

                    byte[] extensionData = extensionReader.ReadOctetString();

                    Extensions.Add(new X509Extension(oid, extensionData, critical));

                    if (extensionReader.HasData)
                    {
                        throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
                    }
                }
            }

            if (tbsCertificate.HasData)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }

            DerSequenceReader signatureAlgorithm = reader.ReadSequence();
            SignatureAlgorithm.AlgorithmId = signatureAlgorithm.ReadOidAsString();
            SignatureAlgorithm.Parameters  = signatureAlgorithm.HasData ? signatureAlgorithm.ReadNextEncodedValue() : Array.Empty <byte>();

            if (signatureAlgorithm.HasData)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }

            SignatureValue = reader.ReadBitString();

            if (reader.HasData)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }

            RawData = rawData;
#if DEBUG
        }

        catch (Exception e)
        {
            throw new CryptographicException(
                      $"Error in reading certificate:{Environment.NewLine}{PemPrintCert(rawData)}",
                      e);
        }
#endif
        }
Example #22
0
        private static X509Certificate2Collection findCertificates(string prop, StoreLocation storeLocation,
                                                                   string name, string value)
        {
            //
            // Open the X509 certificate store.
            //
            X509Store store = null;

            try
            {
                try
                {
                    store = new X509Store((StoreName)Enum.Parse(typeof(StoreName), name, true), storeLocation);
                }
                catch (ArgumentException)
                {
                    store = new X509Store(name, storeLocation);
                }
                store.Open(OpenFlags.ReadOnly);
            }
            catch (Exception ex)
            {
                Ice.PluginInitializationException e = new Ice.PluginInitializationException(ex);
                e.reason = "IceSSL: failure while opening store specified by " + prop;
                throw e;
            }

            //
            // Start with all of the certificates in the collection and filter as necessary.
            //
            // - If the value is "*", return all certificates.
            // - Otherwise, search using key:value pairs. The following keys are supported:
            //
            //   Issuer
            //   IssuerDN
            //   Serial
            //   Subject
            //   SubjectDN
            //   SubjectKeyId
            //   Thumbprint
            //
            //   A value must be enclosed in single or double quotes if it contains whitespace.
            //
            X509Certificate2Collection result = new X509Certificate2Collection();

            result.AddRange(store.Certificates);
            try
            {
                if (value != "*")
                {
                    if (value.IndexOf(':') == -1)
                    {
                        Ice.PluginInitializationException e = new Ice.PluginInitializationException();
                        e.reason = "IceSSL: no key in `" + value + "'";
                        throw e;
                    }
                    int start = 0;
                    int pos;
                    while ((pos = value.IndexOf(':', start)) != -1)
                    {
                        //
                        // Parse the X509FindType.
                        //
                        string       field = value.Substring(start, pos - start).Trim().ToUpperInvariant();
                        X509FindType findType;
                        if (field.Equals("SUBJECT"))
                        {
                            findType = X509FindType.FindBySubjectName;
                        }
                        else if (field.Equals("SUBJECTDN"))
                        {
                            findType = X509FindType.FindBySubjectDistinguishedName;
                        }
                        else if (field.Equals("ISSUER"))
                        {
                            findType = X509FindType.FindByIssuerName;
                        }
                        else if (field.Equals("ISSUERDN"))
                        {
                            findType = X509FindType.FindByIssuerDistinguishedName;
                        }
                        else if (field.Equals("THUMBPRINT"))
                        {
                            findType = X509FindType.FindByThumbprint;
                        }
                        else if (field.Equals("SUBJECTKEYID"))
                        {
                            findType = X509FindType.FindBySubjectKeyIdentifier;
                        }
                        else if (field.Equals("SERIAL"))
                        {
                            findType = X509FindType.FindBySerialNumber;
                        }
                        else
                        {
                            Ice.PluginInitializationException e = new Ice.PluginInitializationException();
                            e.reason = "IceSSL: unknown key in `" + value + "'";
                            throw e;
                        }

                        //
                        // Parse the argument.
                        //
                        start = pos + 1;
                        while (start < value.Length && (value[start] == ' ' || value[start] == '\t'))
                        {
                            ++start;
                        }
                        if (start == value.Length)
                        {
                            Ice.PluginInitializationException e = new Ice.PluginInitializationException();
                            e.reason = "IceSSL: missing argument in `" + value + "'";
                            throw e;
                        }

                        string arg;
                        if (value[start] == '"' || value[start] == '\'')
                        {
                            int end = start;
                            ++end;
                            while (end < value.Length)
                            {
                                if (value[end] == value[start] && value[end - 1] != '\\')
                                {
                                    break;
                                }
                                ++end;
                            }
                            if (end == value.Length || value[end] != value[start])
                            {
                                Ice.PluginInitializationException e = new Ice.PluginInitializationException();
                                e.reason = "IceSSL: unmatched quote in `" + value + "'";
                                throw e;
                            }
                            ++start;
                            arg   = value.Substring(start, end - start);
                            start = end + 1;
                        }
                        else
                        {
                            char[] ws  = new char[] { ' ', '\t' };
                            int    end = value.IndexOfAny(ws, start);
                            if (end == -1)
                            {
                                arg   = value.Substring(start);
                                start = value.Length;
                            }
                            else
                            {
                                arg   = value.Substring(start, end - start);
                                start = end + 1;
                            }
                        }

                        //
                        // Execute the query.
                        //
                        // TODO: allow user to specify a value for validOnly?
                        //
                        bool validOnly = false;
                        if (findType == X509FindType.FindBySubjectDistinguishedName ||
                            findType == X509FindType.FindByIssuerDistinguishedName)
                        {
                            X500DistinguishedNameFlags[] flags =
                            {
                                X500DistinguishedNameFlags.None,
                                X500DistinguishedNameFlags.Reversed,
                            };
                            X500DistinguishedName      dn = new X500DistinguishedName(arg);
                            X509Certificate2Collection r  = result;
                            for (int i = 0; i < flags.Length; ++i)
                            {
                                r = result.Find(findType, dn.Decode(flags[i]), validOnly);
                                if (r.Count > 0)
                                {
                                    break;
                                }
                            }
                            result = r;
                        }
                        else
                        {
                            result = result.Find(findType, arg, validOnly);
                        }
                    }
                }
            }
            finally
            {
                store.Close();
            }

            return(result);
        }
Example #23
0
        //
        // Used only by client SSL code, never returns null.
        //
        internal static string[] GetRequestCertificateAuthorities(SafeDeleteContext securityContext)
        {
            Interop.SspiCli.SecPkgContext_IssuerListInfoEx issuerList =
                (Interop.SspiCli.SecPkgContext_IssuerListInfoEx)SSPIWrapper.QueryContextAttributes(
                    GlobalSSPI.SSPISecureChannel,
                    securityContext,
                    Interop.SspiCli.ContextAttribute.SECPKG_ATTR_ISSUER_LIST_EX);

            string[] issuers = Array.Empty <string>();

            try
            {
                if (issuerList.cIssuers > 0)
                {
                    unsafe
                    {
                        uint count = issuerList.cIssuers;
                        issuers = new string[issuerList.cIssuers];
                        Interop.SspiCli.CERT_CHAIN_ELEMENT *pIL = (Interop.SspiCli.CERT_CHAIN_ELEMENT *)issuerList.aIssuers.DangerousGetHandle();
                        for (int i = 0; i < count; ++i)
                        {
                            Interop.SspiCli.CERT_CHAIN_ELEMENT *pIL2 = pIL + i;
                            if (pIL2->cbSize <= 0)
                            {
                                if (GlobalLog.IsEnabled)
                                {
                                    GlobalLog.Assert("SecureChannel::GetIssuers()", "Interop.SspiCli._CERT_CHAIN_ELEMENT size is not positive: " + pIL2->cbSize.ToString());
                                }

                                Debug.Fail("SecureChannel::GetIssuers()", "Interop.SspiCli._CERT_CHAIN_ELEMENT size is not positive: " + pIL2->cbSize.ToString());
                            }

                            if (pIL2->cbSize > 0)
                            {
                                uint   size = pIL2->cbSize;
                                byte * ptr  = (byte *)(pIL2->pCertContext);
                                byte[] x    = new byte[size];
                                for (int j = 0; j < size; j++)
                                {
                                    x[j] = *(ptr + j);
                                }

                                X500DistinguishedName x500DistinguishedName = new X500DistinguishedName(x);
                                issuers[i] = x500DistinguishedName.Name;
                                if (GlobalLog.IsEnabled)
                                {
                                    GlobalLog.Print("SecureChannel#" + LoggingHash.HashString(securityContext) + "::GetIssuers() IssuerListEx[" + i + "]:" + issuers[i]);
                                }
                            }
                        }
                    }
                }
            }
            finally
            {
                if (issuerList.aIssuers != null)
                {
                    issuerList.aIssuers.Dispose();
                }
            }

            return(issuers);
        }
Example #24
0
        /// <summary>
        /// Create a new certificate
        /// </summary>
        /// <param name="issuer">Issuer certificate, if null then self-sign</param>
        /// <param name="subjectName">Subject name</param>
        /// <param name="serialNumber">Serial number of certificate, if null then will generate a new one</param>
        /// <param name="signature">If true create an AT_SIGNATURE key, otherwise AT_EXCHANGE</param>
        /// <param name="keySize">Size of RSA key</param>
        /// <param name="notBefore">Start date of certificate</param>
        /// <param name="notAfter">End date of certificate</param>
        /// <param name="extensions">Array of extensions, if null then no extensions</param>
        /// <param name="hashAlgorithm">Specify the signature hash algorithm</param>
        /// <returns>The created X509 certificate</returns>
        public X509Certificate2 CreateCert(X509Certificate2 issuer, X500DistinguishedName subjectName, byte[] serialNumber, bool signature, int keySize, CertificateHashAlgorithm hashAlgorithm, DateTime notBefore, DateTime notAfter, X509ExtensionCollection extensions)
        {
            CryptoApiMethods.CERT_INFO certInfo   = new CryptoApiMethods.CERT_INFO();
            RSACryptoServiceProvider   key        = CreateRSAKey(keySize, signature);
            IntPtr               publicKeyInfoPtr = IntPtr.Zero;
            X509Certificate2     cert             = null;
            List <X509Extension> newExts          = null;

            if (extensions != null)
            {
                foreach (X509Extension ext in extensions)
                {
                    if (ext.RawData == null)
                    {
                        throw new ArgumentException(Properties.Resources.CreateCert_NeedEncodedData);
                    }
                }
            }

            try
            {
                if (serialNumber == null)
                {
                    serialNumber = Guid.NewGuid().ToByteArray();
                }

                certInfo.dwVersion    = (uint)CryptoApiMethods.CertVersion.CERT_V3;
                certInfo.SerialNumber = new CryptoApiMethods.CRYPTOAPI_BLOB(serialNumber);
                certInfo.Subject      = new CryptoApiMethods.CRYPTOAPI_BLOB(subjectName.RawData);

                if (issuer == null)
                {
                    // Self-signed
                    certInfo.Issuer = new CryptoApiMethods.CRYPTOAPI_BLOB(subjectName.RawData);
                }
                else
                {
                    certInfo.Issuer = new CryptoApiMethods.CRYPTOAPI_BLOB(issuer.SubjectName.RawData);
                }

                // Never seems to need these set to anything valid?
                certInfo.SubjectUniqueId = new CryptoApiMethods.CRYPT_BIT_BLOB();
                certInfo.IssuerUniqueId  = new CryptoApiMethods.CRYPT_BIT_BLOB();

                certInfo.NotBefore = DateTimeToFileTime(notBefore);
                certInfo.NotAfter  = DateTimeToFileTime(notAfter);

                certInfo.SignatureAlgorithm = new CryptoApiMethods.CRYPT_ALGORITHM_IDENTIFIER();
                // Doesn't seem to work properly with standard szOID_RSA_SHA1RSA
                //certInfo.SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_OIWSEC_sha1RSASign;
                //certInfo.SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_RSA_SHA1RSA;
                //certInfo.SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_RSA_SHA512RSA;
                certInfo.SignatureAlgorithm.pszObjId = HashAlgorithmToOID(hashAlgorithm);

                // Add extension fields
                publicKeyInfoPtr = ExportPublicKeyInfo(key);
                certInfo.SubjectPublicKeyInfo = (CryptoApiMethods.CERT_PUBLIC_KEY_INFO)Marshal.PtrToStructure(publicKeyInfoPtr, typeof(CryptoApiMethods.CERT_PUBLIC_KEY_INFO));

                newExts = new List <X509Extension>();

                if (extensions != null)
                {
                    // Filter out some extensions we don't want
                    newExts.AddRange(
                        extensions.Cast <X509Extension>().Where(
                            x =>
                            !x.Oid.Value.Equals(CryptoApiMethods.szOID_AUTHORITY_KEY_IDENTIFIER) &&
                            !x.Oid.Value.Equals(CryptoApiMethods.szOID_SUBJECT_KEY_IDENTIFIER) &&
                            !x.Oid.Value.Equals(CryptoApiMethods.szOID_AUTHORITY_KEY_IDENTIFIER2)));
                }

                if (issuer != null)
                {
                    newExts.Add(CreateAuthorityKeyInfo2(issuer.GetSerialNumber(), issuer.SubjectName, (RSACryptoServiceProvider)issuer.PrivateKey));
                }
                else
                {
                    newExts.Add(CreateAuthorityKeyInfo2(serialNumber, subjectName, key));
                }

                newExts.Add(new X509SubjectKeyIdentifierExtension(HashPublicKeyInfo(key), false));

                certInfo.rgExtension = MarshalExtensions(newExts.ToArray());
                certInfo.cExtension  = (uint)newExts.Count;

                byte[] certData = EncodeAndSignCertInfo(issuer != null ? issuer.PrivateKey as RSACryptoServiceProvider : key, certInfo, hashAlgorithm);

                cert            = new X509Certificate2(certData, (string)null, X509KeyStorageFlags.Exportable);
                cert.PrivateKey = key;
            }
            finally
            {
                if (certInfo.rgExtension != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(certInfo.rgExtension);
                }

                if (certInfo.Subject != null)
                {
                    certInfo.Subject.Release();
                }

                if (certInfo.Issuer != null)
                {
                    certInfo.Issuer.Release();
                }

                if (publicKeyInfoPtr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(publicKeyInfoPtr);
                }
            }

            return(cert);
        }
Example #25
0
 public override CertificateRequest GenerateCsr(X500DistinguishedName commonName)
 {
     return(new CertificateRequest(commonName, Algorithm, HashAlgorithmName.SHA256));
 }
Example #26
0
 /// <summary>
 /// Initialize a Certificate builder.
 /// </summary>
 protected CertificateBuilderBase(X500DistinguishedName subjectName)
 {
     m_issuerName = m_subjectName = subjectName;
     Initialize();
 }
Example #27
0
 /// <summary>
 /// Comprueba si dos DN son equivalentes
 /// </summary>
 /// <param name="dn"></param>
 /// <param name="other"></param>
 /// <returns></returns>
 private bool EquivalentDN(X500DistinguishedName dn, X500DistinguishedName other)
 {
     return(X509Name.GetInstance(Asn1Object.FromByteArray(dn.RawData)).Equivalent(X509Name.GetInstance(Asn1Object.FromByteArray(other.RawData))));
 }
Example #28
0
 /// <summary>
 /// Initialize a Certificate builder.
 /// </summary>
 protected CertificateBuilderBase(string subjectName)
 {
     m_issuerName = m_subjectName = new X500DistinguishedName(subjectName);
     Initialize();
 }
Example #29
0
        void decodeTbsResponse(Asn1Reader tbsResponseData)
        {
            tbsResponseData.MoveNext();
            if (tbsResponseData.Tag == 160)
            {
                //Asn1Reader aversion = new Asn1Reader(tbsResponseData.RawData, tbsResponseData.PayloadStartOffset);
                Asn1Reader aversion = new Asn1Reader(tbsResponseData);
                aversion.MoveNext();
                Version = aversion.GetPayload()[0] + 1;
                tbsResponseData.MoveNextCurrentLevel();
            }
            else
            {
                Version = 1;
            }
            //responderID
            switch (tbsResponseData.Tag)
            {
            case 161:
                ResponderNameId = new X500DistinguishedName(tbsResponseData.GetPayload());
                tbsResponseData.MoveNextCurrentLevel();
                break;

            case 162:
                tbsResponseData.MoveNext();
                StringBuilder SB = new StringBuilder();
                foreach (Byte element in tbsResponseData.GetPayload())
                {
                    SB.Append(element.ToString("X2"));
                }
                ResponderKeyId = SB.ToString();
                tbsResponseData.MoveNext();
                break;

            default:
                throw new Exception("Invalid tag at responderID. Expected 161 (byName) or 162 (byKey).");
            }
            //tbsResponseData.MoveNextCurrentLevel();
            ProducedAt = Asn1Utils.DecodeGeneralizedTime(tbsResponseData.GetTagRawData());
            if (DateTime.Now < ProducedAt.AddMinutes(-10))
            {
                ResponseErrorInformation += (Int32)OCSPResponseComplianceError.ResponseNotTimeValid;
            }
            //responses
            tbsResponseData.MoveNext();
            //single response
            Asn1Reader responses = new Asn1Reader(tbsResponseData.GetTagRawData());

            responses.MoveNext();
            Int32 Offset;

            Responses = new OCSPSingleResponseCollection();
            do
            {
                Asn1Reader response = new Asn1Reader(responses);
                Offset = response.NextCurrentLevelOffset;
                Responses.Add(new OCSPSingleResponse(response));
                if (Request != null)
                {
                    foreach (OCSPSingleResponse item in Responses)
                    {
                        Boolean certidmatch = Request.RequestList.Any(x => x.CertId.Equals(item.CertId));
                        if (!certidmatch)
                        {
                            ResponseErrorInformation += (Int32)OCSPResponseComplianceError.CertIdMismatch;
                        }
                    }
                }
            } while (Offset != 0);
            if (tbsResponseData.NextCurrentLevelOffset != 0)
            {
                tbsResponseData.MoveNextCurrentLevel();
                if (tbsResponseData.Tag == 161)
                {
                    X509ExtensionCollection exts = new X509ExtensionCollection();
                    exts.Decode(tbsResponseData.GetPayload());
                    foreach (X509Extension item in exts)
                    {
                        _listExtensions.Add(CryptographyUtils.ConvertExtension(item));
                        if (_listExtensions[_listExtensions.Count - 1].Oid.Value == X509CertExtensions.X509OcspNonce)
                        {
                            NonceReceived = true;
                            NonceValue    = _listExtensions[_listExtensions.Count - 1].Format(false);
                        }
                    }
                }
                else
                {
                    throw new Exception("Unexpected tag at responseExtensions. Expected 161.");
                }
            }
        }
        public static void ReproduceBigExponentCert()
        {
            DateTimeOffset notBefore = new DateTimeOffset(2016, 3, 2, 1, 48, 0, TimeSpan.Zero);
            DateTimeOffset notAfter  = new DateTimeOffset(2017, 3, 2, 1, 48, 0, TimeSpan.Zero);

            byte[] serialNumber = "9B5DE6C15126A58B".HexToByteArray();

            var subject = new X500DistinguishedName(
                "CN=localhost, OU=.NET Framework (CoreFX), O=Microsoft Corporation, L=Redmond, S=Washington, C=US");

            X509Extension skidExtension = new X509SubjectKeyIdentifierExtension(
                "78A5C75D51667331D5A96924114C9B5FA00D7BCB",
                false);

            X509Extension akidExtension = new X509Extension(
                "2.5.29.35",
                "3016801478A5C75D51667331D5A96924114C9B5FA00D7BCB".HexToByteArray(),
                false);

            X509Extension basicConstraints = new X509BasicConstraintsExtension(true, false, 0, false);

            X509Certificate2 cert;

            using (RSA rsa = RSA.Create())
            {
                rsa.ImportParameters(TestData.RsaBigExponentParams);

                var request = new CertificateRequest(subject, rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
                request.CertificateExtensions.Add(skidExtension);
                request.CertificateExtensions.Add(akidExtension);
                request.CertificateExtensions.Add(basicConstraints);

                var signatureGenerator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1);

                cert = request.Create(subject, signatureGenerator, notBefore, notAfter, serialNumber);
            }

            const string expectedHex =
                "308203EB308202D3A0030201020209009B5DE6C15126A58B300D06092A864886" +
                "F70D01010B050030818A310B3009060355040613025553311330110603550408" +
                "130A57617368696E67746F6E3110300E060355040713075265646D6F6E64311E" +
                "301C060355040A13154D6963726F736F667420436F72706F726174696F6E3120" +
                "301E060355040B13172E4E4554204672616D65776F726B2028436F7265465829" +
                "31123010060355040313096C6F63616C686F7374301E170D3136303330323031" +
                "343830305A170D3137303330323031343830305A30818A310B30090603550406" +
                "13025553311330110603550408130A57617368696E67746F6E3110300E060355" +
                "040713075265646D6F6E64311E301C060355040A13154D6963726F736F667420" +
                "436F72706F726174696F6E3120301E060355040B13172E4E4554204672616D65" +
                "776F726B2028436F726546582931123010060355040313096C6F63616C686F73" +
                "7430820124300D06092A864886F70D010101050003820111003082010C028201" +
                "0100AF81C1CBD8203F624A539ED6608175372393A2837D4890E48A19DED36973" +
                "115620968D6BE0D3DAA38AA777BE02EE0B6B93B724E8DCC12B632B4FA80BBC92" +
                "5BCE624F4CA7CC606306B39403E28C932D24DD546FFE4EF6A37F10770B2215EA" +
                "8CBB5BF427E8C4D89B79EB338375100C5F83E55DE9B4466DDFBEEE42539AEF33" +
                "EF187B7760C3B1A1B2103C2D8144564A0C1039A09C85CF6B5974EB516FC8D662" +
                "3C94AE3A5A0BB3B4C792957D432391566CF3E2A52AFB0C142B9E0681B8972671" +
                "AF2B82DD390A39B939CF719568687E4990A63050CA7768DCD6B378842F18FDB1" +
                "F6D9FF096BAF7BEB98DCF930D66FCFD503F58D41BFF46212E24E3AFC45EA42BD" +
                "884702050200000441A350304E301D0603551D0E0416041478A5C75D51667331" +
                "D5A96924114C9B5FA00D7BCB301F0603551D2304183016801478A5C75D516673" +
                "31D5A96924114C9B5FA00D7BCB300C0603551D13040530030101FF300D06092A" +
                "864886F70D01010B0500038201010077756D05FFA6ADFED5B6D4AFB540840C6D" +
                "01CF6B3FA6C973DFD61FCAA0A814FA1E2469019D94B1D856D07DD2B95B8550DF" +
                "D2085953A494B99EFCBAA7982CE771984F9D4A445FFEE062E8A049736A39FD99" +
                "4E1FDA0A5DC2B5B0E57A0B10C41BC7FE6A40B24F85977302593E60B98DD4811D" +
                "47D948EDF8D6E6B5AF80A1827496E20BFD240E467674504D4E4703331D64705C" +
                "36FB6E14BABFD9CBEEC44B33A8D7B36479900F3C5BBAB69C5E453D180783E250" +
                "8051B998C038E4622571D2AB891D898E5458828CF18679517D28DBCABF72E813" +
                "07BFD721B73DDB1751123F99D8FC0D533798C4DBD14719D5D8A85B00A144A367" +
                "677B48891A9B56F045334811BACB7A";

            using (cert)
            {
                Assert.Equal(expectedHex, cert.RawData.ByteArrayToHex());
            }
        }
        public static void NotQuotedWithQuotes(string quoted, string notQuoted, string hexEncoded)
        {
            byte[] encoded = hexEncoded.HexToByteArray();
            X500DistinguishedName dn = new X500DistinguishedName(encoded);

            Assert.Equal(notQuoted, dn.Decode(X500DistinguishedNameFlags.DoNotUseQuotes));
        }
Example #32
0
        internal static X509Certificate2 CreateSelfSignedCertificate(string commonName, string country, string state, string locality, string organization, string organizationUnit, SecureString password, string friendlyName, DateTimeOffset from, DateTimeOffset to)
        {
            SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder();

            sanBuilder.AddDnsName("localhost");
            sanBuilder.AddDnsName(Environment.MachineName);

            var x500Values = new List <string>();

            if (!string.IsNullOrWhiteSpace(commonName))
            {
                x500Values.Add($"CN={commonName}");
            }
            if (!string.IsNullOrWhiteSpace(country))
            {
                x500Values.Add($"C={country}");
            }
            if (!string.IsNullOrWhiteSpace(state))
            {
                x500Values.Add($"S={state}");
            }
            if (!string.IsNullOrWhiteSpace(locality))
            {
                x500Values.Add($"L={locality}");
            }
            if (!string.IsNullOrWhiteSpace(organization))
            {
                x500Values.Add($"O={organization}");
            }
            if (!string.IsNullOrWhiteSpace(organizationUnit))
            {
                x500Values.Add($"OU={organizationUnit}");
            }

            string distinguishedNameString = string.Join("; ", x500Values);

            X500DistinguishedName distinguishedName = new X500DistinguishedName(distinguishedNameString);

            using (RSA rsa = MakeExportable(new RSACng(2048)))
            {
                var request = new CertificateRequest(distinguishedName, rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

                request.CertificateExtensions.Add(
                    new X509KeyUsageExtension(X509KeyUsageFlags.DataEncipherment | X509KeyUsageFlags.KeyEncipherment | X509KeyUsageFlags.DigitalSignature, false));


                request.CertificateExtensions.Add(
                    new X509EnhancedKeyUsageExtension(
                        new OidCollection {
                    new Oid("1.3.6.1.5.5.7.3.1")
                }, false));

                request.CertificateExtensions.Add(sanBuilder.Build());

                var certificate = request.CreateSelfSigned(from, to);

                if (Platform.IsWindows)
                {
                    certificate.FriendlyName = friendlyName;
                }

                return(new X509Certificate2(certificate.Export(X509ContentType.Pfx, password), password, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet));
            }
        }
        public static void PrintComplexForwards()
        {
            byte[] encoded = MicrosoftDotComSubject.HexToByteArray();
            X500DistinguishedName dn = new X500DistinguishedName(encoded);

            const string expected =
                ", SERIALNUMBER=600413485, C=US, PostalCode=98052, S=Washington, L=Redmond, " +
                "STREET=1 Microsoft Way, O=Microsoft Corporation, OU=MSCOM, CN=www.microsoft.com";

            Assert.EndsWith(expected, dn.Decode(X500DistinguishedNameFlags.None), StringComparison.Ordinal);
        }
 public X500DistinguishedName(X500DistinguishedName distinguishedName);
        public static void FractionalSecondsNotWritten(bool selfSigned)
        {
            using (X509Certificate2 savedCert = new X509Certificate2(TestData.PfxData, TestData.PfxDataPassword))
                using (RSA rsa = savedCert.GetRSAPrivateKey())
                {
                    X500DistinguishedName subjectName = new X500DistinguishedName("CN=Test");

                    var request = new CertificateRequest(
                        subjectName,
                        rsa,
                        HashAlgorithmName.SHA256,
                        RSASignaturePadding.Pkcs1);

                    // notBefore is a date before 2050 UTC (encoded using UTC TIME),
                    // notAfter is a date after 2050 UTC (encoded using GENERALIZED TIME).

                    DateTimeOffset notBefore = new DateTimeOffset(2049, 3, 4, 5, 6, 7, 89, TimeSpan.Zero);
                    DateTimeOffset notAfter  = notBefore.AddYears(2);
                    Assert.NotEqual(0, notAfter.Millisecond);

                    DateTimeOffset   normalizedBefore   = notBefore.AddMilliseconds(-notBefore.Millisecond);
                    DateTimeOffset   normalizedAfter    = notAfter.AddMilliseconds(-notAfter.Millisecond);
                    byte[]           manualSerialNumber = { 3, 2, 1 };
                    X509Certificate2 cert;

                    if (selfSigned)
                    {
                        cert = request.CreateSelfSigned(notBefore, notAfter);
                    }
                    else
                    {
                        cert = request.Create(
                            subjectName,
                            X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1),
                            notBefore,
                            notAfter,
                            manualSerialNumber);
                    }

                    using (cert)
                    {
                        Assert.Equal(normalizedBefore.DateTime.ToLocalTime(), cert.NotBefore);
                        Assert.Equal(normalizedAfter.DateTime.ToLocalTime(), cert.NotAfter);

                        if (selfSigned)
                        {
                            // The serial number used in CreateSelfSigned is random, so find the issuer name,
                            // and the validity period is the next 34 bytes.  Verify it was encoded as expected.
                            //
                            // Since the random serial number is at most 9 bytes and the subjectName encoded
                            // value is 17 bytes, there's no chance of an early false match.
                            byte[] encodedCert = cert.RawData;
                            byte[] needle      = subjectName.RawData;

                            int index = encodedCert.AsSpan().IndexOf(needle);
                            Assert.Equal(
                                "3020170D3439303330343035303630375A180F32303531303330343035303630375A",
                                encodedCert.AsSpan(index + needle.Length, 34).ByteArrayToHex());
                        }
                        else
                        {
                            // The entire encoding is deterministic in this mode.
                            Assert.Equal(
                                "308201953081FFA0030201020203030201300D06092A864886F70D01010B0500" +
                                "300F310D300B06035504031304546573743020170D3439303330343035303630" +
                                "375A180F32303531303330343035303630375A300F310D300B06035504031304" +
                                "5465737430819F300D06092A864886F70D010101050003818D00308189028181" +
                                "00B11E30EA87424A371E30227E933CE6BE0E65FF1C189D0D888EC8FF13AA7B42" +
                                "B68056128322B21F2B6976609B62B6BC4CF2E55FF5AE64E9B68C78A3C2DACC91" +
                                "6A1BC7322DD353B32898675CFB5B298B176D978B1F12313E3D865BC53465A11C" +
                                "CA106870A4B5D50A2C410938240E92B64902BAEA23EB093D9599E9E372E48336" +
                                "730203010001300D06092A864886F70D01010B0500038181000095ABC7CC7B01" +
                                "9C2A88A7891165B6ACCDBC5137D80C0A5151B11FD4D789CCE808412ABF05FFB1" +
                                "D9BE097776147A6D4C3EE177E5F9C2C9E8C005D72A6473F9904185B95634BFB4" +
                                "EA80B232B271DC1BF20A2FDC46FC93771636B618F29417C31D5F602236FDB414" +
                                "CDC1BEDE700E31E80DC5E7BB7D3F367420B72925605C916BDA",
                                cert.RawData.ByteArrayToHex());
                        }
                    }
                }
        }
Example #36
0
        /// <summary>
        /// Generates and sends a CSR to Xboot.Server REST endpoint.
        /// </summary>
        /// <param name="registrationId"></param>
        /// <param name="name"></param>
        /// <returns>Pfx in DER-encoded byte array</returns>
        public byte[] GetDeviceCertificate(string registrationId, X500DistinguishedName name)
        {
            byte[] pfx = null;

            var req = new CertificateRequest(name, _rsa, HashAlgorithmName.SHA512,
                                             RSASignaturePadding.Pss);

            // Returns a DER-encoded PKCS#10 CSR
            var csr = req.CreateSigningRequest();

            Certificate_Request request = new Certificate_Request
            {
                RegistrationId = registrationId,
                Csr            = Convert.ToBase64String(csr)
            };

            var json = JsonConvert.SerializeObject(request);

            var client = new HttpClient();

            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));

            var buffer      = System.Text.Encoding.UTF8.GetBytes(json);
            var byteContent = new ByteArrayContent(buffer);

            try
            {
                var response = client.PostAsync(_xBootUri, byteContent).Result;

                if (response.IsSuccessStatusCode)
                {
                    // Get the response
                    var jsonString = response.Content.ReadAsStringAsync().Result;
                    var certString = JsonConvert.DeserializeObject <Certificate_Response>(jsonString);

                    byte[] certBytes = Convert.FromBase64String(certString.Certificate);

                    // Read in signed device certificate in DER format
                    X509Certificate2 cert = new X509Certificate2(certBytes);

                    // Add private key to cert
                    cert = cert.CopyWithPrivateKey(_rsa);

                    if (cert.HasPrivateKey)
                    {
                        // Combine certificate and private key into single pfx
                        // The IoT Device SDK needs both the certificate and the private key information.
                        // It expects to load a single PFX-formatted file containing all necessarily information.
                        pfx = cert.Export(X509ContentType.Pfx);
                    }
                }
                else
                {
                    throw new Exception(response.StatusCode.ToString());
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }

            // Return certificate in DER-encoded byte array
            return(pfx);
        }
 public static void QuoteByContents(string expected, string hexEncoded)
 {
     byte[] encoded = hexEncoded.HexToByteArray();
     X500DistinguishedName dn = new X500DistinguishedName(encoded);
     Assert.Equal(expected, dn.Decode(X500DistinguishedNameFlags.None));
 }
        public static void NameWithSTIdentifierForState()
        {
            X500DistinguishedName dn = new X500DistinguishedName("ST=VA, C=US");

            Assert.Equal("C=US, S=VA", dn.Decode(X500DistinguishedNameFlags.None));
        }
Example #39
0
		public override void Reset () 
		{
			_cert = null;
			_archived = false;
			_extensions = null;
			_name = String.Empty;
			_serial = null;
			_publicKey = null;
			issuer_name = null;
			subject_name = null;
			signature_algorithm = null;
			base.Reset ();
		}
 public static Claim CreateX500DistinguishedNameClaim(
     X500DistinguishedName x500DistinguishedName)
 {
     return(new Claim(ClaimTypes.X500DistinguishedName, x500DistinguishedName, Rights.PossessProperty));
 }
        /// <summary>
        /// Create a self-signed certificate.
        /// </summary>
        internal static byte[] CreateSelfSignedCert(
            X500DistinguishedName subjectName,
            string friendlyName,
            DateTime startTime,
            DateTime endTime,
            SecureString password)
        {
            byte[] pfxData;

            SystemTime startSystemTime = ToSystemTime(startTime);
            SystemTime endSystemTime   = ToSystemTime(endTime);
            string     containerName   = Guid.NewGuid().ToString();

            IntPtr providerContext  = IntPtr.Zero;
            IntPtr cryptKey         = IntPtr.Zero;
            IntPtr certContext      = IntPtr.Zero;
            IntPtr certStore        = IntPtr.Zero;
            IntPtr storeCertContext = IntPtr.Zero;
            IntPtr passwordPtr      = IntPtr.Zero;

            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                Check(NativeMethods.CryptAcquireContextW(
                          out providerContext,
                          containerName,
                          null,
                          1,   // PROV_RSA_FULL
                          8)); // CRYPT_NEWKEYSET

                Check(NativeMethods.CryptGenKey(
                          providerContext,
                          1,                   // AT_KEYEXCHANGE
                          1 | (KeySize << 16), // CRYPT_EXPORTABLE
                          out cryptKey));

                unsafe
                {
                    fixed(char *pContainerName = containerName.ToCharArray())
                    {
                        CryptKeyProviderInformation kpi = new CryptKeyProviderInformation();

                        kpi.ContainerName = (IntPtr)pContainerName;
                        kpi.ProviderType  = 1; // PROV_RSA_FULL
                        kpi.KeySpec       = 1; // AT_KEYEXCHANGE

                        fixed(byte *pSubjectName = &subjectName.RawData[0])
                        {
                            CryptoApiBlob nameBlob = new CryptoApiBlob(
                                subjectName.RawData.Length,
                                (IntPtr)pSubjectName);

                            certContext = NativeMethods.CertCreateSelfSignCertificate(
                                providerContext,
                                ref nameBlob,
                                0,
                                ref kpi,
                                IntPtr.Zero, // default = SHA1RSA
                                ref startSystemTime,
                                ref endSystemTime,
                                IntPtr.Zero);
                            Check(certContext != IntPtr.Zero);
                        }

                        certStore = NativeMethods.CertOpenStore(
                            "Memory", // sz_CERT_STORE_PROV_MEMORY
                            0,
                            IntPtr.Zero,
                            0x2000, // CERT_STORE_CREATE_NEW_FLAG
                            IntPtr.Zero);
                        Check(certStore != IntPtr.Zero);

                        Check(NativeMethods.CertAddCertificateContextToStore(
                                  certStore,
                                  certContext,
                                  1, // CERT_STORE_ADD_NEW
                                  out storeCertContext));

                        NativeMethods.CertSetCertificateContextProperty(
                            storeCertContext,
                            2, // CERT_KEY_PROV_INFO_PROP_ID
                            0,
                            (IntPtr)(&kpi));
                    }

                    fixed(char *pFriendlyName = friendlyName.ToCharArray())
                    {
                        var blob = new CryptoApiBlob(
                            friendlyName.Length * sizeof(char),
                            (IntPtr)pFriendlyName);

                        NativeMethods.CertSetCertificateContextProperty(
                            storeCertContext,
                            11, // CERT_FRIENDLY_NAME_PROP_ID
                            0,
                            (IntPtr)(&blob));
                    }

                    if (password != null && password.Length > 0)
                    {
                        passwordPtr = Marshal.SecureStringToCoTaskMemUnicode(password);
                    }

                    CryptoApiBlob pfxBlob = new CryptoApiBlob();

                    Check(NativeMethods.PFXExportCertStoreEx(
                              certStore,
                              ref pfxBlob,
                              passwordPtr,
                              IntPtr.Zero,
                              7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY

                    pfxData = new byte[pfxBlob.DataLength];
                    fixed(byte *pData = pfxData)
                    {
                        pfxBlob.Data = (IntPtr)pData;
                        Check(NativeMethods.PFXExportCertStoreEx(
                                  certStore,
                                  ref pfxBlob,
                                  passwordPtr,
                                  IntPtr.Zero,
                                  7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY
                    }
                }
            }
            finally
            {
                if (passwordPtr != IntPtr.Zero)
                {
                    Marshal.ZeroFreeCoTaskMemUnicode(passwordPtr);
                }

                if (certContext != IntPtr.Zero)
                {
                    NativeMethods.CertFreeCertificateContext(certContext);
                }

                if (storeCertContext != IntPtr.Zero)
                {
                    NativeMethods.CertFreeCertificateContext(storeCertContext);
                }

                if (certStore != IntPtr.Zero)
                {
                    NativeMethods.CertCloseStore(certStore, 0);
                }

                if (cryptKey != IntPtr.Zero)
                {
                    NativeMethods.CryptDestroyKey(cryptKey);
                }

                if (providerContext != IntPtr.Zero)
                {
                    NativeMethods.CryptReleaseContext(providerContext, 0);
                    NativeMethods.CryptAcquireContextW(
                        out providerContext,
                        containerName,
                        null,
                        1,     // PROV_RSA_FULL
                        0x10); // CRYPT_DELETEKEYSET
                }
            }

            return(pfxData);
        }
Example #42
0
 public abstract CertificateRequest GenerateCsr(X500DistinguishedName dn);
Example #43
0
        public static void TestFormat(bool multiLine)
        {
            // The Issuer field from the Microsoft.com test cert.
            byte[] encoding = (
                "3077310B3009060355040613025553311D301B060355040A131453796D616E74" +
                "656320436F72706F726174696F6E311F301D060355040B131653796D616E7465" +
                "63205472757374204E6574776F726B312830260603550403131F53796D616E74" +
                "656320436C61737320332045562053534C204341202D204733").HexToByteArray();

            X500DistinguishedName name = new X500DistinguishedName(encoding);
            string formatted = name.Format(multiLine);
            string expected;

            if (multiLine)
            {
                expected = string.Format(
                    "C=US{0}O=Symantec Corporation{0}OU=Symantec Trust Network{0}CN=Symantec Class 3 EV SSL CA - G3{0}",
                    Environment.NewLine);
            }
            else
            {
                expected = "C=US, O=Symantec Corporation, OU=Symantec Trust Network, CN=Symantec Class 3 EV SSL CA - G3";
            }

            Assert.Equal(expected, formatted);
        }
        /// <inheritdoc/>
        public async Task <Certificate> CreateCertificateAndPrivateKeyAsync(string rootCertificate,
                                                                            string certificateName, X500DistinguishedName subjectName, DateTime?notBefore,
                                                                            CreateKeyParams keyParams, Func <byte[], IEnumerable <X509Extension> > extensions,
                                                                            CancellationToken ct)
        {
            try {
                // (0) Retrieve issuer certificate
                var caCertBundle = await _keyVaultClient.GetCertificateAsync(
                    _vaultBaseUrl, rootCertificate, ct);

                if (caCertBundle == null)
                {
                    throw new ResourceNotFoundException("Issuer cert not found.");
                }
                var caCert = await _certificates.FindCertificateAsync(
                    caCertBundle.CertificateIdentifier.Identifier);

                if (caCert?.IssuerPolicies == null)
                {
                    throw new ArgumentException("Certificate cannot issue.");
                }

                // (1) Create key in key vault and get CSR.

                // policy unknown issuer, new key, exportable key
                var policyUnknownNewExportable = CreateCertificatePolicy(
                    subjectName.Name, keyParams, false, _keyStoreIsHsm, false, true);

                var attributes = CreateCertificateAttributes(notBefore,
                                                             caCert.IssuerPolicies.IssuedLifetime.Value, caCert.NotAfterUtc);
                var createResult = await CreateCertificateAsync(certificateName,
                                                                policyUnknownNewExportable, attributes, null, ct);

                if (createResult.Csr == null)
                {
                    throw new CryptographicUnexpectedOperationException(
                              "Failed to read CSR from CreateCertificate.");
                }
                // decode the CSR and verify consistency
                var info = createResult.Csr.ToCertificationRequest();

                try {
                    // (2) - Issue X509 Certificate with csr and root certificate.

                    // create signed cert
                    var signedcert = await _factory.CreateCertificateAsync(this,
                                                                           caCert, subjectName, info.PublicKey,
                                                                           attributes.NotBefore.Value, attributes.Expires.Value,
                                                                           caCert.IssuerPolicies.SignatureType.Value, false, extensions, ct);

                    // (3) - Complete certificate creation with merger of X509 Certificate.

                    var mergeResult = await _keyVaultClient.MergeCertificateAsync(
                        _vaultBaseUrl, certificateName,
                        new X509Certificate2Collection(signedcert), null, null, ct);

                    // (4) - Get merged certificate and key identifier

                    var mergedCert = await _keyVaultClient.GetCertificateAsync(
                        mergeResult.CertificateIdentifier.Identifier, ct);

                    var cert = CertificateEx.Create(mergedCert.Cer,
                                                    new KeyVaultKeyHandle(mergedCert));
                    System.Diagnostics.Debug.Assert(!cert.IsIssuer());
                    await _certificates.AddCertificateAsync(certificateName,
                                                            cert, mergedCert.CertificateIdentifier.Identifier, ct);

                    return(cert);
                }
                catch {
                    await _keyVaultClient.DeleteCertificateAsync(
                        _vaultBaseUrl, certificateName, ct);

                    await Try.Async(() => _keyVaultClient.PurgeDeletedCertificateAsync(
                                        _vaultBaseUrl, certificateName, ct));

                    throw;
                }
            }
            catch (KeyVaultErrorException ex) {
                throw new ExternalDependencyException(
                          "Failed to create new key pair certificate", ex);
            }
        }