diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2014-07-21 20:05:27 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2014-07-21 20:05:27 +0700 |
commit | 0c51033abe10b6a2b0035ea6bab8c471be6f45dc (patch) | |
tree | 8e48802b9c29d98996cf49b92726ec81ab0edcb2 /crypto | |
parent | Port of PrivateKeyInfo changes from Java (diff) | |
download | BouncyCastle.NET-ed25519-0c51033abe10b6a2b0035ea6bab8c471be6f45dc.tar.xz |
BMA-105
Support for parsing Gost3410x2001 private keys encoded as DER Integer Miscellaneous support methods ported from Java
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/src/asn1/sec/ECPrivateKeyStructure.cs | 226 | ||||
-rw-r--r-- | crypto/src/security/PrivateKeyFactory.cs | 27 | ||||
-rw-r--r-- | crypto/src/util/Arrays.cs | 16 |
3 files changed, 148 insertions, 121 deletions
diff --git a/crypto/src/asn1/sec/ECPrivateKeyStructure.cs b/crypto/src/asn1/sec/ECPrivateKeyStructure.cs index 2e9c27fd2..8d805fa30 100644 --- a/crypto/src/asn1/sec/ECPrivateKeyStructure.cs +++ b/crypto/src/asn1/sec/ECPrivateKeyStructure.cs @@ -6,113 +6,121 @@ using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Asn1.Sec { - /** - * the elliptic curve private key object from SEC 1 - */ - public class ECPrivateKeyStructure - : Asn1Encodable - { - private readonly Asn1Sequence seq; - - public ECPrivateKeyStructure( - Asn1Sequence seq) - { - if (seq == null) - throw new ArgumentNullException("seq"); - - this.seq = seq; - } - - public ECPrivateKeyStructure( - BigInteger key) - { - if (key == null) - throw new ArgumentNullException("key"); - - this.seq = new DerSequence( - new DerInteger(1), - new DerOctetString(key.ToByteArrayUnsigned())); - } - - public ECPrivateKeyStructure( - BigInteger key, - Asn1Encodable parameters) - : this(key, null, parameters) - { - } - - public ECPrivateKeyStructure( - BigInteger key, - DerBitString publicKey, - Asn1Encodable parameters) - { - if (key == null) - throw new ArgumentNullException("key"); - - Asn1EncodableVector v = new Asn1EncodableVector( - new DerInteger(1), - new DerOctetString(key.ToByteArrayUnsigned())); - - if (parameters != null) - { - v.Add(new DerTaggedObject(true, 0, parameters)); - } - - if (publicKey != null) - { - v.Add(new DerTaggedObject(true, 1, publicKey)); - } - - this.seq = new DerSequence(v); - } - - public BigInteger GetKey() - { - Asn1OctetString octs = (Asn1OctetString) seq[1]; - - return new BigInteger(1, octs.GetOctets()); - } - - public DerBitString GetPublicKey() - { - return (DerBitString) GetObjectInTag(1); - } - - public Asn1Object GetParameters() - { - return GetObjectInTag(0); - } - - private Asn1Object GetObjectInTag( - int tagNo) - { - foreach (Asn1Encodable ae in seq) - { - Asn1Object obj = ae.ToAsn1Object(); - - if (obj is Asn1TaggedObject) - { - Asn1TaggedObject tag = (Asn1TaggedObject) obj; - if (tag.TagNo == tagNo) - { - return tag.GetObject(); - } - } - } - - return null; - } - - /** - * ECPrivateKey ::= SEQUENCE { - * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), - * privateKey OCTET STRING, - * parameters [0] Parameters OPTIONAL, - * publicKey [1] BIT STRING OPTIONAL } - */ - public override Asn1Object ToAsn1Object() - { - return seq; - } - } + /** + * the elliptic curve private key object from SEC 1 + */ + public class ECPrivateKeyStructure + : Asn1Encodable + { + private readonly Asn1Sequence seq; + + public static ECPrivateKeyStructure GetInstance(object obj) + { + if (obj == null) + return null; + if (obj is ECPrivateKeyStructure) + return (ECPrivateKeyStructure)obj; + return new ECPrivateKeyStructure(Asn1Sequence.GetInstance(obj)); + } + + public ECPrivateKeyStructure( + Asn1Sequence seq) + { + if (seq == null) + throw new ArgumentNullException("seq"); + + this.seq = seq; + } + + public ECPrivateKeyStructure( + BigInteger key) + { + if (key == null) + throw new ArgumentNullException("key"); + + this.seq = new DerSequence( + new DerInteger(1), + new DerOctetString(key.ToByteArrayUnsigned())); + } + + public ECPrivateKeyStructure( + BigInteger key, + Asn1Encodable parameters) + : this(key, null, parameters) + { + } + + public ECPrivateKeyStructure( + BigInteger key, + DerBitString publicKey, + Asn1Encodable parameters) + { + if (key == null) + throw new ArgumentNullException("key"); + + Asn1EncodableVector v = new Asn1EncodableVector( + new DerInteger(1), + new DerOctetString(key.ToByteArrayUnsigned())); + + if (parameters != null) + { + v.Add(new DerTaggedObject(true, 0, parameters)); + } + + if (publicKey != null) + { + v.Add(new DerTaggedObject(true, 1, publicKey)); + } + + this.seq = new DerSequence(v); + } + + public virtual BigInteger GetKey() + { + Asn1OctetString octs = (Asn1OctetString) seq[1]; + + return new BigInteger(1, octs.GetOctets()); + } + + public virtual DerBitString GetPublicKey() + { + return (DerBitString) GetObjectInTag(1); + } + + public virtual Asn1Object GetParameters() + { + return GetObjectInTag(0); + } + + private Asn1Object GetObjectInTag(int tagNo) + { + foreach (Asn1Encodable ae in seq) + { + Asn1Object obj = ae.ToAsn1Object(); + + if (obj is Asn1TaggedObject) + { + Asn1TaggedObject tag = (Asn1TaggedObject) obj; + if (tag.TagNo == tagNo) + { + return tag.GetObject(); + } + } + } + + return null; + } + + /** + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] Parameters OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL } + */ + public override Asn1Object ToAsn1Object() + { + return seq; + } + } } diff --git a/crypto/src/security/PrivateKeyFactory.cs b/crypto/src/security/PrivateKeyFactory.cs index c346352f5..1cfa37afe 100644 --- a/crypto/src/security/PrivateKeyFactory.cs +++ b/crypto/src/security/PrivateKeyFactory.cs @@ -15,6 +15,7 @@ using Org.BouncyCastle.Crypto.Generators; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Pkcs; +using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Security { @@ -134,13 +135,23 @@ namespace Org.BouncyCastle.Security Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters( Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object())); - ECPrivateKeyStructure ec = new ECPrivateKeyStructure( - Asn1Sequence.GetInstance(keyInfo.ParsePrivateKey())); + Asn1Object privKey = keyInfo.ParsePrivateKey(); + ECPrivateKeyStructure ec; + + if (privKey is DerInteger) + { + // TODO Do we need to pass any parameters here? + ec = new ECPrivateKeyStructure(((DerInteger)privKey).Value); + } + else + { + ec = ECPrivateKeyStructure.GetInstance(privKey); + } ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet); if (ecP == null) - return null; + throw new ArgumentException("Unrecognized curve OID for GostR3410x2001 private key"); return new ECPrivateKeyParameters("ECGOST3410", ec.GetKey(), gostParams.PublicKeyParamSet); } @@ -150,15 +161,7 @@ namespace Org.BouncyCastle.Security Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object())); DerOctetString derX = (DerOctetString)keyInfo.ParsePrivateKey(); - byte[] keyEnc = derX.GetOctets(); - byte[] keyBytes = new byte[keyEnc.Length]; - - for (int i = 0; i != keyEnc.Length; i++) - { - keyBytes[i] = keyEnc[keyEnc.Length - 1 - i]; // was little endian - } - - BigInteger x = new BigInteger(1, keyBytes); + BigInteger x = new BigInteger(1, Arrays.Reverse(derX.GetOctets())); return new Gost3410PrivateKeyParameters(x, gostParams.PublicKeyParamSet); } diff --git a/crypto/src/util/Arrays.cs b/crypto/src/util/Arrays.cs index a21dd00b1..37da3940f 100644 --- a/crypto/src/util/Arrays.cs +++ b/crypto/src/util/Arrays.cs @@ -396,5 +396,21 @@ namespace Org.BouncyCastle.Utilities Array.Copy(b, 0, rv, a.Length, b.Length); return rv; } + + public static byte[] Reverse(byte[] a) + { + if (a == null) + return null; + + int p1 = 0, p2 = a.Length; + byte[] result = new byte[p2]; + + while (--p2 >= 0) + { + result[p2] = a[p1++]; + } + + return result; + } } } |