From 1356622fec93455ad92e2162f04de64363c0df40 Mon Sep 17 00:00:00 2001 From: Jozef Gajdos Date: Mon, 25 Mar 2024 13:52:16 +0100 Subject: Add SignedPublicKeyAndChallenge into Asn1/Mozilla. --- .../asn1/mozilla/SignedPublicKeyAndChallenge.cs | 138 +++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 crypto/src/asn1/mozilla/SignedPublicKeyAndChallenge.cs diff --git a/crypto/src/asn1/mozilla/SignedPublicKeyAndChallenge.cs b/crypto/src/asn1/mozilla/SignedPublicKeyAndChallenge.cs new file mode 100644 index 000000000..243cbefd6 --- /dev/null +++ b/crypto/src/asn1/mozilla/SignedPublicKeyAndChallenge.cs @@ -0,0 +1,138 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Operators; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Asn1.Mozilla +{ + /** + * This is designed to parse + * the SignedPublicKeyAndChallenge created by the KEYGEN tag included by + * Mozilla based browsers. + *
+     *
+     *  SignedPublicKeyAndChallenge ::= SEQUENCE {
+     *    publicKeyAndChallenge PublicKeyAndChallenge,
+     *    signatureAlgorithm AlgorithmIdentifier,
+     *    signature BIT STRING
+     *  }
+     *  
+ */ + internal class SignedPublicKeyAndChallenge : Asn1Encodable + { + private Asn1Sequence seq; + private PublicKeyAndChallenge publicKeyAndChallenge; + private AlgorithmIdentifier algorithmIdentifier; + private DerBitString signature; + + public PublicKeyAndChallenge PublicKeyAndChallenge + { + get { return publicKeyAndChallenge; } + } + + public AlgorithmIdentifier AlgorithmIdentifier + { + get { return algorithmIdentifier; } + } + + public DerBitString Signature + { + get { return signature; } + } + + public static SignedPublicKeyAndChallenge GetInstance(Asn1TaggedObject obj, bool explicitly) + { + return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); + } + + public static SignedPublicKeyAndChallenge GetInstance(object obj) + { + if (null == obj) + { + return null; + } + + if (obj is SignedPublicKeyAndChallenge value) + { + return value; + } + + if (obj is Asn1Sequence asn1Sequence) + { + return new SignedPublicKeyAndChallenge(asn1Sequence); + } + + throw new ArgumentException(string.Format("object of unexpected type provided, type=[{0}]", obj.GetType().FullName)); + } + + public SignedPublicKeyAndChallenge( + PublicKeyAndChallenge publicKeyAndChallenge, + AlgorithmIdentifier algorithmIdentifier, + DerBitString signature) + { + this.publicKeyAndChallenge = publicKeyAndChallenge; + this.algorithmIdentifier = algorithmIdentifier; + this.signature = signature; + } + + public SignedPublicKeyAndChallenge( + Asn1Sequence seq) + { + this.seq = seq; + + if (seq.Count != 3) + throw new FormatException($"Sequence contains {seq.Count} elements. Expected 3 elements"); + + this.publicKeyAndChallenge = PublicKeyAndChallenge.GetInstance(seq[0]); + this.algorithmIdentifier = AlgorithmIdentifier.GetInstance(seq[1]); + this.signature = DerBitString.GetInstance(seq[2]); + } + + public bool Verify() + { + AsymmetricKeyParameter publicKey = PublicKeyFactory.CreateKey(this.PublicKeyAndChallenge.SubjectPublicKeyInfo); + Asn1VerifierFactoryProvider factory = new Asn1VerifierFactoryProvider(publicKey); + IVerifierFactory verifier = factory.CreateVerifierFactory(this.AlgorithmIdentifier); + + try + { + byte[] derEncoded = this.PublicKeyAndChallenge.GetEncoded(); + IStreamCalculator streamCalculator = verifier.CreateCalculator(); + streamCalculator.Stream.Write(derEncoded, 0, derEncoded.Length); + streamCalculator.Stream.Dispose(); + + return streamCalculator.GetResult().IsVerified(this.Signature.GetOctets()); + } + catch (Exception exception) + { + throw new SignatureException("exception encoding SPKAC request", exception); + } + } + + public override Asn1Object ToAsn1Object() + { + if (null == this.seq) + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + if (null == this.PublicKeyAndChallenge) + throw new FormatException($"{nameof(this.PublicKeyAndChallenge)} can not be null"); + + if (null == this.AlgorithmIdentifier) + throw new FormatException($"{nameof(this.AlgorithmIdentifier)} can not be null"); + + if (null == this.Signature) + throw new FormatException($"{nameof(this.Signature)} can not be null"); + + v.Add(this.PublicKeyAndChallenge); + v.Add(this.AlgorithmIdentifier); + v.Add(this.Signature); + + this.seq = new DerSequence(v); + } + return this.seq; + } + } +} -- cgit 1.4.1