From fe659c4b342dcc1aaad7ad44481741bcfa0c2662 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sun, 14 Oct 2018 17:04:55 +0700 Subject: [PATCH 1/4] Move XDH/EdDSA key generation into low-level - Clamp X25519, X448 private keys during generation --- .../crypto/parameters/Ed25519PrivateKeyParameters.cs | 2 +- .../src/crypto/parameters/Ed448PrivateKeyParameters.cs | 2 +- .../crypto/parameters/X25519KeyGenerationParameters.cs | 2 +- .../crypto/parameters/X25519PrivateKeyParameters.cs | 2 +- .../src/crypto/parameters/X448PrivateKeyParameters.cs | 2 +- crypto/src/math/ec/rfc7748/X25519.cs | 10 ++++++++++ crypto/src/math/ec/rfc7748/X448.cs | 9 +++++++++ crypto/src/math/ec/rfc8032/Ed25519.cs | 6 ++++++ crypto/src/math/ec/rfc8032/Ed448.cs | 6 ++++++ 9 files changed, 36 insertions(+), 5 deletions(-) diff --git a/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs b/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs index 97902e093b..8046a0b1b6 100644 --- a/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs +++ b/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs @@ -19,7 +19,7 @@ public sealed class Ed25519PrivateKeyParameters public Ed25519PrivateKeyParameters(SecureRandom random) : base(true) { - random.NextBytes(data); + Ed25519.GeneratePrivateKey(random, data); } public Ed25519PrivateKeyParameters(byte[] buf, int off) diff --git a/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs b/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs index 74b5d63f32..f2fc4d5339 100644 --- a/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs +++ b/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs @@ -19,7 +19,7 @@ public sealed class Ed448PrivateKeyParameters public Ed448PrivateKeyParameters(SecureRandom random) : base(true) { - random.NextBytes(data); + Ed448.GeneratePrivateKey(random, data); } public Ed448PrivateKeyParameters(byte[] buf, int off) diff --git a/crypto/src/crypto/parameters/X25519KeyGenerationParameters.cs b/crypto/src/crypto/parameters/X25519KeyGenerationParameters.cs index 09972c7a23..d0bcffa94d 100644 --- a/crypto/src/crypto/parameters/X25519KeyGenerationParameters.cs +++ b/crypto/src/crypto/parameters/X25519KeyGenerationParameters.cs @@ -8,7 +8,7 @@ public class X25519KeyGenerationParameters : KeyGenerationParameters { public X25519KeyGenerationParameters(SecureRandom random) - : base(random, 256) + : base(random, 255) { } } diff --git a/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs b/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs index fb49a02b31..f7bbdac745 100644 --- a/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs +++ b/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs @@ -19,7 +19,7 @@ public sealed class X25519PrivateKeyParameters public X25519PrivateKeyParameters(SecureRandom random) : base(true) { - random.NextBytes(data); + X25519.GeneratePrivateKey(random, data); } public X25519PrivateKeyParameters(byte[] buf, int off) diff --git a/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs b/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs index d17aa79473..a073e57995 100644 --- a/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs +++ b/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs @@ -19,7 +19,7 @@ public sealed class X448PrivateKeyParameters public X448PrivateKeyParameters(SecureRandom random) : base(true) { - random.NextBytes(data); + X448.GeneratePrivateKey(random, data); } public X448PrivateKeyParameters(byte[] buf, int off) diff --git a/crypto/src/math/ec/rfc7748/X25519.cs b/crypto/src/math/ec/rfc7748/X25519.cs index d8db2527a9..8524b9e2c5 100644 --- a/crypto/src/math/ec/rfc7748/X25519.cs +++ b/crypto/src/math/ec/rfc7748/X25519.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; +using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Math.EC.Rfc7748 @@ -50,6 +51,15 @@ private static void DecodeScalar(byte[] k, int kOff, uint[] n) n[7] |= 0x40000000U; } + public static void GeneratePrivateKey(SecureRandom random, byte[] k) + { + random.NextBytes(k); + + k[0] &= 0xF8; + k[ScalarSize - 1] &= 0x7F; + k[ScalarSize - 1] |= 0x40; + } + private static void PointDouble(int[] x, int[] z) { int[] A = X25519Field.Create(); diff --git a/crypto/src/math/ec/rfc7748/X448.cs b/crypto/src/math/ec/rfc7748/X448.cs index 63d34d1cfd..63e5267030 100644 --- a/crypto/src/math/ec/rfc7748/X448.cs +++ b/crypto/src/math/ec/rfc7748/X448.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; +using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Math.EC.Rfc7748 @@ -52,6 +53,14 @@ private static void DecodeScalar(byte[] k, int kOff, uint[] n) n[13] |= 0x80000000U; } + public static void GeneratePrivateKey(SecureRandom random, byte[] k) + { + random.NextBytes(k); + + k[0] &= 0xFC; + k[ScalarSize - 1] |= 0x80; + } + private static void PointDouble(uint[] x, uint[] z) { uint[] A = X448Field.Create(); diff --git a/crypto/src/math/ec/rfc8032/Ed25519.cs b/crypto/src/math/ec/rfc8032/Ed25519.cs index 403f11f50d..b77853f30b 100644 --- a/crypto/src/math/ec/rfc8032/Ed25519.cs +++ b/crypto/src/math/ec/rfc8032/Ed25519.cs @@ -5,6 +5,7 @@ using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Math.EC.Rfc7748; using Org.BouncyCastle.Math.Raw; +using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Math.EC.Rfc8032 @@ -248,6 +249,11 @@ private static void EncodePoint(PointAccum p, byte[] r, int rOff) r[rOff + PointBytes - 1] |= (byte)((x[0] & 1) << 7); } + public static void GeneratePrivateKey(SecureRandom random, byte[] k) + { + random.NextBytes(k); + } + public static void GeneratePublicKey(byte[] sk, int skOff, byte[] pk, int pkOff) { IDigest d = CreateDigest(); diff --git a/crypto/src/math/ec/rfc8032/Ed448.cs b/crypto/src/math/ec/rfc8032/Ed448.cs index 10ebe8f15c..38bdee83ec 100644 --- a/crypto/src/math/ec/rfc8032/Ed448.cs +++ b/crypto/src/math/ec/rfc8032/Ed448.cs @@ -5,6 +5,7 @@ using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Math.EC.Rfc7748; using Org.BouncyCastle.Math.Raw; +using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Math.EC.Rfc8032 @@ -257,6 +258,11 @@ private static void EncodePoint(PointExt p, byte[] r, int rOff) r[rOff + PointBytes - 1] = (byte)((x[0] & 1) << 7); } + public static void GeneratePrivateKey(SecureRandom random, byte[] k) + { + random.NextBytes(k); + } + public static void GeneratePublicKey(byte[] sk, int skOff, byte[] pk, int pkOff) { IXof d = CreateXof(); From 94173c7f8b2d87b28353b7e9ee8d0f2514f02875 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sun, 14 Oct 2018 19:40:02 +0700 Subject: [PATCH 2/4] Port of CVC-ECDSA and PLAIN-ECDSA from Java --- crypto/BouncyCastle.Android.csproj | 5 + crypto/BouncyCastle.csproj | 5 + crypto/BouncyCastle.iOS.csproj | 5 + crypto/crypto.csproj | 25 ++ crypto/src/asn1/bsi/BsiObjectIdentifiers.cs | 103 +++++++ crypto/src/crypto/IDSA.cs | 1 + crypto/src/crypto/IDsaExt.cs | 17 ++ crypto/src/crypto/signers/DsaDigestSigner.cs | 89 +++--- crypto/src/crypto/signers/DsaSigner.cs | 7 +- crypto/src/crypto/signers/ECDsaSigner.cs | 7 +- crypto/src/crypto/signers/ECGOST3410Signer.cs | 7 +- crypto/src/crypto/signers/ECNRSigner.cs | 9 +- crypto/src/crypto/signers/GOST3410Signer.cs | 7 +- .../src/crypto/signers/HMacDsaKCalculator.cs | 7 +- crypto/src/crypto/signers/IDsaEncoding.cs | 25 ++ crypto/src/crypto/signers/PlainDsaEncoding.cs | 58 ++++ crypto/src/crypto/signers/SM2Signer.cs | 50 ++-- .../src/crypto/signers/StandardDsaEncoding.cs | 56 ++++ crypto/src/crypto/signers/X931Signer.cs | 3 +- crypto/src/security/DigestUtilities.cs | 2 + crypto/src/security/SignerUtilities.cs | 269 ++++++++++-------- crypto/src/util/Arrays.cs | 8 + crypto/src/util/BigIntegers.cs | 5 + 23 files changed, 559 insertions(+), 211 deletions(-) create mode 100644 crypto/src/asn1/bsi/BsiObjectIdentifiers.cs create mode 100644 crypto/src/crypto/IDsaExt.cs create mode 100644 crypto/src/crypto/signers/IDsaEncoding.cs create mode 100644 crypto/src/crypto/signers/PlainDsaEncoding.cs create mode 100644 crypto/src/crypto/signers/StandardDsaEncoding.cs diff --git a/crypto/BouncyCastle.Android.csproj b/crypto/BouncyCastle.Android.csproj index 677c6db04e..367bd7ff95 100644 --- a/crypto/BouncyCastle.Android.csproj +++ b/crypto/BouncyCastle.Android.csproj @@ -142,6 +142,7 @@ + @@ -651,6 +652,7 @@ + @@ -985,14 +987,17 @@ + + + diff --git a/crypto/BouncyCastle.csproj b/crypto/BouncyCastle.csproj index 1b9428c189..5dfdd35e5e 100644 --- a/crypto/BouncyCastle.csproj +++ b/crypto/BouncyCastle.csproj @@ -136,6 +136,7 @@ + @@ -645,6 +646,7 @@ + @@ -979,14 +981,17 @@ + + + diff --git a/crypto/BouncyCastle.iOS.csproj b/crypto/BouncyCastle.iOS.csproj index 2d36cb2230..3208fbce72 100644 --- a/crypto/BouncyCastle.iOS.csproj +++ b/crypto/BouncyCastle.iOS.csproj @@ -137,6 +137,7 @@ + @@ -646,6 +647,7 @@ + @@ -980,14 +982,17 @@ + + + diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index c6dd131e77..bada122a3c 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -568,6 +568,11 @@ SubType = "Code" BuildAction = "Compile" /> + + + + + See https://www.bsi.bund.de/cae/servlet/contentblob/471398/publicationFile/30615/BSI-TR-03111_pdf.pdf + public abstract class BsiObjectIdentifiers + { + public static readonly DerObjectIdentifier bsi_de = new DerObjectIdentifier("0.4.0.127.0.7"); + + /* 0.4.0.127.0.7.1.1 */ + public static readonly DerObjectIdentifier id_ecc = bsi_de.Branch("1.1"); + + /* 0.4.0.127.0.7.1.1.4.1 */ + public static readonly DerObjectIdentifier ecdsa_plain_signatures = id_ecc.Branch("4.1"); + + /* 0.4.0.127.0.7.1.1.4.1.1 */ + public static readonly DerObjectIdentifier ecdsa_plain_SHA1 = ecdsa_plain_signatures.Branch("1"); + + /* 0.4.0.127.0.7.1.1.4.1.2 */ + public static readonly DerObjectIdentifier ecdsa_plain_SHA224 = ecdsa_plain_signatures.Branch("2"); + + /* 0.4.0.127.0.7.1.1.4.1.3 */ + public static readonly DerObjectIdentifier ecdsa_plain_SHA256 = ecdsa_plain_signatures.Branch("3"); + + /* 0.4.0.127.0.7.1.1.4.1.4 */ + public static readonly DerObjectIdentifier ecdsa_plain_SHA384 = ecdsa_plain_signatures.Branch("4"); + + /* 0.4.0.127.0.7.1.1.4.1.5 */ + public static readonly DerObjectIdentifier ecdsa_plain_SHA512 = ecdsa_plain_signatures.Branch("5"); + + /* 0.4.0.127.0.7.1.1.4.1.6 */ + public static readonly DerObjectIdentifier ecdsa_plain_RIPEMD160 = ecdsa_plain_signatures.Branch("6"); + + /** 0.4.0.127.0.7.1 */ + public static readonly DerObjectIdentifier algorithm = bsi_de.Branch("1"); + + public static readonly DerObjectIdentifier ecka_eg = id_ecc.Branch("5.1"); + + /** ElGamal Elliptic Curve Key Agreement and Key Derivation according to X963 OID: 0.4.0.127.0.7.1.1.5.1.1 */ + public static readonly DerObjectIdentifier ecka_eg_X963kdf = ecka_eg.Branch("1"); + + /** ElGamal Elliptic Curve Key Agreement and Key Derivation according to X963 + * with hash function SHA-1 + * OID: 0.4.0.127.0.7.1.1.5.1.1.1 */ + public static readonly DerObjectIdentifier ecka_eg_X963kdf_SHA1 = ecka_eg_X963kdf.Branch("1"); + + /** ElGamal Elliptic Curve Key Agreement and Key Derivation according to X963 + * with hash function SHA224 + * OID: 0.4.0.127.0.7.1.1.5.1.1.2 */ + public static readonly DerObjectIdentifier ecka_eg_X963kdf_SHA224 = ecka_eg_X963kdf.Branch("2"); + + /** ElGamal Elliptic Curve Key Agreement and Key Derivation according to X963 + * with hash function SHA256 + * OID: 0.4.0.127.0.7.1.1.5.1.1.3 */ + public static readonly DerObjectIdentifier ecka_eg_X963kdf_SHA256 = ecka_eg_X963kdf.Branch("3"); + + /** ElGamal Elliptic Curve Key Agreement and Key Derivation according to X963 + * with hash function SHA384 + * OID: 0.4.0.127.0.7.1.1.5.1.1.4 */ + public static readonly DerObjectIdentifier ecka_eg_X963kdf_SHA384 = ecka_eg_X963kdf.Branch("4"); + + /** ElGamal Elliptic Curve Key Agreement and Key Derivation according to X963 + * with hash function SHA512 + * OID: 0.4.0.127.0.7.1.1.5.1.1.5 */ + public static readonly DerObjectIdentifier ecka_eg_X963kdf_SHA512 = ecka_eg_X963kdf.Branch("5"); + + /** ElGamal Elliptic Curve Key Agreement and Key Derivation according to X963 + * with hash function RIPEMD160 + * OID: 0.4.0.127.0.7.1.1.5.1.1.6 */ + public static readonly DerObjectIdentifier ecka_eg_X963kdf_RIPEMD160 = ecka_eg_X963kdf.Branch("6"); + + /** + * Key Derivation Function for Session Keys + */ + public static readonly DerObjectIdentifier ecka_eg_SessionKDF = ecka_eg.Branch("2"); + + public static readonly DerObjectIdentifier ecka_eg_SessionKDF_3DES = ecka_eg_SessionKDF.Branch("1"); + public static readonly DerObjectIdentifier ecka_eg_SessionKDF_AES128 = ecka_eg_SessionKDF.Branch("2"); + public static readonly DerObjectIdentifier ecka_eg_SessionKDF_AES192 = ecka_eg_SessionKDF.Branch("3"); + public static readonly DerObjectIdentifier ecka_eg_SessionKDF_AES256 = ecka_eg_SessionKDF.Branch("4"); + + /** AES encryption (CBC) and authentication (CMAC) + * OID: 0.4.0.127.0.7.1.x */ + //TODO: replace "1" with correct OID + //public static readonly DerObjectIdentifier aes_cbc_cmac = algorithm.Branch("1"); + + /** AES encryption (CBC) and authentication (CMAC) with 128 bit + * OID: 0.4.0.127.0.7.1.x.y1 */ + //TODO: replace "1" with correct OID + //public static readonly DerObjectIdentifier id_aes128_CBC_CMAC = aes_cbc_cmac.Branch("1"); + + + /** AES encryption (CBC) and authentication (CMAC) with 192 bit + * OID: 0.4.0.127.0.7.1.x.y2 */ + //TODO: replace "1" with correct OID + //public static readonly DerObjectIdentifier id_aes192_CBC_CMAC = aes_cbc_cmac.Branch("1"); + + /** AES encryption (CBC) and authentication (CMAC) with 256 bit + * OID: 0.4.0.127.0.7.1.x.y3 */ + //TODO: replace "1" with correct OID + //public static readonly DerObjectIdentifier id_aes256_CBC_CMAC = aes_cbc_cmac.Branch("1"); + } +} diff --git a/crypto/src/crypto/IDSA.cs b/crypto/src/crypto/IDSA.cs index 46056d8ca1..7d1fd51978 100644 --- a/crypto/src/crypto/IDSA.cs +++ b/crypto/src/crypto/IDSA.cs @@ -1,4 +1,5 @@ using System; + using Org.BouncyCastle.Math; namespace Org.BouncyCastle.Crypto diff --git a/crypto/src/crypto/IDsaExt.cs b/crypto/src/crypto/IDsaExt.cs new file mode 100644 index 0000000000..15b55787aa --- /dev/null +++ b/crypto/src/crypto/IDsaExt.cs @@ -0,0 +1,17 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto +{ + /// + /// An "extended" interface for classes implementing DSA-style algorithms, that provides access + /// to the group order. + /// + public interface IDsaExt + : IDsa + { + /// The order of the group that the r, s values in signatures belong to. + BigInteger Order { get; } + } +} diff --git a/crypto/src/crypto/signers/DsaDigestSigner.cs b/crypto/src/crypto/signers/DsaDigestSigner.cs index 0866014813..7fd8f535f9 100644 --- a/crypto/src/crypto/signers/DsaDigestSigner.cs +++ b/crypto/src/crypto/signers/DsaDigestSigner.cs @@ -1,10 +1,5 @@ using System; -using System.Collections; -using System.IO; -using System.Text; -using Org.BouncyCastle.Asn1; -using Org.BouncyCastle.Crypto.Signers; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; @@ -14,26 +9,38 @@ namespace Org.BouncyCastle.Crypto.Signers public class DsaDigestSigner : ISigner { - private readonly IDigest digest; - private readonly IDsa dsaSigner; - private bool forSigning; + private readonly IDsa dsa; + private readonly IDigest digest; + private readonly IDsaEncoding encoding; + private bool forSigning; public DsaDigestSigner( - IDsa signer, + IDsa dsa, IDigest digest) { - this.digest = digest; - this.dsaSigner = signer; + this.dsa = dsa; + this.digest = digest; + this.encoding = StandardDsaEncoding.Instance; } + public DsaDigestSigner( + IDsaExt dsa, + IDigest digest, + IDsaEncoding encoding) + { + this.dsa = dsa; + this.digest = digest; + this.encoding = encoding; + } + public virtual string AlgorithmName { - get { return digest.AlgorithmName + "with" + dsaSigner.AlgorithmName; } + get { return digest.AlgorithmName + "with" + dsa.AlgorithmName; } } public virtual void Init( - bool forSigning, - ICipherParameters parameters) + bool forSigning, + ICipherParameters parameters) { this.forSigning = forSigning; @@ -56,7 +63,7 @@ public virtual void Init( Reset(); - dsaSigner.Init(forSigning, parameters); + dsa.Init(forSigning, parameters); } /** @@ -91,9 +98,16 @@ public virtual byte[] GenerateSignature() byte[] hash = new byte[digest.GetDigestSize()]; digest.DoFinal(hash, 0); - BigInteger[] sig = dsaSigner.GenerateSignature(hash); + BigInteger[] sig = dsa.GenerateSignature(hash); - return DerEncode(sig[0], sig[1]); + try + { + return encoding.Encode(GetOrder(), sig[0], sig[1]); + } + catch (Exception) + { + throw new InvalidOperationException("unable to encode signature"); + } } /// true if the internal state represents the signature described in the passed in array. @@ -106,15 +120,16 @@ public virtual bool VerifySignature( byte[] hash = new byte[digest.GetDigestSize()]; digest.DoFinal(hash, 0); - try - { - BigInteger[] sig = DerDecode(signature); - return dsaSigner.VerifySignature(hash, sig[0], sig[1]); - } - catch (IOException) - { - return false; - } + try + { + BigInteger[] sig = encoding.Decode(GetOrder(), signature); + + return dsa.VerifySignature(hash, sig[0], sig[1]); + } + catch (Exception e) + { + return false; + } } /// Reset the internal state @@ -123,23 +138,9 @@ public virtual void Reset() digest.Reset(); } - private byte[] DerEncode( - BigInteger r, - BigInteger s) - { - return new DerSequence(new DerInteger(r), new DerInteger(s)).GetDerEncoded(); - } - - private BigInteger[] DerDecode( - byte[] encoding) - { - Asn1Sequence s = (Asn1Sequence) Asn1Object.FromByteArray(encoding); - - return new BigInteger[] - { - ((DerInteger) s[0]).Value, - ((DerInteger) s[1]).Value - }; - } + protected virtual BigInteger GetOrder() + { + return dsa is IDsaExt ? ((IDsaExt)dsa).Order : null; + } } } diff --git a/crypto/src/crypto/signers/DsaSigner.cs b/crypto/src/crypto/signers/DsaSigner.cs index bb28addfc7..32a33d0843 100644 --- a/crypto/src/crypto/signers/DsaSigner.cs +++ b/crypto/src/crypto/signers/DsaSigner.cs @@ -12,7 +12,7 @@ namespace Org.BouncyCastle.Crypto.Signers * Cryptography", pages 452 - 453. */ public class DsaSigner - : IDsa + : IDsaExt { protected readonly IDsaKCalculator kCalculator; @@ -72,6 +72,11 @@ public virtual void Init(bool forSigning, ICipherParameters parameters) this.random = InitSecureRandom(forSigning && !kCalculator.IsDeterministic, providedRandom); } + public virtual BigInteger Order + { + get { return key.Parameters.Q; } + } + /** * Generate a signature for the given message using the key we were * initialised with. For conventional DSA the message should be a SHA-1 diff --git a/crypto/src/crypto/signers/ECDsaSigner.cs b/crypto/src/crypto/signers/ECDsaSigner.cs index 520507b8cf..7b04d10762 100644 --- a/crypto/src/crypto/signers/ECDsaSigner.cs +++ b/crypto/src/crypto/signers/ECDsaSigner.cs @@ -13,7 +13,7 @@ namespace Org.BouncyCastle.Crypto.Signers * EC-DSA as described in X9.62 */ public class ECDsaSigner - : IDsa + : IDsaExt { private static readonly BigInteger Eight = BigInteger.ValueOf(8); @@ -75,6 +75,11 @@ public virtual void Init(bool forSigning, ICipherParameters parameters) this.random = InitSecureRandom(forSigning && !kCalculator.IsDeterministic, providedRandom); } + public virtual BigInteger Order + { + get { return key.Parameters.N; } + } + // 5.3 pg 28 /** * Generate a signature for the given message using the key we were diff --git a/crypto/src/crypto/signers/ECGOST3410Signer.cs b/crypto/src/crypto/signers/ECGOST3410Signer.cs index 28ab79c1cf..451cd3dd89 100644 --- a/crypto/src/crypto/signers/ECGOST3410Signer.cs +++ b/crypto/src/crypto/signers/ECGOST3410Signer.cs @@ -13,7 +13,7 @@ namespace Org.BouncyCastle.Crypto.Signers * GOST R 34.10-2001 Signature Algorithm */ public class ECGost3410Signer - : IDsa + : IDsaExt { private ECKeyParameters key; private SecureRandom random; @@ -55,6 +55,11 @@ public virtual void Init( } } + public virtual BigInteger Order + { + get { return key.Parameters.N; } + } + /** * generate a signature for the given message using the key we were * initialised with. For conventional GOST3410 the message should be a GOST3411 diff --git a/crypto/src/crypto/signers/ECNRSigner.cs b/crypto/src/crypto/signers/ECNRSigner.cs index bb21a49940..bc193e7974 100644 --- a/crypto/src/crypto/signers/ECNRSigner.cs +++ b/crypto/src/crypto/signers/ECNRSigner.cs @@ -13,7 +13,7 @@ namespace Org.BouncyCastle.Crypto.Signers * EC-NR as described in IEEE 1363-2000 */ public class ECNRSigner - : IDsa + : IDsaExt { private bool forSigning; private ECKeyParameters key; @@ -58,6 +58,11 @@ public virtual void Init( } } + public virtual BigInteger Order + { + get { return key.Parameters.N; } + } + // Section 7.2.5 ECSP-NR, pg 34 /** * generate a signature for the given message using the key we were @@ -77,7 +82,7 @@ public virtual BigInteger[] GenerateSignature( throw new InvalidOperationException("not initialised for signing"); } - BigInteger n = ((ECPrivateKeyParameters) this.key).Parameters.N; + BigInteger n = Order; int nBitLength = n.BitLength; BigInteger e = new BigInteger(1, message); diff --git a/crypto/src/crypto/signers/GOST3410Signer.cs b/crypto/src/crypto/signers/GOST3410Signer.cs index f1832ae37c..c5f3bd5ef5 100644 --- a/crypto/src/crypto/signers/GOST3410Signer.cs +++ b/crypto/src/crypto/signers/GOST3410Signer.cs @@ -10,7 +10,7 @@ namespace Org.BouncyCastle.Crypto.Signers * Gost R 34.10-94 Signature Algorithm */ public class Gost3410Signer - : IDsa + : IDsaExt { private Gost3410KeyParameters key; private SecureRandom random; @@ -52,6 +52,11 @@ public virtual void Init( } } + public virtual BigInteger Order + { + get { return key.Parameters.Q; } + } + /** * generate a signature for the given message using the key we were * initialised with. For conventional Gost3410 the message should be a Gost3411 diff --git a/crypto/src/crypto/signers/HMacDsaKCalculator.cs b/crypto/src/crypto/signers/HMacDsaKCalculator.cs index 8231197b91..05c4ae5c26 100644 --- a/crypto/src/crypto/signers/HMacDsaKCalculator.cs +++ b/crypto/src/crypto/signers/HMacDsaKCalculator.cs @@ -49,12 +49,13 @@ public void Init(BigInteger n, BigInteger d, byte[] message) Arrays.Fill(V, (byte)0x01); Arrays.Fill(K, (byte)0); - byte[] x = new byte[(n.BitLength + 7) / 8]; + int size = BigIntegers.GetUnsignedByteLength(n); + byte[] x = new byte[size]; byte[] dVal = BigIntegers.AsUnsignedByteArray(d); Array.Copy(dVal, 0, x, x.Length - dVal.Length, dVal.Length); - byte[] m = new byte[(n.BitLength + 7) / 8]; + byte[] m = new byte[size]; BigInteger mInt = BitsToInt(message); @@ -98,7 +99,7 @@ public void Init(BigInteger n, BigInteger d, byte[] message) public virtual BigInteger NextK() { - byte[] t = new byte[((n.BitLength + 7) / 8)]; + byte[] t = new byte[BigIntegers.GetUnsignedByteLength(n)]; for (;;) { diff --git a/crypto/src/crypto/signers/IDsaEncoding.cs b/crypto/src/crypto/signers/IDsaEncoding.cs new file mode 100644 index 0000000000..cccc4f937a --- /dev/null +++ b/crypto/src/crypto/signers/IDsaEncoding.cs @@ -0,0 +1,25 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Signers +{ + /// + /// An interface for different encoding formats for DSA signatures. + /// + public interface IDsaEncoding + { + /// Decode the (r, s) pair of a DSA signature. + /// The order of the group that r, s belong to. + /// An encoding of the (r, s) pair of a DSA signature. + /// The (r, s) of a DSA signature, stored in an array of exactly two elements, r followed by s. + BigInteger[] Decode(BigInteger n, byte[] encoding); + + /// Encode the (r, s) pair of a DSA signature. + /// The order of the group that r, s belong to. + /// The r value of a DSA signature. + /// The s value of a DSA signature. + /// An encoding of the DSA signature given by the provided (r, s) pair. + byte[] Encode(BigInteger n, BigInteger r, BigInteger s); + } +} diff --git a/crypto/src/crypto/signers/PlainDsaEncoding.cs b/crypto/src/crypto/signers/PlainDsaEncoding.cs new file mode 100644 index 0000000000..2e1f65a1fe --- /dev/null +++ b/crypto/src/crypto/signers/PlainDsaEncoding.cs @@ -0,0 +1,58 @@ +using System; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Signers +{ + public class PlainDsaEncoding + : IDsaEncoding + { + public static readonly PlainDsaEncoding Instance = new PlainDsaEncoding(); + + public virtual BigInteger[] Decode(BigInteger n, byte[] encoding) + { + int valueLength = BigIntegers.GetUnsignedByteLength(n); + if (encoding.Length != valueLength * 2) + throw new ArgumentException("Encoding has incorrect length", "encoding"); + + return new BigInteger[] { + DecodeValue(n, encoding, 0, valueLength), + DecodeValue(n, encoding, valueLength, valueLength), + }; + } + + public virtual byte[] Encode(BigInteger n, BigInteger r, BigInteger s) + { + int valueLength = BigIntegers.GetUnsignedByteLength(n); + byte[] result = new byte[valueLength * 2]; + EncodeValue(n, r, result, 0, valueLength); + EncodeValue(n, s, result, valueLength, valueLength); + return result; + } + + protected virtual BigInteger CheckValue(BigInteger n, BigInteger x) + { + if (x.SignValue < 0 || x.CompareTo(n) >= 0) + throw new ArgumentException("Value out of range", "x"); + + return x; + } + + protected virtual BigInteger DecodeValue(BigInteger n, byte[] buf, int off, int len) + { + return CheckValue(n, new BigInteger(1, buf, off, len)); + } + + protected virtual void EncodeValue(BigInteger n, BigInteger x, byte[] buf, int off, int len) + { + byte[] bs = CheckValue(n, x).ToByteArrayUnsigned(); + int bsOff = System.Math.Max(0, bs.Length - len); + int bsLen = bs.Length - bsOff; + + int pos = len - bsLen; + Arrays.Fill(buf, off, off + pos, 0); + Array.Copy(bs, bsOff, buf, off + pos, bsLen); + } + } +} diff --git a/crypto/src/crypto/signers/SM2Signer.cs b/crypto/src/crypto/signers/SM2Signer.cs index 8151e6be07..d9ec205256 100644 --- a/crypto/src/crypto/signers/SM2Signer.cs +++ b/crypto/src/crypto/signers/SM2Signer.cs @@ -1,15 +1,11 @@ using System; -using System.IO; -using Org.BouncyCastle.Asn1; -using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Math.EC; using Org.BouncyCastle.Math.EC.Multiplier; using Org.BouncyCastle.Security; -using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.Encoders; namespace Org.BouncyCastle.Crypto.Signers @@ -20,12 +16,23 @@ public class SM2Signer { private readonly IDsaKCalculator kCalculator = new RandomDsaKCalculator(); private readonly SM3Digest digest = new SM3Digest(); + private readonly IDsaEncoding encoding; private ECDomainParameters ecParams; private ECPoint pubPoint; private ECKeyParameters ecKey; private byte[] z; + public SM2Signer() + { + this.encoding = StandardDsaEncoding.Instance; + } + + public SM2Signer(IDsaEncoding encoding) + { + this.encoding = encoding; + } + public virtual string AlgorithmName { get { return "SM2Sign"; } @@ -92,13 +99,11 @@ public virtual bool VerifySignature(byte[] signature) { try { - BigInteger[] rs = DerDecode(signature); - if (rs != null) - { - return VerifySignature(rs[0], rs[1]); - } + BigInteger[] rs = encoding.Decode(ecParams.N, signature); + + return VerifySignature(rs[0], rs[1]); } - catch (IOException e) + catch (Exception) { } @@ -154,9 +159,9 @@ public virtual byte[] GenerateSignature() // A7 try { - return DerEncode(r, s); + return encoding.Encode(ecParams.N, r, s); } - catch (IOException ex) + catch (Exception ex) { throw new CryptoException("unable to encode signature: " + ex.Message, ex); } @@ -233,26 +238,5 @@ protected virtual ECMultiplier CreateBasePointMultiplier() { return new FixedPointCombMultiplier(); } - - protected virtual BigInteger[] DerDecode(byte[] encoding) - { - Asn1Sequence seq = Asn1Sequence.GetInstance(Asn1Object.FromByteArray(encoding)); - if (seq.Count != 2) - return null; - - BigInteger r = DerInteger.GetInstance(seq[0]).Value; - BigInteger s = DerInteger.GetInstance(seq[1]).Value; - - byte[] expectedEncoding = DerEncode(r, s); - if (!Arrays.ConstantTimeAreEqual(expectedEncoding, encoding)) - return null; - - return new BigInteger[]{ r, s }; - } - - protected virtual byte[] DerEncode(BigInteger r, BigInteger s) - { - return new DerSequence(new DerInteger(r), new DerInteger(s)).GetEncoded(Asn1Encodable.Der); - } } } diff --git a/crypto/src/crypto/signers/StandardDsaEncoding.cs b/crypto/src/crypto/signers/StandardDsaEncoding.cs new file mode 100644 index 0000000000..75ac08411d --- /dev/null +++ b/crypto/src/crypto/signers/StandardDsaEncoding.cs @@ -0,0 +1,56 @@ +using System; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Signers +{ + public class StandardDsaEncoding + : IDsaEncoding + { + public static readonly StandardDsaEncoding Instance = new StandardDsaEncoding(); + + public virtual BigInteger[] Decode(BigInteger n, byte[] encoding) + { + Asn1Sequence seq = (Asn1Sequence)Asn1Object.FromByteArray(encoding); + if (seq.Count == 2) + { + BigInteger r = DecodeValue(n, seq, 0); + BigInteger s = DecodeValue(n, seq, 1); + + byte[] expectedEncoding = Encode(n, r, s); + if (Arrays.AreEqual(expectedEncoding, encoding)) + return new BigInteger[]{ r, s }; + } + + throw new ArgumentException("Malformed signature", "encoding"); + } + + public virtual byte[] Encode(BigInteger n, BigInteger r, BigInteger s) + { + return new DerSequence( + EncodeValue(n, r), + EncodeValue(n, s) + ).GetEncoded(Asn1Encodable.Der); + } + + protected virtual BigInteger CheckValue(BigInteger n, BigInteger x) + { + if (x.SignValue < 0 || (null != n && x.CompareTo(n) >= 0)) + throw new ArgumentException("Value out of range", "x"); + + return x; + } + + protected virtual BigInteger DecodeValue(BigInteger n, Asn1Sequence s, int pos) + { + return CheckValue(n, ((DerInteger)s[pos]).Value); + } + + protected virtual DerInteger EncodeValue(BigInteger n, BigInteger x) + { + return new DerInteger(CheckValue(n, x)); + } + } +} diff --git a/crypto/src/crypto/signers/X931Signer.cs b/crypto/src/crypto/signers/X931Signer.cs index c6e44bad82..6aeff87ad8 100644 --- a/crypto/src/crypto/signers/X931Signer.cs +++ b/crypto/src/crypto/signers/X931Signer.cs @@ -145,7 +145,8 @@ public virtual byte[] GenerateSignature() t = t.Min(kParam.Modulus.Subtract(t)); - return BigIntegers.AsUnsignedByteArray((kParam.Modulus.BitLength + 7) / 8, t); + int size = BigIntegers.GetUnsignedByteLength(kParam.Modulus); + return BigIntegers.AsUnsignedByteArray(size, t); } private void CreateSignatureBlock() diff --git a/crypto/src/security/DigestUtilities.cs b/crypto/src/security/DigestUtilities.cs index 445304196b..24a68f63da 100644 --- a/crypto/src/security/DigestUtilities.cs +++ b/crypto/src/security/DigestUtilities.cs @@ -31,6 +31,7 @@ private enum DigestAlgorithm { GOST3411_2012_256, GOST3411_2012_512, KECCAK_224, KECCAK_256, KECCAK_288, KECCAK_384, KECCAK_512, MD2, MD4, MD5, + NONE, RIPEMD128, RIPEMD160, RIPEMD256, RIPEMD320, SHA_1, SHA_224, SHA_256, SHA_384, SHA_512, SHA_512_224, SHA_512_256, @@ -222,6 +223,7 @@ public static IDigest GetDigest( case DigestAlgorithm.MD2: return new MD2Digest(); case DigestAlgorithm.MD4: return new MD4Digest(); case DigestAlgorithm.MD5: return new MD5Digest(); + case DigestAlgorithm.NONE: return new NullDigest(); case DigestAlgorithm.RIPEMD128: return new RipeMD128Digest(); case DigestAlgorithm.RIPEMD160: return new RipeMD160Digest(); case DigestAlgorithm.RIPEMD256: return new RipeMD256Digest(); diff --git a/crypto/src/security/SignerUtilities.cs b/crypto/src/security/SignerUtilities.cs index 6107bf8787..dc31ae4649 100644 --- a/crypto/src/security/SignerUtilities.cs +++ b/crypto/src/security/SignerUtilities.cs @@ -3,7 +3,9 @@ using System.IO; using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Bsi; using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.Eac; using Org.BouncyCastle.Asn1.EdEC; using Org.BouncyCastle.Asn1.Nist; using Org.BouncyCastle.Asn1.Oiw; @@ -222,6 +224,108 @@ static SignerUtilities() algorithms["RIPEMD160WITHECDSA"] = "RIPEMD160withECDSA"; algorithms[TeleTrusTObjectIdentifiers.ECSignWithRipeMD160.Id] = "RIPEMD160withECDSA"; + algorithms["NONEWITHCVC-ECDSA"] = "NONEwithCVC-ECDSA"; + algorithms["CVC-ECDSAWITHNONE"] = "NONEwithCVC-ECDSA"; + + algorithms["SHA1/CVC-ECDSA"] = "SHA-1withCVC-ECDSA"; + algorithms["SHA-1/CVC-ECDSA"] = "SHA-1withCVC-ECDSA"; + algorithms["CVC-ECDSAWITHSHA1"] = "SHA-1withCVC-ECDSA"; + algorithms["CVC-ECDSAWITHSHA-1"] = "SHA-1withCVC-ECDSA"; + algorithms["SHA1WITHCVC-ECDSA"] = "SHA-1withCVC-ECDSA"; + algorithms["SHA-1WITHCVC-ECDSA"] = "SHA-1withCVC-ECDSA"; + algorithms[EacObjectIdentifiers.id_TA_ECDSA_SHA_1.Id] = "SHA-1withCVC-ECDSA"; + + algorithms["SHA224/CVC-ECDSA"] = "SHA-224withCVC-ECDSA"; + algorithms["SHA-224/CVC-ECDSA"] = "SHA-224withCVC-ECDSA"; + algorithms["CVC-ECDSAWITHSHA224"] = "SHA-224withCVC-ECDSA"; + algorithms["CVC-ECDSAWITHSHA-224"] = "SHA-224withCVC-ECDSA"; + algorithms["SHA224WITHCVC-ECDSA"] = "SHA-224withCVC-ECDSA"; + algorithms["SHA-224WITHCVC-ECDSA"] = "SHA-224withCVC-ECDSA"; + algorithms[EacObjectIdentifiers.id_TA_ECDSA_SHA_224.Id] = "SHA-224withCVC-ECDSA"; + + algorithms["SHA256/CVC-ECDSA"] = "SHA-256withCVC-ECDSA"; + algorithms["SHA-256/CVC-ECDSA"] = "SHA-256withCVC-ECDSA"; + algorithms["CVC-ECDSAWITHSHA256"] = "SHA-256withCVC-ECDSA"; + algorithms["CVC-ECDSAWITHSHA-256"] = "SHA-256withCVC-ECDSA"; + algorithms["SHA256WITHCVC-ECDSA"] = "SHA-256withCVC-ECDSA"; + algorithms["SHA-256WITHCVC-ECDSA"] = "SHA-256withCVC-ECDSA"; + algorithms[EacObjectIdentifiers.id_TA_ECDSA_SHA_256.Id] = "SHA-256withCVC-ECDSA"; + + algorithms["SHA384/CVC-ECDSA"] = "SHA-384withCVC-ECDSA"; + algorithms["SHA-384/CVC-ECDSA"] = "SHA-384withCVC-ECDSA"; + algorithms["CVC-ECDSAWITHSHA384"] = "SHA-384withCVC-ECDSA"; + algorithms["CVC-ECDSAWITHSHA-384"] = "SHA-384withCVC-ECDSA"; + algorithms["SHA384WITHCVC-ECDSA"] = "SHA-384withCVC-ECDSA"; + algorithms["SHA-384WITHCVC-ECDSA"] = "SHA-384withCVC-ECDSA"; + algorithms[EacObjectIdentifiers.id_TA_ECDSA_SHA_384.Id] = "SHA-384withCVC-ECDSA"; + + algorithms["SHA512/CVC-ECDSA"] = "SHA-512withCVC-ECDSA"; + algorithms["SHA-512/CVC-ECDSA"] = "SHA-512withCVC-ECDSA"; + algorithms["CVC-ECDSAWITHSHA512"] = "SHA-512withCVC-ECDSA"; + algorithms["CVC-ECDSAWITHSHA-512"] = "SHA-512withCVC-ECDSA"; + algorithms["SHA512WITHCVC-ECDSA"] = "SHA-512withCVC-ECDSA"; + algorithms["SHA-512WITHCVC-ECDSA"] = "SHA-512withCVC-ECDSA"; + algorithms[EacObjectIdentifiers.id_TA_ECDSA_SHA_512.Id] = "SHA-512withCVC-ECDSA"; + + algorithms["NONEWITHPLAIN-ECDSA"] = "NONEwithPLAIN-ECDSA"; + algorithms["PLAIN-ECDSAWITHNONE"] = "NONEwithPLAIN-ECDSA"; + + algorithms["SHA1/PLAIN-ECDSA"] = "SHA-1withPLAIN-ECDSA"; + algorithms["SHA-1/PLAIN-ECDSA"] = "SHA-1withPLAIN-ECDSA"; + algorithms["PLAIN-ECDSAWITHSHA1"] = "SHA-1withPLAIN-ECDSA"; + algorithms["PLAIN-ECDSAWITHSHA-1"] = "SHA-1withPLAIN-ECDSA"; + algorithms["SHA1WITHPLAIN-ECDSA"] = "SHA-1withPLAIN-ECDSA"; + algorithms["SHA-1WITHPLAIN-ECDSA"] = "SHA-1withPLAIN-ECDSA"; + algorithms[BsiObjectIdentifiers.ecdsa_plain_SHA1.Id] = "SHA-1withPLAIN-ECDSA"; + + algorithms["SHA224/PLAIN-ECDSA"] = "SHA-224withPLAIN-ECDSA"; + algorithms["SHA-224/PLAIN-ECDSA"] = "SHA-224withPLAIN-ECDSA"; + algorithms["PLAIN-ECDSAWITHSHA224"] = "SHA-224withPLAIN-ECDSA"; + algorithms["PLAIN-ECDSAWITHSHA-224"] = "SHA-224withPLAIN-ECDSA"; + algorithms["SHA224WITHPLAIN-ECDSA"] = "SHA-224withPLAIN-ECDSA"; + algorithms["SHA-224WITHPLAIN-ECDSA"] = "SHA-224withPLAIN-ECDSA"; + algorithms[BsiObjectIdentifiers.ecdsa_plain_SHA224.Id] = "SHA-224withPLAIN-ECDSA"; + + algorithms["SHA256/PLAIN-ECDSA"] = "SHA-256withPLAIN-ECDSA"; + algorithms["SHA-256/PLAIN-ECDSA"] = "SHA-256withPLAIN-ECDSA"; + algorithms["PLAIN-ECDSAWITHSHA256"] = "SHA-256withPLAIN-ECDSA"; + algorithms["PLAIN-ECDSAWITHSHA-256"] = "SHA-256withPLAIN-ECDSA"; + algorithms["SHA256WITHPLAIN-ECDSA"] = "SHA-256withPLAIN-ECDSA"; + algorithms["SHA-256WITHPLAIN-ECDSA"] = "SHA-256withPLAIN-ECDSA"; + algorithms[BsiObjectIdentifiers.ecdsa_plain_SHA256.Id] = "SHA-256withPLAIN-ECDSA"; + + algorithms["SHA384/PLAIN-ECDSA"] = "SHA-384withPLAIN-ECDSA"; + algorithms["SHA-384/PLAIN-ECDSA"] = "SHA-384withPLAIN-ECDSA"; + algorithms["PLAIN-ECDSAWITHSHA384"] = "SHA-384withPLAIN-ECDSA"; + algorithms["PLAIN-ECDSAWITHSHA-384"] = "SHA-384withPLAIN-ECDSA"; + algorithms["SHA384WITHPLAIN-ECDSA"] = "SHA-384withPLAIN-ECDSA"; + algorithms["SHA-384WITHPLAIN-ECDSA"] = "SHA-384withPLAIN-ECDSA"; + algorithms[BsiObjectIdentifiers.ecdsa_plain_SHA384.Id] = "SHA-384withPLAIN-ECDSA"; + + algorithms["SHA512/PLAIN-ECDSA"] = "SHA-512withPLAIN-ECDSA"; + algorithms["SHA-512/PLAIN-ECDSA"] = "SHA-512withPLAIN-ECDSA"; + algorithms["PLAIN-ECDSAWITHSHA512"] = "SHA-512withPLAIN-ECDSA"; + algorithms["PLAIN-ECDSAWITHSHA-512"] = "SHA-512withPLAIN-ECDSA"; + algorithms["SHA512WITHPLAIN-ECDSA"] = "SHA-512withPLAIN-ECDSA"; + algorithms["SHA-512WITHPLAIN-ECDSA"] = "SHA-512withPLAIN-ECDSA"; + algorithms[BsiObjectIdentifiers.ecdsa_plain_SHA512.Id] = "SHA-512withPLAIN-ECDSA"; + + algorithms["RIPEMD160/PLAIN-ECDSA"] = "RIPEMD160withPLAIN-ECDSA"; + algorithms["PLAIN-ECDSAWITHRIPEMD160"] = "RIPEMD160withPLAIN-ECDSA"; + algorithms["RIPEMD160WITHPLAIN-ECDSA"] = "RIPEMD160withPLAIN-ECDSA"; + algorithms[BsiObjectIdentifiers.ecdsa_plain_RIPEMD160.Id] = "RIPEMD160withPLAIN-ECDSA"; + + algorithms["SHA1WITHECNR"] = "SHA-1withECNR"; + algorithms["SHA-1WITHECNR"] = "SHA-1withECNR"; + algorithms["SHA224WITHECNR"] = "SHA-224withECNR"; + algorithms["SHA-224WITHECNR"] = "SHA-224withECNR"; + algorithms["SHA256WITHECNR"] = "SHA-256withECNR"; + algorithms["SHA-256WITHECNR"] = "SHA-256withECNR"; + algorithms["SHA384WITHECNR"] = "SHA-384withECNR"; + algorithms["SHA-384WITHECNR"] = "SHA-384withECNR"; + algorithms["SHA512WITHECNR"] = "SHA-512withECNR"; + algorithms["SHA-512WITHECNR"] = "SHA-512withECNR"; + algorithms["GOST-3410"] = "GOST3410"; algorithms["GOST-3410-94"] = "GOST3410"; algorithms["GOST3411WITHGOST3410"] = "GOST3410"; @@ -268,6 +372,20 @@ static SignerUtilities() oids["SHA-256withECDSA"] = X9ObjectIdentifiers.ECDsaWithSha256; oids["SHA-384withECDSA"] = X9ObjectIdentifiers.ECDsaWithSha384; oids["SHA-512withECDSA"] = X9ObjectIdentifiers.ECDsaWithSha512; + oids["RIPEMD160withECDSA"] = TeleTrusTObjectIdentifiers.ECSignWithRipeMD160; + + oids["SHA-1withCVC-ECDSA"] = EacObjectIdentifiers.id_TA_ECDSA_SHA_1; + oids["SHA-224withCVC-ECDSA"] = EacObjectIdentifiers.id_TA_ECDSA_SHA_224; + oids["SHA-256withCVC-ECDSA"] = EacObjectIdentifiers.id_TA_ECDSA_SHA_256; + oids["SHA-384withCVC-ECDSA"] = EacObjectIdentifiers.id_TA_ECDSA_SHA_384; + oids["SHA-512withCVC-ECDSA"] = EacObjectIdentifiers.id_TA_ECDSA_SHA_512; + + oids["SHA-1withPLAIN-ECDSA"] = BsiObjectIdentifiers.ecdsa_plain_SHA1; + oids["SHA-224withPLAIN-ECDSA"] = BsiObjectIdentifiers.ecdsa_plain_SHA224; + oids["SHA-256withPLAIN-ECDSA"] = BsiObjectIdentifiers.ecdsa_plain_SHA256; + oids["SHA-384withPLAIN-ECDSA"] = BsiObjectIdentifiers.ecdsa_plain_SHA384; + oids["SHA-512withPLAIN-ECDSA"] = BsiObjectIdentifiers.ecdsa_plain_SHA512; + oids["RIPEMD160withPLAIN-ECDSA"] = BsiObjectIdentifiers.ecdsa_plain_RIPEMD160; oids["GOST3410"] = CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94; oids["ECGOST3410"] = CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001; @@ -399,49 +517,12 @@ public static ISigner GetSigner( { return (new RsaDigestSigner(new NullDigest(), (AlgorithmIdentifier)null)); } - if (mechanism.Equals("MD2withRSA")) - { - return (new RsaDigestSigner(new MD2Digest())); - } - if (mechanism.Equals("MD4withRSA")) - { - return (new RsaDigestSigner(new MD4Digest())); - } - if (mechanism.Equals("MD5withRSA")) - { - return (new RsaDigestSigner(new MD5Digest())); - } - if (mechanism.Equals("SHA-1withRSA")) - { - return (new RsaDigestSigner(new Sha1Digest())); - } - if (mechanism.Equals("SHA-224withRSA")) - { - return (new RsaDigestSigner(new Sha224Digest())); - } - if (mechanism.Equals("SHA-256withRSA")) - { - return (new RsaDigestSigner(new Sha256Digest())); - } - if (mechanism.Equals("SHA-384withRSA")) - { - return (new RsaDigestSigner(new Sha384Digest())); - } - if (mechanism.Equals("SHA-512withRSA")) - { - return (new RsaDigestSigner(new Sha512Digest())); - } - if (mechanism.Equals("RIPEMD128withRSA")) - { - return (new RsaDigestSigner(new RipeMD128Digest())); - } - if (mechanism.Equals("RIPEMD160withRSA")) - { - return (new RsaDigestSigner(new RipeMD160Digest())); - } - if (mechanism.Equals("RIPEMD256withRSA")) + + if (Platform.EndsWith(mechanism, "withRSA")) { - return (new RsaDigestSigner(new RipeMD256Digest())); + string digestName = mechanism.Substring(0, mechanism.LastIndexOf("with")); + IDigest digest = DigestUtilities.GetDigest(digestName); + return new RsaDigestSigner(digest); } if (mechanism.Equals("RAWRSASSA-PSS")) @@ -455,101 +536,41 @@ public static ISigner GetSigner( // to be used can be overridden by subsequent parameter settings. return (new PssSigner(new RsaBlindedEngine(), new Sha1Digest())); } - if (mechanism.Equals("SHA-1withRSAandMGF1")) - { - return (new PssSigner(new RsaBlindedEngine(), new Sha1Digest())); - } - if (mechanism.Equals("SHA-224withRSAandMGF1")) - { - return (new PssSigner(new RsaBlindedEngine(), new Sha224Digest())); - } - if (mechanism.Equals("SHA-256withRSAandMGF1")) - { - return (new PssSigner(new RsaBlindedEngine(), new Sha256Digest())); - } - if (mechanism.Equals("SHA-384withRSAandMGF1")) - { - return (new PssSigner(new RsaBlindedEngine(), new Sha384Digest())); - } - if (mechanism.Equals("SHA-512withRSAandMGF1")) - { - return (new PssSigner(new RsaBlindedEngine(), new Sha512Digest())); - } - if (mechanism.Equals("NONEwithDSA")) - { - return (new DsaDigestSigner(new DsaSigner(), new NullDigest())); - } - if (mechanism.Equals("SHA-1withDSA")) - { - return (new DsaDigestSigner(new DsaSigner(), new Sha1Digest())); - } - if (mechanism.Equals("SHA-224withDSA")) - { - return (new DsaDigestSigner(new DsaSigner(), new Sha224Digest())); - } - if (mechanism.Equals("SHA-256withDSA")) - { - return (new DsaDigestSigner(new DsaSigner(), new Sha256Digest())); - } - if (mechanism.Equals("SHA-384withDSA")) - { - return (new DsaDigestSigner(new DsaSigner(), new Sha384Digest())); - } - if (mechanism.Equals("SHA-512withDSA")) + if (Platform.EndsWith(mechanism, "withRSAandMGF1")) { - return (new DsaDigestSigner(new DsaSigner(), new Sha512Digest())); + string digestName = mechanism.Substring(0, mechanism.LastIndexOf("with")); + IDigest digest = DigestUtilities.GetDigest(digestName); + return new PssSigner(new RsaBlindedEngine(), digest); } - if (mechanism.Equals("NONEwithECDSA")) - { - return (new DsaDigestSigner(new ECDsaSigner(), new NullDigest())); - } - if (mechanism.Equals("SHA-1withECDSA")) + if (Platform.EndsWith(mechanism, "withDSA")) { - return (new DsaDigestSigner(new ECDsaSigner(), new Sha1Digest())); - } - if (mechanism.Equals("SHA-224withECDSA")) - { - return (new DsaDigestSigner(new ECDsaSigner(), new Sha224Digest())); - } - if (mechanism.Equals("SHA-256withECDSA")) - { - return (new DsaDigestSigner(new ECDsaSigner(), new Sha256Digest())); - } - if (mechanism.Equals("SHA-384withECDSA")) - { - return (new DsaDigestSigner(new ECDsaSigner(), new Sha384Digest())); - } - if (mechanism.Equals("SHA-512withECDSA")) - { - return (new DsaDigestSigner(new ECDsaSigner(), new Sha512Digest())); + string digestName = mechanism.Substring(0, mechanism.LastIndexOf("with")); + IDigest digest = DigestUtilities.GetDigest(digestName); + return new DsaDigestSigner(new DsaSigner(), digest); } - if (mechanism.Equals("RIPEMD160withECDSA")) + if (Platform.EndsWith(mechanism, "withECDSA")) { - return (new DsaDigestSigner(new ECDsaSigner(), new RipeMD160Digest())); + string digestName = mechanism.Substring(0, mechanism.LastIndexOf("with")); + IDigest digest = DigestUtilities.GetDigest(digestName); + return new DsaDigestSigner(new ECDsaSigner(), digest); } - if (mechanism.Equals("SHA1WITHECNR")) + if (Platform.EndsWith(mechanism, "withCVC-ECDSA") + || Platform.EndsWith(mechanism, "withPLAIN-ECDSA")) { - return (new DsaDigestSigner(new ECNRSigner(), new Sha1Digest())); + string digestName = mechanism.Substring(0, mechanism.LastIndexOf("with")); + IDigest digest = DigestUtilities.GetDigest(digestName); + return new DsaDigestSigner(new ECDsaSigner(), digest, PlainDsaEncoding.Instance); } - if (mechanism.Equals("SHA224WITHECNR")) - { - return (new DsaDigestSigner(new ECNRSigner(), new Sha224Digest())); - } - if (mechanism.Equals("SHA256WITHECNR")) - { - return (new DsaDigestSigner(new ECNRSigner(), new Sha256Digest())); - } - if (mechanism.Equals("SHA384WITHECNR")) - { - return (new DsaDigestSigner(new ECNRSigner(), new Sha384Digest())); - } - if (mechanism.Equals("SHA512WITHECNR")) + + if (Platform.EndsWith(mechanism, "withECNR")) { - return (new DsaDigestSigner(new ECNRSigner(), new Sha512Digest())); + string digestName = mechanism.Substring(0, mechanism.LastIndexOf("with")); + IDigest digest = DigestUtilities.GetDigest(digestName); + return new DsaDigestSigner(new ECNRSigner(), digest); } if (mechanism.Equals("GOST3410")) diff --git a/crypto/src/util/Arrays.cs b/crypto/src/util/Arrays.cs index a9a574dbf1..4a8c65e883 100644 --- a/crypto/src/util/Arrays.cs +++ b/crypto/src/util/Arrays.cs @@ -469,6 +469,14 @@ public static void Fill( } } + public static void Fill(byte[] buf, int from, int to, byte b) + { + for (int i = from; i < to; ++i) + { + buf[i] = b; + } + } + public static byte[] CopyOf(byte[] data, int newLength) { byte[] tmp = new byte[newLength]; diff --git a/crypto/src/util/BigIntegers.cs b/crypto/src/util/BigIntegers.cs index f2d0425cc7..df78d1d86c 100644 --- a/crypto/src/util/BigIntegers.cs +++ b/crypto/src/util/BigIntegers.cs @@ -86,5 +86,10 @@ public static BigInteger CreateRandomInRange( // fall back to a faster (restricted) method return new BigInteger(max.Subtract(min).BitLength - 1, random).Add(min); } + + public static int GetUnsignedByteLength(BigInteger n) + { + return (n.BitLength + 7) / 8; + } } } From 074400e77f693d6feaa9e66d50cb4dcbe28b3d39 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sun, 14 Oct 2018 19:49:21 +0700 Subject: [PATCH 3/4] Handle CVC-ECDSA and PLAIN-ECDSA in test case --- crypto/test/src/security/test/TestSignerUtil.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crypto/test/src/security/test/TestSignerUtil.cs b/crypto/test/src/security/test/TestSignerUtil.cs index dc3c1c81be..48bf49a634 100644 --- a/crypto/test/src/security/test/TestSignerUtil.cs +++ b/crypto/test/src/security/test/TestSignerUtil.cs @@ -140,7 +140,9 @@ public void TestAlgorithms() signParams = rsaPrivate; verifyParams = rsaPublic; } - else if (cipherName == "ECDSA") + else if (cipherName == "ECDSA" + || cipherName == "CVC-ECDSA" + || cipherName == "PLAIN-ECDSA") { signParams = ecPriv; verifyParams = ecPub; From c6f976fb582940b476e60463a6a0e9b9fdb71fb0 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sun, 14 Oct 2018 19:50:46 +0700 Subject: [PATCH 4/4] Move generic "...withRSA" handler after PSSwithRSA --- crypto/src/security/SignerUtilities.cs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/crypto/src/security/SignerUtilities.cs b/crypto/src/security/SignerUtilities.cs index dc31ae4649..ae8d21f0a2 100644 --- a/crypto/src/security/SignerUtilities.cs +++ b/crypto/src/security/SignerUtilities.cs @@ -517,14 +517,6 @@ public static ISigner GetSigner( { return (new RsaDigestSigner(new NullDigest(), (AlgorithmIdentifier)null)); } - - if (Platform.EndsWith(mechanism, "withRSA")) - { - string digestName = mechanism.Substring(0, mechanism.LastIndexOf("with")); - IDigest digest = DigestUtilities.GetDigest(digestName); - return new RsaDigestSigner(digest); - } - if (mechanism.Equals("RAWRSASSA-PSS")) { // TODO Add support for other parameter settings @@ -536,7 +528,12 @@ public static ISigner GetSigner( // to be used can be overridden by subsequent parameter settings. return (new PssSigner(new RsaBlindedEngine(), new Sha1Digest())); } - + if (Platform.EndsWith(mechanism, "withRSA")) + { + string digestName = mechanism.Substring(0, mechanism.LastIndexOf("with")); + IDigest digest = DigestUtilities.GetDigest(digestName); + return new RsaDigestSigner(digest); + } if (Platform.EndsWith(mechanism, "withRSAandMGF1")) { string digestName = mechanism.Substring(0, mechanism.LastIndexOf("with"));