diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2023-04-04 21:20:26 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2023-04-04 21:20:26 +0700 |
commit | aa027f072fe8f7871950cd256b2e04f12c1d4551 (patch) | |
tree | 47c4bb1a5b813f7cb82a68ed6b87f431d075a97a | |
parent | Add constructor from template CRL (diff) | |
download | BouncyCastle.NET-ed25519-aa027f072fe8f7871950cd256b2e04f12c1d4551.tar.xz |
X509: generation/validation of alternative signatures for certs and CRLs.
-rw-r--r-- | crypto/src/asn1/x509/TBSCertList.cs | 29 | ||||
-rw-r--r-- | crypto/src/asn1/x509/TBSCertificateStructure.cs | 32 | ||||
-rw-r--r-- | crypto/src/asn1/x509/V1TBSCertificateGenerator.cs | 2 | ||||
-rw-r--r-- | crypto/src/asn1/x509/V2TBSCertListGenerator.cs | 66 | ||||
-rw-r--r-- | crypto/src/asn1/x509/V3TBSCertificateGenerator.cs | 104 | ||||
-rw-r--r-- | crypto/src/x509/X509Certificate.cs | 54 | ||||
-rw-r--r-- | crypto/src/x509/X509Crl.cs | 58 | ||||
-rw-r--r-- | crypto/src/x509/X509Utilities.cs | 43 | ||||
-rw-r--r-- | crypto/src/x509/X509V2AttributeCertificate.cs | 29 | ||||
-rw-r--r-- | crypto/src/x509/X509V2AttributeCertificateGenerator.cs | 21 | ||||
-rw-r--r-- | crypto/src/x509/X509V2CRLGenerator.cs | 38 | ||||
-rw-r--r-- | crypto/src/x509/X509V3CertificateGenerator.cs | 37 |
12 files changed, 309 insertions, 204 deletions
diff --git a/crypto/src/asn1/x509/TBSCertList.cs b/crypto/src/asn1/x509/TBSCertList.cs index 4cfb44c90..fb8a9907c 100644 --- a/crypto/src/asn1/x509/TBSCertList.cs +++ b/crypto/src/asn1/x509/TBSCertList.cs @@ -144,32 +144,21 @@ namespace Org.BouncyCastle.Asn1.X509 internal Asn1Sequence revokedCertificates; internal X509Extensions crlExtensions; - public static TbsCertificateList GetInstance( - Asn1TaggedObject obj, - bool explicitly) + public static TbsCertificateList GetInstance(object obj) { - return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + if (obj == null) + return null; + if (obj is TbsCertificateList tbsCertificateList) + return tbsCertificateList; + return new TbsCertificateList(Asn1Sequence.GetInstance(obj)); } - public static TbsCertificateList GetInstance( - object obj) + public static TbsCertificateList GetInstance(Asn1TaggedObject obj, bool explicitly) { - TbsCertificateList list = obj as TbsCertificateList; - - if (obj == null || list != null) - { - return list; - } - - if (obj is Asn1Sequence) - { - return new TbsCertificateList((Asn1Sequence) obj); - } - - throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(obj), "obj"); + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); } - internal TbsCertificateList(Asn1Sequence seq) + private TbsCertificateList(Asn1Sequence seq) { if (seq.Count < 3 || seq.Count > 7) throw new ArgumentException("Bad sequence size: " + seq.Count); diff --git a/crypto/src/asn1/x509/TBSCertificateStructure.cs b/crypto/src/asn1/x509/TBSCertificateStructure.cs index e1fba2488..e41224f4a 100644 --- a/crypto/src/asn1/x509/TBSCertificateStructure.cs +++ b/crypto/src/asn1/x509/TBSCertificateStructure.cs @@ -39,27 +39,21 @@ namespace Org.BouncyCastle.Asn1.X509 internal DerBitString subjectUniqueID; internal X509Extensions extensions; - public static TbsCertificateStructure GetInstance( - Asn1TaggedObject obj, - bool explicitly) - { - return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); - } - - public static TbsCertificateStructure GetInstance( - object obj) - { - if (obj is TbsCertificateStructure) - return (TbsCertificateStructure) obj; - - if (obj != null) - return new TbsCertificateStructure(Asn1Sequence.GetInstance(obj)); + public static TbsCertificateStructure GetInstance(object obj) + { + if (obj == null) + return null; + if (obj is TbsCertificateStructure tbsCertificateStructure) + return tbsCertificateStructure; + return new TbsCertificateStructure(Asn1Sequence.GetInstance(obj)); + } - return null; - } + public static TbsCertificateStructure GetInstance(Asn1TaggedObject obj, bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } - internal TbsCertificateStructure( - Asn1Sequence seq) + private TbsCertificateStructure(Asn1Sequence seq) { int seqStart = 0; diff --git a/crypto/src/asn1/x509/V1TBSCertificateGenerator.cs b/crypto/src/asn1/x509/V1TBSCertificateGenerator.cs index 9cbff1ef0..7c191b263 100644 --- a/crypto/src/asn1/x509/V1TBSCertificateGenerator.cs +++ b/crypto/src/asn1/x509/V1TBSCertificateGenerator.cs @@ -94,7 +94,7 @@ namespace Org.BouncyCastle.Asn1.X509 throw new InvalidOperationException("not all mandatory fields set in V1 TBScertificate generator"); } - return new TbsCertificateStructure( + return TbsCertificateStructure.GetInstance( new DerSequence( //version, - not required as default value serialNumber, diff --git a/crypto/src/asn1/x509/V2TBSCertListGenerator.cs b/crypto/src/asn1/x509/V2TBSCertListGenerator.cs index bf016c22d..d744ed664 100644 --- a/crypto/src/asn1/x509/V2TBSCertListGenerator.cs +++ b/crypto/src/asn1/x509/V2TBSCertListGenerator.cs @@ -40,40 +40,34 @@ namespace Org.BouncyCastle.Asn1.X509 { } - public void SetSignature( - AlgorithmIdentifier signature) + public void SetSignature(AlgorithmIdentifier signature) { this.signature = signature; } - public void SetIssuer( - X509Name issuer) + public void SetIssuer(X509Name issuer) { this.issuer = issuer; } - public void SetThisUpdate( - Asn1UtcTime thisUpdate) + public void SetThisUpdate(Asn1UtcTime thisUpdate) { this.thisUpdate = new Time(thisUpdate); } - public void SetNextUpdate( - Asn1UtcTime nextUpdate) + public void SetNextUpdate(Asn1UtcTime nextUpdate) { this.nextUpdate = (nextUpdate != null) ? new Time(nextUpdate) : null; } - public void SetThisUpdate( - Time thisUpdate) + public void SetThisUpdate(Time thisUpdate) { this.thisUpdate = thisUpdate; } - public void SetNextUpdate( - Time nextUpdate) + public void SetNextUpdate(Time nextUpdate) { this.nextUpdate = nextUpdate; } @@ -154,39 +148,49 @@ namespace Org.BouncyCastle.Asn1.X509 AddCrlEntry(new DerSequence(v)); } - public void SetExtensions( - X509Extensions extensions) + public void SetExtensions(X509Extensions extensions) { this.extensions = extensions; } - public TbsCertificateList GenerateTbsCertList() + public Asn1Sequence GeneratePreTbsCertList() + { + if (signature != null) + throw new InvalidOperationException("signature should not be set in PreTBSCertList generator"); + + if ((issuer == null) || (thisUpdate == null)) + throw new InvalidOperationException("Not all mandatory fields set in V2 PreTBSCertList generator"); + + return GenerateTbsCertificateStructure(); + } + + public TbsCertificateList GenerateTbsCertList() { if ((signature == null) || (issuer == null) || (thisUpdate == null)) - { throw new InvalidOperationException("Not all mandatory fields set in V2 TbsCertList generator."); - } - Asn1EncodableVector v = new Asn1EncodableVector( - version, signature, issuer, thisUpdate); + return TbsCertificateList.GetInstance(GenerateTbsCertificateStructure()); + } - if (nextUpdate != null) - { - v.Add(nextUpdate); - } + private Asn1Sequence GenerateTbsCertificateStructure() + { + Asn1EncodableVector v = new Asn1EncodableVector(7); - // Add CRLEntries if they exist - if (crlEntries != null) - { - v.Add(new DerSequence(crlEntries.ToArray())); - } + v.Add(version); + v.AddOptional(signature); + v.Add(issuer); + v.Add(thisUpdate); + v.AddOptional(nextUpdate); - if (extensions != null) + // Add CRLEntries if they exist + if (crlEntries != null && crlEntries.Count > 0) { - v.Add(new DerTaggedObject(0, extensions)); + v.Add(new DerSequence(crlEntries.ToArray())); } - return new TbsCertificateList(new DerSequence(v)); + v.AddOptionalTagged(true, 0, extensions); + + return new DerSequence(v); } } } diff --git a/crypto/src/asn1/x509/V3TBSCertificateGenerator.cs b/crypto/src/asn1/x509/V3TBSCertificateGenerator.cs index 544582ddb..f58e4a7ab 100644 --- a/crypto/src/asn1/x509/V3TBSCertificateGenerator.cs +++ b/crypto/src/asn1/x509/V3TBSCertificateGenerator.cs @@ -39,74 +39,62 @@ namespace Org.BouncyCastle.Asn1.X509 { } - public void SetSerialNumber( - DerInteger serialNumber) + public void SetSerialNumber(DerInteger serialNumber) { this.serialNumber = serialNumber; } - public void SetSignature( - AlgorithmIdentifier signature) + public void SetSignature(AlgorithmIdentifier signature) { this.signature = signature; } - public void SetIssuer( - X509Name issuer) + public void SetIssuer(X509Name issuer) { this.issuer = issuer; } - public void SetStartDate( - Asn1UtcTime startDate) + public void SetStartDate(Asn1UtcTime startDate) { this.startDate = new Time(startDate); } - public void SetStartDate( - Time startDate) + public void SetStartDate(Time startDate) { this.startDate = startDate; } - public void SetEndDate( - Asn1UtcTime endDate) + public void SetEndDate(Asn1UtcTime endDate) { this.endDate = new Time(endDate); } - public void SetEndDate( - Time endDate) + public void SetEndDate(Time endDate) { this.endDate = endDate; } - public void SetSubject( - X509Name subject) + public void SetSubject(X509Name subject) { this.subject = subject; } - public void SetIssuerUniqueID( - DerBitString uniqueID) + public void SetIssuerUniqueID(DerBitString uniqueID) { this.issuerUniqueID = uniqueID; } - public void SetSubjectUniqueID( - DerBitString uniqueID) + public void SetSubjectUniqueID(DerBitString uniqueID) { this.subjectUniqueID = uniqueID; } - public void SetSubjectPublicKeyInfo( - SubjectPublicKeyInfo pubKeyInfo) + public void SetSubjectPublicKeyInfo(SubjectPublicKeyInfo pubKeyInfo) { this.subjectPublicKeyInfo = pubKeyInfo; } - public void SetExtensions( - X509Extensions extensions) + public void SetExtensions(X509Extensions extensions) { this.extensions = extensions; @@ -121,48 +109,62 @@ namespace Org.BouncyCastle.Asn1.X509 } } - public TbsCertificateStructure GenerateTbsCertificate() + public Asn1Sequence GeneratePreTbsCertificate() { - if ((serialNumber == null) || (signature == null) + if (signature != null) + throw new InvalidOperationException("signature field should not be set in PreTBSCertificate"); + + if ((serialNumber == null) || (issuer == null) || (startDate == null) || (endDate == null) - || (subject == null && !altNamePresentAndCritical) - || (subjectPublicKeyInfo == null)) + || (subject == null && !altNamePresentAndCritical) || (subjectPublicKeyInfo == null)) { throw new InvalidOperationException("not all mandatory fields set in V3 TBScertificate generator"); } - DerSequence validity = new DerSequence(startDate, endDate); // before and after dates + return GenerateTbsStructure(); + } - Asn1EncodableVector v = new Asn1EncodableVector( - version, serialNumber, signature, issuer, validity); + public TbsCertificateStructure GenerateTbsCertificate() + { + if ((serialNumber == null) || (signature == null) + || (issuer == null) || (startDate == null) || (endDate == null) + || (subject == null && !altNamePresentAndCritical) || (subjectPublicKeyInfo == null)) + { + throw new InvalidOperationException("not all mandatory fields set in V3 TBScertificate generator"); + } - if (subject != null) - { - v.Add(subject); - } - else - { - v.Add(DerSequence.Empty); - } + return TbsCertificateStructure.GetInstance(GenerateTbsStructure()); + } - v.Add(subjectPublicKeyInfo); + private Asn1Sequence GenerateTbsStructure() + { + Asn1EncodableVector v = new Asn1EncodableVector(10); - if (issuerUniqueID != null) - { - v.Add(new DerTaggedObject(false, 1, issuerUniqueID)); - } + v.Add(version); + v.Add(serialNumber); + v.AddOptional(signature); + v.Add(issuer); - if (subjectUniqueID != null) - { - v.Add(new DerTaggedObject(false, 2, subjectUniqueID)); - } + // + // before and after dates + // + v.Add(new DerSequence(startDate, endDate)); - if (extensions != null) + if (subject != null) { - v.Add(new DerTaggedObject(3, extensions)); + v.Add(subject); } + else + { + v.Add(DerSequence.Empty); + } + + v.Add(subjectPublicKeyInfo); + v.AddOptionalTagged(false, 1, issuerUniqueID); + v.AddOptionalTagged(false, 2, subjectUniqueID); + v.AddOptionalTagged(true, 3, extensions); - return new TbsCertificateStructure(new DerSequence(v)); + return new DerSequence(v); } } } diff --git a/crypto/src/x509/X509Certificate.cs b/crypto/src/x509/X509Certificate.cs index cd3d6d680..39df381df 100644 --- a/crypto/src/x509/X509Certificate.cs +++ b/crypto/src/x509/X509Certificate.cs @@ -638,8 +638,7 @@ namespace Org.BouncyCastle.X509 /// <param name="key">An appropriate public key parameter object, RsaPublicKeyParameters, DsaPublicKeyParameters or ECDsaPublicKeyParameters</param> /// <returns>True if the signature is valid.</returns> /// <exception cref="Exception">If key submitted is not of the above nominated types.</exception> - public virtual void Verify( - AsymmetricKeyParameter key) + public virtual void Verify(AsymmetricKeyParameter key) { CheckSignature(new Asn1VerifierFactory(c.SignatureAlgorithm, key)); } @@ -648,27 +647,54 @@ namespace Org.BouncyCastle.X509 /// Verify the certificate's signature using a verifier created using the passed in verifier provider. /// </summary> /// <param name="verifierProvider">An appropriate provider for verifying the certificate's signature.</param> - /// <returns>True if the signature is valid.</returns> - /// <exception cref="Exception">If verifier provider is not appropriate or the certificate algorithm is invalid.</exception> - public virtual void Verify( - IVerifierFactoryProvider verifierProvider) + /// <exception cref="Exception">If verifier provider is not appropriate or the certificate signature algorithm + /// is invalid.</exception> + public virtual void Verify(IVerifierFactoryProvider verifierProvider) { CheckSignature(verifierProvider.CreateVerifierFactory(c.SignatureAlgorithm)); } - protected virtual void CheckSignature( - IVerifierFactory verifier) + /// <summary>Verify the certificate's alternative signature using a verifier created using the passed in + /// verifier provider.</summary> + /// <param name="verifierProvider">An appropriate provider for verifying the certificate's alternative + /// signature.</param> + /// <exception cref="Exception">If verifier provider is not appropriate or the certificate alternative signature + /// algorithm is invalid.</exception> + public virtual void VerifyAltSignature(IVerifierFactoryProvider verifierProvider) { - if (!IsAlgIDEqual(c.SignatureAlgorithm, c.TbsCertificate.Signature)) - throw new CertificateException("signature algorithm in TBS cert not same as outer cert"); + var tbsCertificate = c.TbsCertificate; + var extensions = tbsCertificate.Extensions; + + AltSignatureAlgorithm altSigAlg = AltSignatureAlgorithm.FromExtensions(extensions); + AltSignatureValue altSigValue = AltSignatureValue.FromExtensions(extensions); + + var verifier = verifierProvider.CreateVerifierFactory(altSigAlg.Algorithm); - IStreamCalculator<IVerifier> streamCalculator = verifier.CreateCalculator(); - using (var stream = streamCalculator.Stream) + Asn1Sequence tbsSeq = Asn1Sequence.GetInstance(tbsCertificate.ToAsn1Object()); + Asn1EncodableVector v = new Asn1EncodableVector(); + + for (int i = 0; i < tbsSeq.Count - 1; i++) { - c.TbsCertificate.EncodeTo(stream, Asn1Encodable.Der); + if (i != 2) // signature field - must be ver 3 so version always present + { + v.Add(tbsSeq[i]); + } } - if (!streamCalculator.GetResult().IsVerified(GetSignature())) + v.Add(X509Utilities.TrimExtensions(3, extensions)); + + if (!X509Utilities.VerifySignature(verifier, new DerSequence(v), altSigValue.Signature)) + throw new InvalidKeyException("Public key presented not for certificate alternative signature"); + } + + protected virtual void CheckSignature(IVerifierFactory verifier) + { + var tbsCertificate = c.TbsCertificate; + + if (!IsAlgIDEqual(c.SignatureAlgorithm, tbsCertificate.Signature)) + throw new CertificateException("signature algorithm in TBS cert not same as outer cert"); + + if (!X509Utilities.VerifySignature(verifier, tbsCertificate, c.Signature)) throw new InvalidKeyException("Public key presented not for certificate signature"); } diff --git a/crypto/src/x509/X509Crl.cs b/crypto/src/x509/X509Crl.cs index 81dd1c20e..1fc13a0a2 100644 --- a/crypto/src/x509/X509Crl.cs +++ b/crypto/src/x509/X509Crl.cs @@ -104,8 +104,7 @@ namespace Org.BouncyCastle.X509 : null; } - public virtual void Verify( - AsymmetricKeyParameter publicKey) + public virtual void Verify(AsymmetricKeyParameter publicKey) { Verify(new Asn1VerifierFactoryProvider(publicKey)); } @@ -116,26 +115,57 @@ namespace Org.BouncyCastle.X509 /// <param name="verifierProvider">An appropriate provider for verifying the CRL's signature.</param> /// <returns>True if the signature is valid.</returns> /// <exception cref="Exception">If verifier provider is not appropriate or the CRL algorithm is invalid.</exception> - public virtual void Verify( - IVerifierFactoryProvider verifierProvider) + public virtual void Verify(IVerifierFactoryProvider verifierProvider) { CheckSignature(verifierProvider.CreateVerifierFactory(c.SignatureAlgorithm)); } - protected virtual void CheckSignature( - IVerifierFactory verifier) + /// <summary>Verify the CRL's alternative signature using a verifier created using the passed in + /// verifier provider.</summary> + /// <param name="verifierProvider">An appropriate provider for verifying the CRL's alternative signature. + /// </param> + /// <exception cref="Exception">If verifier provider is not appropriate or the CRL alternative signature + /// algorithm is invalid.</exception> + public virtual void VerifyAltSignature(IVerifierFactoryProvider verifierProvider) { - // TODO Compare IsAlgIDEqual in X509Certificate.CheckSignature - if (!c.SignatureAlgorithm.Equals(c.TbsCertList.Signature)) - throw new CrlException("Signature algorithm on CertificateList does not match TbsCertList."); + var tbsCertList = c.TbsCertList; + var extensions = tbsCertList.Extensions; + + AltSignatureAlgorithm altSigAlg = AltSignatureAlgorithm.FromExtensions(extensions); + AltSignatureValue altSigValue = AltSignatureValue.FromExtensions(extensions); + + var verifier = verifierProvider.CreateVerifierFactory(altSigAlg.Algorithm); + + Asn1Sequence tbsSeq = Asn1Sequence.GetInstance(tbsCertList.ToAsn1Object()); + Asn1EncodableVector v = new Asn1EncodableVector(); - IStreamCalculator<IVerifier> streamCalculator = verifier.CreateCalculator(); - using (var stream = streamCalculator.Stream) + int start = 1; // want to skip signature field + if (tbsSeq[0] is DerInteger derInteger) + { + v.Add(derInteger); + start++; + } + + for (int i = start; i < tbsSeq.Count - 1; i++) { - c.TbsCertList.EncodeTo(stream, Asn1Encodable.Der); - } + v.Add(tbsSeq[i]); + } + + v.Add(X509Utilities.TrimExtensions(0, extensions)); + + if (!X509Utilities.VerifySignature(verifier, new DerSequence(v), altSigValue.Signature)) + throw new InvalidKeyException("CRL alternative signature does not verify with supplied public key."); + } + + protected virtual void CheckSignature(IVerifierFactory verifier) + { + var tbsCertList = c.TbsCertList; + + // TODO Compare IsAlgIDEqual in X509Certificate.CheckSignature + if (!c.SignatureAlgorithm.Equals(tbsCertList.Signature)) + throw new CrlException("Signature algorithm on CertificateList does not match TbsCertList."); - if (!streamCalculator.GetResult().IsVerified(GetSignature())) + if (!X509Utilities.VerifySignature(verifier, tbsCertList, c.Signature)) throw new InvalidKeyException("CRL does not verify with supplied public key."); } diff --git a/crypto/src/x509/X509Utilities.cs b/crypto/src/x509/X509Utilities.cs index 30ca0b080..bb9b7155f 100644 --- a/crypto/src/x509/X509Utilities.cs +++ b/crypto/src/x509/X509Utilities.cs @@ -9,6 +9,7 @@ using Org.BouncyCastle.Asn1.Pkcs; using Org.BouncyCastle.Asn1.TeleTrust; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Utilities.Collections; namespace Org.BouncyCastle.X509 @@ -159,5 +160,45 @@ namespace Org.BouncyCastle.X509 { return CollectionUtilities.Proxy(m_algorithms.Keys); } - } + + internal static DerBitString GenerateSignature(ISignatureFactory signatureFactory, Asn1Encodable asn1Encodable) + { + var result = CalculateResult(signatureFactory.CreateCalculator(), asn1Encodable); + return new DerBitString(result.Collect()); + } + + internal static bool VerifySignature(IVerifierFactory verifierFactory, Asn1Encodable asn1Encodable, + DerBitString signature) + { + var result = CalculateResult(verifierFactory.CreateCalculator(), asn1Encodable); + return result.IsVerified(signature.GetOctets()); + } + + internal static Asn1TaggedObject TrimExtensions(int tagNo, X509Extensions exts) + { + Asn1Sequence extSeq = Asn1Sequence.GetInstance(exts.ToAsn1Object()); + Asn1EncodableVector extV = new Asn1EncodableVector(); + foreach (var extEntry in extSeq) + { + Asn1Sequence ext = Asn1Sequence.GetInstance(extEntry); + + if (!X509Extensions.AltSignatureValue.Equals(ext[0])) + { + extV.Add(ext); + } + } + + return new DerTaggedObject(true, tagNo, new DerSequence(extV)); + } + + private static TResult CalculateResult<TResult>(IStreamCalculator<TResult> streamCalculator, + Asn1Encodable asn1Encodable) + { + using (var stream = streamCalculator.Stream) + { + asn1Encodable.EncodeTo(stream, Asn1Encodable.Der); + } + return streamCalculator.GetResult(); + } + } } diff --git a/crypto/src/x509/X509V2AttributeCertificate.cs b/crypto/src/x509/X509V2AttributeCertificate.cs index 836213fdc..963f1ea4f 100644 --- a/crypto/src/x509/X509V2AttributeCertificate.cs +++ b/crypto/src/x509/X509V2AttributeCertificate.cs @@ -161,8 +161,7 @@ namespace Org.BouncyCastle.X509 return cert.GetSignatureOctets(); } - public virtual void Verify( - AsymmetricKeyParameter key) + public virtual void Verify(AsymmetricKeyParameter key) { CheckSignature(new Asn1VerifierFactory(cert.SignatureAlgorithm, key)); } @@ -173,34 +172,20 @@ namespace Org.BouncyCastle.X509 /// <param name="verifierProvider">An appropriate provider for verifying the certificate's signature.</param> /// <returns>True if the signature is valid.</returns> /// <exception cref="Exception">If verifier provider is not appropriate or the certificate algorithm is invalid.</exception> - public virtual void Verify( - IVerifierFactoryProvider verifierProvider) + public virtual void Verify(IVerifierFactoryProvider verifierProvider) { CheckSignature(verifierProvider.CreateVerifierFactory(cert.SignatureAlgorithm)); } - protected virtual void CheckSignature( - IVerifierFactory verifier) + protected virtual void CheckSignature(IVerifierFactory verifier) { + var acInfo = cert.ACInfo; + // TODO Compare IsAlgIDEqual in X509Certificate.CheckSignature - if (!cert.SignatureAlgorithm.Equals(cert.ACInfo.Signature)) + if (!cert.SignatureAlgorithm.Equals(acInfo.Signature)) throw new CertificateException("Signature algorithm in certificate info not same as outer certificate"); - IStreamCalculator<IVerifier> streamCalculator = verifier.CreateCalculator(); - - try - { - using (var stream = streamCalculator.Stream) - { - cert.ACInfo.EncodeTo(stream); - } - } - catch (IOException e) - { - throw new SignatureException("Exception encoding certificate info object", e); - } - - if (!streamCalculator.GetResult().IsVerified(GetSignature())) + if (!X509Utilities.VerifySignature(verifier, acInfo, cert.SignatureValue)) throw new InvalidKeyException("Public key presented not for certificate signature"); } diff --git a/crypto/src/x509/X509V2AttributeCertificateGenerator.cs b/crypto/src/x509/X509V2AttributeCertificateGenerator.cs index f1f4c0473..bbb246273 100644 --- a/crypto/src/x509/X509V2AttributeCertificateGenerator.cs +++ b/crypto/src/x509/X509V2AttributeCertificateGenerator.cs @@ -117,24 +117,17 @@ namespace Org.BouncyCastle.X509 acInfoGen.SetExtensions(extGenerator.Generate()); } - AttributeCertificateInfo acInfo = acInfoGen.GenerateAttributeCertificateInfo(); + var acInfo = acInfoGen.GenerateAttributeCertificateInfo(); - IStreamCalculator<IBlockResult> streamCalculator = signatureFactory.CreateCalculator(); - using (var sigStream = streamCalculator.Stream) - { - acInfo.EncodeTo(sigStream, Asn1Encodable.Der); - } - - var signature = streamCalculator.GetResult().Collect(); + var signature = X509Utilities.GenerateSignature(signatureFactory, acInfo); - return new X509V2AttributeCertificate( - new AttributeCertificate(acInfo, sigAlgID, new DerBitString(signature))); + return new X509V2AttributeCertificate(new AttributeCertificate(acInfo, sigAlgID, signature)); } - /// <summary> - /// Allows enumeration of the signature names supported by the generator. - /// </summary> - public IEnumerable<string> SignatureAlgNames + /// <summary> + /// Allows enumeration of the signature names supported by the generator. + /// </summary> + public IEnumerable<string> SignatureAlgNames { get { return X509Utilities.GetAlgNames(); } } diff --git a/crypto/src/x509/X509V2CRLGenerator.cs b/crypto/src/x509/X509V2CRLGenerator.cs index d7c72d673..358dc63de 100644 --- a/crypto/src/x509/X509V2CRLGenerator.cs +++ b/crypto/src/x509/X509V2CRLGenerator.cs @@ -217,18 +217,38 @@ namespace Org.BouncyCastle.X509 tbsGen.SetExtensions(extGenerator.Generate()); } - TbsCertificateList tbsCertList = tbsGen.GenerateTbsCertList(); + var tbsCertList = tbsGen.GenerateTbsCertList(); - IStreamCalculator<IBlockResult> streamCalculator = signatureFactory.CreateCalculator(); - using (var sigStream = streamCalculator.Stream) - { - tbsCertList.EncodeTo(sigStream, Asn1Encodable.Der); - } + var signature = X509Utilities.GenerateSignature(signatureFactory, tbsCertList); + + return new X509Crl(CertificateList.GetInstance(new DerSequence(tbsCertList, sigAlgID, signature))); + } + + /// <summary> + /// Generate a new <see cref="X509Crl"/> using the provided <see cref="ISignatureFactory"/> and + /// containing altSignatureAlgorithm and altSignatureValue extensions based on the passed + /// <paramref name="altSignatureFactory"/>. + /// </summary> + /// <param name="signatureFactory">A <see cref="ISignatureFactory">signature factory</see> with the necessary + /// algorithm details.</param> + /// <param name="isCritical">Whether the 'alt' extensions should be marked critical.</param> + /// <param name="altSignatureFactory">A <see cref="ISignatureFactory">signature factory</see> used to create the + /// altSignatureAlgorithm and altSignatureValue extensions.</param> + /// <returns>An <see cref="X509Certificate"/>.</returns> + public X509Crl Generate(ISignatureFactory signatureFactory, bool isCritical, + ISignatureFactory altSignatureFactory) + { + tbsGen.SetSignature(null); + + var altSigAlgID = (AlgorithmIdentifier)altSignatureFactory.AlgorithmDetails; + extGenerator.AddExtension(X509Extensions.AltSignatureAlgorithm, isCritical, altSigAlgID); + + tbsGen.SetExtensions(extGenerator.Generate()); - var signature = streamCalculator.GetResult().Collect(); + var altSignature = X509Utilities.GenerateSignature(altSignatureFactory, tbsGen.GeneratePreTbsCertList()); + extGenerator.AddExtension(X509Extensions.AltSignatureValue, isCritical, altSignature); - return new X509Crl( - CertificateList.GetInstance(new DerSequence(tbsCertList, sigAlgID, new DerBitString(signature)))); + return Generate(signatureFactory); } /// <summary> diff --git a/crypto/src/x509/X509V3CertificateGenerator.cs b/crypto/src/x509/X509V3CertificateGenerator.cs index d5c9ffe92..65e3c9177 100644 --- a/crypto/src/x509/X509V3CertificateGenerator.cs +++ b/crypto/src/x509/X509V3CertificateGenerator.cs @@ -290,17 +290,38 @@ namespace Org.BouncyCastle.X509 tbsGen.SetExtensions(extGenerator.Generate()); } - TbsCertificateStructure tbsCert = tbsGen.GenerateTbsCertificate(); + var tbsCertificate = tbsGen.GenerateTbsCertificate(); - IStreamCalculator<IBlockResult> streamCalculator = signatureFactory.CreateCalculator(); - using (var sigStream = streamCalculator.Stream) - { - tbsCert.EncodeTo(sigStream, Asn1Encodable.Der); - } + var signature = X509Utilities.GenerateSignature(signatureFactory, tbsCertificate); + + return new X509Certificate(new X509CertificateStructure(tbsCertificate, sigAlgID, signature)); + } + + /// <summary> + /// Generate a new <see cref="X509Certificate"/> using the provided <see cref="ISignatureFactory"/> and + /// containing altSignatureAlgorithm and altSignatureValue extensions based on the passed + /// <paramref name="altSignatureFactory"/>. + /// </summary> + /// <param name="signatureFactory">A <see cref="ISignatureFactory">signature factory</see> with the necessary + /// algorithm details.</param> + /// <param name="isCritical">Whether the 'alt' extensions should be marked critical.</param> + /// <param name="altSignatureFactory">A <see cref="ISignatureFactory">signature factory</see> used to create the + /// altSignatureAlgorithm and altSignatureValue extensions.</param> + /// <returns>An <see cref="X509Certificate"/>.</returns> + public X509Certificate Generate(ISignatureFactory signatureFactory, bool isCritical, + ISignatureFactory altSignatureFactory) + { + tbsGen.SetSignature(null); + + var altSigAlgID = (AlgorithmIdentifier)altSignatureFactory.AlgorithmDetails; + extGenerator.AddExtension(X509Extensions.AltSignatureAlgorithm, isCritical, altSigAlgID); + + tbsGen.SetExtensions(extGenerator.Generate()); - var signature = streamCalculator.GetResult().Collect(); + var altSignature = X509Utilities.GenerateSignature(altSignatureFactory, tbsGen.GeneratePreTbsCertificate()); + extGenerator.AddExtension(X509Extensions.AltSignatureValue, isCritical, altSignature); - return new X509Certificate(new X509CertificateStructure(tbsCert, sigAlgID, new DerBitString(signature))); + return Generate(signatureFactory); } /// <summary> |