summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2024-07-01 16:58:53 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2024-07-01 16:58:53 +0700
commitfe161d043699655430af72f77d50c4924d764662 (patch)
tree03b3f654c0bccd0c498c322edee051de8da56cb5
parentRefactoring in Asn1.Oiw (diff)
downloadBouncyCastle.NET-ed25519-fe161d043699655430af72f77d50c4924d764662.tar.xz
Refactoring in Asn1.Sec
-rw-r--r--crypto/src/asn1/sec/ECPrivateKeyStructure.cs103
-rw-r--r--crypto/src/crypto/util/OpenSshPrivateKeyUtilities.cs2
-rw-r--r--crypto/src/openssl/PEMReader.cs4
-rw-r--r--crypto/test/src/tls/test/TlsTestUtilities.cs3
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);
             }