using System; using System.Collections.Generic; namespace Org.BouncyCastle.Asn1.X509 { /// Generator for X.509 extensions public class X509ExtensionsGenerator { private Dictionary m_extensions = new Dictionary(); private List m_ordering = new List(); private static readonly HashSet m_dupsAllowed = new HashSet() { X509Extensions.SubjectAlternativeName, X509Extensions.IssuerAlternativeName, X509Extensions.SubjectDirectoryAttributes, X509Extensions.CertificateIssuer }; /// Reset the generator public void Reset() { m_extensions = new Dictionary(); m_ordering = new List(); } /// /// 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 (!m_extensions.TryGetValue(oid, out X509Extension existingExtension)) { m_ordering.Add(oid); m_extensions.Add(oid, new X509Extension(critical, new DerOctetString(extValue))); return; } if (!m_dupsAllowed.Contains(oid)) throw new ArgumentException("extension " + oid + " already added"); Asn1Sequence seq1 = Asn1Sequence.GetInstance(existingExtension.Value.GetOctets()); Asn1Sequence seq2 = Asn1Sequence.GetInstance(extValue); var concat = DerSequence.Concatenate(seq1, seq2); m_extensions[oid] = new X509Extension( existingExtension.IsCritical | critical, new DerOctetString(concat.GetEncoded(Asn1Encodable.Der))); } 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 m_ordering.Count < 1; } } /// Generate an X509Extensions object based on the current state of the generator. /// An X509Extensions object public X509Extensions Generate() { return new X509Extensions(m_ordering, m_extensions); } internal void AddExtension(DerObjectIdentifier oid, X509Extension x509Extension) { if (m_extensions.ContainsKey(oid)) throw new ArgumentException("extension " + oid + " already added"); m_ordering.Add(oid); m_extensions.Add(oid, x509Extension); } } }