From fe161d043699655430af72f77d50c4924d764662 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 1 Jul 2024 16:58:53 +0700 Subject: Refactoring in Asn1.Sec --- crypto/src/asn1/sec/ECPrivateKeyStructure.cs | 103 ++++++++++----------- .../src/crypto/util/OpenSshPrivateKeyUtilities.cs | 2 +- crypto/src/openssl/PEMReader.cs | 4 +- crypto/test/src/tls/test/TlsTestUtilities.cs | 3 +- 4 files changed, 51 insertions(+), 61 deletions(-) diff --git a/crypto/src/asn1/sec/ECPrivateKeyStructure.cs b/crypto/src/asn1/sec/ECPrivateKeyStructure.cs index 298a0ba79..193d40a29 100644 --- a/crypto/src/asn1/sec/ECPrivateKeyStructure.cs +++ b/crypto/src/asn1/sec/ECPrivateKeyStructure.cs @@ -11,8 +11,6 @@ namespace Org.BouncyCastle.Asn1.Sec public class ECPrivateKeyStructure : Asn1Encodable { - private readonly Asn1Sequence m_seq; - public static ECPrivateKeyStructure GetInstance(object obj) { if (obj == null) @@ -22,85 +20,74 @@ namespace Org.BouncyCastle.Asn1.Sec return new ECPrivateKeyStructure(Asn1Sequence.GetInstance(obj)); } + public static ECPrivateKeyStructure GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) => + new ECPrivateKeyStructure(Asn1Sequence.GetInstance(taggedObject, declaredExplicit)); + + public static ECPrivateKeyStructure GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) => + new ECPrivateKeyStructure(Asn1Sequence.GetTagged(taggedObject, declaredExplicit)); + + private readonly DerInteger m_version; + private readonly Asn1OctetString m_privateKey; + private readonly Asn1Encodable m_parameters; + private readonly DerBitString m_publicKey; + private ECPrivateKeyStructure(Asn1Sequence seq) { - m_seq = seq ?? throw new ArgumentNullException(nameof(seq)); + int count = seq.Count, pos = 0; + if (count < 2 || count > 4) + throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); + + m_version = DerInteger.GetInstance(seq[pos++]); + m_privateKey = Asn1OctetString.GetInstance(seq[pos++]); + m_parameters = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, + (t, e) => t.GetExplicitBaseObject()); + m_publicKey = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, DerBitString.GetTagged); + + if (pos != count) + throw new ArgumentException("Unexpected elements in sequence", nameof(seq)); } - public ECPrivateKeyStructure( - int orderBitLength, - BigInteger key) + public ECPrivateKeyStructure(int orderBitLength, BigInteger key) : this(orderBitLength, key, null) { } - public ECPrivateKeyStructure( - int orderBitLength, - BigInteger key, - Asn1Encodable parameters) + public ECPrivateKeyStructure(int orderBitLength, BigInteger key, Asn1Encodable parameters) : this(orderBitLength, key, null, parameters) { } - public ECPrivateKeyStructure( - int orderBitLength, - BigInteger key, - DerBitString publicKey, - Asn1Encodable parameters) + public ECPrivateKeyStructure(int orderBitLength, BigInteger key, DerBitString publicKey, + Asn1Encodable parameters) { if (key == null) throw new ArgumentNullException(nameof(key)); if (orderBitLength < key.BitLength) throw new ArgumentException("must be >= key bitlength", nameof(orderBitLength)); - byte[] bytes = BigIntegers.AsUnsignedByteArray((orderBitLength + 7) / 8, key); + byte[] privateKeyContents = BigIntegers.AsUnsignedByteArray((orderBitLength + 7) / 8, key); - Asn1EncodableVector v = new Asn1EncodableVector( - DerInteger.One, - new DerOctetString(bytes)); + m_version = DerInteger.One; + m_privateKey = new DerOctetString(privateKeyContents); + m_parameters = parameters; + m_publicKey = publicKey; + } - v.AddOptionalTagged(true, 0, parameters); - v.AddOptionalTagged(true, 1, publicKey); + public DerInteger Version => m_version; - m_seq = new DerSequence(v); - } + public Asn1OctetString PrivateKey => m_privateKey; - public virtual BigInteger GetKey() - { - Asn1OctetString octs = (Asn1OctetString)m_seq[1]; + public Asn1Encodable Parameters => m_parameters; - return new BigInteger(1, octs.GetOctets()); - } + public DerBitString PublicKey => m_publicKey; - public virtual DerBitString GetPublicKey() - { - return (DerBitString)GetObjectInTag(1, Asn1Tags.BitString); - } + public virtual BigInteger GetKey() => BigIntegers.FromUnsignedByteArray(m_privateKey.GetOctets()); - public virtual Asn1Object GetParameters() - { - return GetObjectInTag(0, -1); - } + [Obsolete("Use 'PublicKey' instead")] + public virtual DerBitString GetPublicKey() => m_publicKey; - private Asn1Object GetObjectInTag(int tagNo, int baseTagNo) - { - foreach (Asn1Encodable ae in m_seq) - { - Asn1Object obj = ae.ToAsn1Object(); - - if (obj is Asn1TaggedObject tag) - { - if (tag.HasContextTag(tagNo)) - { - return baseTagNo < 0 - ? tag.GetExplicitBaseObject().ToAsn1Object() - : tag.GetBaseUniversal(true, baseTagNo); - } - } - } - - return null; - } + [Obsolete("Use 'Parameters' instead")] + public virtual Asn1Object GetParameters() => m_parameters?.ToAsn1Object(); /** * ECPrivateKey ::= SEQUENCE { @@ -111,7 +98,11 @@ namespace Org.BouncyCastle.Asn1.Sec */ public override Asn1Object ToAsn1Object() { - return m_seq; + Asn1EncodableVector v = new Asn1EncodableVector(4); + v.Add(m_version, m_privateKey); + v.AddOptionalTagged(true, 0, m_parameters); + v.AddOptionalTagged(true, 1, m_publicKey); + return new DerSequence(v); } } } diff --git a/crypto/src/crypto/util/OpenSshPrivateKeyUtilities.cs b/crypto/src/crypto/util/OpenSshPrivateKeyUtilities.cs index 164cea6e4..c322262fe 100644 --- a/crypto/src/crypto/util/OpenSshPrivateKeyUtilities.cs +++ b/crypto/src/crypto/util/OpenSshPrivateKeyUtilities.cs @@ -162,7 +162,7 @@ namespace Org.BouncyCastle.Crypto.Utilities if (sequence[3] is Asn1TaggedObject && sequence[2] is Asn1TaggedObject) { ECPrivateKeyStructure ecPrivateKey = ECPrivateKeyStructure.GetInstance(sequence); - DerObjectIdentifier curveOID = DerObjectIdentifier.GetInstance(ecPrivateKey.GetParameters()); + DerObjectIdentifier curveOID = DerObjectIdentifier.GetInstance(ecPrivateKey.Parameters); X9ECParameters x9Params = ECNamedCurveTable.GetByOid(curveOID); result = new ECPrivateKeyParameters( ecPrivateKey.GetKey(), diff --git a/crypto/src/openssl/PEMReader.cs b/crypto/src/openssl/PEMReader.cs index b963ed56a..bbe253f51 100644 --- a/crypto/src/openssl/PEMReader.cs +++ b/crypto/src/openssl/PEMReader.cs @@ -311,14 +311,14 @@ namespace Org.BouncyCastle.OpenSsl { ECPrivateKeyStructure pKey = ECPrivateKeyStructure.GetInstance(seq); AlgorithmIdentifier algId = new AlgorithmIdentifier( - X9ObjectIdentifiers.IdECPublicKey, pKey.GetParameters()); + X9ObjectIdentifiers.IdECPublicKey, pKey.Parameters); PrivateKeyInfo privInfo = new PrivateKeyInfo(algId, pKey.ToAsn1Object()); // TODO Are the keys returned here ECDSA, as Java version forces? privSpec = PrivateKeyFactory.CreateKey(privInfo); - DerBitString pubKey = pKey.GetPublicKey(); + DerBitString pubKey = pKey.PublicKey; if (pubKey != null) { SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo(algId, pubKey); diff --git a/crypto/test/src/tls/test/TlsTestUtilities.cs b/crypto/test/src/tls/test/TlsTestUtilities.cs index 72d09c808..b7ab5463d 100644 --- a/crypto/test/src/tls/test/TlsTestUtilities.cs +++ b/crypto/test/src/tls/test/TlsTestUtilities.cs @@ -362,8 +362,7 @@ namespace Org.BouncyCastle.Tls.Tests if (pem.Type.Equals("EC PRIVATE KEY")) { ECPrivateKeyStructure pKey = ECPrivateKeyStructure.GetInstance(pem.Content); - AlgorithmIdentifier algId = new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, - pKey.GetParameters()); + AlgorithmIdentifier algId = new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, pKey.Parameters); PrivateKeyInfo privInfo = new PrivateKeyInfo(algId, pKey); return PrivateKeyFactory.CreateKey(privInfo); } -- cgit 1.4.1