diff options
Diffstat (limited to 'crypto/src')
-rw-r--r-- | crypto/src/asn1/pkcs/PrivateKeyInfo.cs | 4 | ||||
-rw-r--r-- | crypto/src/asn1/sec/ECPrivateKeyStructure.cs | 58 | ||||
-rw-r--r-- | crypto/src/openssl/PEMReader.cs | 2 | ||||
-rw-r--r-- | crypto/src/pkcs/PrivateKeyInfoFactory.cs | 33 | ||||
-rw-r--r-- | crypto/src/security/PrivateKeyFactory.cs | 15 |
5 files changed, 83 insertions, 29 deletions
diff --git a/crypto/src/asn1/pkcs/PrivateKeyInfo.cs b/crypto/src/asn1/pkcs/PrivateKeyInfo.cs index 404277ba6..c5be7a315 100644 --- a/crypto/src/asn1/pkcs/PrivateKeyInfo.cs +++ b/crypto/src/asn1/pkcs/PrivateKeyInfo.cs @@ -29,14 +29,14 @@ namespace Org.BouncyCastle.Asn1.Pkcs return new PrivateKeyInfo(Asn1Sequence.GetInstance(obj)); } - public PrivateKeyInfo(AlgorithmIdentifier algID, Asn1Object privateKey) + public PrivateKeyInfo(AlgorithmIdentifier algID, Asn1Encodable privateKey) : this(algID, privateKey, null) { } public PrivateKeyInfo( AlgorithmIdentifier algID, - Asn1Object privateKey, + Asn1Encodable privateKey, Asn1Set attributes) { this.algID = algID; diff --git a/crypto/src/asn1/sec/ECPrivateKeyStructure.cs b/crypto/src/asn1/sec/ECPrivateKeyStructure.cs index 8d805fa30..32e020c0b 100644 --- a/crypto/src/asn1/sec/ECPrivateKeyStructure.cs +++ b/crypto/src/asn1/sec/ECPrivateKeyStructure.cs @@ -23,6 +23,7 @@ namespace Org.BouncyCastle.Asn1.Sec return new ECPrivateKeyStructure(Asn1Sequence.GetInstance(obj)); } + [Obsolete("Use 'GetInstance' instead")] public ECPrivateKeyStructure( Asn1Sequence seq) { @@ -32,6 +33,7 @@ namespace Org.BouncyCastle.Asn1.Sec this.seq = seq; } + [Obsolete("Use constructor which takes 'orderBitLength' instead, to guarantee correct encoding")] public ECPrivateKeyStructure( BigInteger key) { @@ -44,12 +46,30 @@ namespace Org.BouncyCastle.Asn1.Sec } public ECPrivateKeyStructure( + int orderBitLength, + BigInteger key) + { + if (key == null) + throw new ArgumentNullException("key"); + if (orderBitLength < key.BitLength) + throw new ArgumentException("must be >= key bitlength", "orderBitLength"); + + byte[] bytes = BigIntegers.AsUnsignedByteArray((orderBitLength + 7) / 8, key); + + this.seq = new DerSequence( + new DerInteger(1), + new DerOctetString(bytes)); + } + + [Obsolete("Use constructor which takes 'orderBitLength' instead, to guarantee correct encoding")] + public ECPrivateKeyStructure( BigInteger key, Asn1Encodable parameters) : this(key, null, parameters) { } + [Obsolete("Use constructor which takes 'orderBitLength' instead, to guarantee correct encoding")] public ECPrivateKeyStructure( BigInteger key, DerBitString publicKey, @@ -75,6 +95,44 @@ namespace Org.BouncyCastle.Asn1.Sec this.seq = new DerSequence(v); } + public ECPrivateKeyStructure( + int orderBitLength, + BigInteger key, + Asn1Encodable parameters) + : this(orderBitLength, key, null, parameters) + { + } + + public ECPrivateKeyStructure( + int orderBitLength, + BigInteger key, + DerBitString publicKey, + Asn1Encodable parameters) + { + if (key == null) + throw new ArgumentNullException("key"); + if (orderBitLength < key.BitLength) + throw new ArgumentException("must be >= key bitlength", "orderBitLength"); + + byte[] bytes = BigIntegers.AsUnsignedByteArray((orderBitLength + 7) / 8, key); + + Asn1EncodableVector v = new Asn1EncodableVector( + new DerInteger(1), + new DerOctetString(bytes)); + + 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]; diff --git a/crypto/src/openssl/PEMReader.cs b/crypto/src/openssl/PEMReader.cs index 987f4471c..9a5f99b1a 100644 --- a/crypto/src/openssl/PEMReader.cs +++ b/crypto/src/openssl/PEMReader.cs @@ -311,7 +311,7 @@ namespace Org.BouncyCastle.OpenSsl case "EC": { - ECPrivateKeyStructure pKey = new ECPrivateKeyStructure(seq); + ECPrivateKeyStructure pKey = ECPrivateKeyStructure.GetInstance(seq); AlgorithmIdentifier algId = new AlgorithmIdentifier( X9ObjectIdentifiers.IdECPublicKey, pKey.GetParameters()); diff --git a/crypto/src/pkcs/PrivateKeyInfoFactory.cs b/crypto/src/pkcs/PrivateKeyInfoFactory.cs index c6aab4884..aafc4c292 100644 --- a/crypto/src/pkcs/PrivateKeyInfoFactory.cs +++ b/crypto/src/pkcs/PrivateKeyInfoFactory.cs @@ -106,49 +106,46 @@ namespace Org.BouncyCastle.Pkcs if (key is ECPrivateKeyParameters) { - ECPrivateKeyParameters _key = (ECPrivateKeyParameters)key; + ECPrivateKeyParameters priv = (ECPrivateKeyParameters)key; + ECDomainParameters dp = priv.Parameters; + int orderBitLength = dp.N.BitLength; + AlgorithmIdentifier algID; ECPrivateKeyStructure ec; - if (_key.AlgorithmName == "ECGOST3410") + if (priv.AlgorithmName == "ECGOST3410") { - if (_key.PublicKeyParamSet == null) + if (priv.PublicKeyParamSet == null) throw Platform.CreateNotImplementedException("Not a CryptoPro parameter set"); Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters( - _key.PublicKeyParamSet, CryptoProObjectIdentifiers.GostR3411x94CryptoProParamSet); + priv.PublicKeyParamSet, CryptoProObjectIdentifiers.GostR3411x94CryptoProParamSet); - algID = new AlgorithmIdentifier( - CryptoProObjectIdentifiers.GostR3410x2001, - gostParams.ToAsn1Object()); + algID = new AlgorithmIdentifier(CryptoProObjectIdentifiers.GostR3410x2001, gostParams); // TODO Do we need to pass any parameters here? - ec = new ECPrivateKeyStructure(_key.D); + ec = new ECPrivateKeyStructure(orderBitLength, priv.D); } else { X962Parameters x962; - if (_key.PublicKeyParamSet == null) + if (priv.PublicKeyParamSet == null) { - ECDomainParameters kp = _key.Parameters; - X9ECParameters ecP = new X9ECParameters(kp.Curve, kp.G, kp.N, kp.H, kp.GetSeed()); - + X9ECParameters ecP = new X9ECParameters(dp.Curve, dp.G, dp.N, dp.H, dp.GetSeed()); x962 = new X962Parameters(ecP); } else { - x962 = new X962Parameters(_key.PublicKeyParamSet); + x962 = new X962Parameters(priv.PublicKeyParamSet); } - Asn1Object x962Object = x962.ToAsn1Object(); - // TODO Possible to pass the publicKey bitstring here? - ec = new ECPrivateKeyStructure(_key.D, x962Object); + ec = new ECPrivateKeyStructure(orderBitLength, priv.D, x962); - algID = new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, x962Object); + algID = new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, x962); } - return new PrivateKeyInfo(algID, ec.ToAsn1Object()); + return new PrivateKeyInfo(algID, ec); } if (key is Gost3410PrivateKeyParameters) diff --git a/crypto/src/security/PrivateKeyFactory.cs b/crypto/src/security/PrivateKeyFactory.cs index b9538b33d..8c2ecfdb0 100644 --- a/crypto/src/security/PrivateKeyFactory.cs +++ b/crypto/src/security/PrivateKeyFactory.cs @@ -117,8 +117,7 @@ namespace Org.BouncyCastle.Security x9 = new X9ECParameters((Asn1Sequence)para.Parameters); } - ECPrivateKeyStructure ec = new ECPrivateKeyStructure( - Asn1Sequence.GetInstance(keyInfo.ParsePrivateKey())); + ECPrivateKeyStructure ec = ECPrivateKeyStructure.GetInstance(keyInfo.ParsePrivateKey()); BigInteger d = ec.GetKey(); if (para.IsNamedCurve) @@ -134,24 +133,24 @@ namespace Org.BouncyCastle.Security Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters( Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object())); + ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet); + + if (ecP == null) + throw new ArgumentException("Unrecognized curve OID for GostR3410x2001 private key"); + 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); + ec = new ECPrivateKeyStructure(ecP.N.BitLength, ((DerInteger)privKey).Value); } else { ec = ECPrivateKeyStructure.GetInstance(privKey); } - ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet); - - if (ecP == null) - throw new ArgumentException("Unrecognized curve OID for GostR3410x2001 private key"); - return new ECPrivateKeyParameters("ECGOST3410", ec.GetKey(), gostParams.PublicKeyParamSet); } else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x94)) |