using System; using System.Collections; using System.IO; using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Operators; using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; using Org.BouncyCastle.Security.Certificates; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.X509 { /// Class to produce an X.509 Version 2 AttributeCertificate. public class X509V2AttributeCertificateGenerator { private readonly X509ExtensionsGenerator extGenerator = new X509ExtensionsGenerator(); private V2AttributeCertificateInfoGenerator acInfoGen; private DerObjectIdentifier sigOID; private AlgorithmIdentifier sigAlgId; private string signatureAlgorithm; public X509V2AttributeCertificateGenerator() { acInfoGen = new V2AttributeCertificateInfoGenerator(); } /// Reset the generator public void Reset() { acInfoGen = new V2AttributeCertificateInfoGenerator(); extGenerator.Reset(); } /// Set the Holder of this Attribute Certificate. public void SetHolder( AttributeCertificateHolder holder) { acInfoGen.SetHolder(holder.holder); } /// Set the issuer. public void SetIssuer( AttributeCertificateIssuer issuer) { acInfoGen.SetIssuer(AttCertIssuer.GetInstance(issuer.form)); } /// Set the serial number for the certificate. public void SetSerialNumber( BigInteger serialNumber) { acInfoGen.SetSerialNumber(new DerInteger(serialNumber)); } public void SetNotBefore( DateTime date) { acInfoGen.SetStartDate(new DerGeneralizedTime(date)); } public void SetNotAfter( DateTime date) { acInfoGen.SetEndDate(new DerGeneralizedTime(date)); } /// /// Set the signature algorithm. This can be either a name or an OID, names /// are treated as case insensitive. /// /// The algorithm name. [Obsolete("Not needed if Generate used with an ISignatureFactory")] public void SetSignatureAlgorithm( string signatureAlgorithm) { this.signatureAlgorithm = signatureAlgorithm; try { sigOID = X509Utilities.GetAlgorithmOid(signatureAlgorithm); } catch (Exception) { throw new ArgumentException("Unknown signature type requested"); } sigAlgId = X509Utilities.GetSigAlgID(sigOID, signatureAlgorithm); acInfoGen.SetSignature(sigAlgId); } /// Add an attribute. public void AddAttribute( X509Attribute attribute) { acInfoGen.AddAttribute(AttributeX509.GetInstance(attribute.ToAsn1Object())); } public void SetIssuerUniqueId( bool[] iui) { // TODO convert bool array to bit string //acInfoGen.SetIssuerUniqueID(iui); throw Platform.CreateNotImplementedException("SetIssuerUniqueId()"); } /// Add a given extension field for the standard extensions tag. public void AddExtension( string oid, bool critical, Asn1Encodable extensionValue) { extGenerator.AddExtension(new DerObjectIdentifier(oid), critical, extensionValue); } /// /// Add a given extension field for the standard extensions tag. /// The value parameter becomes the contents of the octet string associated /// with the extension. /// public void AddExtension( string oid, bool critical, byte[] extensionValue) { extGenerator.AddExtension(new DerObjectIdentifier(oid), critical, extensionValue); } /// /// Generate an X509 certificate, based on the current issuer and subject. /// [Obsolete("Use Generate with an ISignatureFactory")] public IX509AttributeCertificate Generate( AsymmetricKeyParameter privateKey) { return Generate(privateKey, null); } /// /// Generate an X509 certificate, based on the current issuer and subject, /// using the supplied source of randomness, if required. /// [Obsolete("Use Generate with an ISignatureFactory")] public IX509AttributeCertificate Generate( AsymmetricKeyParameter privateKey, SecureRandom random) { return Generate(new Asn1SignatureFactory(signatureAlgorithm, privateKey, random)); } /// /// Generate a new X.509 Attribute Certificate using the passed in SignatureCalculator. /// /// A signature calculator factory with the necessary algorithm details. /// An IX509AttributeCertificate. public IX509AttributeCertificate Generate(ISignatureFactory signatureCalculatorFactory) { if (!extGenerator.IsEmpty) { acInfoGen.SetExtensions(extGenerator.Generate()); } AlgorithmIdentifier sigAlgID = (AlgorithmIdentifier)signatureCalculatorFactory.AlgorithmDetails; acInfoGen.SetSignature(sigAlgID); AttributeCertificateInfo acInfo = acInfoGen.GenerateAttributeCertificateInfo(); byte[] encoded = acInfo.GetDerEncoded(); IStreamCalculator streamCalculator = signatureCalculatorFactory.CreateCalculator(); streamCalculator.Stream.Write(encoded, 0, encoded.Length); Platform.Dispose(streamCalculator.Stream); try { DerBitString signatureValue = new DerBitString(((IBlockResult)streamCalculator.GetResult()).Collect()); return new X509V2AttributeCertificate(new AttributeCertificate(acInfo, sigAlgID, signatureValue)); } catch (Exception e) { // TODO // throw new ExtCertificateEncodingException("constructed invalid certificate", e); throw new CertificateEncodingException("constructed invalid certificate", e); } } /// /// Allows enumeration of the signature names supported by the generator. /// public IEnumerable SignatureAlgNames { get { return X509Utilities.GetAlgNames(); } } } }