public static string ConvertDistinguishedNameToString(X500DistinguishedName dnString) { string name = dnString.Name; bool flag = false; string[] strArray = dnString.Decode(X500DistinguishedNameFlags.UseNewLines).Split(new char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); if (strArray.Length > 0) { flag = true; string pairAndValue = string.Empty; for (int i = 0; i < strArray.Length; i++) { pairAndValue = strArray[i]; Pair pair = ConvertStringToPair(pairAndValue); if (string.Equals((string) pair.First, "CN", StringComparison.OrdinalIgnoreCase)) { name = (string) pair.Second; flag = false; break; } } } else { name = (string) ConvertStringToPair(name).Second; flag = false; } if (flag) { name = dnString.Name; } return name; }
public static X509Certificate2 CreateCertificate(X500DistinguishedName subjectName, string friendlyName) { var key = Create2048RsaKey(); var cert = CreateSelfSignedCertificate(key, subjectName); cert.FriendlyName = friendlyName; return cert; }
private static X509Certificate2 CreateSelfSignedCertificate(CngKey key, X500DistinguishedName subjectName) { using (SafeCertContextHandle selfSignedCertHandle = CreateSelfSignedCertificate(key, true, subjectName.RawData, X509CertificateCreationOptions.None, // NONE RsaSha1Oid, DateTime.UtcNow, DateTime.UtcNow.AddYears(1))) { X509Certificate2 certificate = null; bool addedRef = false; RuntimeHelpers.PrepareConstrainedRegions(); try { selfSignedCertHandle.DangerousAddRef(ref addedRef); certificate = new X509Certificate2(selfSignedCertHandle.DangerousGetHandle()); } finally { if (addedRef) { selfSignedCertHandle.DangerousRelease(); } } key.Dispose(); return certificate; } }
public SelfSignedCertProperties() { DateTime today = DateTime.Today; ValidFrom = today.AddDays(-1); ValidTo = today.AddYears(10); Name = new X500DistinguishedName("cn=self"); KeyBitLength = 4096; }
/// <summary> /// Create a RSA based certificate (to be used with encryption) with the given options /// </summary> /// <param name="buildOptions">Allows for more advanced configuration</param> /// <returns>An exportable X509Certificate2 object (with private key)</returns> public static X509Certificate2 CreateNewCertificate(RSACertificateBuilderOptions buildOptions) { if (buildOptions == null) { throw new ArgumentNullException("buildOptions"); } string keyName = buildOptions.RSAKeyName ?? "RSAKey"; CngKey objCngKey = null; if (CngKey.Exists(keyName)) { objCngKey = CngKey.Open(keyName); objCngKey.Delete(); } var creationParameters = new CngKeyCreationParameters(); creationParameters.ExportPolicy = CngExportPolicies.AllowExport; creationParameters.KeyUsage = CngKeyUsages.AllUsages; creationParameters.Provider = CngProvider.MicrosoftSoftwareKeyStorageProvider; var keySizeProperty = new CngProperty("Length", BitConverter.GetBytes(buildOptions.KeySize ?? 4096), CngPropertyOptions.None); creationParameters.Parameters.Add(keySizeProperty); objCngKey = CngKey.Create(CngAlgorithm2.Rsa, keyName, creationParameters); var name = new X500DistinguishedName(buildOptions.FullSubjectName); X509CertificateSignatureAlgorithm certAlg; switch (buildOptions.HashingMethod ?? HashingMethods.Sha256) { case HashingMethods.Sha1: certAlg = X509CertificateSignatureAlgorithm.RsaSha1; break; case HashingMethods.Sha256: certAlg = X509CertificateSignatureAlgorithm.RsaSha256; break; case HashingMethods.Sha384: certAlg = X509CertificateSignatureAlgorithm.RsaSha384; break; case HashingMethods.Sha512: certAlg = X509CertificateSignatureAlgorithm.RsaSha512; break; default: throw new InvalidOperationException("Selected hashing method is not supported"); } var options = new X509CertificateCreationParameters(name) { SignatureAlgorithm = certAlg, TakeOwnershipOfKey = true }; return objCngKey.CreateSelfSignedCertificate(options); }
public override void Reset() { _lazyRawData = null; _lazySignatureAlgorithm = null; _lazyVersion = 0; _lazySubjectName = null; _lazyIssuerName = null; _lazyPublicKey = null; _lazyPrivateKey = null; _lazyExtensions = null; base.Reset(); }
public SimpleCA(string countryCode, string organization, string orgunit, string commonName) { var distinguishedName = $"C={countryCode};O={organization};OU={orgunit};CN={commonName}"; //var distinguishedName = "C=US;O=Microsoft;OU=WGA;CN=TedSt"; //CN={commonName}/OU={organizationUnit}/O={organization}/DC={domain}/STREET={address}/L={locality}/ST={state}/C={country}/DC={domainComponent}" var dn = new System.Security.Cryptography.X509Certificates.X500DistinguishedName( distinguishedName ); var key = System.Security.Cryptography.RSA.Create(); key.KeySize = 4096; var hash = System.Security.Cryptography.HashAlgorithmName.SHA512; var req = new System.Security.Cryptography.X509Certificates.CertificateRequest(dn, key, hash, RSASignaturePadding.Pss); var q = Oid.FromFriendlyName("", OidGroup.EnhancedKeyUsage); Oid.FromOidValue("", OidGroup.EnhancedKeyUsage); var r = new OidCollection(); r.Add(q); var v = new X509EnhancedKeyUsageExtension(r, false); req.CertificateExtensions.Add(SetEnhancedKeyUsage(keyCertSign: true)); req.CertificateExtensions.Add(SetBasicConstraints(true)); req.CertificateExtensions.Add(v); var now = DateTimeOffset.UtcNow; var startDate = now - TimeSpan.FromMinutes(5); var endDate = DateTimeOffset.UtcNow + TimeSpan.FromDays(365.25 * 10); rootCert = req.CreateSelfSigned(startDate, endDate); rootKey = key; var rootKeyChain = rootCert.Export(X509ContentType.Pkcs12); }
public X500DistinguishedName(X500DistinguishedName distinguishedName) : base(distinguishedName) { this.m_distinguishedName = distinguishedName.Name; }
void m_decode(Byte[] rawData) { try { Type = X509CrlType.BaseCrl; var signedInfo = new SignedContentBlob(rawData, ContentBlobType.SignedBlob); // signature and alg signature = signedInfo.Signature.Value; sigUnused = signedInfo.Signature.UnusedBits; SignatureAlgorithm = signedInfo.SignatureAlgorithm.AlgorithmId; // tbs Asn1Reader asn = new Asn1Reader(signedInfo.ToBeSignedData); if (!asn.MoveNext()) { throw new Asn1InvalidTagException(); } // version if (asn.Tag == (Byte)Asn1Type.INTEGER) { Version = (Int32)Asn1Utils.DecodeInteger(asn.GetTagRawData()) + 1; asn.MoveNextCurrentLevel(); } else { Version = 1; } // hash algorithm var h = new AlgorithmIdentifier(asn.GetTagRawData()); if (h.AlgorithmId.Value != SignatureAlgorithm.Value) { throw new CryptographicException("Algorithm mismatch."); } if (!asn.MoveNextCurrentLevel()) { throw new Asn1InvalidTagException(); } // issuer IssuerName = new X500DistinguishedName(asn.GetTagRawData()); // NextUpdate, RevokedCerts and Extensions are optional. Ref: RFC5280, p.118 if (!asn.MoveNextCurrentLevel()) { throw new Asn1InvalidTagException(); } switch (asn.Tag) { case (Byte)Asn1Type.UTCTime: ThisUpdate = new Asn1UtcTime(asn.GetTagRawData()).Value; break; case (Byte)Asn1Type.GeneralizedTime: ThisUpdate = Asn1Utils.DecodeGeneralizedTime(asn.GetTagRawData()); break; default: throw new Asn1InvalidTagException(); } if (!asn.MoveNextCurrentLevel()) { return; } switch (asn.Tag) { case (Byte)Asn1Type.UTCTime: case (Byte)Asn1Type.GeneralizedTime: switch (asn.Tag) { case (Byte)Asn1Type.UTCTime: NextUpdate = new Asn1UtcTime(asn.GetTagRawData()).Value; break; case (Byte)Asn1Type.GeneralizedTime: NextUpdate = Asn1Utils.DecodeGeneralizedTime(asn.GetTagRawData()); break; default: throw new Asn1InvalidTagException(); } if (!asn.MoveNextCurrentLevel()) { return; } if (asn.Tag == 48) { getRevCerts(asn); if (!asn.MoveNextCurrentLevel()) { return; } getExts(asn); } else { getExts(asn); } break; case 48: if (asn.Tag == 48) { getRevCerts(asn); if (!asn.MoveNextCurrentLevel()) { return; } getExts(asn); } else { getExts(asn); } break; default: getExts(asn); break; } } catch (Exception e) { throw new CryptographicException("Cannot find the requested object.", e); } }
private static String FormatX509Name(X500DistinguishedName name) { Asn1StreamParser parser = new Asn1StreamParser(name.RawData); X509Name _name = X509Name.GetInstance(parser.ReadObject().ToAsn1Object()); return _name.ToString(true, X509Name.RFC1779Symbols); }
// // Used only by client SSL code, never returns null. // private string[] GetIssuers() { string[] issuers = new string[0]; if (IsValidContext) { #if MONO_NOT_IMPLEMENTED IssuerListInfoEx issuerList = (IssuerListInfoEx)SSPIWrapper.QueryContextAttributes(m_SecModule, m_SecurityContext, ContextAttribute.IssuerListInfoEx); try { if (issuerList.cIssuers>0) { unsafe { uint count = issuerList.cIssuers; issuers = new string[issuerList.cIssuers]; _CERT_CHAIN_ELEMENT* pIL = (_CERT_CHAIN_ELEMENT*)issuerList.aIssuers.DangerousGetHandle(); for (uint i =0; i<count; ++i) { _CERT_CHAIN_ELEMENT* pIL2 = pIL + i; uint size = pIL2->cbSize; byte* ptr = (byte*)(pIL2->pCertContext); byte[] x = new byte[size]; for (uint j=0; j<size; j++) { x[j] = *(ptr + j); } // Oid oid = new Oid(); // oid.Value = "1.3.6.1.5.5.7.3.2"; // Value of issuers[i] can be an empty string when size of x is 0. X500DistinguishedName x500DistinguishedName = new X500DistinguishedName(x); issuers[i] = x500DistinguishedName.Name; GlobalLog.Print("SecureChannel#" + ValidationHelper.HashString(this) + "::GetIssuers() IssuerListEx[" + i + "]:" + issuers[i]); } } } } finally { if (issuerList.aIssuers != null) { issuerList.aIssuers.Close(); } } #endif } return issuers; }
public void RFC3280MandatoryAttributeTypes () { string expected = "dnQualifier=CA, OID.2.5.4.5=345, S=Maryland, DC=testcertificates, DC=gov, O=Test Certificates, C=US"; X509Certificate2 cert = new X509Certificate2 (RFC3280MandatoryAttributeTypesCACert_crt); // note: strangely the (also CryptoAPI based) certificate viewer in Windows seems to resolve 2.5.4.5 as "Serial Number" Assert.AreEqual (expected, cert.SubjectName.Name, "SubjectName"); X500DistinguishedName build = new X500DistinguishedName (expected); Assert.AreEqual (expected, build.Name, "Name"); }
public void T61String () { // http://bugzilla.ximian.com/show_bug.cgi?id=77295 byte[] sn = { 0x30, 0x81, 0xB5, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x44, 0x4B, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x14, 0x24, 0x48, 0x65, 0x64, 0x65, 0x62, 0x79, 0x27, 0x73, 0x20, 0x4D, 0xF8, 0x62, 0x65, 0x6C, 0x68, 0x61, 0x6E, 0x64, 0x65, 0x6C, 0x20, 0x2F, 0x2F, 0x20, 0x43, 0x56, 0x52, 0x3A, 0x31, 0x33, 0x34, 0x37, 0x31, 0x39, 0x36, 0x37, 0x31, 0x2F, 0x30, 0x2D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x14, 0x26, 0x48, 0x65, 0x64, 0x65, 0x62, 0x79, 0x27, 0x73, 0x20, 0x4D, 0xF8, 0x62, 0x65, 0x6C, 0x68, 0x61, 0x6E, 0x64, 0x65, 0x6C, 0x20, 0x2D, 0x20, 0x53, 0x61, 0x6C, 0x67, 0x73, 0x61, 0x66, 0x64, 0x65, 0x6C, 0x69, 0x6E, 0x67, 0x65, 0x6E, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x0F, 0x76, 0x68, 0x6D, 0x40, 0x75, 0x73, 0x65, 0x2E, 0x74, 0x65, 0x73, 0x74, 0x2E, 0x64, 0x6B, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x05, 0x13, 0x1D, 0x43, 0x56, 0x52, 0x3A, 0x31, 0x33, 0x34, 0x37, 0x31, 0x39, 0x36, 0x37, 0x2D, 0x55, 0x49, 0x44, 0x3A, 0x31, 0x32, 0x31, 0x32, 0x31, 0x32, 0x31, 0x32, 0x31, 0x32, 0x31, 0x32 }; X500DistinguishedName dn = new X500DistinguishedName (sn); string subject = "OID.2.5.4.5=CVR:13471967-UID:121212121212, [email protected], CN=Hedeby's Møbelhandel - Salgsafdelingen, O=Hedeby's Møbelhandel // CVR:13471967, C=DK"; Assert.AreEqual (subject, dn.Name, "Name"); }
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); if (nameType == X509NameType.SimpleName) { X500DistinguishedName name = forIssuer ? Issuer : 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 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 ? Issuer : Subject; foreach (var kvp in ReadReverseRdns(name)) { if (kvp.Key == expectedKey) { return(kvp.Value); } } } } return(""); }
public void Constructor_X500DistinguishedName () { X500DistinguishedName dn = new X500DistinguishedName (x509a.IssuerName); Assert.IsNotNull (dn.Oid, "Oid"); Assert.IsNull (dn.Oid.Value, "Oid.Value"); Assert.IsNull (dn.Oid.FriendlyName, "Oid.FriendlyName"); RsaIssuer (dn); }
public X509Certificate2 Create(X500DistinguishedName issuerName, X509SignatureGenerator generator, System.DateTimeOffset notBefore, System.DateTimeOffset notAfter, byte[] serialNumber) => throw new PlatformNotSupportedException();
public X500DistinguishedName(X500DistinguishedName distinguishedName) : base(distinguishedName) { _lazyDistinguishedName = distinguishedName.Name; }
public CertificateRequest(X500DistinguishedName subjectName, PublicKey publicKey, HashAlgorithmName hashAlgorithm) => throw new PlatformNotSupportedException();
public CertificateRequest(X500DistinguishedName subjectName, RSA key, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) => throw new PlatformNotSupportedException();
/// <summary> /// Sign the current certificate request to create a chain-signed or self-signed certificate. /// </summary> /// <param name="issuerName">The X500DistinguishedName for the Issuer</param> /// <param name="generator"> /// An <see cref="X509SignatureGenerator"/> representing the issuing certificate authority. /// </param> /// <param name="notBefore"> /// The oldest date and time where this certificate is considered valid. /// Typically <see cref="DateTimeOffset.UtcNow"/>, plus or minus a few seconds. /// </param> /// <param name="notAfter"> /// The date and time where this certificate is no longer considered valid. /// </param> /// <param name="serialNumber"> /// The serial number to use for the new certificate. This value should be unique per issuer. /// The value is interpreted as an unsigned (big) integer in big endian byte ordering. /// </param> /// <returns> /// The ASN.1 DER-encoded certificate, suitable to be passed to <see cref="X509Certificate2(byte[])"/>. /// </returns> /// <exception cref="ArgumentNullException"><paramref name="issuerName"/> is null.</exception> /// <exception cref="ArgumentNullException"><paramref name="generator"/> is null.</exception> /// <exception cref="ArgumentException"> /// <paramref name="notAfter"/> represents a date and time before <paramref name="notBefore"/>. /// </exception> /// <exception cref="ArgumentException"><paramref name="serialNumber"/> is null or has length 0.</exception> /// <exception cref="CryptographicException">Any error occurs during the signing operation.</exception> public X509Certificate2 Create( X500DistinguishedName issuerName, X509SignatureGenerator generator, DateTimeOffset notBefore, DateTimeOffset notAfter, byte[] serialNumber) { if (issuerName == null) { throw new ArgumentNullException(nameof(issuerName)); } if (generator == null) { throw new ArgumentNullException(nameof(generator)); } if (notAfter < notBefore) { throw new ArgumentException(SR.Cryptography_CertReq_DatesReversed); } if (serialNumber == null || serialNumber.Length < 1) { throw new ArgumentException(SR.Arg_EmptyOrNullArray, nameof(serialNumber)); } byte[] signatureAlgorithm = generator.GetSignatureAlgorithmIdentifier(HashAlgorithm); AlgorithmIdentifierAsn signatureAlgorithmAsn; // Deserialization also does validation of the value (except for Parameters, which have to be validated separately). signatureAlgorithmAsn = AlgorithmIdentifierAsn.Decode(signatureAlgorithm, AsnEncodingRules.DER); if (signatureAlgorithmAsn.Parameters.HasValue) { Helpers.ValidateDer(signatureAlgorithmAsn.Parameters.Value); } TbsCertificateAsn tbsCertificate = new TbsCertificateAsn { Version = 2, SerialNumber = NormalizeSerialNumber(serialNumber), SignatureAlgorithm = signatureAlgorithmAsn, Issuer = issuerName.RawData, SubjectPublicKeyInfo = new SubjectPublicKeyInfoAsn { Algorithm = new AlgorithmIdentifierAsn { Algorithm = PublicKey.Oid, Parameters = PublicKey.EncodedParameters.RawData, }, SubjectPublicKey = PublicKey.EncodedKeyValue.RawData, }, Validity = new ValidityAsn(notBefore, notAfter), Subject = SubjectName.RawData, }; if (CertificateExtensions.Count > 0) { HashSet <string> usedOids = new HashSet <string>(CertificateExtensions.Count); List <X509ExtensionAsn> extensionAsns = new List <X509ExtensionAsn>(CertificateExtensions.Count); // An interesting quirk of skipping null values here is that // Extensions.Count == 0 => no extensions // Extensions.ContainsOnly(null) => empty extensions list foreach (X509Extension extension in CertificateExtensions) { if (extension == null) { continue; } if (!usedOids.Add(extension.Oid.Value)) { throw new InvalidOperationException( SR.Format(SR.Cryptography_CertReq_DuplicateExtension, extension.Oid.Value)); } extensionAsns.Add(new X509ExtensionAsn(extension, false)); } tbsCertificate.Extensions = extensionAsns.ToArray(); } using (AsnWriter writer = new AsnWriter(AsnEncodingRules.DER)) using (AsnWriter signedWriter = new AsnWriter(AsnEncodingRules.DER)) { tbsCertificate.Encode(writer); byte[] encodedTbsCertificate = writer.Encode(); CertificateAsn certificate = new CertificateAsn { TbsCertificate = tbsCertificate, SignatureAlgorithm = signatureAlgorithmAsn, SignatureValue = generator.SignData(encodedTbsCertificate, HashAlgorithm), }; certificate.Encode(signedWriter); return(new X509Certificate2(signedWriter.Encode())); } }
// *** certificate chain/path validation stuff *** // Currently a subset of RFC3280 (hopefully a full implementation someday) private void ValidateChain (X509ChainStatusFlags flag) { // 'n' should be the root certificate... int n = elements.Count - 1; X509Certificate2 certificate = elements [n].Certificate; // ... and, if so, must be treated outside the chain... if (((flag & X509ChainStatusFlags.PartialChain) == 0)) { Process (n); // deal with the case where the chain == the root certificate // (which isn't for RFC3280) part of the chain if (n == 0) { elements [0].UncompressFlags (); return; } // skip the root certificate when processing the chain (in 6.1.3) n--; } // ... unless the chain is a partial one (then we start with that one) // 6.1.1 - Inputs // 6.1.1.a - a prospective certificate path of length n (i.e. elements) // 6.1.1.b - the current date/time (i.e. ChainPolicy.VerificationTime) // 6.1.1.c - user-initial-policy-set (i.e. ChainPolicy.CertificatePolicy) // 6.1.1.d - the trust anchor information (i.e. certificate, unless it's a partial chain) // 6.1.1.e - initial-policy-mapping-inhibit (NOT SUPPORTED BY THE API) // 6.1.1.f - initial-explicit-policy (NOT SUPPORTED BY THE API) // 6.1.1.g - initial-any-policy-inhibit (NOT SUPPORTED BY THE API) // 6.1.2 - Initialization (incomplete) // 6.1.2.a-f - policy stuff, some TODO, some not supported // 6.1.2.g - working public key algorithm // working_public_key_algorithm = certificate.PublicKey.Oid.Value; // 6.1.2.h-i - our key contains both the "working public key" and "working public key parameters" data working_public_key = certificate.PublicKey.Key; // 6.1.2.j - working issuer name working_issuer_name = certificate.IssuerName; // 6.1.2.k - this integer is initialized to n, is decremented for each non-self-issued, certificate and // may be reduced to the value in the path length constraint field max_path_length = n; // 6.1.3 - Basic Certificate Processing // note: loop looks reversed (the list is) but we process this part just like RFC3280 does for (int i = n; i > 0; i--) { Process (i); // 6.1.4 - preparation for certificate i+1 (for not with i+1, or i-1 in our loop) PrepareForNextCertificate (i); } Process (0); // 6.1.3.a.3 - revocation checks CheckRevocationOnChain (flag); // 6.1.5 - Wrap-up procedure WrapUp (); }
private void Process(int n) { X509ChainElement element = elements [n]; X509Certificate2 certificate = element.Certificate; // pre-step: DSA certificates may inherit the parameters of their CA if ((n != elements.Count - 1) && (certificate.MonoCertificate.KeyAlgorithm == "1.2.840.10040.4.1")) { if (certificate.MonoCertificate.KeyAlgorithmParameters == null) { X509Certificate2 parent = elements [n + 1].Certificate; certificate.MonoCertificate.KeyAlgorithmParameters = parent.MonoCertificate.KeyAlgorithmParameters; } } bool root = (working_public_key == null); // 6.1.3.a.1 - check signature (with special case to deal with root certificates) if (!IsSignedWith(certificate, root ? certificate.PublicKey.Key : working_public_key)) { // another special case where only an end-entity is available and can't be verified. // In this case we do not report an invalid signature (since this is unknown) if (root || (n != elements.Count - 1) || IsSelfIssued(certificate)) { element.StatusFlags |= X509ChainStatusFlags.NotSignatureValid; } } // 6.1.3.a.2 - check validity period if ((ChainPolicy.VerificationTime < certificate.NotBefore) || (ChainPolicy.VerificationTime > certificate.NotAfter)) { element.StatusFlags |= X509ChainStatusFlags.NotTimeValid; } // TODO - for X509ChainStatusFlags.NotTimeNested (needs global structure) // note: most of them don't apply to the root certificate if (root) { return; } // 6.1.3.a.3 - revocation check (we're doing at the last stage) // note: you revoke a trusted root by removing it from your trusted store (i.e. no CRL can do this job) // 6.1.3.a.4 - check certificate issuer name if (!X500DistinguishedName.AreEqual(certificate.IssuerName, working_issuer_name)) { // NOTE: this is not the "right" error flag, but it's the closest one defined element.StatusFlags |= X509ChainStatusFlags.InvalidNameConstraints; } if (!IsSelfIssued(certificate) && (n != 0)) { // TODO 6.1.3.b - subject name in the permitted_subtrees ... // TODO 6.1.3.c - subject name not within excluded_subtrees... // TODO - check for X509ChainStatusFlags.InvalidNameConstraint // TODO - check for X509ChainStatusFlags.HasNotSupportedNameConstraint // TODO - check for X509ChainStatusFlags.HasNotPermittedNameConstraint // TODO - check for X509ChainStatusFlags.HasExcludedNameConstraint } // TODO 6.1.3.d - check if certificate policies extension is present //if (false) { // TODO - for X509ChainStatusFlags.InvalidPolicyConstraints // using X509ChainPolicy.ApplicationPolicy and X509ChainPolicy.CertificatePolicy // TODO - check for X509ChainStatusFlags.NoIssuanceChainPolicy //} else { // TODO 6.1.3.e - set valid_policy_tree to NULL //} // TODO 6.1.3.f - verify explict_policy > 0 if valid_policy_tree != NULL }
private static unsafe CertificateRequest LoadSigningRequest( ReadOnlySpan <byte> pkcs10, bool permitTrailingData, HashAlgorithmName signerHashAlgorithm, out int bytesConsumed, CertificateRequestLoadOptions options, RSASignaturePadding?signerSignaturePadding) { ArgumentException.ThrowIfNullOrEmpty(signerHashAlgorithm.Name, nameof(signerHashAlgorithm)); if ((options & ~AllOptions) != 0) { throw new ArgumentOutOfRangeException(nameof(options), options, SR.Argument_InvalidFlag); } bool skipSignatureValidation = (options & CertificateRequestLoadOptions.SkipSignatureValidation) != 0; bool unsafeLoadCertificateExtensions = (options & CertificateRequestLoadOptions.UnsafeLoadCertificateExtensions) != 0; try { AsnValueReader outer = new AsnValueReader(pkcs10, AsnEncodingRules.DER); int encodedLength = outer.PeekEncodedValue().Length; AsnValueReader pkcs10Asn = outer.ReadSequence(); CertificateRequest req; if (!permitTrailingData) { outer.ThrowIfNotEmpty(); } fixed(byte *p10ptr = pkcs10) { using (PointerMemoryManager <byte> manager = new PointerMemoryManager <byte>(p10ptr, encodedLength)) { ReadOnlyMemory <byte> rebind = manager.Memory; ReadOnlySpan <byte> encodedRequestInfo = pkcs10Asn.PeekEncodedValue(); CertificationRequestInfoAsn requestInfo; AlgorithmIdentifierAsn algorithmIdentifier; ReadOnlySpan <byte> signature; int signatureUnusedBitCount; CertificationRequestInfoAsn.Decode(ref pkcs10Asn, rebind, out requestInfo); AlgorithmIdentifierAsn.Decode(ref pkcs10Asn, rebind, out algorithmIdentifier); if (!pkcs10Asn.TryReadPrimitiveBitString(out signatureUnusedBitCount, out signature)) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } pkcs10Asn.ThrowIfNotEmpty(); if (requestInfo.Version < 0) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } // They haven't bumped from v0 to v1 as of 2022. const int MaxSupportedVersion = 0; if (requestInfo.Version != MaxSupportedVersion) { throw new CryptographicException( SR.Format( SR.Cryptography_CertReq_Load_VersionTooNew, requestInfo.Version, MaxSupportedVersion)); } PublicKey publicKey = PublicKey.DecodeSubjectPublicKeyInfo(ref requestInfo.SubjectPublicKeyInfo); if (!skipSignatureValidation) { // None of the supported signature algorithms support signatures that are not full bytes. // So, shortcut the verification on the bit length if (signatureUnusedBitCount != 0 || !VerifyX509Signature(encodedRequestInfo, signature, publicKey, algorithmIdentifier)) { throw new CryptographicException(SR.Cryptography_CertReq_SignatureVerificationFailed); } } X500DistinguishedName subject = new X500DistinguishedName(requestInfo.Subject.Span); req = new CertificateRequest( subject, publicKey, signerHashAlgorithm, signerSignaturePadding); if (requestInfo.Attributes is not null) { bool foundCertExt = false; foreach (AttributeAsn attr in requestInfo.Attributes) { if (attr.AttrType == Oids.Pkcs9ExtensionRequest) { if (foundCertExt) { throw new CryptographicException( SR.Cryptography_CertReq_Load_DuplicateExtensionRequests); } foundCertExt = true; if (attr.AttrValues.Length != 1) { throw new CryptographicException( SR.Cryptography_CertReq_Load_DuplicateExtensionRequests); } AsnValueReader extsReader = new AsnValueReader( attr.AttrValues[0].Span, AsnEncodingRules.DER); AsnValueReader exts = extsReader.ReadSequence(); extsReader.ThrowIfNotEmpty(); // Minimum length is 1, so do..while do { X509ExtensionAsn.Decode(ref exts, rebind, out X509ExtensionAsn extAsn); if (unsafeLoadCertificateExtensions) { X509Extension ext = new X509Extension( extAsn.ExtnId, extAsn.ExtnValue.Span, extAsn.Critical); X509Extension?rich = X509Certificate2.CreateCustomExtensionIfAny(extAsn.ExtnId); if (rich is not null) { rich.CopyFrom(ext); req.CertificateExtensions.Add(rich); } else { req.CertificateExtensions.Add(ext); } } } while (exts.HasData); } else { if (attr.AttrValues.Length == 0) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } foreach (ReadOnlyMemory <byte> val in attr.AttrValues) { req.OtherRequestAttributes.Add( new AsnEncodedData(attr.AttrType, val.Span)); } } } } } } bytesConsumed = encodedLength; return(req); } catch (AsnContentException e) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e); } }
// 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]; X509Certificate2 certificate = element.Certificate; // TODO 6.1.4.a-b // 6.1.4.c working_issuer_name = certificate.SubjectName; // 6.1.4.d-e - our key includes both the public key and it's parameters working_public_key = certificate.PublicKey.Key; // 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 X509BasicConstraintsExtension bce = (X509BasicConstraintsExtension)certificate.Extensions["2.5.29.19"]; if (bce != null) { if (!bce.CertificateAuthority) { 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.HasPathLengthConstraint)) { // ... and is less that max_path_length, set max_path_length to it's value if (bce.PathLengthConstraint < max_path_length) { max_path_length = bce.PathLengthConstraint; bce_restriction = element; } } // 6.1.4.n - if key usage extension is present... X509KeyUsageExtension kue = (X509KeyUsageExtension)certificate.Extensions["2.5.29.15"]; if (kue != null) { // ... verify keyCertSign is set X509KeyUsageFlags success = X509KeyUsageFlags.KeyCertSign; if ((kue.KeyUsages & success) != success) { element.StatusFlags |= X509ChainStatusFlags.NotValidForUsage; } } // 6.1.4.o - recognize and process other critical extension present in the certificate ProcessCertificateExtensions(element); }
public void Decode_Separators () { string semicolons = "C=US; O=\"RSA Data Security, Inc.\"; OU=Secure Server Certification Authority"; string newline = String.Format ("C=US{0}O=\"RSA Data Security, Inc.\"{0}OU=Secure Server Certification Authority", Environment.NewLine); X500DistinguishedName dn = new X500DistinguishedName (rname, X500DistinguishedNameFlags.None); Assert.AreEqual (rname, dn.Name, "Name"); Assert.AreEqual (rname, dn.Decode (X500DistinguishedNameFlags.None), "Decode(None)"); Assert.AreEqual (rname, dn.Decode (X500DistinguishedNameFlags.UseCommas), "Decode(UseCommas)"); Assert.AreEqual (semicolons, dn.Decode (X500DistinguishedNameFlags.UseSemicolons), "Decode(UseCommas|UseSemicolons)"); Assert.AreEqual (newline, dn.Decode (X500DistinguishedNameFlags.UseNewLines), "Decode(UseNewLines)"); Assert.AreEqual (semicolons, dn.Decode (X500DistinguishedNameFlags.UseCommas | X500DistinguishedNameFlags.UseSemicolons), "Decode(UseCommas|UseSemicolons)"); Assert.AreEqual (semicolons, dn.Decode (X500DistinguishedNameFlags.UseNewLines | X500DistinguishedNameFlags.UseSemicolons), "Decode(UseNewLines|UseSemicolons)"); Assert.AreEqual (rname, dn.Decode (X500DistinguishedNameFlags.UseCommas | X500DistinguishedNameFlags.UseNewLines), "Decode(UseCommas|UseNewLines)"); }
private void Decode() { if (_decoded) { return; } // AuthorityKeyIdentifier ::= SEQUENCE { // keyIdentifier [0] KeyIdentifier OPTIONAL, // authorityCertIssuer [1] GeneralNames OPTIONAL, // authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } // // KeyIdentifier ::= OCTET STRING string keyId = null; X500DistinguishedName firstIssuerName = null; DerSequenceReader reader = new DerSequenceReader(RawData); byte[] serialNumber = null; // Primitive Context 0 const byte KeyIdTag = DerSequenceReader.ContextSpecificTagFlag | 0; // Constructed Context 1 const byte CertIssuerTag = DerSequenceReader.ContextSpecificConstructedTag1; // Primitive Context 2 const byte CertSerialTag = DerSequenceReader.ContextSpecificTagFlag | 2; if (reader.HasTag(KeyIdTag)) { keyId = reader.ReadOctetString().ToHexStringUpper(); } if (reader.HasTag(CertIssuerTag)) { DerSequenceReader generalNames = reader.ReadSequence(); while (generalNames.HasData) { const byte DirectoryNameTag = DerSequenceReader.ConstructedFlag | (byte)GeneralNameEncoder.GeneralNameTag.DirectoryName; if (firstIssuerName == null && generalNames.HasTag(DirectoryNameTag)) { firstIssuerName = new X500DistinguishedName(generalNames.ReadNextEncodedValue()); } reader.ValidateAndSkipDerValue(); } } if (reader.HasTag(CertSerialTag)) { serialNumber = reader.ReadOctetString(); } if (reader.HasData) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } _firstIssuerName = firstIssuerName; _serialNumber = serialNumber; _keyIdentifier = keyId; _decoded = true; }
public void RFC3280OptionalAttributeTypes () { string expected = "T=M.D., OID.2.5.4.44=III, SN=CA, OID.2.5.4.65=Fictitious, I=Q, G=John, L=Gaithersburg, O=Test Certificates, C=US"; X509Certificate2 cert = new X509Certificate2 (RFC3280OptionalAttributeTypesCACert_crt); Assert.AreEqual (expected, cert.SubjectName.Name, "SubjectName"); X500DistinguishedName build = new X500DistinguishedName (expected); Assert.AreEqual (expected, build.Name, "Name"); }
// // Used only by client SSL code, never returns null. // internal static string[] GetRequestCertificateAuthorities(SafeDeleteContext securityContext) { Interop.SspiCli.IssuerListInfoEx issuerList = (Interop.SspiCli.IssuerListInfoEx)SSPIWrapper.QueryContextAttributes( GlobalSSPI.SSPISecureChannel, securityContext, Interop.SspiCli.ContextAttribute.IssuerListInfoEx); 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; }
private void Empty (X500DistinguishedName dn) { Assert.AreEqual (String.Empty, dn.Name, "Name"); Assert.AreEqual (String.Empty, dn.Decode (X500DistinguishedNameFlags.None), "Decode(None)"); Assert.AreEqual (String.Empty, dn.Decode (X500DistinguishedNameFlags.Reversed), "Decode(Reversed)"); Assert.AreEqual (String.Empty, dn.Decode (X500DistinguishedNameFlags.UseSemicolons), "Decode(UseSemicolons)"); Assert.AreEqual (String.Empty, dn.Decode (X500DistinguishedNameFlags.DoNotUsePlusSign), "Decode(DoNotUsePlusSign)"); Assert.AreEqual (String.Empty, dn.Decode (X500DistinguishedNameFlags.DoNotUseQuotes), "Decode(DoNotUseQuotes)"); Assert.AreEqual (String.Empty, dn.Decode (X500DistinguishedNameFlags.UseCommas), "Decode(UseCommas)"); Assert.AreEqual (String.Empty, dn.Decode (X500DistinguishedNameFlags.UseNewLines), "Decode(UseNewLines)"); Assert.AreEqual (String.Empty, dn.Decode (X500DistinguishedNameFlags.UseUTF8Encoding), "Decode(UseUTF8Encoding)"); Assert.AreEqual (String.Empty, dn.Decode (X500DistinguishedNameFlags.UseT61Encoding), "Decode(UseT61Encoding)"); Assert.AreEqual (String.Empty, dn.Decode (X500DistinguishedNameFlags.ForceUTF8Encoding), "Decode(ForceUTF8Encoding)"); Assert.AreEqual (String.Empty, dn.Format (true), "Format(true)"); Assert.AreEqual (String.Empty, dn.Format (false), "Format(false)"); }
public X509Identity(X500DistinguishedName x500DistinguishedName) : base(X509, X509) { _x500DistinguishedName = x500DistinguishedName; }
private byte[] Build( X500DistinguishedName issuerName, X509SignatureGenerator generator, BigInteger crlNumber, DateTimeOffset nextUpdate, DateTimeOffset thisUpdate, HashAlgorithmName hashAlgorithm, X509AuthorityKeyIdentifierExtension authorityKeyIdentifier) { ArgumentNullException.ThrowIfNull(issuerName); ArgumentNullException.ThrowIfNull(generator); if (crlNumber < 0) { throw new ArgumentOutOfRangeException(nameof(crlNumber), SR.ArgumentOutOfRange_NeedNonNegNum); } if (nextUpdate <= thisUpdate) { throw new ArgumentException(SR.Cryptography_CRLBuilder_DatesReversed); } ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); ArgumentNullException.ThrowIfNull(authorityKeyIdentifier); byte[] signatureAlgId = generator.GetSignatureAlgorithmIdentifier(hashAlgorithm); { AlgorithmIdentifierAsn signatureAlgorithmAsn; // Deserialization also does validation of the value (except for Parameters, // which have to be validated separately). signatureAlgorithmAsn = AlgorithmIdentifierAsn.Decode(signatureAlgId, AsnEncodingRules.DER); if (signatureAlgorithmAsn.Parameters.HasValue) { Helpers.ValidateDer(signatureAlgorithmAsn.Parameters.GetValueOrDefault().Span); } } AsnWriter writer = (_writer ??= new AsnWriter(AsnEncodingRules.DER)); writer.Reset(); // TBSCertList using (writer.PushSequence()) { // version v2(1) writer.WriteInteger(1); // signature (AlgorithmIdentifier) writer.WriteEncodedValue(signatureAlgId); // issuer writer.WriteEncodedValue(issuerName.RawData); // thisUpdate WriteX509Time(writer, thisUpdate); // nextUpdate WriteX509Time(writer, nextUpdate); // revokedCertificates (don't write down if empty) if (_revoked.Count > 0) { // SEQUENCE OF using (writer.PushSequence()) { foreach (RevokedCertificate revoked in _revoked) { // Anonymous CRL Entry type using (writer.PushSequence()) { writer.WriteInteger(revoked.Serial); WriteX509Time(writer, revoked.RevocationTime); if (revoked.Extensions is not null) { writer.WriteEncodedValue(revoked.Extensions); } } } } } // extensions [0] EXPLICIT Extensions using (writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, 0))) { // Extensions (SEQUENCE OF) using (writer.PushSequence()) { // Authority Key Identifier Extension using (writer.PushSequence()) { writer.WriteObjectIdentifier(authorityKeyIdentifier.Oid !.Value !); if (authorityKeyIdentifier.Critical) { writer.WriteBoolean(true); } byte[] encodedAkid = authorityKeyIdentifier.RawData; Helpers.ValidateDer(encodedAkid); writer.WriteOctetString(encodedAkid); } // CRL Number Extension using (writer.PushSequence()) { writer.WriteObjectIdentifier(Oids.CrlNumber); using (writer.PushOctetString()) { writer.WriteInteger(crlNumber); } } } } } byte[] tbsCertList = writer.Encode(); writer.Reset(); byte[] signature = generator.SignData(tbsCertList, hashAlgorithm); // CertificateList using (writer.PushSequence()) { writer.WriteEncodedValue(tbsCertList); writer.WriteEncodedValue(signatureAlgId); writer.WriteBitString(signature); } byte[] crl = writer.Encode(); return(crl); }
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 (); }
internal unsafe SubjectIdentifier (CAPI.CRYPTOAPI_BLOB issuer, CAPI.CRYPTOAPI_BLOB serialNumber) { // If serial number is 0, then it is the special SKI encoding or NoSignature bool isSKIorHashOnly = true; byte * pb = (byte *) serialNumber.pbData; for (uint i = 0; i < serialNumber.cbData; i++) { if (*pb++ != (byte) 0) { isSKIorHashOnly = false; break; } } if (isSKIorHashOnly) { byte[] issuerBytes = new byte[issuer.cbData]; Marshal.Copy(issuer.pbData, issuerBytes, 0, issuerBytes.Length); X500DistinguishedName dummyName = new X500DistinguishedName(issuerBytes); if (String.Compare(CAPI.DummySignerCommonName, dummyName.Name, StringComparison.OrdinalIgnoreCase) == 0) { Reset(SubjectIdentifierType.NoSignature, null); return; } } if (isSKIorHashOnly) { // Decode disguised SKI in issuer field (See WinCrypt.h for more info). Note that some certificates may contain // an all-zero serial number but not be encoded with an szOID_KEYID_RDN. In order to allow use of signatures created // using these certificates, we will first try to find the szOID_KEYID_RDN, but if it does not exist, fall back to just // decoding the incoming issuer and serial number. m_type = SubjectIdentifierType.SubjectKeyIdentifier; m_value = String.Empty; uint cbCertNameInfo = 0; SafeLocalAllocHandle pbCertNameInfo = SafeLocalAllocHandle.InvalidHandle; if (CAPI.DecodeObject(new IntPtr(CAPI.X509_NAME), issuer.pbData, issuer.cbData, out pbCertNameInfo, out cbCertNameInfo)) { using (pbCertNameInfo) { checked { CAPI.CERT_NAME_INFO certNameInfo = (CAPI.CERT_NAME_INFO) Marshal.PtrToStructure(pbCertNameInfo.DangerousGetHandle(), typeof(CAPI.CERT_NAME_INFO)); for (uint i = 0; i < certNameInfo.cRDN; i++) { CAPI.CERT_RDN certRdn = (CAPI.CERT_RDN) Marshal.PtrToStructure(new IntPtr((long) certNameInfo.rgRDN + (long) (i * Marshal.SizeOf(typeof(CAPI.CERT_RDN)))), typeof(CAPI.CERT_RDN)); for (uint j = 0; j < certRdn.cRDNAttr; j++) { CAPI.CERT_RDN_ATTR certRdnAttr = (CAPI.CERT_RDN_ATTR)Marshal.PtrToStructure(new IntPtr((long)certRdn.rgRDNAttr + (long)(j * Marshal.SizeOf(typeof(CAPI.CERT_RDN_ATTR)))), typeof(CAPI.CERT_RDN_ATTR)); if (String.Compare(CAPI.szOID_KEYID_RDN, certRdnAttr.pszObjId, StringComparison.OrdinalIgnoreCase) == 0) { if (certRdnAttr.dwValueType == CAPI.CERT_RDN_OCTET_STRING) { byte[] ski = new byte[certRdnAttr.Value.cbData]; Marshal.Copy(certRdnAttr.Value.pbData, ski, 0, ski.Length); Reset(SubjectIdentifierType.SubjectKeyIdentifier, X509Utils.EncodeHexString(ski)); return; } } } } } } } } CAPI.CERT_ISSUER_SERIAL_NUMBER IssuerAndSerial; IssuerAndSerial.Issuer = issuer; IssuerAndSerial.SerialNumber = serialNumber; X509IssuerSerial issuerSerial = PkcsUtils.DecodeIssuerSerial(IssuerAndSerial); Reset(SubjectIdentifierType.IssuerAndSerialNumber, issuerSerial); }
public X500DistinguishedName (X500DistinguishedName distinguishedName) { if (distinguishedName == null) throw new ArgumentNullException ("distinguishedName"); Oid = new Oid (); RawData = distinguishedName.RawData; name = distinguishedName.name; }
private string FormatDistinguishedName(X500DistinguishedName dn) { var subjectName = dn.Name; if (subjectName.Contains("\"")) { bool insideQuotes = false; string subjectName2 = string.Empty; for (int i = 0; i < subjectName.Length; i++) { if (subjectName[i] == '"') insideQuotes = !insideQuotes; if ((subjectName[i] == ',') && insideQuotes) subjectName2 += '#'; else subjectName2 += subjectName[i]; } subjectName = subjectName2; } var parts = subjectName.Split(','); var part = string.Empty; if (parts.Length == 0) part = dn.Name; else part = parts[0]; part = part.Replace('#', ','); part = part.Replace("\"", string.Empty); int index = part.IndexOf('='); if (index != -1) part = part.Substring(index + 1); return part; }
public X500DistinguishedName(X500DistinguishedName distinguishedName) : base((AsnEncodedData)distinguishedName) { m_distinguishedName = distinguishedName.Name; }
public X500DistinguishedNameClaimSet(X500DistinguishedName x500DistinguishedName) { if (x500DistinguishedName == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("x500DistinguishedName"); _identity = new X509Identity(x500DistinguishedName); List<Claim> claims = new List<Claim>(2); claims.Add(new Claim(ClaimTypes.X500DistinguishedName, x500DistinguishedName, Rights.Identity)); claims.Add(Claim.CreateX500DistinguishedNameClaim(x500DistinguishedName)); Initialize(ClaimSet.Anonymous, claims); }
/// <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 SystemX509.X509Certificate2 CreateCert(SystemX509.X509Certificate2 issuer, SystemX509.X500DistinguishedName subjectName, byte[] serialNumber, bool signature, int keySize, CertificateHashAlgorithm hashAlgorithm, DateTime notBefore, DateTime notAfter, SystemX509.X509ExtensionCollection extensions) { X509V3CertificateGenerator builder = new X509V3CertificateGenerator(); AsymmetricAlgorithm subjectKey = CreateRSAKey(keySize, signature); AsymmetricAlgorithm signKey = issuer == null ? subjectKey : issuer.PrivateKey; if (signKey == null) { throw new ArgumentException(Properties.Resources.CreateCert_NoPrivateKey); } AsymmetricCipherKeyPair bcSubjectKey = GetRsaKeyPair((RSACryptoServiceProvider)subjectKey); AsymmetricCipherKeyPair bcSignKey = GetRsaKeyPair((RSACryptoServiceProvider)signKey); X509Name issuerNameObj = issuer == null?X509Name.GetInstance(Asn1Object.FromByteArray(subjectName.RawData)) : X509Name.GetInstance(Asn1Object.FromByteArray(issuer.SubjectName.RawData)); X509Name subjectNameObj = X509Name.GetInstance(Asn1Object.FromByteArray(subjectName.RawData)); BigInteger subjectSerial = new BigInteger(1, serialNumber != null ? serialNumber : Guid.NewGuid().ToByteArray()); BigInteger issuerSerial = issuer == null ? subjectSerial : new BigInteger(1, issuer.GetSerialNumber()); builder.SetIssuerDN(issuerNameObj); builder.SetSubjectDN(subjectNameObj); builder.SetSerialNumber(subjectSerial); builder.SetSignatureAlgorithm(HashAlgorithmToName(hashAlgorithm)); builder.SetNotBefore(notBefore.ToUniversalTime()); builder.SetNotAfter(notAfter.ToUniversalTime()); builder.SetPublicKey(bcSubjectKey.Public); SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(bcSignKey.Public); AuthorityKeyIdentifier authKeyId = new AuthorityKeyIdentifier(info, new GeneralNames(new GeneralName(issuerNameObj)), issuerSerial); SubjectKeyIdentifier subjectKeyid = new SubjectKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(bcSubjectKey.Public)); builder.AddExtension(X509Extensions.AuthorityKeyIdentifier.Id, true, authKeyId); builder.AddExtension(X509Extensions.SubjectKeyIdentifier.Id, true, subjectKeyid); if (extensions != null) { foreach (SystemX509.X509Extension ext in extensions) { if (!ext.Oid.Value.Equals(X509Extensions.AuthorityKeyIdentifier.Id) && !ext.Oid.Value.Equals(X509Extensions.SubjectKeyIdentifier.Id) && !ext.Oid.Value.Equals(szOID_AUTHORITY_KEY_IDENTIFIER2)) { Asn1InputStream istm = new Org.BouncyCastle.Asn1.Asn1InputStream(ext.RawData); Asn1Object obj = istm.ReadObject(); builder.AddExtension(ext.Oid.Value, ext.Critical, obj); } } } X509Certificate cert = builder.Generate(bcSignKey.Private); SystemX509.X509Certificate2 ret = new SystemX509.X509Certificate2(cert.GetEncoded(), (string)null, SystemX509.X509KeyStorageFlags.Exportable); ret.PrivateKey = subjectKey; return(ret); }
public static Claim CreateX500DistinguishedNameClaim(X500DistinguishedName x500DistinguishedName) { if (x500DistinguishedName == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("x500DistinguishedName"); return new Claim(ClaimTypes.X500DistinguishedName, x500DistinguishedName, Rights.PossessProperty, ClaimComparer.X500DistinguishedName); }
public void Constructor_String () { X500DistinguishedName dn = new X500DistinguishedName ("OU=Secure Server Certification Authority, O=\"RSA Data Security, Inc.\", C=US"); Assert.IsNotNull (dn.Oid, "Oid"); Assert.IsNull (dn.Oid.Value, "Oid.Value"); Assert.IsNull (dn.Oid.FriendlyName, "Oid.FriendlyName"); RsaIssuer (dn); }
///// <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="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 static SystemX509.X509Certificate2 CreateCert(SystemX509.X509Certificate2 issuer, SystemX509.X500DistinguishedName subjectName, byte[] serialNumber, int keySize, CertificateHashAlgorithm hashAlgorithm, DateTime notBefore, DateTime notAfter, SystemX509.X509ExtensionCollection extensions) { SecureRandom random = new SecureRandom(); X509V3CertificateGenerator builder = new X509V3CertificateGenerator(); AsymmetricCipherKeyPair bcSubjectKey = CreateRSAKey(keySize, random); AsymmetricCipherKeyPair bcSignKey = issuer == null ? bcSubjectKey : issuer.GetBCPrivateKey(); if (bcSignKey == null) { throw new ArgumentException("issuer"); } X509Name issuerNameObj = issuer == null?X509Name.GetInstance(Asn1Object.FromByteArray(subjectName.RawData)) : X509Name.GetInstance(Asn1Object.FromByteArray(issuer.SubjectName.RawData)); X509Name subjectNameObj = X509Name.GetInstance(Asn1Object.FromByteArray(subjectName.RawData)); BigInteger subjectSerial = new BigInteger(1, serialNumber != null ? serialNumber : Guid.NewGuid().ToByteArray()); BigInteger issuerSerial = issuer == null ? subjectSerial : new BigInteger(1, issuer.GetSerialNumber()); builder.SetIssuerDN(issuerNameObj); builder.SetSubjectDN(subjectNameObj); builder.SetSerialNumber(subjectSerial); builder.SetNotBefore(notBefore.ToUniversalTime()); builder.SetNotAfter(notAfter.ToUniversalTime()); builder.SetPublicKey(bcSubjectKey.Public); SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(bcSignKey.Public); AuthorityKeyIdentifier authKeyId = new AuthorityKeyIdentifier(info, new GeneralNames(new GeneralName(issuerNameObj)), issuerSerial); SubjectKeyIdentifier subjectKeyid = new SubjectKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(bcSubjectKey.Public)); builder.AddExtension(X509Extensions.AuthorityKeyIdentifier.Id, true, authKeyId); builder.AddExtension(X509Extensions.SubjectKeyIdentifier.Id, true, subjectKeyid); if (extensions != null) { foreach (SystemX509.X509Extension ext in extensions) { if (!ext.Oid.Value.Equals(X509Extensions.AuthorityKeyIdentifier.Id) && !ext.Oid.Value.Equals(X509Extensions.SubjectKeyIdentifier.Id) && !ext.Oid.Value.Equals(szOID_AUTHORITY_KEY_IDENTIFIER2)) { Asn1InputStream istm = new Asn1InputStream(ext.RawData); Asn1Object obj = istm.ReadObject(); builder.AddExtension(ext.Oid.Value, ext.Critical, obj); } } } X509Certificate cert = builder.Generate(CreateSignatureFactory(hashAlgorithm, bcSignKey, random)); Pkcs12StoreBuilder pkcs = new Pkcs12StoreBuilder(); Pkcs12Store store = pkcs.Build(); X509CertificateEntry entry = new X509CertificateEntry(cert); store.SetCertificateEntry("main", entry); AsymmetricKeyEntry key_entry = new AsymmetricKeyEntry(bcSubjectKey.Private); store.SetKeyEntry("main", key_entry, new[] { entry }); MemoryStream stm = new MemoryStream(); store.Save(stm, new char[0], new SecureRandom()); return(new SystemX509.X509Certificate2(stm.ToArray(), String.Empty, SystemX509.X509KeyStorageFlags.Exportable)); }
public void Constructor_String_Empty_Flags () { X500DistinguishedName dn = new X500DistinguishedName (String.Empty, X500DistinguishedNameFlags.None); Assert.AreEqual (2, dn.RawData.Length, "RawData.Length"); Assert.AreEqual ("30-00", BitConverter.ToString (dn.RawData), "RawData"); Empty (dn); }
// of all X500DistinguishedNameFlags flags nothing can do a "correct" comparison :| internal static bool AreEqual (X500DistinguishedName name1, X500DistinguishedName name2) { if (name1 == null) return (name2 == null); if (name2 == null) return false; if (name1.canonEncoding != null && name2.canonEncoding != null) { if (name1.canonEncoding.Length != name2.canonEncoding.Length) return false; for (int i = 0; i < name1.canonEncoding.Length; i++) { if (name1.canonEncoding[i] != name2.canonEncoding[i]) return false; } return true; } X500DistinguishedNameFlags flags = X500DistinguishedNameFlags.UseNewLines | X500DistinguishedNameFlags.DoNotUseQuotes; string[] split = new string[] { Environment.NewLine }; string[] parts1 = name1.Decode (flags).Split (split, StringSplitOptions.RemoveEmptyEntries); string[] parts2 = name2.Decode (flags).Split (split, StringSplitOptions.RemoveEmptyEntries); if (parts1.Length != parts2.Length) return false; for (int i = 0; i < parts1.Length; i++) { if (Canonize (parts1[i]) != Canonize (parts2[i])) return false; } return true; }
public void Constructor_String_Flags_None () { X500DistinguishedName dn = new X500DistinguishedName (rname, X500DistinguishedNameFlags.None); // can't call RsaIssuer because Name is reversed from None in those cases // i.e. X500DistinguishedName (string) != X500DistinguishedName (string, X500DistinguishedNameFlags) Assert.AreEqual (rname, dn.Name, "Name"); Assert.AreEqual (rname, dn.Decode (X500DistinguishedNameFlags.None), "Decode(None)"); Assert.AreEqual (name, dn.Decode (X500DistinguishedNameFlags.Reversed), "Decode(Reversed)"); Assert.AreEqual ("C=US; O=\"RSA Data Security, Inc.\"; OU=Secure Server Certification Authority", dn.Decode (X500DistinguishedNameFlags.UseSemicolons), "Decode(UseSemicolons)"); Assert.AreEqual (rname, dn.Decode (X500DistinguishedNameFlags.DoNotUsePlusSign), "Decode(DoNotUsePlusSign)"); Assert.AreEqual ("C=US, O=RSA Data Security, Inc., OU=Secure Server Certification Authority", dn.Decode (X500DistinguishedNameFlags.DoNotUseQuotes), "Decode(DoNotUseQuotes)"); Assert.AreEqual (rname, dn.Decode (X500DistinguishedNameFlags.UseCommas), "Decode(UseCommas)"); string newline = String.Format ("C=US{0}O=\"RSA Data Security, Inc.\"{0}OU=Secure Server Certification Authority", Environment.NewLine); Assert.AreEqual (newline, dn.Decode (X500DistinguishedNameFlags.UseNewLines), "Decode(UseNewLines)"); Assert.AreEqual (rname, dn.Decode (X500DistinguishedNameFlags.UseUTF8Encoding), "Decode(UseUTF8Encoding)"); Assert.AreEqual (rname, dn.Decode (X500DistinguishedNameFlags.UseT61Encoding), "Decode(UseT61Encoding)"); Assert.AreEqual (rname, dn.Decode (X500DistinguishedNameFlags.ForceUTF8Encoding), "Decode(ForceUTF8Encoding)"); }
// 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]; X509Certificate2 certificate = element.Certificate; // TODO 6.1.4.a-b // 6.1.4.c working_issuer_name = certificate.SubjectName; // 6.1.4.d-e - our key includes both the public key and it's parameters working_public_key = certificate.PublicKey.Key; // 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 X509BasicConstraintsExtension bce = (certificate.Extensions["2.5.29.19"] as X509BasicConstraintsExtension); if (bce != null) { if (!bce.CertificateAuthority) { 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.HasPathLengthConstraint)) { // ... and is less that max_path_length, set max_path_length to it's value if (bce.PathLengthConstraint < max_path_length) { max_path_length = bce.PathLengthConstraint; bce_restriction = element; } } // 6.1.4.n - if key usage extension is present... X509KeyUsageExtension kue = (certificate.Extensions["2.5.29.15"] as X509KeyUsageExtension); if (kue != null) { // ... verify keyCertSign is set X509KeyUsageFlags success = X509KeyUsageFlags.KeyCertSign; if ((kue.KeyUsages & success) != success) element.StatusFlags |= X509ChainStatusFlags.NotValidForUsage; } // 6.1.4.o - recognize and process other critical extension present in the certificate ProcessCertificateExtensions (element); }
public void Constructor_String_Flags_Reversed () { X500DistinguishedName dn = new X500DistinguishedName (name, X500DistinguishedNameFlags.None); // can't call RsaIssuer because Name is reversed from None in those cases Assert.AreEqual (name, dn.Name, "Name"); Assert.AreEqual (name, dn.Decode (X500DistinguishedNameFlags.None), "Decode(None)"); Assert.AreEqual (rname, dn.Decode (X500DistinguishedNameFlags.Reversed), "Decode(Reversed)"); Assert.AreEqual (name, dn.Decode (X500DistinguishedNameFlags.DoNotUsePlusSign), "Decode(DoNotUsePlusSign)"); Assert.AreEqual (name, dn.Decode (X500DistinguishedNameFlags.UseCommas), "Decode(UseCommas)"); Assert.AreEqual (name, dn.Decode (X500DistinguishedNameFlags.UseUTF8Encoding), "Decode(UseUTF8Encoding)"); Assert.AreEqual (name, dn.Decode (X500DistinguishedNameFlags.UseT61Encoding), "Decode(UseT61Encoding)"); Assert.AreEqual (name, dn.Decode (X500DistinguishedNameFlags.ForceUTF8Encoding), "Decode(ForceUTF8Encoding)"); }