1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024 |
- #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
- #pragma warning disable
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Text;
- using Best.HTTP.Shared.PlatformSupport.Text;
- using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.Pkcs;
- using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities.Collections;
- using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities.Encoders;
- namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509
- {
- /**
- * <pre>
- * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
- *
- * RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
- *
- * AttributeTypeAndValue ::= SEQUENCE {
- * type OBJECT IDENTIFIER,
- * value ANY }
- * </pre>
- */
- public class X509Name
- : Asn1Encodable
- {
- /**
- * country code - StringType(SIZE(2))
- */
- public static readonly DerObjectIdentifier C = new DerObjectIdentifier("2.5.4.6");
- /**
- * organization - StringType(SIZE(1..64))
- */
- public static readonly DerObjectIdentifier O = new DerObjectIdentifier("2.5.4.10");
- /**
- * organizational unit name - StringType(SIZE(1..64))
- */
- public static readonly DerObjectIdentifier OU = new DerObjectIdentifier("2.5.4.11");
- /**
- * Title
- */
- public static readonly DerObjectIdentifier T = new DerObjectIdentifier("2.5.4.12");
- /**
- * common name - StringType(SIZE(1..64))
- */
- public static readonly DerObjectIdentifier CN = new DerObjectIdentifier("2.5.4.3");
- /**
- * street - StringType(SIZE(1..64))
- */
- public static readonly DerObjectIdentifier Street = new DerObjectIdentifier("2.5.4.9");
- /**
- * device serial number name - StringType(SIZE(1..64))
- */
- public static readonly DerObjectIdentifier SerialNumber = new DerObjectIdentifier("2.5.4.5");
- /**
- * locality name - StringType(SIZE(1..64))
- */
- public static readonly DerObjectIdentifier L = new DerObjectIdentifier("2.5.4.7");
- /**
- * state, or province name - StringType(SIZE(1..64))
- */
- public static readonly DerObjectIdentifier ST = new DerObjectIdentifier("2.5.4.8");
- /**
- * Naming attributes of type X520name
- */
- public static readonly DerObjectIdentifier Surname = new DerObjectIdentifier("2.5.4.4");
- public static readonly DerObjectIdentifier GivenName = new DerObjectIdentifier("2.5.4.42");
- public static readonly DerObjectIdentifier Initials = new DerObjectIdentifier("2.5.4.43");
- public static readonly DerObjectIdentifier Generation = new DerObjectIdentifier("2.5.4.44");
- public static readonly DerObjectIdentifier UniqueIdentifier = new DerObjectIdentifier("2.5.4.45");
- /**
- * businessCategory - DirectoryString(SIZE(1..128)
- */
- public static readonly DerObjectIdentifier BusinessCategory = new DerObjectIdentifier(
- "2.5.4.15");
- /**
- * postalCode - DirectoryString(SIZE(1..40)
- */
- public static readonly DerObjectIdentifier PostalCode = new DerObjectIdentifier(
- "2.5.4.17");
- /**
- * dnQualifier - DirectoryString(SIZE(1..64)
- */
- public static readonly DerObjectIdentifier DnQualifier = new DerObjectIdentifier(
- "2.5.4.46");
- /**
- * RFC 3039 Pseudonym - DirectoryString(SIZE(1..64)
- */
- public static readonly DerObjectIdentifier Pseudonym = new DerObjectIdentifier(
- "2.5.4.65");
- /**
- * RFC 3039 DateOfBirth - GeneralizedTime - YYYYMMDD000000Z
- */
- public static readonly DerObjectIdentifier DateOfBirth = new DerObjectIdentifier(
- "1.3.6.1.5.5.7.9.1");
- /**
- * RFC 3039 PlaceOfBirth - DirectoryString(SIZE(1..128)
- */
- public static readonly DerObjectIdentifier PlaceOfBirth = new DerObjectIdentifier(
- "1.3.6.1.5.5.7.9.2");
- /**
- * RFC 3039 DateOfBirth - PrintableString (SIZE(1)) -- "M", "F", "m" or "f"
- */
- public static readonly DerObjectIdentifier Gender = new DerObjectIdentifier(
- "1.3.6.1.5.5.7.9.3");
- /**
- * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166
- * codes only
- */
- public static readonly DerObjectIdentifier CountryOfCitizenship = new DerObjectIdentifier(
- "1.3.6.1.5.5.7.9.4");
- /**
- * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166
- * codes only
- */
- public static readonly DerObjectIdentifier CountryOfResidence = new DerObjectIdentifier(
- "1.3.6.1.5.5.7.9.5");
- /**
- * ISIS-MTT NameAtBirth - DirectoryString(SIZE(1..64)
- */
- public static readonly DerObjectIdentifier NameAtBirth = new DerObjectIdentifier("1.3.36.8.3.14");
- /**
- * RFC 3039 PostalAddress - SEQUENCE SIZE (1..6) OF
- * DirectoryString(SIZE(1..30))
- */
- public static readonly DerObjectIdentifier PostalAddress = new DerObjectIdentifier("2.5.4.16");
- /**
- * RFC 2256 dmdName
- */
- public static readonly DerObjectIdentifier DmdName = new DerObjectIdentifier("2.5.4.54");
- /**
- * id-at-telephoneNumber
- */
- public static readonly DerObjectIdentifier TelephoneNumber = X509ObjectIdentifiers.id_at_telephoneNumber;
- /**
- * id-at-organizationIdentifier
- */
- public static readonly DerObjectIdentifier OrganizationIdentifier = X509ObjectIdentifiers.id_at_organizationIdentifier;
- /**
- * id-at-name
- */
- public static readonly DerObjectIdentifier Name = X509ObjectIdentifiers.id_at_name;
- /**
- * Email address (RSA PKCS#9 extension) - IA5String.
- * <p>Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.</p>
- */
- public static readonly DerObjectIdentifier EmailAddress = PkcsObjectIdentifiers.Pkcs9AtEmailAddress;
- /**
- * more from PKCS#9
- */
- public static readonly DerObjectIdentifier UnstructuredName = PkcsObjectIdentifiers.Pkcs9AtUnstructuredName;
- public static readonly DerObjectIdentifier UnstructuredAddress = PkcsObjectIdentifiers.Pkcs9AtUnstructuredAddress;
- /**
- * email address in Verisign certificates
- */
- public static readonly DerObjectIdentifier E = EmailAddress;
- /*
- * others...
- */
- public static readonly DerObjectIdentifier DC = new DerObjectIdentifier("0.9.2342.19200300.100.1.25");
- /**
- * LDAP User id.
- */
- public static readonly DerObjectIdentifier UID = new DerObjectIdentifier("0.9.2342.19200300.100.1.1");
- /**
- * determines whether or not strings should be processed and printed
- * from back to front.
- */
- public static bool DefaultReverse
- {
- get { lock (defaultReverse) return defaultReverse[0]; }
- set { lock (defaultReverse) defaultReverse[0] = value; }
- }
- private static readonly bool[] defaultReverse = { false };
- /**
- * default look up table translating OID values into their common symbols following
- * the convention in RFC 2253 with a few extras
- */
- private static readonly IDictionary<DerObjectIdentifier, string> DefaultSymbolsInternal =
- new Dictionary<DerObjectIdentifier, string>();
- public static readonly IDictionary<DerObjectIdentifier, string> DefaultSymbols =
- CollectionUtilities.ReadOnly(DefaultSymbolsInternal);
- /**
- * look up table translating OID values into their common symbols following the convention in RFC 2253
- */
- private static readonly IDictionary<DerObjectIdentifier, string> RFC2253SymbolsInternal =
- new Dictionary<DerObjectIdentifier, string>();
- public static readonly IDictionary<DerObjectIdentifier, string> RFC2253Symbols =
- CollectionUtilities.ReadOnly(RFC2253SymbolsInternal);
- /**
- * look up table translating OID values into their common symbols following the convention in RFC 1779
- *
- */
- private static readonly IDictionary<DerObjectIdentifier, string> RFC1779SymbolsInternal =
- new Dictionary<DerObjectIdentifier, string>();
- public static readonly IDictionary<DerObjectIdentifier, string> RFC1779Symbols =
- CollectionUtilities.ReadOnly(RFC1779SymbolsInternal);
- /**
- * look up table translating common symbols into their OIDS.
- */
- private static readonly IDictionary<string, DerObjectIdentifier> DefaultLookupInternal =
- new Dictionary<string, DerObjectIdentifier>(StringComparer.OrdinalIgnoreCase);
- public static readonly IDictionary<string, DerObjectIdentifier> DefaultLookup =
- CollectionUtilities.ReadOnly(DefaultLookupInternal);
- static X509Name()
- {
- DefaultSymbolsInternal.Add(C, "C");
- DefaultSymbolsInternal.Add(O, "O");
- DefaultSymbolsInternal.Add(T, "T");
- DefaultSymbolsInternal.Add(OU, "OU");
- DefaultSymbolsInternal.Add(CN, "CN");
- DefaultSymbolsInternal.Add(L, "L");
- DefaultSymbolsInternal.Add(ST, "ST");
- DefaultSymbolsInternal.Add(SerialNumber, "SERIALNUMBER");
- DefaultSymbolsInternal.Add(EmailAddress, "E");
- DefaultSymbolsInternal.Add(DC, "DC");
- DefaultSymbolsInternal.Add(UID, "UID");
- DefaultSymbolsInternal.Add(Street, "STREET");
- DefaultSymbolsInternal.Add(Surname, "SURNAME");
- DefaultSymbolsInternal.Add(GivenName, "GIVENNAME");
- DefaultSymbolsInternal.Add(Initials, "INITIALS");
- DefaultSymbolsInternal.Add(Generation, "GENERATION");
- DefaultSymbolsInternal.Add(UnstructuredAddress, "unstructuredAddress");
- DefaultSymbolsInternal.Add(UnstructuredName, "unstructuredName");
- DefaultSymbolsInternal.Add(UniqueIdentifier, "UniqueIdentifier");
- DefaultSymbolsInternal.Add(DnQualifier, "DN");
- DefaultSymbolsInternal.Add(Pseudonym, "Pseudonym");
- DefaultSymbolsInternal.Add(PostalAddress, "PostalAddress");
- DefaultSymbolsInternal.Add(NameAtBirth, "NameAtBirth");
- DefaultSymbolsInternal.Add(CountryOfCitizenship, "CountryOfCitizenship");
- DefaultSymbolsInternal.Add(CountryOfResidence, "CountryOfResidence");
- DefaultSymbolsInternal.Add(Gender, "Gender");
- DefaultSymbolsInternal.Add(PlaceOfBirth, "PlaceOfBirth");
- DefaultSymbolsInternal.Add(DateOfBirth, "DateOfBirth");
- DefaultSymbolsInternal.Add(PostalCode, "PostalCode");
- DefaultSymbolsInternal.Add(BusinessCategory, "BusinessCategory");
- DefaultSymbolsInternal.Add(TelephoneNumber, "TelephoneNumber");
- RFC2253SymbolsInternal.Add(C, "C");
- RFC2253SymbolsInternal.Add(O, "O");
- RFC2253SymbolsInternal.Add(OU, "OU");
- RFC2253SymbolsInternal.Add(CN, "CN");
- RFC2253SymbolsInternal.Add(L, "L");
- RFC2253SymbolsInternal.Add(ST, "ST");
- RFC2253SymbolsInternal.Add(Street, "STREET");
- RFC2253SymbolsInternal.Add(DC, "DC");
- RFC2253SymbolsInternal.Add(UID, "UID");
- RFC1779SymbolsInternal.Add(C, "C");
- RFC1779SymbolsInternal.Add(O, "O");
- RFC1779SymbolsInternal.Add(OU, "OU");
- RFC1779SymbolsInternal.Add(CN, "CN");
- RFC1779SymbolsInternal.Add(L, "L");
- RFC1779SymbolsInternal.Add(ST, "ST");
- RFC1779SymbolsInternal.Add(Street, "STREET");
- DefaultLookupInternal.Add("c", C);
- DefaultLookupInternal.Add("o", O);
- DefaultLookupInternal.Add("t", T);
- DefaultLookupInternal.Add("ou", OU);
- DefaultLookupInternal.Add("cn", CN);
- DefaultLookupInternal.Add("l", L);
- DefaultLookupInternal.Add("st", ST);
- DefaultLookupInternal.Add("serialnumber", SerialNumber);
- DefaultLookupInternal.Add("street", Street);
- DefaultLookupInternal.Add("emailaddress", E);
- DefaultLookupInternal.Add("dc", DC);
- DefaultLookupInternal.Add("e", E);
- DefaultLookupInternal.Add("uid", UID);
- DefaultLookupInternal.Add("surname", Surname);
- DefaultLookupInternal.Add("givenname", GivenName);
- DefaultLookupInternal.Add("initials", Initials);
- DefaultLookupInternal.Add("generation", Generation);
- DefaultLookupInternal.Add("unstructuredaddress", UnstructuredAddress);
- DefaultLookupInternal.Add("unstructuredname", UnstructuredName);
- DefaultLookupInternal.Add("uniqueidentifier", UniqueIdentifier);
- DefaultLookupInternal.Add("dn", DnQualifier);
- DefaultLookupInternal.Add("pseudonym", Pseudonym);
- DefaultLookupInternal.Add("postaladdress", PostalAddress);
- DefaultLookupInternal.Add("nameofbirth", NameAtBirth);
- DefaultLookupInternal.Add("countryofcitizenship", CountryOfCitizenship);
- DefaultLookupInternal.Add("countryofresidence", CountryOfResidence);
- DefaultLookupInternal.Add("gender", Gender);
- DefaultLookupInternal.Add("placeofbirth", PlaceOfBirth);
- DefaultLookupInternal.Add("dateofbirth", DateOfBirth);
- DefaultLookupInternal.Add("postalcode", PostalCode);
- DefaultLookupInternal.Add("businesscategory", BusinessCategory);
- DefaultLookupInternal.Add("telephonenumber", TelephoneNumber);
- }
- private readonly List<DerObjectIdentifier> ordering = new List<DerObjectIdentifier>();
- private readonly X509NameEntryConverter converter;
- private IList<string> values = new List<string>();
- private IList<bool> added = new List<bool>();
- private Asn1Sequence seq;
- /**
- * Return a X509Name based on the passed in tagged object.
- *
- * @param obj tag object holding name.
- * @param explicitly true if explicitly tagged false otherwise.
- * @return the X509Name
- */
- public static X509Name GetInstance(
- Asn1TaggedObject obj,
- bool explicitly)
- {
- return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
- }
- public static X509Name GetInstance(
- object obj)
- {
- if (obj is X509Name)
- return (X509Name)obj;
- if (obj == null)
- return null;
- return new X509Name(Asn1Sequence.GetInstance(obj));
- }
- protected X509Name()
- {
- }
- /**
- * Constructor from Asn1Sequence
- *
- * the principal will be a list of constructed sets, each containing an (OID, string) pair.
- */
- protected X509Name(Asn1Sequence seq)
- {
- this.seq = seq;
- foreach (Asn1Encodable asn1Obj in seq)
- {
- Asn1Set asn1Set = Asn1Set.GetInstance(asn1Obj.ToAsn1Object());
- for (int i = 0; i < asn1Set.Count; i++)
- {
- Asn1Sequence s = Asn1Sequence.GetInstance(asn1Set[i].ToAsn1Object());
- if (s.Count != 2)
- throw new ArgumentException("badly sized pair");
- ordering.Add(DerObjectIdentifier.GetInstance(s[0].ToAsn1Object()));
- Asn1Object derValue = s[1].ToAsn1Object();
- if (derValue is IAsn1String && !(derValue is DerUniversalString))
- {
- string v = ((IAsn1String)derValue).GetString();
- #if NET_STANDARD_2_1
- if (v.StartsWith('#'))
- #else
- if (v.StartsWith("#"))
- #endif
- {
- v = "\\" + v;
- }
- values.Add(v);
- }
- else
- {
- values.Add("#" + Hex.ToHexString(derValue.GetEncoded()));
- }
- added.Add(i != 0);
- }
- }
- }
- /**
- * Constructor from a table of attributes with ordering.
- * <p>
- * it's is assumed the table contains OID/string pairs, and the contents
- * of the table are copied into an internal table as part of the
- * construction process. The ordering ArrayList should contain the OIDs
- * in the order they are meant to be encoded or printed in ToString.</p>
- */
- public X509Name(
- IList<DerObjectIdentifier> ordering,
- IDictionary<DerObjectIdentifier, string> attributes)
- : this(ordering, attributes, new X509DefaultEntryConverter())
- {
- }
- /**
- * Constructor from a table of attributes with ordering.
- * <p>
- * it's is assumed the table contains OID/string pairs, and the contents
- * of the table are copied into an internal table as part of the
- * construction process. The ordering ArrayList should contain the OIDs
- * in the order they are meant to be encoded or printed in ToString.</p>
- * <p>
- * The passed in converter will be used to convert the strings into their
- * ASN.1 counterparts.</p>
- */
- public X509Name(
- IList<DerObjectIdentifier> ordering,
- IDictionary<DerObjectIdentifier, string> attributes,
- X509NameEntryConverter converter)
- {
- this.converter = converter;
- foreach (DerObjectIdentifier oid in ordering)
- {
- if (!attributes.TryGetValue(oid, out var attribute))
- throw new ArgumentException("No attribute for object id - " + oid + " - passed to distinguished name");
- //object attribute = attributes[oid];
- //if (attribute == null)
- //{
- // throw new ArgumentException("No attribute for object id - " + oid + " - passed to distinguished name");
- //}
- this.ordering.Add(oid);
- this.added.Add(false);
- this.values.Add(attribute); // copy the hash table
- }
- }
- /**
- * Takes two vectors one of the oids and the other of the values.
- */
- public X509Name(IList<DerObjectIdentifier> oids, IList<string> values)
- : this(oids, values, new X509DefaultEntryConverter())
- {
- }
- /**
- * Takes two vectors one of the oids and the other of the values.
- * <p>
- * The passed in converter will be used to convert the strings into their
- * ASN.1 counterparts.</p>
- */
- public X509Name(IList<DerObjectIdentifier> oids, IList<string> values, X509NameEntryConverter converter)
- {
- this.converter = converter;
- if (oids.Count != values.Count)
- throw new ArgumentException("'oids' must be same length as 'values'.");
- for (int i = 0; i < oids.Count; i++)
- {
- this.ordering.Add(oids[i]);
- this.values.Add(values[i]);
- this.added.Add(false);
- }
- }
- /**
- * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
- * some such, converting it into an ordered set of name attributes.
- */
- public X509Name(string dirName)
- : this(DefaultReverse, DefaultLookup, dirName)
- {
- }
- /**
- * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
- * some such, converting it into an ordered set of name attributes with each
- * string value being converted to its associated ASN.1 type using the passed
- * in converter.
- */
- public X509Name(string dirName, X509NameEntryConverter converter)
- : this(DefaultReverse, DefaultLookup, dirName, converter)
- {
- }
- /**
- * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
- * some such, converting it into an ordered set of name attributes. If reverse
- * is true, create the encoded version of the sequence starting from the
- * last element in the string.
- */
- public X509Name(bool reverse, string dirName)
- : this(reverse, DefaultLookup, dirName)
- {
- }
- /**
- * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
- * some such, converting it into an ordered set of name attributes with each
- * string value being converted to its associated ASN.1 type using the passed
- * in converter. If reverse is true the ASN.1 sequence representing the DN will
- * be built by starting at the end of the string, rather than the start.
- */
- public X509Name(bool reverse, string dirName, X509NameEntryConverter converter)
- : this(reverse, DefaultLookup, dirName, converter)
- {
- }
- /**
- * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
- * some such, converting it into an ordered set of name attributes. lookUp
- * should provide a table of lookups, indexed by lowercase only strings and
- * yielding a DerObjectIdentifier, other than that OID. and numeric oids
- * will be processed automatically.
- * <br/>
- * If reverse is true, create the encoded version of the sequence
- * starting from the last element in the string.
- * @param reverse true if we should start scanning from the end (RFC 2553).
- * @param lookUp table of names and their oids.
- * @param dirName the X.500 string to be parsed.
- */
- public X509Name(bool reverse, IDictionary<string, DerObjectIdentifier> lookup, string dirName)
- : this(reverse, lookup, dirName, new X509DefaultEntryConverter())
- {
- }
- private DerObjectIdentifier DecodeOid(string name, IDictionary<string, DerObjectIdentifier> lookup)
- {
- if (name.StartsWith("OID.", StringComparison.OrdinalIgnoreCase))
- return new DerObjectIdentifier(name.Substring("OID.".Length));
- if (name[0] >= '0' && name[0] <= '9')
- return new DerObjectIdentifier(name);
- if (lookup.TryGetValue(name, out var oid))
- return oid;
- throw new ArgumentException("Unknown object id - " + name + " - passed to distinguished name");
- }
- /**
- * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
- * some such, converting it into an ordered set of name attributes. lookUp
- * should provide a table of lookups, indexed by lowercase only strings and
- * yielding a DerObjectIdentifier, other than that OID. and numeric oids
- * will be processed automatically. The passed in converter is used to convert the
- * string values to the right of each equals sign to their ASN.1 counterparts.
- * <br/>
- * @param reverse true if we should start scanning from the end, false otherwise.
- * @param lookUp table of names and oids.
- * @param dirName the string dirName
- * @param converter the converter to convert string values into their ASN.1 equivalents
- */
- public X509Name(bool reverse, IDictionary<string, DerObjectIdentifier> lookup, string dirName,
- X509NameEntryConverter converter)
- {
- this.converter = converter;
- X509NameTokenizer nTok = new X509NameTokenizer(dirName);
- while (nTok.HasMoreTokens())
- {
- string token = nTok.NextToken();
- int index = token.IndexOf('=');
- if (index == -1)
- throw new ArgumentException("badly formated directory string");
- string name = token.Substring(0, index);
- string value = token.Substring(index + 1);
- DerObjectIdentifier oid = DecodeOid(name, lookup);
- if (value.IndexOf('+') > 0)
- {
- X509NameTokenizer vTok = new X509NameTokenizer(value, '+');
- string v = vTok.NextToken();
- this.ordering.Add(oid);
- this.values.Add(v);
- this.added.Add(false);
- while (vTok.HasMoreTokens())
- {
- string sv = vTok.NextToken();
- int ndx = sv.IndexOf('=');
- string nm = sv.Substring(0, ndx);
- string vl = sv.Substring(ndx + 1);
- this.ordering.Add(DecodeOid(nm, lookup));
- this.values.Add(vl);
- this.added.Add(true);
- }
- }
- else
- {
- this.ordering.Add(oid);
- this.values.Add(value);
- this.added.Add(false);
- }
- }
- if (reverse)
- {
- // this.ordering.Reverse();
- // this.values.Reverse();
- // this.added.Reverse();
- var o = new List<DerObjectIdentifier>();
- var v = new List<string>();
- var a = new List<bool>();
- int count = 1;
- for (int i = 0; i < this.ordering.Count; i++)
- {
- if (!((bool) this.added[i]))
- {
- count = 0;
- }
- int index = count++;
- o.Insert(index, this.ordering[i]);
- v.Insert(index, this.values[i]);
- a.Insert(index, this.added[i]);
- }
- this.ordering = o;
- this.values = v;
- this.added = a;
- }
- }
- /**
- * return an IList of the oids in the name, in the order they were found.
- */
- public IList<DerObjectIdentifier> GetOidList()
- {
- return new List<DerObjectIdentifier>(ordering);
- }
- /**
- * return an IList of the values found in the name, in the order they
- * were found.
- */
- public IList<string> GetValueList()
- {
- return GetValueList(null);
- }
- /**
- * return an IList of the values found in the name, in the order they
- * were found, with the DN label corresponding to passed in oid.
- */
- public IList<string> GetValueList(DerObjectIdentifier oid)
- {
- var v = new List<string>();
- for (int i = 0; i != values.Count; i++)
- {
- if (null == oid || oid.Equals(ordering[i]))
- {
- string val = (string)values[i];
- if (val.StartsWith("\\#", StringComparison.OrdinalIgnoreCase))
- {
- val = val.Substring(1);
- }
- v.Add(val);
- }
- }
- return v;
- }
- public override Asn1Object ToAsn1Object()
- {
- if (seq == null)
- {
- Asn1EncodableVector vec = new Asn1EncodableVector();
- Asn1EncodableVector sVec = new Asn1EncodableVector();
- DerObjectIdentifier lstOid = null;
- for (int i = 0; i != ordering.Count; i++)
- {
- DerObjectIdentifier oid = (DerObjectIdentifier)ordering[i];
- string str = (string)values[i];
- if (lstOid == null
- || ((bool)this.added[i]))
- {
- }
- else
- {
- vec.Add(new DerSet(sVec));
- sVec = new Asn1EncodableVector();
- }
- sVec.Add(
- new DerSequence(
- oid,
- converter.GetConvertedValue(oid, str)));
- lstOid = oid;
- }
- vec.Add(new DerSet(sVec));
- seq = new DerSequence(vec);
- }
- return seq;
- }
- /// <param name="other">The X509Name object to test equivalency against.</param>
- /// <param name="inOrder">If true, the order of elements must be the same,
- /// as well as the values associated with each element.</param>
- public bool Equivalent(
- X509Name other,
- bool inOrder)
- {
- if (!inOrder)
- return this.Equivalent(other);
- if (other == null)
- return false;
- if (other == this)
- return true;
- int orderingSize = ordering.Count;
- if (orderingSize != other.ordering.Count)
- return false;
- for (int i = 0; i < orderingSize; i++)
- {
- DerObjectIdentifier oid = (DerObjectIdentifier) ordering[i];
- DerObjectIdentifier oOid = (DerObjectIdentifier) other.ordering[i];
- if (!oid.Equals(oOid))
- return false;
- string val = (string) values[i];
- string oVal = (string) other.values[i];
- if (!EquivalentStrings(val, oVal))
- return false;
- }
- return true;
- }
- /**
- * test for equivalence - note: case is ignored.
- */
- public bool Equivalent(
- X509Name other)
- {
- if (other == null)
- return false;
- if (other == this)
- return true;
- int orderingSize = ordering.Count;
- if (orderingSize != other.ordering.Count)
- {
- return false;
- }
- bool[] indexes = new bool[orderingSize];
- int start, end, delta;
- if (ordering[0].Equals(other.ordering[0])) // guess forward
- {
- start = 0;
- end = orderingSize;
- delta = 1;
- }
- else // guess reversed - most common problem
- {
- start = orderingSize - 1;
- end = -1;
- delta = -1;
- }
- for (int i = start; i != end; i += delta)
- {
- bool found = false;
- DerObjectIdentifier oid = (DerObjectIdentifier)ordering[i];
- string value = (string)values[i];
- for (int j = 0; j < orderingSize; j++)
- {
- if (indexes[j])
- {
- continue;
- }
- DerObjectIdentifier oOid = (DerObjectIdentifier)other.ordering[j];
- if (oid.Equals(oOid))
- {
- string oValue = (string)other.values[j];
- if (EquivalentStrings(value, oValue))
- {
- indexes[j] = true;
- found = true;
- break;
- }
- }
- }
- if (!found)
- {
- return false;
- }
- }
- return true;
- }
- private static bool EquivalentStrings(string s1, string s2)
- {
- string v1 = Canonicalize(s1);
- string v2 = Canonicalize(s2);
- if (!v1.Equals(v2))
- {
- v1 = StripInternalSpaces(v1);
- v2 = StripInternalSpaces(v2);
- if (!v1.Equals(v2))
- return false;
- }
- return true;
- }
- private static string Canonicalize(string s)
- {
- string v = s.ToLowerInvariant().Trim();
- #if NET_STANDARD_2_1
- if (v.StartsWith('#'))
- #else
- if (v.StartsWith("#"))
- #endif
- {
- Asn1Object obj = DecodeObject(v);
- if (obj is IAsn1String str)
- {
- v = str.GetString().ToLowerInvariant().Trim();
- }
- }
- return v;
- }
- private static Asn1Object DecodeObject(string v)
- {
- try
- {
- return Asn1Object.FromByteArray(Hex.DecodeStrict(v, 1, v.Length - 1));
- }
- catch (IOException e)
- {
- throw new InvalidOperationException("unknown encoding in name: " + e.Message, e);
- }
- }
- private static string StripInternalSpaces(string str)
- {
- StringBuilder res = new StringBuilder();
- if (str.Length != 0)
- {
- char c1 = str[0];
- res.Append(c1);
- for (int k = 1; k < str.Length; k++)
- {
- char c2 = str[k];
- if (!(c1 == ' ' && c2 == ' '))
- {
- res.Append(c2);
- }
- c1 = c2;
- }
- }
- return res.ToString();
- }
- private void AppendValue(StringBuilder buf, IDictionary<DerObjectIdentifier, string> oidSymbols,
- DerObjectIdentifier oid, string val)
- {
- if (oidSymbols.TryGetValue(oid, out var sym))
- {
- buf.Append(sym);
- }
- else
- {
- buf.Append(oid.Id);
- }
- buf.Append('=');
- int index = buf.Length;
- buf.Append(val);
- int end = buf.Length;
- if (val.StartsWith("\\#", StringComparison.OrdinalIgnoreCase))
- {
- index += 2;
- }
- while (index != end)
- {
- if ((buf[index] == ',')
- || (buf[index] == '"')
- || (buf[index] == '\\')
- || (buf[index] == '+')
- || (buf[index] == '=')
- || (buf[index] == '<')
- || (buf[index] == '>')
- || (buf[index] == ';'))
- {
- buf.Insert(index++, "\\");
- end++;
- }
- index++;
- }
- }
- /**
- * convert the structure to a string - if reverse is true the
- * oids and values are listed out starting with the last element
- * in the sequence (ala RFC 2253), otherwise the string will begin
- * with the first element of the structure. If no string definition
- * for the oid is found in oidSymbols the string value of the oid is
- * added. Two standard symbol tables are provided DefaultSymbols, and
- * RFC2253Symbols as part of this class.
- *
- * @param reverse if true start at the end of the sequence and work back.
- * @param oidSymbols look up table strings for oids.
- */
- public string ToString(bool reverse, IDictionary<DerObjectIdentifier, string> oidSymbols)
- {
- var components = new List<StringBuilder>();
- StringBuilder ava = null;
- for (int i = 0; i < ordering.Count; i++)
- {
- if (added[i])
- {
- ava.Append('+');
- AppendValue(ava, oidSymbols, ordering[i], values[i]);
- }
- else
- {
- ava = StringBuilderPool.Get(0); //new StringBuilder();
- AppendValue(ava, oidSymbols, ordering[i], values[i]);
- components.Add(ava);
- }
- }
- if (reverse)
- {
- components.Reverse();
- }
- StringBuilder buf = StringBuilderPool.Get(components.Count); //new StringBuilder();
- if (components.Count > 0)
- {
- buf.Append(StringBuilderPool.ReleaseAndGrab(components[0]));
- for (int i = 1; i < components.Count; ++i)
- {
- buf.Append(',');
- buf.Append(StringBuilderPool.ReleaseAndGrab(components[i]));
- }
- }
- return StringBuilderPool.ReleaseAndGrab(buf);
- }
- string cachedStrRepresentation = null;
- public override string ToString()
- {
- return cachedStrRepresentation ?? (cachedStrRepresentation = ToString(DefaultReverse, DefaultSymbols));
- }
- }
- }
- #pragma warning restore
- #endif
|