diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2019-08-04 14:59:54 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2019-08-04 14:59:54 +0700 |
commit | bbfa024697bd0ec381fc1a0507bd0dedc6696f63 (patch) | |
tree | b8a60695d573c661642f7e3d6636331408ce2f18 | |
parent | Improve caching behaviour for algorithms using endomorphisms (diff) | |
download | BouncyCastle.NET-ed25519-bbfa024697bd0ec381fc1a0507bd0dedc6696f63.tar.xz |
Refactoring in PublicKeyFactory
- add SubjectPublicKeyInfo.ParsePublicKey and use where applicable - validate GOST3410 public key lengths
-rw-r--r-- | crypto/src/asn1/x509/SubjectPublicKeyInfo.cs | 13 | ||||
-rw-r--r-- | crypto/src/security/PublicKeyFactory.cs | 113 | ||||
-rw-r--r-- | crypto/test/src/crypto/test/OAEPTest.cs | 2 |
3 files changed, 73 insertions, 55 deletions
diff --git a/crypto/src/asn1/x509/SubjectPublicKeyInfo.cs b/crypto/src/asn1/x509/SubjectPublicKeyInfo.cs index 477329b7e..ae44a451f 100644 --- a/crypto/src/asn1/x509/SubjectPublicKeyInfo.cs +++ b/crypto/src/asn1/x509/SubjectPublicKeyInfo.cs @@ -66,6 +66,18 @@ namespace Org.BouncyCastle.Asn1.X509 get { return algID; } } + /** + * for when the public key is an encoded object - if the bitstring + * can't be decoded this routine raises an IOException. + * + * @exception IOException - if the bit string doesn't represent a Der + * encoded object. + */ + public Asn1Object ParsePublicKey() + { + return Asn1Object.FromByteArray(keyData.GetOctets()); + } + /** * for when the public key is an encoded object - if the bitstring * can't be decoded this routine raises an IOException. @@ -73,6 +85,7 @@ namespace Org.BouncyCastle.Asn1.X509 * @exception IOException - if the bit string doesn't represent a Der * encoded object. */ + [Obsolete("Use 'ParsePublicKey' instead")] public Asn1Object GetPublicKey() { return Asn1Object.FromByteArray(keyData.GetOctets()); diff --git a/crypto/src/security/PublicKeyFactory.cs b/crypto/src/security/PublicKeyFactory.cs index 7a34d71df..7b19f1c0f 100644 --- a/crypto/src/security/PublicKeyFactory.cs +++ b/crypto/src/security/PublicKeyFactory.cs @@ -17,6 +17,7 @@ using Org.BouncyCastle.Crypto.Generators; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.Encoders; namespace Org.BouncyCastle.Security @@ -56,7 +57,7 @@ namespace Org.BouncyCastle.Security || algOid.Equals(PkcsObjectIdentifiers.IdRsaesOaep)) { RsaPublicKeyStructure pubKey = RsaPublicKeyStructure.GetInstance( - keyInfo.GetPublicKey()); + keyInfo.ParsePublicKey()); return new RsaKeyParameters(false, pubKey.Modulus, pubKey.PublicExponent); } @@ -64,7 +65,7 @@ namespace Org.BouncyCastle.Security { Asn1Sequence seq = Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()); - DHPublicKey dhPublicKey = DHPublicKey.GetInstance(keyInfo.GetPublicKey()); + DHPublicKey dhPublicKey = DHPublicKey.GetInstance(keyInfo.ParsePublicKey()); BigInteger y = dhPublicKey.Y.Value; @@ -101,7 +102,7 @@ namespace Org.BouncyCastle.Security { Asn1Sequence seq = Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()); - DerInteger derY = (DerInteger) keyInfo.GetPublicKey(); + DerInteger derY = (DerInteger)keyInfo.ParsePublicKey(); return ReadPkcsDHParam(algOid, derY.Value, seq); } @@ -109,7 +110,7 @@ namespace Org.BouncyCastle.Security { ElGamalParameter para = new ElGamalParameter( Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object())); - DerInteger derY = (DerInteger) keyInfo.GetPublicKey(); + DerInteger derY = (DerInteger)keyInfo.ParsePublicKey(); return new ElGamalPublicKeyParameters( derY.Value, @@ -118,7 +119,7 @@ namespace Org.BouncyCastle.Security else if (algOid.Equals(X9ObjectIdentifiers.IdDsa) || algOid.Equals(OiwObjectIdentifiers.DsaWithSha1)) { - DerInteger derY = (DerInteger) keyInfo.GetPublicKey(); + DerInteger derY = (DerInteger)keyInfo.ParsePublicKey(); Asn1Encodable ae = algID.Parameters; DsaParameters parameters = null; @@ -158,64 +159,57 @@ namespace Org.BouncyCastle.Security } else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x2001)) { - Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters( - (Asn1Sequence) algID.Parameters); + Gost3410PublicKeyAlgParameters gostParams = Gost3410PublicKeyAlgParameters.GetInstance(algID.Parameters); + DerObjectIdentifier publicKeyParamSet = gostParams.PublicKeyParamSet; + + ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(publicKeyParamSet); + if (ecP == null) + return null; Asn1OctetString key; try { - key = (Asn1OctetString) keyInfo.GetPublicKey(); + key = (Asn1OctetString)keyInfo.ParsePublicKey(); } - catch (IOException) + catch (IOException e) { - throw new ArgumentException("invalid info structure in GOST3410 public key"); + throw new ArgumentException("error recovering GOST3410_2001 public key", e); } - byte[] keyEnc = key.GetOctets(); - byte[] x = new byte[32]; - byte[] y = new byte[32]; + int fieldSize = 32; + int keySize = 2 * fieldSize; - for (int i = 0; i != y.Length; i++) - { - x[i] = keyEnc[32 - 1 - i]; - } + byte[] keyEnc = key.GetOctets(); + if (keyEnc.Length != keySize) + throw new ArgumentException("invalid length for GOST3410_2001 public key"); - for (int i = 0; i != x.Length; i++) + byte[] x9Encoding = new byte[1 + keySize]; + x9Encoding[0] = 0x04; + for (int i = 1; i <= fieldSize; ++i) { - y[i] = keyEnc[64 - 1 - i]; + x9Encoding[i] = keyEnc[fieldSize - i]; + x9Encoding[i + fieldSize] = keyEnc[keySize - i]; } - ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet); - - if (ecP == null) - return null; - - ECPoint q = ecP.Curve.CreatePoint(new BigInteger(1, x), new BigInteger(1, y)); + ECPoint q = ecP.Curve.DecodePoint(x9Encoding); - return new ECPublicKeyParameters("ECGOST3410", q, gostParams.PublicKeyParamSet); + return new ECPublicKeyParameters("ECGOST3410", q, publicKeyParamSet); } else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x94)) { - Gost3410PublicKeyAlgParameters algParams = new Gost3410PublicKeyAlgParameters( - (Asn1Sequence) algID.Parameters); + Gost3410PublicKeyAlgParameters algParams = Gost3410PublicKeyAlgParameters.GetInstance(algID.Parameters); - DerOctetString derY; + Asn1OctetString key; try { - derY = (DerOctetString) keyInfo.GetPublicKey(); + key = (Asn1OctetString)keyInfo.ParsePublicKey(); } - catch (IOException) + catch (IOException e) { - throw new ArgumentException("invalid info structure in GOST3410 public key"); + throw new ArgumentException("error recovering GOST3410_94 public key", e); } - byte[] keyEnc = derY.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 - } + byte[] keyBytes = Arrays.Reverse(key.GetOctets()); // was little endian BigInteger y = new BigInteger(1, keyBytes); @@ -236,21 +230,40 @@ namespace Org.BouncyCastle.Security else if (algOid.Equals(EdECObjectIdentifiers.id_Ed448)) { return new Ed448PublicKeyParameters(GetRawKey(keyInfo, Ed448PublicKeyParameters.KeySize), 0); - } else if ( - algOid.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256) || - algOid.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512)) + } + else if (algOid.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256) + || algOid.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512)) { + Gost3410PublicKeyAlgParameters gostParams = Gost3410PublicKeyAlgParameters.GetInstance(algID.Parameters); + DerObjectIdentifier publicKeyParamSet = gostParams.PublicKeyParamSet; - byte[] keyEnc = ((DerOctetString)Asn1Object.FromByteArray(keyInfo.PublicKeyData.GetOctets())).str; + ECGost3410Parameters ecDomainParameters =new ECGost3410Parameters( + new ECNamedDomainParameters(publicKeyParamSet, ECGost3410NamedCurves.GetByOid(publicKeyParamSet)), + publicKeyParamSet, + gostParams.DigestParamSet, + gostParams.EncryptionParamSet); + + Asn1OctetString key; + try + { + key = (Asn1OctetString)keyInfo.ParsePublicKey(); + } + catch (IOException e) + { + throw new ArgumentException("error recovering GOST3410_2012 public key", e); + } int fieldSize = 32; if (algOid.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512)) { fieldSize = 64; } - int keySize = 2 * fieldSize; + byte[] keyEnc = key.GetOctets(); + if (keyEnc.Length != keySize) + throw new ArgumentException("invalid length for GOST3410_2012 public key"); + byte[] x9Encoding = new byte[1 + keySize]; x9Encoding[0] = 0x04; for (int i = 1; i <= fieldSize; ++i) @@ -259,17 +272,9 @@ namespace Org.BouncyCastle.Security x9Encoding[i + fieldSize] = keyEnc[keySize - i]; } - Gost3410PublicKeyAlgParameters gostParams = Gost3410PublicKeyAlgParameters.GetInstance(keyInfo.AlgorithmID.Parameters); - - ECGost3410Parameters ecDomainParameters = - new ECGost3410Parameters( - new ECNamedDomainParameters(gostParams.PublicKeyParamSet, ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet)), - gostParams.PublicKeyParamSet, - gostParams.DigestParamSet, - gostParams.EncryptionParamSet); - - return new ECPublicKeyParameters(ecDomainParameters.Curve.DecodePoint(x9Encoding), ecDomainParameters); + ECPoint q = ecDomainParameters.Curve.DecodePoint(x9Encoding); + return new ECPublicKeyParameters(q, ecDomainParameters); } else { diff --git a/crypto/test/src/crypto/test/OAEPTest.cs b/crypto/test/src/crypto/test/OAEPTest.cs index 204784cee..0d4374db1 100644 --- a/crypto/test/src/crypto/test/OAEPTest.cs +++ b/crypto/test/src/crypto/test/OAEPTest.cs @@ -310,7 +310,7 @@ namespace Org.BouncyCastle.Crypto.Tests // Asn1Object pubKeyObj = Asn1Object.FromByteArray(pubKeyEnc); RsaPublicKeyStructure pubStruct = RsaPublicKeyStructure.GetInstance( - SubjectPublicKeyInfo.GetInstance(pubKeyObj).GetPublicKey()); + SubjectPublicKeyInfo.GetInstance(pubKeyObj).ParsePublicKey()); // // extract the private key info. |