From 0b0f03c598b558c7acf79a969315a8d2e0aa1f1b Mon Sep 17 00:00:00 2001 From: mw Date: Wed, 1 Sep 2021 16:00:23 +1000 Subject: Issue #1 Added logic to handle duplicate extensions. New method on Pkcs10CertificationRequest for extracting X509Extensions Tests --- crypto/src/asn1/x509/X509ExtensionsGenerator.cs | 195 +++++++++++++++--------- 1 file changed, 120 insertions(+), 75 deletions(-) (limited to 'crypto/src/asn1/x509') diff --git a/crypto/src/asn1/x509/X509ExtensionsGenerator.cs b/crypto/src/asn1/x509/X509ExtensionsGenerator.cs index 58620ea5e..3b952fffa 100644 --- a/crypto/src/asn1/x509/X509ExtensionsGenerator.cs +++ b/crypto/src/asn1/x509/X509ExtensionsGenerator.cs @@ -5,88 +5,133 @@ using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Asn1.X509 { - /// Generator for X.509 extensions - public class X509ExtensionsGenerator - { - private IDictionary extensions = Platform.CreateHashtable(); + /// Generator for X.509 extensions + public class X509ExtensionsGenerator + { + private IDictionary extensions = Platform.CreateHashtable(); private IList extOrdering = Platform.CreateArrayList(); - /// Reset the generator - public void Reset() - { + private static readonly IDictionary dupsAllowed = Platform.CreateHashtable(); + + static X509ExtensionsGenerator() + { + dupsAllowed.Add(X509Extensions.SubjectAlternativeName, true); + dupsAllowed.Add(X509Extensions.IssuerAlternativeName, true); + dupsAllowed.Add(X509Extensions.SubjectDirectoryAttributes, true); + dupsAllowed.Add(X509Extensions.CertificateIssuer, true); + + } + + + + /// Reset the generator + public void Reset() + { extensions = Platform.CreateHashtable(); extOrdering = Platform.CreateArrayList(); - } - - /// - /// Add an extension with the given oid and the passed in value to be included - /// in the OCTET STRING associated with the extension. - /// - /// OID for the extension. - /// True if critical, false otherwise. - /// The ASN.1 object to be included in the extension. - public void AddExtension( - DerObjectIdentifier oid, - bool critical, - Asn1Encodable extValue) - { - byte[] encoded; - try - { - encoded = extValue.GetDerEncoded(); - } - catch (Exception e) - { - throw new ArgumentException("error encoding value: " + e); - } - - this.AddExtension(oid, critical, encoded); - } - - /// - /// Add an extension with the given oid and the passed in byte array to be wrapped - /// in the OCTET STRING associated with the extension. - /// - /// OID for the extension. - /// True if critical, false otherwise. - /// The byte array to be wrapped. - public void AddExtension( - DerObjectIdentifier oid, - bool critical, - byte[] extValue) - { - if (extensions.Contains(oid)) - { - throw new ArgumentException("extension " + oid + " already added"); - } - - extOrdering.Add(oid); - extensions.Add(oid, new X509Extension(critical, new DerOctetString(extValue))); - } - - /// Return true if there are no extension present in this generator. - /// True if empty, false otherwise - public bool IsEmpty - { - get { return extOrdering.Count < 1; } - } - - /// Generate an X509Extensions object based on the current state of the generator. - /// An X509Extensions object - public X509Extensions Generate() - { - return new X509Extensions(extOrdering, extensions); - } - - internal void AddExtension(DerObjectIdentifier oid, X509Extension x509Extension) + } + + /// + /// Add an extension with the given oid and the passed in value to be included + /// in the OCTET STRING associated with the extension. + /// + /// OID for the extension. + /// True if critical, false otherwise. + /// The ASN.1 object to be included in the extension. + public void AddExtension( + DerObjectIdentifier oid, + bool critical, + Asn1Encodable extValue) + { + byte[] encoded; + try + { + encoded = extValue.GetDerEncoded(); + } + catch (Exception e) + { + throw new ArgumentException("error encoding value: " + e); + } + + this.AddExtension(oid, critical, encoded); + } + + /// + /// Add an extension with the given oid and the passed in byte array to be wrapped + /// in the OCTET STRING associated with the extension. + /// + /// OID for the extension. + /// True if critical, false otherwise. + /// The byte array to be wrapped. + public void AddExtension( + DerObjectIdentifier oid, + bool critical, + byte[] extValue) + { + if (extensions.Contains(oid)) + { + if (dupsAllowed.Contains(oid)) + { + X509Extension existingExtension = (X509Extension)extensions[oid]; + + Asn1Sequence seq1 = Asn1Sequence.GetInstance(DerOctetString.GetInstance(existingExtension.Value).GetOctets()); + Asn1EncodableVector items = Asn1EncodableVector.FromEnumerable(seq1); + Asn1Sequence seq2 = Asn1Sequence.GetInstance(extValue); + + foreach (Asn1Encodable enc in seq2) + { + items.Add(enc); + } + + extensions[oid] = new X509Extension(existingExtension.IsCritical, new DerOctetString(new DerSequence(items).GetEncoded())); + + } + else + { + throw new ArgumentException("extension " + oid + " already added"); + } + } + else + { + extOrdering.Add(oid); + extensions.Add(oid, new X509Extension(critical, new DerOctetString(extValue))); + } + } + + public void AddExtensions(X509Extensions extensions) + { + foreach (DerObjectIdentifier ident in extensions.ExtensionOids) + { + X509Extension ext = extensions.GetExtension(ident); + AddExtension(ident, ext.critical, ext.Value.GetOctets()); + } + } + + + + /// Return true if there are no extension present in this generator. + /// True if empty, false otherwise + public bool IsEmpty + { + get { return extOrdering.Count < 1; } + } + + /// Generate an X509Extensions object based on the current state of the generator. + /// An X509Extensions object + public X509Extensions Generate() + { + return new X509Extensions(extOrdering, extensions); + } + + internal void AddExtension(DerObjectIdentifier oid, X509Extension x509Extension) { if (extensions.Contains(oid)) - { - throw new ArgumentException ("extension " + oid + " already added"); - } + { + throw new ArgumentException("extension " + oid + " already added"); + } - extOrdering.Add(oid); - extensions.Add(oid, x509Extension); + extOrdering.Add(oid); + extensions.Add(oid, x509Extension); } } } -- cgit 1.4.1