summary refs log tree commit diff
diff options
context:
space:
mode:
authorOren Novotny <oren@novotny.org>2018-10-16 21:29:47 -0400
committerOren Novotny <oren@novotny.org>2018-10-16 21:29:47 -0400
commitb249a506034cd0d1a03a6e9bb23e5faecc7d370e (patch)
treef5c94cfec87cfa860dbb5d4306d2e44c31eb3c2a
parentmerge from master (diff)
parentMove generic "...withRSA" handler after PSSwithRSA (diff)
downloadBouncyCastle.NET-ed25519-b249a506034cd0d1a03a6e9bb23e5faecc7d370e.tar.xz
merge from master pcl-v1.8.3.37
-rw-r--r--crypto/crypto.csproj25
-rw-r--r--crypto/src/asn1/bsi/BsiObjectIdentifiers.cs103
-rw-r--r--crypto/src/crypto/IDSA.cs1
-rw-r--r--crypto/src/crypto/IDsaExt.cs17
-rw-r--r--crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs2
-rw-r--r--crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs2
-rw-r--r--crypto/src/crypto/parameters/X25519KeyGenerationParameters.cs2
-rw-r--r--crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs2
-rw-r--r--crypto/src/crypto/parameters/X448PrivateKeyParameters.cs2
-rw-r--r--crypto/src/crypto/signers/DsaDigestSigner.cs89
-rw-r--r--crypto/src/crypto/signers/DsaSigner.cs7
-rw-r--r--crypto/src/crypto/signers/ECDsaSigner.cs7
-rw-r--r--crypto/src/crypto/signers/ECGOST3410Signer.cs7
-rw-r--r--crypto/src/crypto/signers/ECNRSigner.cs9
-rw-r--r--crypto/src/crypto/signers/GOST3410Signer.cs7
-rw-r--r--crypto/src/crypto/signers/HMacDsaKCalculator.cs7
-rw-r--r--crypto/src/crypto/signers/IDsaEncoding.cs25
-rw-r--r--crypto/src/crypto/signers/PlainDsaEncoding.cs58
-rw-r--r--crypto/src/crypto/signers/SM2Signer.cs50
-rw-r--r--crypto/src/crypto/signers/StandardDsaEncoding.cs56
-rw-r--r--crypto/src/crypto/signers/X931Signer.cs3
-rw-r--r--crypto/src/math/ec/rfc7748/X25519.cs10
-rw-r--r--crypto/src/math/ec/rfc7748/X448.cs9
-rw-r--r--crypto/src/math/ec/rfc8032/Ed25519.cs6
-rw-r--r--crypto/src/math/ec/rfc8032/Ed448.cs6
-rw-r--r--crypto/src/security/DigestUtilities.cs2
-rw-r--r--crypto/src/security/SignerUtilities.cs268
-rw-r--r--crypto/src/util/Arrays.cs8
-rw-r--r--crypto/src/util/BigIntegers.cs5
-rw-r--r--crypto/test/src/security/test/TestSignerUtil.cs4
30 files changed, 581 insertions, 218 deletions
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj
index c6dd131e7..bada122a3 100644
--- a/crypto/crypto.csproj
+++ b/crypto/crypto.csproj
@@ -569,6 +569,11 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\asn1\bsi\BsiObjectIdentifiers.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\asn1\cmp\CAKeyUpdAnnContent.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -3099,6 +3104,11 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\crypto\IDsaExt.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\crypto\IEntropySource.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -4784,6 +4794,11 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\crypto\signers\IDsaEncoding.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\crypto\signers\IDsaKCalculator.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -4804,6 +4819,11 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\crypto\signers\PlainDsaEncoding.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\crypto\signers\PSSSigner.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -4824,6 +4844,11 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\crypto\signers\StandardDsaEncoding.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\crypto\signers\X931Signer.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
diff --git a/crypto/src/asn1/bsi/BsiObjectIdentifiers.cs b/crypto/src/asn1/bsi/BsiObjectIdentifiers.cs
new file mode 100644
index 000000000..95a0d7b52
--- /dev/null
+++ b/crypto/src/asn1/bsi/BsiObjectIdentifiers.cs
@@ -0,0 +1,103 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Bsi
+{
+    /// <remarks>See https://www.bsi.bund.de/cae/servlet/contentblob/471398/publicationFile/30615/BSI-TR-03111_pdf.pdf</remarks>
+    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 46056d8ca..7d1fd5197 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 000000000..15b55787a
--- /dev/null
+++ b/crypto/src/crypto/IDsaExt.cs
@@ -0,0 +1,17 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto
+{
+    /// <summary>
+    /// An "extended" interface for classes implementing DSA-style algorithms, that provides access
+    /// to the group order.
+    /// </summary>
+    public interface IDsaExt
+        : IDsa
+    {
+        /// <summary>The order of the group that the r, s values in signatures belong to.</summary>
+        BigInteger Order { get; }
+    }
+}
diff --git a/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs b/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs
index 97902e093..8046a0b1b 100644
--- a/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs
+++ b/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs
@@ -19,7 +19,7 @@ namespace Org.BouncyCastle.Crypto.Parameters
         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 74b5d63f3..f2fc4d533 100644
--- a/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs
+++ b/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs
@@ -19,7 +19,7 @@ namespace Org.BouncyCastle.Crypto.Parameters
         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 09972c7a2..d0bcffa94 100644
--- a/crypto/src/crypto/parameters/X25519KeyGenerationParameters.cs
+++ b/crypto/src/crypto/parameters/X25519KeyGenerationParameters.cs
@@ -8,7 +8,7 @@ namespace Org.BouncyCastle.Crypto.Parameters
         : 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 fb49a02b3..f7bbdac74 100644
--- a/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs
+++ b/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs
@@ -19,7 +19,7 @@ namespace Org.BouncyCastle.Crypto.Parameters
         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 d17aa7947..a073e5799 100644
--- a/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs
+++ b/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs
@@ -19,7 +19,7 @@ namespace Org.BouncyCastle.Crypto.Parameters
         public X448PrivateKeyParameters(SecureRandom random)
             : base(true)
         {
-            random.NextBytes(data);
+            X448.GeneratePrivateKey(random, data);
         }
 
         public X448PrivateKeyParameters(byte[] buf, int off)
diff --git a/crypto/src/crypto/signers/DsaDigestSigner.cs b/crypto/src/crypto/signers/DsaDigestSigner.cs
index 086601481..7fd8f535f 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 @@ namespace Org.BouncyCastle.Crypto.Signers
 
 			Reset();
 
-			dsaSigner.Init(forSigning, parameters);
+			dsa.Init(forSigning, parameters);
 		}
 
 		/**
@@ -91,9 +98,16 @@ namespace Org.BouncyCastle.Crypto.Signers
 			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");
+            }
 		}
 
 		/// <returns>true if the internal state represents the signature described in the passed in array.</returns>
@@ -106,15 +120,16 @@ namespace Org.BouncyCastle.Crypto.Signers
 			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;
+            }
 		}
 
 		/// <summary>Reset the internal state</summary>
@@ -123,23 +138,9 @@ namespace Org.BouncyCastle.Crypto.Signers
 			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 bb28addfc..32a33d084 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 @@ namespace Org.BouncyCastle.Crypto.Signers
             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 520507b8c..7b04d1076 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 @@ namespace Org.BouncyCastle.Crypto.Signers
             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 28ab79c1c..451cd3dd8 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 @@ namespace Org.BouncyCastle.Crypto.Signers
             }
         }
 
+        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 bb21a4994..bc193e797 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 @@ namespace Org.BouncyCastle.Crypto.Signers
             }
         }
 
+        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 @@ namespace Org.BouncyCastle.Crypto.Signers
                 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 f1832ae37..c5f3bd5ef 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 @@ namespace Org.BouncyCastle.Crypto.Signers
 			}
 		}
 
+        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 8231197b9..05c4ae5c2 100644
--- a/crypto/src/crypto/signers/HMacDsaKCalculator.cs
+++ b/crypto/src/crypto/signers/HMacDsaKCalculator.cs
@@ -49,12 +49,13 @@ namespace Org.BouncyCastle.Crypto.Signers
             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 @@ namespace Org.BouncyCastle.Crypto.Signers
 
         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 000000000..cccc4f937
--- /dev/null
+++ b/crypto/src/crypto/signers/IDsaEncoding.cs
@@ -0,0 +1,25 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Signers
+{
+    /// <summary>
+    /// An interface for different encoding formats for DSA signatures.
+    /// </summary>
+    public interface IDsaEncoding
+    {
+        /// <summary>Decode the (r, s) pair of a DSA signature.</summary>
+        /// <param name="n">The order of the group that r, s belong to.</param>
+        /// <param name="encoding">An encoding of the (r, s) pair of a DSA signature.</param>
+        /// <returns>The (r, s) of a DSA signature, stored in an array of exactly two elements, r followed by s.</returns>
+        BigInteger[] Decode(BigInteger n, byte[] encoding);
+
+        /// <summary>Encode the (r, s) pair of a DSA signature.</summary>
+        /// <param name="n">The order of the group that r, s belong to.</param>
+        /// <param name="r">The r value of a DSA signature.</param>
+        /// <param name="s">The s value of a DSA signature.</param>
+        /// <returns>An encoding of the DSA signature given by the provided (r, s) pair.</returns>
+        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 000000000..2e1f65a1f
--- /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 8151e6be0..d9ec20525 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 @@ namespace Org.BouncyCastle.Crypto.Signers
     {
         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 @@ namespace Org.BouncyCastle.Crypto.Signers
         {
             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 @@ namespace Org.BouncyCastle.Crypto.Signers
             // 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 @@ namespace Org.BouncyCastle.Crypto.Signers
         {
             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 000000000..75ac08411
--- /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 c6e44bad8..6aeff87ad 100644
--- a/crypto/src/crypto/signers/X931Signer.cs
+++ b/crypto/src/crypto/signers/X931Signer.cs
@@ -145,7 +145,8 @@ namespace Org.BouncyCastle.Crypto.Signers
 
             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/math/ec/rfc7748/X25519.cs b/crypto/src/math/ec/rfc7748/X25519.cs
index d8db2527a..8524b9e2c 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 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
             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 63d34d1cf..63e526703 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 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
             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 403f11f50..b77853f30 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;
 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 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             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 10ebe8f15..38bdee83e 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;
 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 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             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();
diff --git a/crypto/src/security/DigestUtilities.cs b/crypto/src/security/DigestUtilities.cs
index 445304196..24a68f63d 100644
--- a/crypto/src/security/DigestUtilities.cs
+++ b/crypto/src/security/DigestUtilities.cs
@@ -31,6 +31,7 @@ namespace Org.BouncyCastle.Security
             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 @@ namespace Org.BouncyCastle.Security
                     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 6107bf878..ae8d21f0a 100644
--- a/crypto/src/security/SignerUtilities.cs
+++ b/crypto/src/security/SignerUtilities.cs
@@ -3,7 +3,9 @@ using System.Collections;
 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 @@ namespace Org.BouncyCastle.Security
             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 @@ namespace Org.BouncyCastle.Security
             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,51 +517,6 @@ namespace Org.BouncyCastle.Security
             {
                 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"))
-            {
-                return (new RsaDigestSigner(new RipeMD256Digest()));
-            }
-
             if (mechanism.Equals("RAWRSASSA-PSS"))
             {
                 // TODO Add support for other parameter settings
@@ -455,101 +528,46 @@ namespace Org.BouncyCastle.Security
                 // 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"))
+            if (Platform.EndsWith(mechanism, "withRSA"))
             {
-                return (new PssSigner(new RsaBlindedEngine(), new Sha256Digest()));
+                string digestName = mechanism.Substring(0, mechanism.LastIndexOf("with"));
+                IDigest digest = DigestUtilities.GetDigest(digestName);
+                return new RsaDigestSigner(digest);
             }
-            if (mechanism.Equals("SHA-384withRSAandMGF1"))
-            {
-                return (new PssSigner(new RsaBlindedEngine(), new Sha384Digest()));
-            }
-            if (mechanism.Equals("SHA-512withRSAandMGF1"))
+            if (Platform.EndsWith(mechanism, "withRSAandMGF1"))
             {
-                return (new PssSigner(new RsaBlindedEngine(), new Sha512Digest()));
+                string digestName = mechanism.Substring(0, mechanism.LastIndexOf("with"));
+                IDigest digest = DigestUtilities.GetDigest(digestName);
+                return new PssSigner(new RsaBlindedEngine(), digest);
             }
 
-            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, "withDSA"))
             {
-                return (new DsaDigestSigner(new DsaSigner(), new Sha512Digest()));
+                string digestName = mechanism.Substring(0, mechanism.LastIndexOf("with"));
+                IDigest digest = DigestUtilities.GetDigest(digestName);
+                return new DsaDigestSigner(new DsaSigner(), digest);
             }
 
-            if (mechanism.Equals("NONEwithECDSA"))
-            {
-                return (new DsaDigestSigner(new ECDsaSigner(), new NullDigest()));
-            }
-            if (mechanism.Equals("SHA-1withECDSA"))
+            if (Platform.EndsWith(mechanism, "withECDSA"))
             {
-                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 ECDsaSigner(), digest);
             }
 
-            if (mechanism.Equals("RIPEMD160withECDSA"))
+            if (Platform.EndsWith(mechanism, "withCVC-ECDSA")
+                || Platform.EndsWith(mechanism, "withPLAIN-ECDSA"))
             {
-                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, PlainDsaEncoding.Instance);
             }
 
-            if (mechanism.Equals("SHA1WITHECNR"))
-            {
-                return (new DsaDigestSigner(new ECNRSigner(), new Sha1Digest()));
-            }
-            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 a9a574dbf..4a8c65e88 100644
--- a/crypto/src/util/Arrays.cs
+++ b/crypto/src/util/Arrays.cs
@@ -469,6 +469,14 @@ namespace Org.BouncyCastle.Utilities
             }
         }
 
+        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 f2d0425cc..df78d1d86 100644
--- a/crypto/src/util/BigIntegers.cs
+++ b/crypto/src/util/BigIntegers.cs
@@ -86,5 +86,10 @@ namespace Org.BouncyCastle.Utilities
             // 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;
+        }
     }
 }
diff --git a/crypto/test/src/security/test/TestSignerUtil.cs b/crypto/test/src/security/test/TestSignerUtil.cs
index afd85ff4d..fb359d79d 100644
--- a/crypto/test/src/security/test/TestSignerUtil.cs
+++ b/crypto/test/src/security/test/TestSignerUtil.cs
@@ -140,7 +140,9 @@ namespace Org.BouncyCastle.Security.Tests
                     signParams = rsaPrivate;
                     verifyParams = rsaPublic;
                 }
-                else if (cipherName == "ECDSA")
+                else if (cipherName == "ECDSA"
+                    || cipherName == "CVC-ECDSA"
+                    || cipherName == "PLAIN-ECDSA")
                 {
                     signParams = ecPriv;
                     verifyParams = ecPub;