<PackageReference Include="BouncyCastle.Cryptography" Version="2.6.0" />

PublicKeyAndChallenge

For parsing the PublicKeyAndChallenge created by the KEYGEN tag included by Mozilla based browsers.
using Org.BouncyCastle.Asn1.X509; using System; namespace Org.BouncyCastle.Asn1.Mozilla { public class PublicKeyAndChallenge : Asn1Encodable { private readonly SubjectPublicKeyInfo m_spki; private readonly DerIA5String m_challenge; public DerIA5String Challenge => m_challenge; public SubjectPublicKeyInfo Spki => m_spki; [Obsolete("Use 'Spki' instead")] public SubjectPublicKeyInfo SubjectPublicKeyInfo { get { return m_spki; } } public static PublicKeyAndChallenge GetInstance(object obj) { if (obj == null) return null; PublicKeyAndChallenge publicKeyAndChallenge = obj as PublicKeyAndChallenge; if (publicKeyAndChallenge != null) return publicKeyAndChallenge; return new PublicKeyAndChallenge(Asn1Sequence.GetInstance(obj)); } public static PublicKeyAndChallenge GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) { return new PublicKeyAndChallenge(Asn1Sequence.GetInstance(taggedObject, declaredExplicit)); } public static PublicKeyAndChallenge GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) { return new PublicKeyAndChallenge(Asn1Sequence.GetTagged(taggedObject, declaredExplicit)); } public PublicKeyAndChallenge(SubjectPublicKeyInfo spki, DerIA5String challenge) { if (spki == null) throw new ArgumentNullException("spki"); m_spki = spki; if (challenge == null) throw new ArgumentNullException("m_challenge"); m_challenge = challenge; } [Obsolete("Use 'GetInstance' instead")] public PublicKeyAndChallenge(Asn1Sequence seq) { if (seq == null) throw new ArgumentNullException("seq"); if (seq.Count != 2) throw new ArgumentException($"""{seq.Count}", "seq"); m_spki = SubjectPublicKeyInfo.GetInstance(seq[0]); m_challenge = DerIA5String.GetInstance(seq[1]); } public override Asn1Object ToAsn1Object() { return new DerSequence(m_spki, m_challenge); } } }