summary refs log tree commit diff
path: root/crypto
diff options
context:
space:
mode:
authorOren Novotny <oren@novotny.org>2019-08-22 08:01:33 -0400
committerOren Novotny <oren@novotny.org>2019-08-22 08:01:33 -0400
commit92975859b63738a249cd6065b085eb16da197d26 (patch)
tree4e6b75594f9dbb3a3c5ab579f4d0fc67f72a537f /crypto
parentsingle hit to true (diff)
parentFix circular dependence of statics (diff)
downloadBouncyCastle.NET-ed25519-92975859b63738a249cd6065b085eb16da197d26.tar.xz
merge master into netstandard
Diffstat (limited to 'crypto')
-rw-r--r--crypto/crypto.csproj40
-rw-r--r--crypto/src/asn1/ASN1StreamParser.cs26
-rw-r--r--crypto/src/asn1/Asn1Encodable.cs2
-rw-r--r--crypto/src/asn1/Asn1EncodableVector.cs248
-rw-r--r--crypto/src/asn1/Asn1InputStream.cs23
-rw-r--r--crypto/src/asn1/Asn1Sequence.cs112
-rw-r--r--crypto/src/asn1/Asn1Set.cs156
-rw-r--r--crypto/src/asn1/Asn1TaggedObject.cs2
-rw-r--r--crypto/src/asn1/BerSequence.cs26
-rw-r--r--crypto/src/asn1/BerSet.cs26
-rw-r--r--crypto/src/asn1/DerEnumerated.cs98
-rw-r--r--crypto/src/asn1/DerInteger.cs137
-rw-r--r--crypto/src/asn1/DerObjectIdentifier.cs30
-rw-r--r--crypto/src/asn1/DerSequence.cs34
-rw-r--r--crypto/src/asn1/DerSet.cs48
-rw-r--r--crypto/src/asn1/LazyDERSequence.cs22
-rw-r--r--crypto/src/asn1/LazyDERSet.cs10
-rw-r--r--crypto/src/asn1/anssi/ANSSINamedCurves.cs13
-rw-r--r--crypto/src/asn1/cms/EnvelopedData.cs2
-rw-r--r--crypto/src/asn1/cms/Evidence.cs38
-rw-r--r--crypto/src/asn1/cms/SignedData.cs2
-rw-r--r--crypto/src/asn1/crmf/CertTemplate.cs2
-rw-r--r--crypto/src/asn1/crmf/PopoPrivKey.cs2
-rw-r--r--crypto/src/asn1/cryptopro/ECGOST3410NamedCurves.cs72
-rw-r--r--crypto/src/asn1/cryptopro/GOST3410ParamSetParameters.cs2
-rw-r--r--crypto/src/asn1/gm/GMNamedCurves.cs19
-rw-r--r--crypto/src/asn1/icao/CscaMasterList.cs2
-rw-r--r--crypto/src/asn1/icao/DataGroupHash.cs2
-rw-r--r--crypto/src/asn1/isismtt/x509/DeclarationOfMajority.cs2
-rw-r--r--crypto/src/asn1/misc/CAST5CBCParameters.cs2
-rw-r--r--crypto/src/asn1/ocsp/OCSPResponseStatus.cs2
-rw-r--r--crypto/src/asn1/pkcs/CertBag.cs2
-rw-r--r--crypto/src/asn1/pkcs/EncryptedData.cs2
-rw-r--r--crypto/src/asn1/pkcs/SignedData.cs4
-rw-r--r--crypto/src/asn1/sec/SECNamedCurves.cs274
-rw-r--r--crypto/src/asn1/teletrust/TeleTrusTNamedCurves.cs122
-rw-r--r--crypto/src/asn1/tsp/Accuracy.cs78
-rw-r--r--crypto/src/asn1/util/Asn1Dump.cs4
-rw-r--r--crypto/src/asn1/x500/style/IetfUtilities.cs4
-rw-r--r--crypto/src/asn1/x509/CRLReason.cs7
-rw-r--r--crypto/src/asn1/x509/GeneralName.cs31
-rw-r--r--crypto/src/asn1/x509/SubjectPublicKeyInfo.cs13
-rw-r--r--crypto/src/asn1/x509/TBSCertList.cs6
-rw-r--r--crypto/src/asn1/x509/TBSCertificateStructure.cs7
-rw-r--r--crypto/src/asn1/x509/qualified/Iso4217CurrencyCode.cs4
-rw-r--r--crypto/src/asn1/x509/qualified/TypeOfBiometricData.cs4
-rw-r--r--crypto/src/asn1/x9/X962NamedCurves.cs379
-rw-r--r--crypto/src/asn1/x9/X9Curve.cs13
-rw-r--r--crypto/src/cmp/ProtectedPkiMessage.cs6
-rw-r--r--crypto/src/cmp/ProtectedPkiMessageBuilder.cs6
-rw-r--r--crypto/src/cms/CMSSignedData.cs2
-rw-r--r--crypto/src/cms/CMSSignedDataParser.cs2
-rw-r--r--crypto/src/cms/CMSSignedDataStreamGenerator.cs2
-rw-r--r--crypto/src/cms/SignerInformation.cs6
-rw-r--r--crypto/src/crmf/EncryptedValueBuilder.cs6
-rw-r--r--crypto/src/crmf/PKMacBuilder.cs4
-rw-r--r--crypto/src/crmf/ProofOfPossessionSigningKeyBuilder.cs13
-rw-r--r--crypto/src/crypto/digests/Sha256Digest.cs48
-rw-r--r--crypto/src/crypto/ec/CustomNamedCurves.cs240
-rw-r--r--crypto/src/crypto/engines/RSABlindedEngine.cs24
-rw-r--r--crypto/src/crypto/generators/SCrypt.cs2
-rw-r--r--crypto/src/crypto/parameters/MqvPrivateParameters.cs9
-rw-r--r--crypto/src/crypto/parameters/SM2KeyExchangePrivateParameters.cs7
-rw-r--r--crypto/src/crypto/signers/ECGOST3410Signer.cs15
-rw-r--r--crypto/src/crypto/signers/GOST3410Signer.cs17
-rw-r--r--crypto/src/math/BigInteger.cs24
-rw-r--r--crypto/src/math/ec/AbstractECLookupTable.cs16
-rw-r--r--crypto/src/math/ec/ECAlgorithms.cs160
-rw-r--r--crypto/src/math/ec/ECCurve.cs77
-rw-r--r--crypto/src/math/ec/ECFieldElement.cs53
-rw-r--r--crypto/src/math/ec/ECLookupTable.cs1
-rw-r--r--crypto/src/math/ec/ECPoint.cs62
-rw-r--r--crypto/src/math/ec/ScaleXNegateYPointMap.cs20
-rw-r--r--crypto/src/math/ec/ScaleYNegateXPointMap.cs20
-rw-r--r--crypto/src/math/ec/SimpleLookupTable.cs11
-rw-r--r--crypto/src/math/ec/custom/djb/Curve25519.cs45
-rw-r--r--crypto/src/math/ec/custom/djb/Curve25519FieldElement.cs2
-rw-r--r--crypto/src/math/ec/custom/gm/SM2P256V1Curve.cs31
-rw-r--r--crypto/src/math/ec/custom/gm/SM2P256V1FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecP128R1Curve.cs31
-rw-r--r--crypto/src/math/ec/custom/sec/SecP128R1FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecP160K1Curve.cs30
-rw-r--r--crypto/src/math/ec/custom/sec/SecP160R1Curve.cs31
-rw-r--r--crypto/src/math/ec/custom/sec/SecP160R1FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecP160R2Curve.cs31
-rw-r--r--crypto/src/math/ec/custom/sec/SecP160R2FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecP192K1Curve.cs31
-rw-r--r--crypto/src/math/ec/custom/sec/SecP192K1FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecP192R1Curve.cs31
-rw-r--r--crypto/src/math/ec/custom/sec/SecP192R1FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecP224K1Curve.cs31
-rw-r--r--crypto/src/math/ec/custom/sec/SecP224K1FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecP224R1Curve.cs31
-rw-r--r--crypto/src/math/ec/custom/sec/SecP224R1FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecP256K1Curve.cs31
-rw-r--r--crypto/src/math/ec/custom/sec/SecP256K1FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecP256R1Curve.cs31
-rw-r--r--crypto/src/math/ec/custom/sec/SecP256R1FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecP384R1Curve.cs31
-rw-r--r--crypto/src/math/ec/custom/sec/SecP384R1FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecP521R1Curve.cs31
-rw-r--r--crypto/src/math/ec/custom/sec/SecP521R1FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecT113Field.cs25
-rw-r--r--crypto/src/math/ec/custom/sec/SecT113FieldElement.cs12
-rw-r--r--crypto/src/math/ec/custom/sec/SecT113R1Curve.cs28
-rw-r--r--crypto/src/math/ec/custom/sec/SecT113R2Curve.cs28
-rw-r--r--crypto/src/math/ec/custom/sec/SecT131Field.cs27
-rw-r--r--crypto/src/math/ec/custom/sec/SecT131FieldElement.cs12
-rw-r--r--crypto/src/math/ec/custom/sec/SecT131R1Curve.cs28
-rw-r--r--crypto/src/math/ec/custom/sec/SecT131R2Curve.cs28
-rw-r--r--crypto/src/math/ec/custom/sec/SecT163Field.cs31
-rw-r--r--crypto/src/math/ec/custom/sec/SecT163FieldElement.cs12
-rw-r--r--crypto/src/math/ec/custom/sec/SecT163K1Curve.cs28
-rw-r--r--crypto/src/math/ec/custom/sec/SecT163R1Curve.cs28
-rw-r--r--crypto/src/math/ec/custom/sec/SecT163R2Curve.cs28
-rw-r--r--crypto/src/math/ec/custom/sec/SecT193Field.cs27
-rw-r--r--crypto/src/math/ec/custom/sec/SecT193FieldElement.cs12
-rw-r--r--crypto/src/math/ec/custom/sec/SecT193R1Curve.cs28
-rw-r--r--crypto/src/math/ec/custom/sec/SecT193R2Curve.cs28
-rw-r--r--crypto/src/math/ec/custom/sec/SecT233Field.cs32
-rw-r--r--crypto/src/math/ec/custom/sec/SecT233FieldElement.cs12
-rw-r--r--crypto/src/math/ec/custom/sec/SecT233K1Curve.cs28
-rw-r--r--crypto/src/math/ec/custom/sec/SecT233R1Curve.cs28
-rw-r--r--crypto/src/math/ec/custom/sec/SecT239Field.cs32
-rw-r--r--crypto/src/math/ec/custom/sec/SecT239FieldElement.cs12
-rw-r--r--crypto/src/math/ec/custom/sec/SecT239K1Curve.cs28
-rw-r--r--crypto/src/math/ec/custom/sec/SecT283Field.cs36
-rw-r--r--crypto/src/math/ec/custom/sec/SecT283FieldElement.cs12
-rw-r--r--crypto/src/math/ec/custom/sec/SecT283K1Curve.cs28
-rw-r--r--crypto/src/math/ec/custom/sec/SecT283R1Curve.cs28
-rw-r--r--crypto/src/math/ec/custom/sec/SecT409Field.cs40
-rw-r--r--crypto/src/math/ec/custom/sec/SecT409FieldElement.cs12
-rw-r--r--crypto/src/math/ec/custom/sec/SecT409K1Curve.cs28
-rw-r--r--crypto/src/math/ec/custom/sec/SecT409R1Curve.cs28
-rw-r--r--crypto/src/math/ec/custom/sec/SecT571Field.cs40
-rw-r--r--crypto/src/math/ec/custom/sec/SecT571FieldElement.cs12
-rw-r--r--crypto/src/math/ec/custom/sec/SecT571K1Curve.cs28
-rw-r--r--crypto/src/math/ec/custom/sec/SecT571R1Curve.cs28
-rw-r--r--crypto/src/math/ec/endo/EndoPreCompInfo.cs26
-rw-r--r--crypto/src/math/ec/endo/EndoUtilities.cs79
-rw-r--r--crypto/src/math/ec/endo/GlvTypeAEndomorphism.cs38
-rw-r--r--crypto/src/math/ec/endo/GlvTypeAParameters.cs32
-rw-r--r--crypto/src/math/ec/endo/GlvTypeBEndomorphism.cs31
-rw-r--r--crypto/src/math/ec/endo/GlvTypeBParameters.cs41
-rw-r--r--crypto/src/math/ec/endo/ScalarSplitParameters.cs69
-rw-r--r--crypto/src/math/ec/multiplier/GlvMultiplier.cs7
-rw-r--r--crypto/src/math/ec/multiplier/WNafL2RMultiplier.cs25
-rw-r--r--crypto/src/math/ec/multiplier/WNafPreCompInfo.cs41
-rw-r--r--crypto/src/math/ec/multiplier/WNafUtilities.cs242
-rw-r--r--crypto/src/math/ec/rfc7748/X25519Field.cs25
-rw-r--r--crypto/src/math/ec/rfc7748/X448Field.cs31
-rw-r--r--crypto/src/math/ec/rfc8032/Ed25519.cs24
-rw-r--r--crypto/src/math/ec/rfc8032/Ed448.cs22
-rw-r--r--crypto/src/math/raw/Nat.cs136
-rw-r--r--crypto/src/math/raw/Nat128.cs14
-rw-r--r--crypto/src/math/raw/Nat160.cs14
-rw-r--r--crypto/src/math/raw/Nat192.cs14
-rw-r--r--crypto/src/math/raw/Nat224.cs14
-rw-r--r--crypto/src/math/raw/Nat256.cs14
-rw-r--r--crypto/src/ocsp/BasicOCSPResp.cs2
-rw-r--r--crypto/src/ocsp/OCSPReq.cs2
-rw-r--r--crypto/src/ocsp/OCSPResp.cs2
-rw-r--r--crypto/src/ocsp/RespData.cs2
-rw-r--r--crypto/src/ocsp/RevokedStatus.cs2
-rw-r--r--crypto/src/pkix/Rfc3280CertPathUtilities.cs8
-rw-r--r--crypto/src/security/PrivateKeyFactory.cs11
-rw-r--r--crypto/src/security/PublicKeyFactory.cs113
-rw-r--r--crypto/src/tsp/GenTimeAccuracy.cs2
-rw-r--r--crypto/src/tsp/TimeStampRequest.cs2
-rw-r--r--crypto/src/util/Arrays.cs65
-rw-r--r--crypto/src/util/Integers.cs15
-rw-r--r--crypto/src/util/collections/CollectionUtilities.cs17
-rw-r--r--crypto/src/x509/AttributeCertificateHolder.cs4
-rw-r--r--crypto/src/x509/X509Certificate.cs63
-rw-r--r--crypto/src/x509/X509Crl.cs47
-rw-r--r--crypto/src/x509/X509CrlEntry.cs33
-rw-r--r--crypto/src/x509/X509V2AttributeCertificate.cs2
-rw-r--r--crypto/test/src/asn1/test/ASN1IntegerTest.cs21
-rw-r--r--crypto/test/src/asn1/test/DeclarationOfMajorityUnitTest.cs20
-rw-r--r--crypto/test/src/asn1/test/LinkedCertificateTest.cs2
-rw-r--r--crypto/test/src/asn1/test/MiscTest.cs8
-rw-r--r--crypto/test/src/cmp/test/ProtectedMessageTest.cs10
-rw-r--r--crypto/test/src/crypto/test/OAEPTest.cs2
-rw-r--r--crypto/test/src/crypto/test/SCryptTest.cs2
-rw-r--r--crypto/test/src/math/ec/test/ECPointTest.cs145
-rw-r--r--crypto/test/src/test/NamedCurveTest.cs18
186 files changed, 4108 insertions, 1859 deletions
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj
index 1b4cccd52..ca6dba5ff 100644
--- a/crypto/crypto.csproj
+++ b/crypto/crypto.csproj
@@ -5949,6 +5949,11 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\math\ec\AbstractECLookupTable.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\math\ec\ECAlgorithms.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -5984,11 +5989,21 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\math\ec\ScaleXNegateYPointMap.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\math\ec\ScaleXPointMap.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\math\ec\ScaleYNegateXPointMap.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\math\ec\ScaleYPointMap.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -6559,11 +6574,31 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\math\ec\endo\EndoPreCompInfo.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "src\math\ec\endo\EndoUtilities.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\math\ec\endo\GlvEndomorphism.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\math\ec\endo\GlvTypeAEndomorphism.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "src\math\ec\endo\GlvTypeAParameters.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\math\ec\endo\GlvTypeBEndomorphism.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -6574,6 +6609,11 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\math\ec\endo\ScalarSplitParameters.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\math\ec\multiplier\AbstractECMultiplier.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
diff --git a/crypto/src/asn1/ASN1StreamParser.cs b/crypto/src/asn1/ASN1StreamParser.cs
index 0c6b4413a..3eaaadaee 100644
--- a/crypto/src/asn1/ASN1StreamParser.cs
+++ b/crypto/src/asn1/ASN1StreamParser.cs
@@ -218,17 +218,19 @@ namespace Org.BouncyCastle.Asn1
 			}
 		}
 
-		internal Asn1EncodableVector ReadVector()
-		{
-			Asn1EncodableVector v = new Asn1EncodableVector();
-
-			IAsn1Convertible obj;
-			while ((obj = ReadObject()) != null)
-			{
-				v.Add(obj.ToAsn1Object());
-			}
-
-			return v;
-		}
+        internal Asn1EncodableVector ReadVector()
+        {
+            IAsn1Convertible obj = ReadObject();
+            if (null == obj)
+                return new Asn1EncodableVector(0);
+
+            Asn1EncodableVector v = new Asn1EncodableVector();
+            do
+            {
+                v.Add(obj.ToAsn1Object());
+            }
+            while ((obj = ReadObject()) != null);
+            return v;
+        }
 	}
 }
diff --git a/crypto/src/asn1/Asn1Encodable.cs b/crypto/src/asn1/Asn1Encodable.cs
index e3dd9a14c..12628082d 100644
--- a/crypto/src/asn1/Asn1Encodable.cs
+++ b/crypto/src/asn1/Asn1Encodable.cs
@@ -70,7 +70,7 @@ namespace Org.BouncyCastle.Asn1
 			Asn1Object o1 = ToAsn1Object();
 			Asn1Object o2 = other.ToAsn1Object();
 
-			return o1 == o2 || o1.CallAsn1Equals(o2);
+			return o1 == o2 || (null != o2 && o1.CallAsn1Equals(o2));
 		}
 
 		public abstract Asn1Object ToAsn1Object();
diff --git a/crypto/src/asn1/Asn1EncodableVector.cs b/crypto/src/asn1/Asn1EncodableVector.cs
index 8a97e8b4f..987aa5298 100644
--- a/crypto/src/asn1/Asn1EncodableVector.cs
+++ b/crypto/src/asn1/Asn1EncodableVector.cs
@@ -1,101 +1,191 @@
 using System;
 using System.Collections;
 
-using Org.BouncyCastle.Utilities;
-
 namespace Org.BouncyCastle.Asn1
 {
+    /**
+     * Mutable class for building ASN.1 constructed objects such as SETs or SEQUENCEs.
+     */
     public class Asn1EncodableVector
-		: IEnumerable
+        : IEnumerable
     {
-        private IList v = Platform.CreateArrayList();
-
-		public static Asn1EncodableVector FromEnumerable(
-			IEnumerable e)
-		{
-			Asn1EncodableVector v = new Asn1EncodableVector();
-			foreach (Asn1Encodable obj in e)
-			{
-				v.Add(obj);
-			}
-			return v;
-		}
-
-//		public Asn1EncodableVector()
-//		{
-//		}
-
-		public Asn1EncodableVector(
-			params Asn1Encodable[] v)
-		{
-			Add(v);
-		}
-
-//		public void Add(
-//			Asn1Encodable obj)
-//		{
-//			v.Add(obj);
-//		}
-
-		public void Add(
-			params Asn1Encodable[] objs)
-		{
-			foreach (Asn1Encodable obj in objs)
-			{
-				v.Add(obj);
-			}
-		}
-
-		public void AddOptional(
-			params Asn1Encodable[] objs)
-		{
-			if (objs != null)
-			{
-				foreach (Asn1Encodable obj in objs)
-				{
-					if (obj != null)
-					{
-						v.Add(obj);
-					}
-				}
-			}
-		}
+        internal static readonly Asn1Encodable[] EmptyElements = new Asn1Encodable[0];
+
+        private const int DefaultCapacity = 10;
+
+        private Asn1Encodable[] elements;
+        private int elementCount;
+        private bool copyOnWrite;
+
+        public static Asn1EncodableVector FromEnumerable(IEnumerable e)
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+            foreach (Asn1Encodable obj in e)
+            {
+                v.Add(obj);
+            }
+            return v;
+        }
+
+        public Asn1EncodableVector()
+            : this(DefaultCapacity)
+        {
+        }
+
+        public Asn1EncodableVector(int initialCapacity)
+        {
+            if (initialCapacity < 0)
+                throw new ArgumentException("must not be negative", "initialCapacity");
+
+            this.elements = (initialCapacity == 0) ? EmptyElements : new Asn1Encodable[initialCapacity];
+            this.elementCount = 0;
+            this.copyOnWrite = false;
+        }
+
+        public Asn1EncodableVector(params Asn1Encodable[] v)
+            : this()
+        {
+            Add(v);
+        }
+
+        public void Add(Asn1Encodable element)
+        {
+            if (null == element)
+                throw new ArgumentNullException("element");
+
+            int capacity = elements.Length;
+            int minCapacity = elementCount + 1;
+            if ((minCapacity > capacity) | copyOnWrite)
+            {
+                Reallocate(minCapacity);
+            }
+
+            this.elements[elementCount] = element;
+            this.elementCount = minCapacity;
+        }
+
+        public void Add(params Asn1Encodable[] objs)
+        {
+            foreach (Asn1Encodable obj in objs)
+            {
+                Add(obj);
+            }
+        }
+
+        public void AddOptional(params Asn1Encodable[] objs)
+        {
+            if (objs != null)
+            {
+                foreach (Asn1Encodable obj in objs)
+                {
+                    if (obj != null)
+                    {
+                        Add(obj);
+                    }
+                }
+            }
+        }
 
         public void AddOptionalTagged(bool isExplicit, int tagNo, Asn1Encodable obj)
         {
             if (null != obj)
             {
-                v.Add(new DerTaggedObject(isExplicit, tagNo, obj));
+                Add(new DerTaggedObject(isExplicit, tagNo, obj));
             }
         }
 
-		public Asn1Encodable this[
-			int index]
-		{
-			get { return (Asn1Encodable) v[index]; }
-		}
+        public void AddAll(Asn1EncodableVector other)
+        {
+            if (null == other)
+                throw new ArgumentNullException("other");
 
-		[Obsolete("Use 'object[index]' syntax instead")]
-		public Asn1Encodable Get(
-            int index)
+            int otherElementCount = other.Count;
+            if (otherElementCount < 1)
+                return;
+
+            int capacity = elements.Length;
+            int minCapacity = elementCount + otherElementCount;
+            if ((minCapacity > capacity) | copyOnWrite)
+            {
+                Reallocate(minCapacity);
+            }
+
+            int i = 0;
+            do
+            {
+                Asn1Encodable otherElement = other[i];
+                if (null == otherElement)
+                    throw new NullReferenceException("'other' elements cannot be null");
+
+                this.elements[elementCount + i] = otherElement;
+            }
+            while (++i < otherElementCount);
+
+            this.elementCount = minCapacity;
+        }
+
+        public Asn1Encodable this[int index]
         {
-            return this[index];
+            get
+            {
+                if (index >= elementCount)
+                    throw new IndexOutOfRangeException(index + " >= " + elementCount);
+
+                return elements[index];
+            }
         }
 
-		[Obsolete("Use 'Count' property instead")]
-		public int Size
-		{
-			get { return v.Count; }
-		}
+        public int Count
+        {
+            get { return elementCount; }
+        }
 
-		public int Count
-		{
-			get { return v.Count; }
-		}
+        public IEnumerator GetEnumerator()
+        {
+            return CopyElements().GetEnumerator();
+        }
 
-		public IEnumerator GetEnumerator()
-		{
-			return v.GetEnumerator();
-		}
-	}
+        internal Asn1Encodable[] CopyElements()
+        {
+            if (0 == elementCount)
+                return EmptyElements;
+
+            Asn1Encodable[] copy = new Asn1Encodable[elementCount];
+            Array.Copy(elements, 0, copy, 0, elementCount);
+            return copy;
+        }
+
+        internal Asn1Encodable[] TakeElements()
+        {
+            if (0 == elementCount)
+                return EmptyElements;
+
+            if (elements.Length == elementCount)
+            {
+                this.copyOnWrite = true;
+                return elements;
+            }
+
+            Asn1Encodable[] copy = new Asn1Encodable[elementCount];
+            Array.Copy(elements, 0, copy, 0, elementCount);
+            return copy;
+        }
+
+        private void Reallocate(int minCapacity)
+        {
+            int oldCapacity = elements.Length;
+            int newCapacity = System.Math.Max(oldCapacity, minCapacity + (minCapacity >> 1));
+
+            Asn1Encodable[] copy = new Asn1Encodable[newCapacity];
+            Array.Copy(elements, 0, copy, 0, elementCount);
+
+            this.elements = copy;
+            this.copyOnWrite = false;
+        }
+
+        internal static Asn1Encodable[] CloneElements(Asn1Encodable[] elements)
+        {
+            return elements.Length < 1 ? EmptyElements : (Asn1Encodable[])elements.Clone();
+        }
+    }
 }
diff --git a/crypto/src/asn1/Asn1InputStream.cs b/crypto/src/asn1/Asn1InputStream.cs
index a94ae5235..0c7461c98 100644
--- a/crypto/src/asn1/Asn1InputStream.cs
+++ b/crypto/src/asn1/Asn1InputStream.cs
@@ -98,13 +98,13 @@ namespace Org.BouncyCastle.Asn1
                         //
                         // yes, people actually do this...
                         //
-                        return new BerOctetString(BuildDerEncodableVector(defIn));
+                        return new BerOctetString(ReadVector(defIn));
                     case Asn1Tags.Sequence:
                         return CreateDerSequence(defIn);
                     case Asn1Tags.Set:
                         return CreateDerSet(defIn);
                     case Asn1Tags.External:
-                        return new DerExternal(BuildDerEncodableVector(defIn));                
+                        return new DerExternal(ReadVector(defIn));                
                     default:
                         throw new IOException("unknown tag " + tagNo + " encountered");
                 }
@@ -113,12 +113,15 @@ namespace Org.BouncyCastle.Asn1
             return CreatePrimitiveDerObject(tagNo, defIn, tmpBuffers);
         }
 
-        internal Asn1EncodableVector BuildEncodableVector()
+        internal virtual Asn1EncodableVector ReadVector(DefiniteLengthInputStream dIn)
         {
-            Asn1EncodableVector v = new Asn1EncodableVector();
+            if (dIn.Remaining < 1)
+                return new Asn1EncodableVector(0);
 
+            Asn1InputStream subStream = new Asn1InputStream(dIn);
+            Asn1EncodableVector v = new Asn1EncodableVector();
             Asn1Object o;
-            while ((o = ReadObject()) != null)
+            while ((o = subStream.ReadObject()) != null)
             {
                 v.Add(o);
             }
@@ -126,22 +129,16 @@ namespace Org.BouncyCastle.Asn1
             return v;
         }
 
-        internal virtual Asn1EncodableVector BuildDerEncodableVector(
-            DefiniteLengthInputStream dIn)
-        {
-            return new Asn1InputStream(dIn).BuildEncodableVector();
-        }
-
         internal virtual DerSequence CreateDerSequence(
             DefiniteLengthInputStream dIn)
         {
-            return DerSequence.FromVector(BuildDerEncodableVector(dIn));
+            return DerSequence.FromVector(ReadVector(dIn));
         }
 
         internal virtual DerSet CreateDerSet(
             DefiniteLengthInputStream dIn)
         {
-            return DerSet.FromVector(BuildDerEncodableVector(dIn), false);
+            return DerSet.FromVector(ReadVector(dIn), false);
         }
 
         public Asn1Object ReadObject()
diff --git a/crypto/src/asn1/Asn1Sequence.cs b/crypto/src/asn1/Asn1Sequence.cs
index 849f5e308..854c81590 100644
--- a/crypto/src/asn1/Asn1Sequence.cs
+++ b/crypto/src/asn1/Asn1Sequence.cs
@@ -10,7 +10,8 @@ namespace Org.BouncyCastle.Asn1
     public abstract class Asn1Sequence
         : Asn1Object, IEnumerable
     {
-        private readonly IList seq;
+        // NOTE: Only non-readonly to support LazyDerSequence
+        internal Asn1Encodable[] elements;
 
         /**
          * return an Asn1Sequence from the given object.
@@ -106,21 +107,38 @@ namespace Org.BouncyCastle.Asn1
             throw new ArgumentException("Unknown object in GetInstance: " + Platform.GetTypeName(obj), "obj");
         }
 
-        protected internal Asn1Sequence(
-            int capacity)
+        protected internal Asn1Sequence()
         {
-            seq = Platform.CreateArrayList(capacity);
+            this.elements = Asn1EncodableVector.EmptyElements;
         }
 
-        public virtual IEnumerator GetEnumerator()
+        protected internal Asn1Sequence(Asn1Encodable element)
+        {
+            if (null == element)
+                throw new ArgumentNullException("element");
+
+            this.elements = new Asn1Encodable[]{ element };
+        }
+
+        protected internal Asn1Sequence(params Asn1Encodable[] elements)
         {
-            return seq.GetEnumerator();
+            if (Arrays.IsNullOrContainsNull(elements))
+                throw new NullReferenceException("'elements' cannot be null, or contain null");
+
+            this.elements = Asn1EncodableVector.CloneElements(elements);
         }
 
-        [Obsolete("Use GetEnumerator() instead")]
-        public IEnumerator GetObjects()
+        protected internal Asn1Sequence(Asn1EncodableVector elementVector)
         {
-            return GetEnumerator();
+            if (null == elementVector)
+                throw new ArgumentNullException("elementVector");
+
+            this.elements = elementVector.TakeElements();
+        }
+
+        public virtual IEnumerator GetEnumerator()
+        {
+            return elements.GetEnumerator();
         }
 
         private class Asn1SequenceParserImpl
@@ -176,93 +194,59 @@ namespace Org.BouncyCastle.Asn1
          */
         public virtual Asn1Encodable this[int index]
         {
-            get { return (Asn1Encodable) seq[index]; }
+            get { return elements[index]; }
         }
 
-        [Obsolete("Use 'object[index]' syntax instead")]
-        public Asn1Encodable GetObjectAt(
-            int index)
-        {
-             return this[index];
-        }
-
-        [Obsolete("Use 'Count' property instead")]
-        public int Size
+        public virtual int Count
         {
-            get { return Count; }
+            get { return elements.Length; }
         }
 
-        public virtual int Count
+        public virtual Asn1Encodable[] ToArray()
         {
-            get { return seq.Count; }
+            return Asn1EncodableVector.CloneElements(elements);
         }
 
         protected override int Asn1GetHashCode()
         {
-            int hc = Count;
+            //return Arrays.GetHashCode(elements);
+            int i = elements.Length;
+            int hc = i + 1;
 
-            foreach (object o in this)
+            while (--i >= 0)
             {
-                hc *= 17;
-                if (o == null)
-                {
-                    hc ^= DerNull.Instance.GetHashCode();
-                }
-                else
-                {
-                    hc ^= o.GetHashCode();
-                }
+                hc *= 257;
+                hc ^= elements[i].ToAsn1Object().CallAsn1GetHashCode();
             }
 
             return hc;
         }
 
-        protected override bool Asn1Equals(
-            Asn1Object asn1Object)
+        protected override bool Asn1Equals(Asn1Object asn1Object)
         {
-            Asn1Sequence other = asn1Object as Asn1Sequence;
-
-            if (other == null)
+            Asn1Sequence that = asn1Object as Asn1Sequence;
+            if (null == that)
                 return false;
 
-            if (Count != other.Count)
+            int count = this.Count;
+            if (that.Count != count)
                 return false;
 
-            IEnumerator s1 = GetEnumerator();
-            IEnumerator s2 = other.GetEnumerator();
-
-            while (s1.MoveNext() && s2.MoveNext())
+            for (int i = 0; i < count; ++i)
             {
-                Asn1Object o1 = GetCurrent(s1).ToAsn1Object();
-                Asn1Object o2 = GetCurrent(s2).ToAsn1Object();
+                Asn1Object o1 = this.elements[i].ToAsn1Object();
+                Asn1Object o2 = that.elements[i].ToAsn1Object();
 
-                if (!o1.Equals(o2))
+                if (o1 != o2 && !o1.CallAsn1Equals(o2))
                     return false;
             }
 
             return true;
         }
 
-        private Asn1Encodable GetCurrent(IEnumerator e)
-        {
-            Asn1Encodable encObj = (Asn1Encodable)e.Current;
-
-            // unfortunately null was allowed as a substitute for DER null
-            if (encObj == null)
-                return DerNull.Instance;
-
-            return encObj;
-        }
-
-        protected internal void AddObject(
-            Asn1Encodable obj)
-        {
-            seq.Add(obj);
-        }
-
         public override string ToString()
         {
-            return CollectionUtilities.ToString(seq);
+            return CollectionUtilities.ToString(elements);
         }
     }
 }
diff --git a/crypto/src/asn1/Asn1Set.cs b/crypto/src/asn1/Asn1Set.cs
index 7fa072c0d..68ede2275 100644
--- a/crypto/src/asn1/Asn1Set.cs
+++ b/crypto/src/asn1/Asn1Set.cs
@@ -16,7 +16,8 @@ namespace Org.BouncyCastle.Asn1
     abstract public class Asn1Set
         : Asn1Object, IEnumerable
     {
-        private readonly IList _set;
+        // NOTE: Only non-readonly to support LazyDerSet
+        internal Asn1Encodable[] elements;
 
         /**
          * return an ASN1Set from the given object.
@@ -125,21 +126,38 @@ namespace Org.BouncyCastle.Asn1
             throw new ArgumentException("Unknown object in GetInstance: " + Platform.GetTypeName(obj), "obj");
         }
 
-        protected internal Asn1Set(
-            int capacity)
+        protected internal Asn1Set()
         {
-            _set = Platform.CreateArrayList(capacity);
+            this.elements = Asn1EncodableVector.EmptyElements;
         }
 
-        public virtual IEnumerator GetEnumerator()
+        protected internal Asn1Set(Asn1Encodable element)
+        {
+            if (null == element)
+                throw new ArgumentNullException("element");
+
+            this.elements = new Asn1Encodable[]{ element };
+        }
+
+        protected internal Asn1Set(params Asn1Encodable[] elements)
         {
-            return _set.GetEnumerator();
+            if (Arrays.IsNullOrContainsNull(elements))
+                throw new NullReferenceException("'elements' cannot be null, or contain null");
+
+            this.elements = Asn1EncodableVector.CloneElements(elements);
         }
 
-        [Obsolete("Use GetEnumerator() instead")]
-        public IEnumerator GetObjects()
+        protected internal Asn1Set(Asn1EncodableVector elementVector)
+        {
+            if (null == elementVector)
+                throw new ArgumentNullException("elementVector");
+
+            this.elements = elementVector.TakeElements();
+        }
+
+        public virtual IEnumerator GetEnumerator()
         {
-            return GetEnumerator();
+            return elements.GetEnumerator();
         }
 
         /**
@@ -150,35 +168,17 @@ namespace Org.BouncyCastle.Asn1
          */
         public virtual Asn1Encodable this[int index]
         {
-            get { return (Asn1Encodable) _set[index]; }
-        }
-
-        [Obsolete("Use 'object[index]' syntax instead")]
-        public Asn1Encodable GetObjectAt(
-            int index)
-        {
-             return this[index];
-        }
-
-        [Obsolete("Use 'Count' property instead")]
-        public int Size
-        {
-            get { return Count; }
+            get { return elements[index]; }
         }
 
         public virtual int Count
         {
-            get { return _set.Count; }
+            get { return elements.Length; }
         }
 
         public virtual Asn1Encodable[] ToArray()
         {
-            Asn1Encodable[] values = new Asn1Encodable[this.Count];
-            for (int i = 0; i < this.Count; ++i)
-            {
-                values[i] = this[i];
-            }
-            return values;
+            return Asn1EncodableVector.CloneElements(elements);
         }
 
         private class Asn1SetParserImpl
@@ -227,107 +227,67 @@ namespace Org.BouncyCastle.Asn1
 
         protected override int Asn1GetHashCode()
         {
-            int hc = Count;
+            //return Arrays.GetHashCode(elements);
+            int i = elements.Length;
+            int hc = i + 1;
 
-            foreach (object o in this)
+            while (--i >= 0)
             {
-                hc *= 17;
-                if (o == null)
-                {
-                    hc ^= DerNull.Instance.GetHashCode();
-                }
-                else
-                {
-                    hc ^= o.GetHashCode();
-                }
+                hc *= 257;
+                hc ^= elements[i].ToAsn1Object().CallAsn1GetHashCode();
             }
 
             return hc;
         }
 
-        protected override bool Asn1Equals(
-            Asn1Object asn1Object)
+        protected override bool Asn1Equals(Asn1Object asn1Object)
         {
-            Asn1Set other = asn1Object as Asn1Set;
-
-            if (other == null)
+            Asn1Set that = asn1Object as Asn1Set;
+            if (null == that)
                 return false;
 
-            if (Count != other.Count)
-            {
+            int count = this.Count;
+            if (that.Count != count)
                 return false;
-            }
-
-            IEnumerator s1 = GetEnumerator();
-            IEnumerator s2 = other.GetEnumerator();
 
-            while (s1.MoveNext() && s2.MoveNext())
+            for (int i = 0; i < count; ++i)
             {
-                Asn1Object o1 = GetCurrent(s1).ToAsn1Object();
-                Asn1Object o2 = GetCurrent(s2).ToAsn1Object();
+                Asn1Object o1 = this.elements[i].ToAsn1Object();
+                Asn1Object o2 = that.elements[i].ToAsn1Object();
 
-                if (!o1.Equals(o2))
+                if (o1 != o2 && !o1.CallAsn1Equals(o2))
                     return false;
             }
 
             return true;
         }
 
-        private Asn1Encodable GetCurrent(IEnumerator e)
-        {
-            Asn1Encodable encObj = (Asn1Encodable)e.Current;
-
-            // unfortunately null was allowed as a substitute for DER null
-            if (encObj == null)
-                return DerNull.Instance;
-
-            return encObj;
-        }
-
         protected internal void Sort()
         {
-            if (_set.Count < 2)
+            if (elements.Length < 2)
                 return;
 
 #if PORTABLE
-            var sorted = _set.Cast<Asn1Encodable>()
-                             .Select(a => new { Item = a, Key = a.GetEncoded(Asn1Encodable.Der) })
-                             .OrderBy(t => t.Key, new DerComparer())
-                             .Select(t => t.Item)
-                             .ToList();
-
-            for (int i = 0; i < _set.Count; ++i)
-            {
-                _set[i] = sorted[i];
-            }
+            this.elements = elements
+                .Cast<Asn1Encodable>()
+                .Select(a => new { Item = a, Key = a.GetEncoded(Asn1Encodable.Der) })
+                .OrderBy(t => t.Key, new DerComparer())
+                .Select(t => t.Item)
+                .ToArray();
 #else
-            Asn1Encodable[] items = new Asn1Encodable[_set.Count];
-            byte[][] keys = new byte[_set.Count][];
-
-            for (int i = 0; i < _set.Count; ++i)
-            {
-                Asn1Encodable item = (Asn1Encodable)_set[i];
-                items[i] = item;
-                keys[i] = item.GetEncoded(Asn1Encodable.Der);
-            }
-
-            Array.Sort(keys, items, new DerComparer());
-
-            for (int i = 0; i < _set.Count; ++i)
+            int count = elements.Length;
+            byte[][] keys = new byte[count][];
+            for (int i = 0; i < count; ++i)
             {
-                _set[i] = items[i];
+                keys[i] = elements[i].GetEncoded(Asn1Encodable.Der);
             }
+            Array.Sort(keys, elements, new DerComparer());
 #endif
         }
 
-        protected internal void AddObject(Asn1Encodable obj)
-        {
-            _set.Add(obj);
-        }
-
         public override string ToString()
         {
-            return CollectionUtilities.ToString(_set);
+            return CollectionUtilities.ToString(elements);
         }
 
 #if PORTABLE
diff --git a/crypto/src/asn1/Asn1TaggedObject.cs b/crypto/src/asn1/Asn1TaggedObject.cs
index a6d4b2c28..14b1bc65f 100644
--- a/crypto/src/asn1/Asn1TaggedObject.cs
+++ b/crypto/src/asn1/Asn1TaggedObject.cs
@@ -33,7 +33,7 @@ namespace Org.BouncyCastle.Asn1
         {
             if (explicitly)
             {
-                return (Asn1TaggedObject) obj.GetObject();
+                return GetInstance(obj.GetObject());
             }
 
             throw new ArgumentException("implicitly tagged tagged object");
diff --git a/crypto/src/asn1/BerSequence.cs b/crypto/src/asn1/BerSequence.cs
index 70b43fc79..55c93a72e 100644
--- a/crypto/src/asn1/BerSequence.cs
+++ b/crypto/src/asn1/BerSequence.cs
@@ -5,47 +5,41 @@ namespace Org.BouncyCastle.Asn1
 	{
 		public static new readonly BerSequence Empty = new BerSequence();
 
-		public static new BerSequence FromVector(
-			Asn1EncodableVector v)
+		public static new BerSequence FromVector(Asn1EncodableVector elementVector)
 		{
-			return v.Count < 1 ? Empty : new BerSequence(v);
+            return elementVector.Count < 1 ? Empty : new BerSequence(elementVector);
 		}
 
 		/**
 		 * create an empty sequence
 		 */
 		public BerSequence()
+            : base()
 		{
 		}
 
 		/**
 		 * create a sequence containing one object
 		 */
-		public BerSequence(
-			Asn1Encodable obj)
-			: base(obj)
+		public BerSequence(Asn1Encodable element)
+            : base(element)
 		{
 		}
 
-		public BerSequence(
-			params Asn1Encodable[] v)
-			: base(v)
+		public BerSequence(params Asn1Encodable[] elements)
+            : base(elements)
 		{
 		}
 
 		/**
 		 * create a sequence containing a vector of objects.
 		 */
-		public BerSequence(
-			Asn1EncodableVector v)
-			: base(v)
+		public BerSequence(Asn1EncodableVector elementVector)
+            : base(elementVector)
 		{
 		}
 
-		/*
-		 */
-		internal override void Encode(
-			DerOutputStream derOut)
+        internal override void Encode(DerOutputStream derOut)
 		{
 			if (derOut is Asn1OutputStream || derOut is BerOutputStream)
 			{
diff --git a/crypto/src/asn1/BerSet.cs b/crypto/src/asn1/BerSet.cs
index a181e172d..6209e71a8 100644
--- a/crypto/src/asn1/BerSet.cs
+++ b/crypto/src/asn1/BerSet.cs
@@ -5,48 +5,46 @@ namespace Org.BouncyCastle.Asn1
     {
 		public static new readonly BerSet Empty = new BerSet();
 
-		public static new BerSet FromVector(
-			Asn1EncodableVector v)
+		public static new BerSet FromVector(Asn1EncodableVector elementVector)
 		{
-			return v.Count < 1 ? Empty : new BerSet(v);
+            return elementVector.Count < 1 ? Empty : new BerSet(elementVector);
 		}
 
-		internal static new BerSet FromVector(
-			Asn1EncodableVector v,
-			bool				needsSorting)
+        internal static new BerSet FromVector(Asn1EncodableVector elementVector, bool needsSorting)
 		{
-			return v.Count < 1 ? Empty : new BerSet(v, needsSorting);
+            return elementVector.Count < 1 ? Empty : new BerSet(elementVector, needsSorting);
 		}
 
 		/**
          * create an empty sequence
          */
         public BerSet()
+            : base()
         {
         }
 
         /**
          * create a set containing one object
          */
-        public BerSet(Asn1Encodable obj) : base(obj)
+        public BerSet(Asn1Encodable element)
+            : base(element)
         {
         }
 
         /**
          * create a set containing a vector of objects.
          */
-        public BerSet(Asn1EncodableVector v) : base(v, false)
+        public BerSet(Asn1EncodableVector elementVector)
+            : base(elementVector, false)
         {
         }
 
-        internal BerSet(Asn1EncodableVector v, bool needsSorting) : base(v, needsSorting)
+        internal BerSet(Asn1EncodableVector elementVector, bool needsSorting)
+            : base(elementVector, needsSorting)
         {
         }
 
-        /*
-         */
-        internal override void Encode(
-            DerOutputStream derOut)
+        internal override void Encode(DerOutputStream derOut)
         {
             if (derOut is Asn1OutputStream || derOut is BerOutputStream)
             {
diff --git a/crypto/src/asn1/DerEnumerated.cs b/crypto/src/asn1/DerEnumerated.cs
index 6690feceb..8654a3bfd 100644
--- a/crypto/src/asn1/DerEnumerated.cs
+++ b/crypto/src/asn1/DerEnumerated.cs
@@ -9,6 +9,7 @@ namespace Org.BouncyCastle.Asn1
         : Asn1Object
     {
         private readonly byte[] bytes;
+        private readonly int start;
 
         /**
          * return an integer from the passed in object
@@ -49,32 +50,42 @@ namespace Org.BouncyCastle.Asn1
             return FromOctetString(((Asn1OctetString)o).GetOctets());
         }
 
-        public DerEnumerated(
-            int val)
+        public DerEnumerated(int val)
         {
-            bytes = BigInteger.ValueOf(val).ToByteArray();
+            if (val < 0)
+                throw new ArgumentException("enumerated must be non-negative", "val");
+
+            this.bytes = BigInteger.ValueOf(val).ToByteArray();
+            this.start = 0;
         }
 
-        public DerEnumerated(
-            BigInteger val)
+        public DerEnumerated(long val)
         {
-            bytes = val.ToByteArray();
+            if (val < 0L)
+                throw new ArgumentException("enumerated must be non-negative", "val");
+
+            this.bytes = BigInteger.ValueOf(val).ToByteArray();
+            this.start = 0;
         }
 
-        public DerEnumerated(
-            byte[] bytes)
+        public DerEnumerated(BigInteger val)
         {
-            if (bytes.Length > 1)
-            {
-                if ((bytes[0] == 0 && (bytes[1] & 0x80) == 0)
-                    || (bytes[0] == (byte)0xff && (bytes[1] & 0x80) != 0))
-                {
-                    if (!DerInteger.AllowUnsafe())
-                        throw new ArgumentException("malformed enumerated");
-                }
-            }
+            if (val.SignValue < 0)
+                throw new ArgumentException("enumerated must be non-negative", "val");
+
+            this.bytes = val.ToByteArray();
+            this.start = 0;
+        }
+
+        public DerEnumerated(byte[] bytes)
+        {
+            if (DerInteger.IsMalformed(bytes))
+                throw new ArgumentException("malformed enumerated", "bytes");
+            if (0 != (bytes[0] & 0x80))
+                throw new ArgumentException("enumerated must be non-negative", "bytes");
 
             this.bytes = Arrays.Clone(bytes);
+            this.start = DerInteger.SignBytesToSkip(bytes);
         }
 
         public BigInteger Value
@@ -82,17 +93,34 @@ namespace Org.BouncyCastle.Asn1
             get { return new BigInteger(bytes); }
         }
 
-        internal override void Encode(
-            DerOutputStream derOut)
+        public bool HasValue(BigInteger x)
+        {
+            return null != x
+                // Fast check to avoid allocation
+                && DerInteger.IntValue(bytes, start, DerInteger.SignExtSigned) == x.IntValue
+                && Value.Equals(x);
+        }
+
+        public int IntValueExact
+        {
+            get
+            {
+                int count = bytes.Length - start;
+                if (count > 4)
+                    throw new ArithmeticException("ASN.1 Enumerated out of int range");
+
+                return DerInteger.IntValue(bytes, start, DerInteger.SignExtSigned);
+            }
+        }
+
+        internal override void Encode(DerOutputStream derOut)
         {
             derOut.WriteEncoded(Asn1Tags.Enumerated, bytes);
         }
 
-        protected override bool Asn1Equals(
-            Asn1Object asn1Object)
+        protected override bool Asn1Equals(Asn1Object asn1Object)
         {
             DerEnumerated other = asn1Object as DerEnumerated;
-
             if (other == null)
                 return false;
 
@@ -108,27 +136,21 @@ namespace Org.BouncyCastle.Asn1
 
         internal static DerEnumerated FromOctetString(byte[] enc)
         {
+            if (enc.Length > 1)
+                return new DerEnumerated(enc);
             if (enc.Length == 0)
-            {
                 throw new ArgumentException("ENUMERATED has zero length", "enc");
-            }
 
-            if (enc.Length == 1)
+            int value = enc[0];
+            if (value >= cache.Length)
+                return new DerEnumerated(enc);
+
+            DerEnumerated possibleMatch = cache[value];
+            if (possibleMatch == null)
             {
-                int value = enc[0];
-                if (value < cache.Length)
-                {
-                    DerEnumerated cached = cache[value];
-                    if (cached != null)
-                    {
-                        return cached;
-                    }
-
-                    return cache[value] = new DerEnumerated(Arrays.Clone(enc));
-                }
+                cache[value] = possibleMatch = new DerEnumerated(enc);
             }
-
-            return new DerEnumerated(Arrays.Clone(enc));
+            return possibleMatch;
         }
     }
 }
diff --git a/crypto/src/asn1/DerInteger.cs b/crypto/src/asn1/DerInteger.cs
index ae14d2a9f..3e19a07b6 100644
--- a/crypto/src/asn1/DerInteger.cs
+++ b/crypto/src/asn1/DerInteger.cs
@@ -16,7 +16,11 @@ namespace Org.BouncyCastle.Asn1
             return allowUnsafeValue != null && Platform.EqualsIgnoreCase("true", allowUnsafeValue);
         }
 
+        internal const int SignExtSigned = -1;
+        internal const int SignExtUnsigned = 0xFF;
+
         private readonly byte[] bytes;
+        private readonly int start;
 
         /**
          * return an integer from the passed in object
@@ -60,42 +64,42 @@ namespace Org.BouncyCastle.Asn1
 			return new DerInteger(Asn1OctetString.GetInstance(o).GetOctets());
         }
 
-		public DerInteger(
-            int value)
+		public DerInteger(int value)
+        {
+            this.bytes = BigInteger.ValueOf(value).ToByteArray();
+            this.start = 0;
+        }
+
+        public DerInteger(long value)
         {
-            bytes = BigInteger.ValueOf(value).ToByteArray();
+            this.bytes = BigInteger.ValueOf(value).ToByteArray();
+            this.start = 0;
         }
 
-		public DerInteger(
-            BigInteger value)
+		public DerInteger(BigInteger value)
         {
             if (value == null)
                 throw new ArgumentNullException("value");
 
-			bytes = value.ToByteArray();
+			this.bytes = value.ToByteArray();
+            this.start = 0;
         }
 
-		public DerInteger(
-            byte[] bytes)
+        public DerInteger(byte[] bytes)
+            : this(bytes, true)
         {
-            if (bytes.Length > 1)
-            {
-                if ((bytes[0] == 0 && (bytes[1] & 0x80) == 0)
-                    || (bytes[0] == (byte)0xff && (bytes[1] & 0x80) != 0))
-                {
-                    if (!AllowUnsafe())
-                        throw new ArgumentException("malformed integer");
-                }
-            }
-            this.bytes = Arrays.Clone(bytes);
         }
 
-		public BigInteger Value
+        internal DerInteger(byte[] bytes, bool clone)
         {
-            get { return new BigInteger(bytes); }
+            if (IsMalformed(bytes))
+                throw new ArgumentException("malformed integer", "bytes");
+
+            this.bytes = clone ? Arrays.Clone(bytes) : bytes;
+            this.start = SignBytesToSkip(bytes);
         }
 
-		/**
+        /**
          * in some cases positive values Get crammed into a space,
          * that's not quite big enough...
          */
@@ -104,8 +108,44 @@ namespace Org.BouncyCastle.Asn1
             get { return new BigInteger(1, bytes); }
         }
 
-        internal override void Encode(
-            DerOutputStream derOut)
+        public BigInteger Value
+        {
+            get { return new BigInteger(bytes); }
+        }
+
+        public bool HasValue(BigInteger x)
+        {
+            return null != x
+                // Fast check to avoid allocation
+                && IntValue(bytes, start, SignExtSigned) == x.IntValue
+                && Value.Equals(x);
+        }
+
+        public int IntPositiveValueExact
+        {
+            get
+            {
+                int count = bytes.Length - start;
+                if (count > 4 || (count == 4 && 0 != (bytes[start] & 0x80)))
+                    throw new ArithmeticException("ASN.1 Integer out of positive int range");
+
+                return IntValue(bytes, start, SignExtUnsigned);
+            }
+        }
+
+        public int IntValueExact
+        {
+            get
+            {
+                int count = bytes.Length - start;
+                if (count > 4)
+                    throw new ArithmeticException("ASN.1 Integer out of int range");
+
+                return IntValue(bytes, start, SignExtSigned);
+            }
+        }
+
+        internal override void Encode(DerOutputStream derOut)
         {
             derOut.WriteEncoded(Asn1Tags.Integer, bytes);
         }
@@ -115,20 +155,61 @@ namespace Org.BouncyCastle.Asn1
 			return Arrays.GetHashCode(bytes);
         }
 
-		protected override bool Asn1Equals(
-			Asn1Object asn1Object)
+		protected override bool Asn1Equals(Asn1Object asn1Object)
 		{
 			DerInteger other = asn1Object as DerInteger;
-
 			if (other == null)
 				return false;
 
-			return Arrays.AreEqual(this.bytes, other.bytes);
+            return Arrays.AreEqual(this.bytes, other.bytes);
         }
 
 		public override string ToString()
 		{
 			return Value.ToString();
 		}
-	}
+
+        internal static int IntValue(byte[] bytes, int start, int signExt)
+        {
+            int length = bytes.Length;
+            int pos = System.Math.Max(start, length - 4);
+
+            int val = (sbyte)bytes[pos] & signExt;
+            while (++pos < length)
+            {
+                val = (val << 8) | bytes[pos];
+            }
+            return val;
+        }
+
+        /**
+         * Apply the correct validation for an INTEGER primitive following the BER rules.
+         *
+         * @param bytes The raw encoding of the integer.
+         * @return true if the (in)put fails this validation.
+         */
+        internal static bool IsMalformed(byte[] bytes)
+        {
+            switch (bytes.Length)
+            {
+            case 0:
+                return true;
+            case 1:
+                return false;
+            default:
+                return (sbyte)bytes[0] == ((sbyte)bytes[1] >> 7) && !AllowUnsafe();
+            }
+        }
+
+        internal static int SignBytesToSkip(byte[] bytes)
+        {
+            int pos = 0, last = bytes.Length - 1;
+            while (pos < last
+                && (sbyte)bytes[pos] == ((sbyte)bytes[pos + 1] >> 7))
+            {
+                ++pos;
+            }
+            return pos;
+        }
+    }
 }
diff --git a/crypto/src/asn1/DerObjectIdentifier.cs b/crypto/src/asn1/DerObjectIdentifier.cs
index 1c8032f45..fb38d5f05 100644
--- a/crypto/src/asn1/DerObjectIdentifier.cs
+++ b/crypto/src/asn1/DerObjectIdentifier.cs
@@ -210,36 +210,36 @@ namespace Org.BouncyCastle.Asn1
             return identifier;
         }
 
-        private static bool IsValidBranchID(
-            string branchID, int start)
+        private static bool IsValidBranchID(string branchID, int start)
         {
-            bool periodAllowed = false;
+            int digitCount = 0;
 
             int pos = branchID.Length;
             while (--pos >= start)
             {
                 char ch = branchID[pos];
 
-                // TODO Leading zeroes?
-                if ('0' <= ch && ch <= '9')
-                {
-                    periodAllowed = true;
-                    continue;
-                }
-
                 if (ch == '.')
                 {
-                    if (!periodAllowed)
+                    if (0 == digitCount || (digitCount > 1 && branchID[pos + 1] == '0'))
                         return false;
 
-                    periodAllowed = false;
-                    continue;
+                    digitCount = 0;
+                }
+                else if ('0' <= ch && ch <= '9')
+                {
+                    ++digitCount;
                 }
+                else
+                {
+                    return false;
+                }
+            }
 
+            if (0 == digitCount || (digitCount > 1 && branchID[pos + 1] == '0'))
                 return false;
-            }
 
-            return periodAllowed;
+            return true;
         }
 
         private static bool IsValidIdentifier(string identifier)
diff --git a/crypto/src/asn1/DerSequence.cs b/crypto/src/asn1/DerSequence.cs
index a76cf2882..823fa869b 100644
--- a/crypto/src/asn1/DerSequence.cs
+++ b/crypto/src/asn1/DerSequence.cs
@@ -11,51 +11,38 @@ namespace Org.BouncyCastle.Asn1
 	{
 		public static readonly DerSequence Empty = new DerSequence();
 
-		public static DerSequence FromVector(
-			Asn1EncodableVector v)
+		public static DerSequence FromVector(Asn1EncodableVector elementVector)
 		{
-			return v.Count < 1 ? Empty : new DerSequence(v);
+            return elementVector.Count < 1 ? Empty : new DerSequence(elementVector);
 		}
 
 		/**
 		 * create an empty sequence
 		 */
 		public DerSequence()
-			: base(0)
+			: base()
 		{
 		}
 
 		/**
 		 * create a sequence containing one object
 		 */
-		public DerSequence(
-			Asn1Encodable obj)
-			: base(1)
+		public DerSequence(Asn1Encodable element)
+			: base(element)
 		{
-			AddObject(obj);
 		}
 
-		public DerSequence(
-			params Asn1Encodable[] v)
-			: base(v.Length)
+		public DerSequence(params Asn1Encodable[] elements)
+            : base(elements)
 		{
-			foreach (Asn1Encodable ae in v)
-			{
-				AddObject(ae);
-			}
 		}
 
 		/**
 		 * create a sequence containing a vector of objects.
 		 */
-		public DerSequence(
-			Asn1EncodableVector v)
-			: base(v.Count)
+		public DerSequence(Asn1EncodableVector elementVector)
+            : base(elementVector)
 		{
-			foreach (Asn1Encodable ae in v)
-			{
-				AddObject(ae);
-			}
 		}
 
 		/*
@@ -66,8 +53,7 @@ namespace Org.BouncyCastle.Asn1
 		 * ASN.1 descriptions given. Rather than just outputing Sequence,
 		 * we also have to specify Constructed, and the objects length.
 		 */
-		internal override void Encode(
-			DerOutputStream derOut)
+		internal override void Encode(DerOutputStream derOut)
 		{
 			// TODO Intermediate buffer could be avoided if we could calculate expected length
 			MemoryStream bOut = new MemoryStream();
diff --git a/crypto/src/asn1/DerSet.cs b/crypto/src/asn1/DerSet.cs
index 3df1a6766..d4c242778 100644
--- a/crypto/src/asn1/DerSet.cs
+++ b/crypto/src/asn1/DerSet.cs
@@ -13,68 +13,49 @@ namespace Org.BouncyCastle.Asn1
 	{
 		public static readonly DerSet Empty = new DerSet();
 
-		public static DerSet FromVector(
-			Asn1EncodableVector v)
+		public static DerSet FromVector(Asn1EncodableVector elementVector)
 		{
-			return v.Count < 1 ? Empty : new DerSet(v);
+            return elementVector.Count < 1 ? Empty : new DerSet(elementVector);
 		}
 
-		internal static DerSet FromVector(
-			Asn1EncodableVector	v,
-			bool				needsSorting)
+		internal static DerSet FromVector(Asn1EncodableVector elementVector, bool needsSorting)
 		{
-			return v.Count < 1 ? Empty : new DerSet(v, needsSorting);
+            return elementVector.Count < 1 ? Empty : new DerSet(elementVector, needsSorting);
 		}
 
 		/**
 		 * create an empty set
 		 */
 		public DerSet()
-			: base(0)
+			: base()
 		{
 		}
 
 		/**
 		 * @param obj - a single object that makes up the set.
 		 */
-		public DerSet(
-			Asn1Encodable obj)
-			: base(1)
+		public DerSet(Asn1Encodable element)
+			: base(element)
 		{
-			AddObject(obj);
 		}
 
-		public DerSet(
-			params Asn1Encodable[] v)
-			: base(v.Length)
+		public DerSet(params Asn1Encodable[] elements)
+			: base(elements)
 		{
-			foreach (Asn1Encodable o in v)
-			{
-				AddObject(o);
-			}
-
 			Sort();
 		}
 
 		/**
 		 * @param v - a vector of objects making up the set.
 		 */
-		public DerSet(
-			Asn1EncodableVector v)
-			: this(v, true)
+		public DerSet(Asn1EncodableVector elementVector)
+			: this(elementVector, true)
 		{
 		}
 
-		internal DerSet(
-			Asn1EncodableVector	v,
-			bool				needsSorting)
-			: base(v.Count)
+		internal DerSet(Asn1EncodableVector	elementVector, bool needsSorting)
+			: base(elementVector)
 		{
-			foreach (Asn1Encodable o in v)
-			{
-				AddObject(o);
-			}
-
 			if (needsSorting)
 			{
 				Sort();
@@ -89,8 +70,7 @@ namespace Org.BouncyCastle.Asn1
 		 * ASN.1 descriptions given. Rather than just outputing Set,
 		 * we also have to specify Constructed, and the objects length.
 		 */
-		internal override void Encode(
-			DerOutputStream derOut)
+		internal override void Encode(DerOutputStream derOut)
 		{
 			// TODO Intermediate buffer could be avoided if we could calculate expected length
 			MemoryStream bOut = new MemoryStream();
diff --git a/crypto/src/asn1/LazyDERSequence.cs b/crypto/src/asn1/LazyDERSequence.cs
index 7301bc158..8fa7a0792 100644
--- a/crypto/src/asn1/LazyDERSequence.cs
+++ b/crypto/src/asn1/LazyDERSequence.cs
@@ -19,18 +19,20 @@ namespace Org.BouncyCastle.Asn1
 		{
 			lock (this)
 			{
-				if (encoded != null)
-				{
-					Asn1InputStream e = new LazyAsn1InputStream(encoded);
+                if (null != encoded)
+                {
+                    Asn1EncodableVector v = new Asn1EncodableVector();
+                    Asn1InputStream e = new LazyAsn1InputStream(encoded);
 
-					Asn1Object o;
-					while ((o = e.ReadObject()) != null)
-					{
-						AddObject(o);
-					}
+                    Asn1Object o;
+                    while ((o = e.ReadObject()) != null)
+                    {
+                        v.Add(o);
+                    }
 
-					encoded = null;
-				}
+                    this.elements = v.TakeElements();
+                    this.encoded = null;
+                }
 			}
 		}
 
diff --git a/crypto/src/asn1/LazyDERSet.cs b/crypto/src/asn1/LazyDERSet.cs
index e6c9319dd..eac64cbbe 100644
--- a/crypto/src/asn1/LazyDERSet.cs
+++ b/crypto/src/asn1/LazyDERSet.cs
@@ -21,16 +21,18 @@ namespace Org.BouncyCastle.Asn1
 			{
 				if (encoded != null)
 				{
-					Asn1InputStream e = new LazyAsn1InputStream(encoded);
+                    Asn1EncodableVector v = new Asn1EncodableVector();
+                    Asn1InputStream e = new LazyAsn1InputStream(encoded);
 
 					Asn1Object o;
 					while ((o = e.ReadObject()) != null)
 					{
-						AddObject(o);
+						v.Add(o);
 					}
 
-					encoded = null;
-				}
+                    this.elements = v.TakeElements();
+                    this.encoded = null;
+                }
 			}
 		}
 
diff --git a/crypto/src/asn1/anssi/ANSSINamedCurves.cs b/crypto/src/asn1/anssi/ANSSINamedCurves.cs
index d0c90ebf1..ce941709f 100644
--- a/crypto/src/asn1/anssi/ANSSINamedCurves.cs
+++ b/crypto/src/asn1/anssi/ANSSINamedCurves.cs
@@ -4,6 +4,7 @@ using System.Collections;
 using Org.BouncyCastle.Asn1.X9;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Math.EC.Multiplier;
 using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.Collections;
 using Org.BouncyCastle.Utilities.Encoders;
@@ -12,6 +13,13 @@ namespace Org.BouncyCastle.Asn1.Anssi
 {
     public class AnssiNamedCurves
     {
+        private static X9ECPoint ConfigureBasepoint(ECCurve curve, string encoding)
+        {
+            X9ECPoint G = new X9ECPoint(curve, Hex.Decode(encoding));
+            WNafUtilities.ConfigureBasepoint(G.Point);
+            return G;
+        }
+
         private static ECCurve ConfigureCurve(ECCurve curve)
         {
             return curve;
@@ -42,9 +50,8 @@ namespace Org.BouncyCastle.Asn1.Anssi
                 BigInteger h = BigInteger.One;
 
                 ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "B6B3D4C356C139EB31183D4749D423958C27D2DCAF98B70164C97A2DD98F5CFF"
-                    + "6142E0F7C8B204911F9271F0F3ECEF8C2701C307E8E4C9E183115A1554062CFB"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "04B6B3D4C356C139EB31183D4749D423958C27D2DCAF98B70164C97A2DD98F5CFF6142E0F7C8B204911F9271F0F3ECEF8C2701C307E8E4C9E183115A1554062CFB");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
diff --git a/crypto/src/asn1/cms/EnvelopedData.cs b/crypto/src/asn1/cms/EnvelopedData.cs
index 41dae548f..fbde00b28 100644
--- a/crypto/src/asn1/cms/EnvelopedData.cs
+++ b/crypto/src/asn1/cms/EnvelopedData.cs
@@ -154,7 +154,7 @@ namespace Org.BouncyCastle.Asn1.Cms
             {
                 RecipientInfo ri = RecipientInfo.GetInstance(o);
 
-                if (ri.Version.Value.IntValue != 0)
+                if (ri.Version.IntValueExact != 0)
                 {
                     return 2;
                 }
diff --git a/crypto/src/asn1/cms/Evidence.cs b/crypto/src/asn1/cms/Evidence.cs
index 8374aed55..b12f090a9 100644
--- a/crypto/src/asn1/cms/Evidence.cs
+++ b/crypto/src/asn1/cms/Evidence.cs
@@ -8,6 +8,7 @@ namespace Org.BouncyCastle.Asn1.Cms
 		: Asn1Encodable, IAsn1Choice
 	{
 		private TimeStampTokenEvidence tstEvidence;
+        private Asn1Sequence otherEvidence;
 
 		public Evidence(TimeStampTokenEvidence tstEvidence)
 		{
@@ -16,11 +17,23 @@ namespace Org.BouncyCastle.Asn1.Cms
 
 		private Evidence(Asn1TaggedObject tagged)
 		{
-			if (tagged.TagNo == 0)
-			{
-				this.tstEvidence = TimeStampTokenEvidence.GetInstance(tagged, false);
-			}
-		}
+            if (tagged.TagNo == 0)
+            {
+                this.tstEvidence = TimeStampTokenEvidence.GetInstance(tagged, false);
+            }
+            //else if (tagged.TagNo == 1)
+            //{
+            //    this.ersEvidence = EvidenceRecord.GetInstance(tagged, false);
+            //}
+            else if (tagged.TagNo == 2)
+            {
+                this.otherEvidence = Asn1Sequence.GetInstance(tagged, false);
+            }
+            else
+            {
+                throw new ArgumentException("unknown tag in Evidence", "tagged");
+            }
+        }
 
 		public static Evidence GetInstance(object obj)
 		{
@@ -33,17 +46,28 @@ namespace Org.BouncyCastle.Asn1.Cms
 			throw new ArgumentException("Unknown object in GetInstance: " + Platform.GetTypeName(obj), "obj");
 		}
 
+        public static Evidence GetInstance(Asn1TaggedObject obj, bool isExplicit)
+        {
+            return GetInstance(obj.GetObject()); // must be explicitly tagged
+        }
+
 		public virtual TimeStampTokenEvidence TstEvidence
 		{
 			get { return tstEvidence; }
 		}
 
+        //public EvidenceRecord ErsEvidence
+        //{
+        //    get { return ersEvidence; }
+        //}
+
 		public override Asn1Object ToAsn1Object()
 		{
 			if (tstEvidence != null)
 				return new DerTaggedObject(false, 0, tstEvidence);
-
-			return null;
+            //if (ersEvidence != null)
+            //    return new DerTaggedObject(false, 1, ersEvidence);
+            return new DerTaggedObject(false, 2, otherEvidence);
 		}
 	}
 }
diff --git a/crypto/src/asn1/cms/SignedData.cs b/crypto/src/asn1/cms/SignedData.cs
index 957b81cd8..dfc1e2829 100644
--- a/crypto/src/asn1/cms/SignedData.cs
+++ b/crypto/src/asn1/cms/SignedData.cs
@@ -150,7 +150,7 @@ namespace Org.BouncyCastle.Asn1.Cms
             {
                 SignerInfo s = SignerInfo.GetInstance(obj);
 
-                if (s.Version.Value.IntValue == 3)
+                if (s.Version.IntValueExact == 3)
                 {
                     return true;
                 }
diff --git a/crypto/src/asn1/crmf/CertTemplate.cs b/crypto/src/asn1/crmf/CertTemplate.cs
index 3de9f1d5a..f731ac12e 100644
--- a/crypto/src/asn1/crmf/CertTemplate.cs
+++ b/crypto/src/asn1/crmf/CertTemplate.cs
@@ -77,7 +77,7 @@ namespace Org.BouncyCastle.Asn1.Crmf
 
         public virtual int Version
         {
-            get { return version.Value.IntValue; }
+            get { return version.IntValueExact; }
         }
 
         public virtual DerInteger SerialNumber
diff --git a/crypto/src/asn1/crmf/PopoPrivKey.cs b/crypto/src/asn1/crmf/PopoPrivKey.cs
index 0cedc5127..2b38cb109 100644
--- a/crypto/src/asn1/crmf/PopoPrivKey.cs
+++ b/crypto/src/asn1/crmf/PopoPrivKey.cs
@@ -26,7 +26,7 @@ namespace Org.BouncyCastle.Asn1.Crmf
                 this.obj = DerBitString.GetInstance(obj, false);
                 break;
             case subsequentMessage:
-                this.obj = SubsequentMessage.ValueOf(DerInteger.GetInstance(obj, false).Value.IntValue);
+                this.obj = SubsequentMessage.ValueOf(DerInteger.GetInstance(obj, false).IntValueExact);
                 break;
             case dhMAC:
                 this.obj = DerBitString.GetInstance(obj, false);
diff --git a/crypto/src/asn1/cryptopro/ECGOST3410NamedCurves.cs b/crypto/src/asn1/cryptopro/ECGOST3410NamedCurves.cs
index f4a3fce64..92c9312c7 100644
--- a/crypto/src/asn1/cryptopro/ECGOST3410NamedCurves.cs
+++ b/crypto/src/asn1/cryptopro/ECGOST3410NamedCurves.cs
@@ -5,6 +5,7 @@ using Org.BouncyCastle.Asn1.Rosstandart;
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Math.EC.Multiplier;
 using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.Collections;
 
@@ -15,6 +16,18 @@ namespace Org.BouncyCastle.Asn1.CryptoPro
     /// </summary>
     public sealed class ECGost3410NamedCurves
     {
+        private static ECPoint ConfigureBasepoint(ECCurve curve, BigInteger x, BigInteger y)
+        {
+            ECPoint G = curve.CreatePoint(x, y);
+            WNafUtilities.ConfigureBasepoint(G);
+            return G;
+        }
+
+        private static ECCurve ConfigureCurve(ECCurve curve)
+        {
+            return curve;
+        }
+
         private ECGost3410NamedCurves()
         {
         }
@@ -28,15 +41,15 @@ namespace Org.BouncyCastle.Asn1.CryptoPro
             BigInteger mod_p = new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639319");
             BigInteger mod_q = new BigInteger("115792089237316195423570985008687907853073762908499243225378155805079068850323");
 
-            FpCurve curve = new FpCurve(
+            ECCurve curve = ConfigureCurve(new FpCurve(
                 mod_p, // p
                 new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639316"), // a
                 new BigInteger("166"), // b
-                mod_q, BigInteger.One);
+                mod_q, BigInteger.One));
 
             ECDomainParameters ecParams = new ECDomainParameters(
                 curve,
-                curve.CreatePoint(
+                ConfigureBasepoint(curve,
                     new BigInteger("1"), // x
                     new BigInteger("64033881142927202683649881450433473985931760268884941288852745803908878638612")), // y
                 mod_q, BigInteger.One);
@@ -46,15 +59,15 @@ namespace Org.BouncyCastle.Asn1.CryptoPro
             mod_p = new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639319");
             mod_q = new BigInteger("115792089237316195423570985008687907853073762908499243225378155805079068850323");
 
-            curve = new FpCurve(
+            curve = ConfigureCurve(new FpCurve(
                 mod_p, // p
                 new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639316"),
                 new BigInteger("166"),
-                mod_q, BigInteger.One);
+                mod_q, BigInteger.One));
 
             ecParams = new ECDomainParameters(
                 curve,
-                curve.CreatePoint(
+                ConfigureBasepoint(curve,
                     new BigInteger("1"), // x
                     new BigInteger("64033881142927202683649881450433473985931760268884941288852745803908878638612")), // y
                 mod_q, BigInteger.One);
@@ -64,15 +77,15 @@ namespace Org.BouncyCastle.Asn1.CryptoPro
             mod_p = new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564823193"); //p
             mod_q = new BigInteger("57896044618658097711785492504343953927102133160255826820068844496087732066703"); //q
 
-            curve = new FpCurve(
+            curve = ConfigureCurve(new FpCurve(
                 mod_p, // p
                 new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564823190"), // a
                 new BigInteger("28091019353058090096996979000309560759124368558014865957655842872397301267595"), // b
-                mod_q, BigInteger.One);
+                mod_q, BigInteger.One));
 
             ecParams = new ECDomainParameters(
                 curve,
-                curve.CreatePoint(
+                ConfigureBasepoint(curve,
                     new BigInteger("1"), // x
                     new BigInteger("28792665814854611296992347458380284135028636778229113005756334730996303888124")), // y
                 mod_q, BigInteger.One);
@@ -82,15 +95,15 @@ namespace Org.BouncyCastle.Asn1.CryptoPro
             mod_p = new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502619");
             mod_q = new BigInteger("70390085352083305199547718019018437840920882647164081035322601458352298396601");
 
-            curve = new FpCurve(
+            curve = ConfigureCurve(new FpCurve(
                 mod_p, // p
                 new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502616"),
                 new BigInteger("32858"),
-                mod_q, BigInteger.One);
+                mod_q, BigInteger.One));
 
             ecParams = new ECDomainParameters(
                 curve,
-                curve.CreatePoint(
+                ConfigureBasepoint(curve,
                     new BigInteger("0"),
                     new BigInteger("29818893917731240733471273240314769927240550812383695689146495261604565990247")),
                 mod_q, BigInteger.One);
@@ -99,15 +112,16 @@ namespace Org.BouncyCastle.Asn1.CryptoPro
 
             mod_p = new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502619"); //p
             mod_q = new BigInteger("70390085352083305199547718019018437840920882647164081035322601458352298396601"); //q
-            curve = new FpCurve(
+
+            curve = ConfigureCurve(new FpCurve(
                 mod_p, // p
                 new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502616"), // a
                 new BigInteger("32858"), // b
-                mod_q, BigInteger.One);
+                mod_q, BigInteger.One));
 
             ecParams = new ECDomainParameters(
                 curve,
-                curve.CreatePoint(
+                ConfigureBasepoint(curve,
                     new BigInteger("0"), // x
                     new BigInteger("29818893917731240733471273240314769927240550812383695689146495261604565990247")), // y
                 mod_q, BigInteger.One);
@@ -117,15 +131,16 @@ namespace Org.BouncyCastle.Asn1.CryptoPro
             //GOST34.10 2012
             mod_p = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97", 16); //p
             mod_q = new BigInteger("400000000000000000000000000000000FD8CDDFC87B6635C115AF556C360C67", 16); //q
-            curve = new FpCurve(
+
+            curve = ConfigureCurve(new FpCurve(
                 mod_p, // p
                 new BigInteger("C2173F1513981673AF4892C23035A27CE25E2013BF95AA33B22C656F277E7335", 16), // a
                 new BigInteger("295F9BAE7428ED9CCC20E7C359A9D41A22FCCD9108E17BF7BA9337A6F8AE9513", 16), // b
-                mod_q, BigInteger.Four);
+                mod_q, BigInteger.Four));
 
             ecParams = new ECDomainParameters(
                 curve,
-                curve.CreatePoint(
+                ConfigureBasepoint(curve,
                     new BigInteger("91E38443A5E82C0D880923425712B2BB658B9196932E02C78B2582FE742DAA28", 16), // x
                     new BigInteger("32879423AB1A0375895786C4BB46E9565FDE0B5344766740AF268ADB32322E5C", 16)), // y
                 mod_q, BigInteger.Four);
@@ -134,15 +149,16 @@ namespace Org.BouncyCastle.Asn1.CryptoPro
 
             mod_p = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7", 16); //p
             mod_q = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27E69532F48D89116FF22B8D4E0560609B4B38ABFAD2B85DCACDB1411F10B275", 16); //q
-            curve = new FpCurve(
+
+            curve = ConfigureCurve(new FpCurve(
                 mod_p, // p
                 new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC4", 16), // a
                 new BigInteger("E8C2505DEDFC86DDC1BD0B2B6667F1DA34B82574761CB0E879BD081CFD0B6265EE3CB090F30D27614CB4574010DA90DD862EF9D4EBEE4761503190785A71C760", 16), // b
-                mod_q, BigInteger.One);
+                mod_q, BigInteger.One));
 
             ecParams = new ECDomainParameters(
                 curve,
-                curve.CreatePoint(
+                ConfigureBasepoint(curve,
                     new BigInteger("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003"), // x
                     new BigInteger("7503CFE87A836AE3A61B8816E25450E6CE5E1C93ACF1ABC1778064FDCBEFA921DF1626BE4FD036E93D75E6A50E3A41E98028FE5FC235F5B889A589CB5215F2A4", 16)), // y
                 mod_q, BigInteger.One);
@@ -151,15 +167,16 @@ namespace Org.BouncyCastle.Asn1.CryptoPro
 
             mod_p = new BigInteger("8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006F", 16); //p
             mod_q = new BigInteger("800000000000000000000000000000000000000000000000000000000000000149A1EC142565A545ACFDB77BD9D40CFA8B996712101BEA0EC6346C54374F25BD", 16); //q
-            curve = new FpCurve(
+
+            curve = ConfigureCurve(new FpCurve(
                 mod_p, // p
                 new BigInteger("8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006C", 16), // a
                 new BigInteger("687D1B459DC841457E3E06CF6F5E2517B97C7D614AF138BCBF85DC806C4B289F3E965D2DB1416D217F8B276FAD1AB69C50F78BEE1FA3106EFB8CCBC7C5140116", 16), // b
-                mod_q, BigInteger.One);
+                mod_q, BigInteger.One));
 
             ecParams = new ECDomainParameters(
                 curve,
-                curve.CreatePoint(
+                ConfigureBasepoint(curve,
                     new BigInteger("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002"), // x
                     new BigInteger("1A8F7EDA389B094C2C071E3647A8940F3C123B697578C213BE6DD9E6C8EC7335DCB228FD1EDF4A39152CBCAAF8C0398828041055F94CEEEC7E21340780FE41BD", 16)), // y
                 mod_q, BigInteger.One);
@@ -168,15 +185,16 @@ namespace Org.BouncyCastle.Asn1.CryptoPro
 
             mod_p = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7", 16); //p
             mod_q = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC98CDBA46506AB004C33A9FF5147502CC8EDA9E7A769A12694623CEF47F023ED", 16); //q
-            curve = new FpCurve(
+
+            curve = ConfigureCurve(new FpCurve(
                 mod_p, // p
                 new BigInteger("DC9203E514A721875485A529D2C722FB187BC8980EB866644DE41C68E143064546E861C0E2C9EDD92ADE71F46FCF50FF2AD97F951FDA9F2A2EB6546F39689BD3", 16), // a
                 new BigInteger("B4C4EE28CEBC6C2C8AC12952CF37F16AC7EFB6A9F69F4B57FFDA2E4F0DE5ADE038CBC2FFF719D2C18DE0284B8BFEF3B52B8CC7A5F5BF0A3C8D2319A5312557E1", 16), // b
-                mod_q, BigInteger.Four);
+                mod_q, BigInteger.Four));
 
             ecParams = new ECDomainParameters(
                 curve,
-                curve.CreatePoint(
+                ConfigureBasepoint(curve,
                     new BigInteger("E2E31EDFC23DE7BDEBE241CE593EF5DE2295B7A9CBAEF021D385F7074CEA043AA27272A7AE602BF2A7B9033DB9ED3610C6FB85487EAE97AAC5BC7928C1950148", 16), // x
                     new BigInteger("F5CE40D95B5EB899ABBCCFF5911CB8577939804D6527378B8C108C3D2090FF9BE18E2D33E3021ED2EF32D85822423B6304F726AA854BAE07D0396E9A9ADDC40F", 16)), // y
                 mod_q, BigInteger.Four);
diff --git a/crypto/src/asn1/cryptopro/GOST3410ParamSetParameters.cs b/crypto/src/asn1/cryptopro/GOST3410ParamSetParameters.cs
index b347f8dbd..ee6ed8c99 100644
--- a/crypto/src/asn1/cryptopro/GOST3410ParamSetParameters.cs
+++ b/crypto/src/asn1/cryptopro/GOST3410ParamSetParameters.cs
@@ -53,7 +53,7 @@ namespace Org.BouncyCastle.Asn1.CryptoPro
 			if (seq.Count != 4)
 				throw new ArgumentException("Wrong number of elements in sequence", "seq");
 
-			this.keySize = DerInteger.GetInstance(seq[0]).Value.IntValue;
+            this.keySize = DerInteger.GetInstance(seq[0]).IntValueExact;
 			this.p = DerInteger.GetInstance(seq[1]);
             this.q = DerInteger.GetInstance(seq[2]);
 			this.a = DerInteger.GetInstance(seq[3]);
diff --git a/crypto/src/asn1/gm/GMNamedCurves.cs b/crypto/src/asn1/gm/GMNamedCurves.cs
index e2ec6d854..5b1072f8c 100644
--- a/crypto/src/asn1/gm/GMNamedCurves.cs
+++ b/crypto/src/asn1/gm/GMNamedCurves.cs
@@ -5,6 +5,7 @@ using Org.BouncyCastle.Asn1.X9;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Math.EC;
 using Org.BouncyCastle.Math.EC.Endo;
+using Org.BouncyCastle.Math.EC.Multiplier;
 using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.Collections;
 using Org.BouncyCastle.Utilities.Encoders;
@@ -17,6 +18,13 @@ namespace Org.BouncyCastle.Asn1.GM
         {
         }
 
+        private static X9ECPoint ConfigureBasepoint(ECCurve curve, string encoding)
+        {
+            X9ECPoint G = new X9ECPoint(curve, Hex.Decode(encoding));
+            WNafUtilities.ConfigureBasepoint(G.Point);
+            return G;
+        }
+
         private static ECCurve ConfigureCurve(ECCurve curve)
         {
             return curve;
@@ -47,10 +55,8 @@ namespace Org.BouncyCastle.Asn1.GM
                 BigInteger h = BigInteger.One;
 
                 ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7"
-                    + "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"));
-
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0432C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0");
                 return new X9ECParameters(curve, G, n, h, S);
             }
         }
@@ -75,9 +81,8 @@ namespace Org.BouncyCastle.Asn1.GM
                 BigInteger h = BigInteger.One;
 
                 ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "4AD5F7048DE709AD51236DE6" + "5E4D4B482C836DC6E4106640"
-                    + "02BB3A02D4AAADACAE24817A" + "4CA3A1B014B5270432DB27D2"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "044AD5F7048DE709AD51236DE65E4D4B482C836DC6E410664002BB3A02D4AAADACAE24817A4CA3A1B014B5270432DB27D2");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
diff --git a/crypto/src/asn1/icao/CscaMasterList.cs b/crypto/src/asn1/icao/CscaMasterList.cs
index 6890d8a2e..d03b3adb4 100644
--- a/crypto/src/asn1/icao/CscaMasterList.cs
+++ b/crypto/src/asn1/icao/CscaMasterList.cs
@@ -62,7 +62,7 @@ namespace Org.BouncyCastle.Asn1.Icao
 
 		public virtual int Version
 		{
-			get { return version.Value.IntValue; }
+            get { return version.IntValueExact; }
 		}
 
 		public X509CertificateStructure[] GetCertStructs()
diff --git a/crypto/src/asn1/icao/DataGroupHash.cs b/crypto/src/asn1/icao/DataGroupHash.cs
index e0d7eee7b..bf83718f3 100644
--- a/crypto/src/asn1/icao/DataGroupHash.cs
+++ b/crypto/src/asn1/icao/DataGroupHash.cs
@@ -70,7 +70,7 @@ namespace Org.BouncyCastle.Asn1.Icao
 
 		public int DataGroupNumber
 		{
-			get { return dataGroupNumber.Value.IntValue; }
+            get { return dataGroupNumber.IntValueExact; }
 		}
 
 		public Asn1OctetString DataGroupHashValue
diff --git a/crypto/src/asn1/isismtt/x509/DeclarationOfMajority.cs b/crypto/src/asn1/isismtt/x509/DeclarationOfMajority.cs
index c4ebb2b72..b82c9373d 100644
--- a/crypto/src/asn1/isismtt/x509/DeclarationOfMajority.cs
+++ b/crypto/src/asn1/isismtt/x509/DeclarationOfMajority.cs
@@ -134,7 +134,7 @@ namespace Org.BouncyCastle.Asn1.IsisMtt.X509
 				switch ((Choice) declaration.TagNo)
 				{
 					case Choice.NotYoungerThan:
-						return DerInteger.GetInstance(declaration, false).Value.IntValue;
+                        return DerInteger.GetInstance(declaration, false).IntValueExact;
 					default:
 						return -1;
 				}
diff --git a/crypto/src/asn1/misc/CAST5CBCParameters.cs b/crypto/src/asn1/misc/CAST5CBCParameters.cs
index 51fd6607a..7bd9f1ec6 100644
--- a/crypto/src/asn1/misc/CAST5CBCParameters.cs
+++ b/crypto/src/asn1/misc/CAST5CBCParameters.cs
@@ -52,7 +52,7 @@ namespace Org.BouncyCastle.Asn1.Misc
 
 		public int KeyLength
 		{
-			get { return keyLength.Value.IntValue; }
+            get { return keyLength.IntValueExact; }
 		}
 
 		/**
diff --git a/crypto/src/asn1/ocsp/OCSPResponseStatus.cs b/crypto/src/asn1/ocsp/OCSPResponseStatus.cs
index 653317e33..cf52c73e4 100644
--- a/crypto/src/asn1/ocsp/OCSPResponseStatus.cs
+++ b/crypto/src/asn1/ocsp/OCSPResponseStatus.cs
@@ -34,7 +34,7 @@ namespace Org.BouncyCastle.Asn1.Ocsp
         }
 
 		public OcspResponseStatus(DerEnumerated value)
-			: base(value.Value.IntValue)
+            : base(value.IntValueExact)
         {
         }
     }
diff --git a/crypto/src/asn1/pkcs/CertBag.cs b/crypto/src/asn1/pkcs/CertBag.cs
index b6f4c8a30..e561fb890 100644
--- a/crypto/src/asn1/pkcs/CertBag.cs
+++ b/crypto/src/asn1/pkcs/CertBag.cs
@@ -17,7 +17,7 @@ namespace Org.BouncyCastle.Asn1.Pkcs
 
 //			this.seq = seq;
             this.certID = DerObjectIdentifier.GetInstance(seq[0]);
-            this.certValue = DerTaggedObject.GetInstance(seq[1]).GetObject();
+            this.certValue = Asn1TaggedObject.GetInstance(seq[1]).GetObject();
         }
 
 		public CertBag(
diff --git a/crypto/src/asn1/pkcs/EncryptedData.cs b/crypto/src/asn1/pkcs/EncryptedData.cs
index 7e95eb586..6a4c04f25 100644
--- a/crypto/src/asn1/pkcs/EncryptedData.cs
+++ b/crypto/src/asn1/pkcs/EncryptedData.cs
@@ -52,7 +52,7 @@ namespace Org.BouncyCastle.Asn1.Pkcs
 			if (seq.Count != 2)
 				throw new ArgumentException("Wrong number of elements in sequence", "seq");
 
-			int version = ((DerInteger) seq[0]).Value.IntValue;
+            int version = ((DerInteger)seq[0]).IntValueExact;
 			if (version != 0)
             {
                 throw new ArgumentException("sequence not version 0");
diff --git a/crypto/src/asn1/pkcs/SignedData.cs b/crypto/src/asn1/pkcs/SignedData.cs
index 3442e671c..ae335103c 100644
--- a/crypto/src/asn1/pkcs/SignedData.cs
+++ b/crypto/src/asn1/pkcs/SignedData.cs
@@ -66,9 +66,9 @@ namespace Org.BouncyCastle.Asn1.Pkcs
                 // an interesting feature of SignedData is that there appear to be varying implementations...
                 // for the moment we ignore anything which doesn't fit.
                 //
-                if (o is DerTaggedObject)
+                if (o is Asn1TaggedObject)
                 {
-                    DerTaggedObject tagged = (DerTaggedObject) o;
+                    Asn1TaggedObject tagged = (Asn1TaggedObject)o;
 
                     switch (tagged.TagNo)
                     {
diff --git a/crypto/src/asn1/sec/SECNamedCurves.cs b/crypto/src/asn1/sec/SECNamedCurves.cs
index b753ac5d1..44190d2b2 100644
--- a/crypto/src/asn1/sec/SECNamedCurves.cs
+++ b/crypto/src/asn1/sec/SECNamedCurves.cs
@@ -6,6 +6,7 @@ using Org.BouncyCastle.Asn1.X9;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Math.EC;
 using Org.BouncyCastle.Math.EC.Endo;
+using Org.BouncyCastle.Math.EC.Multiplier;
 using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.Collections;
 using Org.BouncyCastle.Utilities.Encoders;
@@ -18,6 +19,13 @@ namespace Org.BouncyCastle.Asn1.Sec
         {
         }
 
+        private static X9ECPoint ConfigureBasepoint(ECCurve curve, string encoding)
+        {
+            X9ECPoint G = new X9ECPoint(curve, Hex.Decode(encoding));
+            WNafUtilities.ConfigureBasepoint(G.Point);
+            return G;
+        }
+
         private static ECCurve ConfigureCurve(ECCurve curve)
         {
             return curve;
@@ -54,9 +62,9 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.One;
 
                 ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "09487239995A5EE76B55F9C2F098"
-                    + "A89CE5AF8724C0A23E0E0FF77500"));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0409487239995A5EE76B55F9C2F098A89CE5AF8724C0A23E0E0FF77500"); 
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -83,9 +91,9 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.ValueOf(4);
 
                 ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "4BA30AB5E892B4E1649DD0928643"
-                    + "ADCD46F5882E3747DEF36E956E97"));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "044BA30AB5E892B4E1649DD0928643ADCD46F5882E3747DEF36E956E97");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -112,9 +120,9 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.One;
 
                 ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "161FF7528B899B2D0C28607CA52C5B86"
-                    + "CF5AC8395BAFEB13C02DA292DDED7A83"));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "04161FF7528B899B2D0C28607CA52C5B86CF5AC8395BAFEB13C02DA292DDED7A83");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -141,9 +149,9 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.ValueOf(4);
 
                 ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "7B6AA5D85E572983E6FB32A7CDEBC140"
-                    + "27B6916A894D3AEE7106FE805FC34B44"));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "047B6AA5D85E572983E6FB32A7CDEBC14027B6916A894D3AEE7106FE805FC34B44");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -172,20 +180,21 @@ namespace Org.BouncyCastle.Asn1.Sec
                 GlvTypeBParameters glv = new GlvTypeBParameters(
                     new BigInteger("9ba48cba5ebcb9b6bd33b92830b2a2e0e192f10a", 16),
                     new BigInteger("c39c6c3b3a36d7701b9c71a1f5804ae5d0003f4", 16),
-                    new BigInteger[]{
-                        new BigInteger("9162fbe73984472a0a9e", 16),
-                        new BigInteger("-96341f1138933bc2f505", 16) },
-                    new BigInteger[]{
-                        new BigInteger("127971af8721782ecffa3", 16),
-                        new BigInteger("9162fbe73984472a0a9e", 16) },
-                    new BigInteger("9162fbe73984472a0a9d0590", 16),
-                    new BigInteger("96341f1138933bc2f503fd44", 16),
-                    176);
+                    new ScalarSplitParameters(
+                        new BigInteger[]{
+                            new BigInteger("9162fbe73984472a0a9e", 16),
+                            new BigInteger("-96341f1138933bc2f505", 16) },
+                        new BigInteger[]{
+                            new BigInteger("127971af8721782ecffa3", 16),
+                            new BigInteger("9162fbe73984472a0a9e", 16) },
+                        new BigInteger("9162fbe73984472a0a9d0590", 16),
+                        new BigInteger("96341f1138933bc2f503fd44", 16),
+                        176));
 
                 ECCurve curve = ConfigureCurveGlv(new FpCurve(p, a, b, n, h), glv);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB"
-                    + "938CF935318FDCED6BC28286531733C3F03C4FEE"));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "043B4C382CE37AA192A4019E763036F4F5DD4D7EBB938CF935318FDCED6BC28286531733C3F03C4FEE");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -212,9 +221,9 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.One;
 
                 ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "4A96B5688EF573284664698968C38BB913CBFC82"
-                    + "23A628553168947D59DCC912042351377AC5FB32"));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "044A96B5688EF573284664698968C38BB913CBFC8223A628553168947D59DCC912042351377AC5FB32");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -241,9 +250,9 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.One;
 
                 ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "52DCB034293A117E1F4FF11B30F7199D3144CE6D"
-                    + "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E"));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0452DCB034293A117E1F4FF11B30F7199D3144CE6DFEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -272,20 +281,21 @@ namespace Org.BouncyCastle.Asn1.Sec
                 GlvTypeBParameters glv = new GlvTypeBParameters(
                     new BigInteger("bb85691939b869c1d087f601554b96b80cb4f55b35f433c2", 16),
                     new BigInteger("3d84f26c12238d7b4f3d516613c1759033b1a5800175d0b1", 16),
-                    new BigInteger[]{
-                        new BigInteger("71169be7330b3038edb025f1", 16),
-                        new BigInteger("-b3fb3400dec5c4adceb8655c", 16) },
-                    new BigInteger[]{
-                        new BigInteger("12511cfe811d0f4e6bc688b4d", 16),
-                        new BigInteger("71169be7330b3038edb025f1", 16) },
-                    new BigInteger("71169be7330b3038edb025f1d0f9", 16),
-                    new BigInteger("b3fb3400dec5c4adceb8655d4c94", 16),
-                    208);
+                    new ScalarSplitParameters(
+                        new BigInteger[]{
+                            new BigInteger("71169be7330b3038edb025f1", 16),
+                            new BigInteger("-b3fb3400dec5c4adceb8655c", 16) },
+                        new BigInteger[]{
+                            new BigInteger("12511cfe811d0f4e6bc688b4d", 16),
+                            new BigInteger("71169be7330b3038edb025f1", 16) },
+                        new BigInteger("71169be7330b3038edb025f1d0f9", 16),
+                        new BigInteger("b3fb3400dec5c4adceb8655d4c94", 16),
+                        208));
 
                 ECCurve curve = ConfigureCurveGlv(new FpCurve(p, a, b, n, h), glv);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"
-                    + "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D"));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "04DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -312,9 +322,9 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.One;
 
                 ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"
-                    + "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811"));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "04188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF101207192B95FFC8DA78631011ED6B24CDD573F977A11E794811");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -343,20 +353,21 @@ namespace Org.BouncyCastle.Asn1.Sec
                 GlvTypeBParameters glv = new GlvTypeBParameters(
                     new BigInteger("fe0e87005b4e83761908c5131d552a850b3f58b749c37cf5b84d6768", 16),
                     new BigInteger("60dcd2104c4cbc0be6eeefc2bdd610739ec34e317f9b33046c9e4788", 16),
-                    new BigInteger[]{
-                        new BigInteger("6b8cf07d4ca75c88957d9d670591", 16),
-                        new BigInteger("-b8adf1378a6eb73409fa6c9c637d", 16) },
-                    new BigInteger[]{
-                        new BigInteger("1243ae1b4d71613bc9f780a03690e", 16),
-                        new BigInteger("6b8cf07d4ca75c88957d9d670591", 16) },
-                    new BigInteger("6b8cf07d4ca75c88957d9d67059037a4", 16),
-                    new BigInteger("b8adf1378a6eb73409fa6c9c637ba7f5", 16),
-                    240);
+                    new ScalarSplitParameters(
+                        new BigInteger[]{
+                            new BigInteger("6b8cf07d4ca75c88957d9d670591", 16),
+                            new BigInteger("-b8adf1378a6eb73409fa6c9c637d", 16) },
+                        new BigInteger[]{
+                            new BigInteger("1243ae1b4d71613bc9f780a03690e", 16),
+                            new BigInteger("6b8cf07d4ca75c88957d9d670591", 16) },
+                        new BigInteger("6b8cf07d4ca75c88957d9d67059037a4", 16),
+                        new BigInteger("b8adf1378a6eb73409fa6c9c637ba7f5", 16),
+                        240));
 
                 ECCurve curve = ConfigureCurveGlv(new FpCurve(p, a, b, n, h), glv);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C"
-                    + "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5"));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "04A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -383,9 +394,9 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.One;
 
                 ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"
-                    + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "04B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -414,20 +425,21 @@ namespace Org.BouncyCastle.Asn1.Sec
                 GlvTypeBParameters glv = new GlvTypeBParameters(
                     new BigInteger("7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee", 16),
                     new BigInteger("5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72", 16),
-                    new BigInteger[]{
-                        new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16),
-                        new BigInteger("-e4437ed6010e88286f547fa90abfe4c3", 16) },
-                    new BigInteger[]{
-                        new BigInteger("114ca50f7a8e2f3f657c1108d9d44cfd8", 16),
-                        new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16) },
-                    new BigInteger("3086d221a7d46bcde86c90e49284eb153dab", 16),
-                    new BigInteger("e4437ed6010e88286f547fa90abfe4c42212", 16),
-                    272);
+                    new ScalarSplitParameters(
+                        new BigInteger[]{
+                            new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16),
+                            new BigInteger("-e4437ed6010e88286f547fa90abfe4c3", 16) },
+                        new BigInteger[]{
+                            new BigInteger("114ca50f7a8e2f3f657c1108d9d44cfd8", 16),
+                            new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16) },
+                        new BigInteger("3086d221a7d46bcde86c90e49284eb153dab", 16),
+                        new BigInteger("e4437ed6010e88286f547fa90abfe4c42212", 16),
+                        272));
 
                 ECCurve curve = ConfigureCurveGlv(new FpCurve(p, a, b, n, h), glv);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
-                    + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -454,9 +466,9 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.One;
 
                 ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"
-                    + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -483,9 +495,10 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.One;
 
                 ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+
+                X9ECPoint G = ConfigureBasepoint(curve, "04"
                     + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7"
-                    + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F"));
+                    + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -512,9 +525,10 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.One;
 
                 ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+
+                X9ECPoint G = ConfigureBasepoint(curve, "04"
                     + "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"
-                    + "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"));
+                    + "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -542,9 +556,9 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.ValueOf(2);
 
                 ECCurve curve = new F2mCurve(m, k, a, b, n, h);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "009D73616F35F4AB1407D73562C10F"
-                    + "00A52830277958EE84D1315ED31886"));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "04009D73616F35F4AB1407D73562C10F00A52830277958EE84D1315ED31886");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -572,9 +586,9 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.ValueOf(2);
 
                 ECCurve curve = new F2mCurve(m, k, a, b, n, h);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "01A57A6A7B26CA5EF52FCDB8164797"
-                    + "00B3ADC94ED1FE674C06E695BABA1D"));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0401A57A6A7B26CA5EF52FCDB816479700B3ADC94ED1FE674C06E695BABA1D");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -604,9 +618,9 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.ValueOf(2);
 
                 ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "0081BAF91FDF9833C40F9C181343638399"
-                    + "078C6E7EA38C001F73C8134B1B4EF9E150"));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "040081BAF91FDF9833C40F9C181343638399078C6E7EA38C001F73C8134B1B4EF9E150");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -636,9 +650,9 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.ValueOf(2);
 
                 ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "0356DCD8F2F95031AD652D23951BB366A8"
-                    + "0648F06D867940A5366D9E265DE9EB240F"));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "040356DCD8F2F95031AD652D23951BB366A80648F06D867940A5366D9E265DE9EB240F");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -668,9 +682,9 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.ValueOf(2);
 
                 ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8"
-                    + "0289070FB05D38FF58321F2E800536D538CCDAA3D9"));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0402FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE80289070FB05D38FF58321F2E800536D538CCDAA3D9");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -700,9 +714,9 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.ValueOf(2);
 
                 ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "0369979697AB43897789566789567F787A7876A654"
-                    + "00435EDB42EFAFB2989D51FEFCE3C80988F41FF883"));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "040369979697AB43897789566789567F787A7876A65400435EDB42EFAFB2989D51FEFCE3C80988F41FF883");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -732,9 +746,9 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.ValueOf(2);
 
                 ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "03F0EBA16286A2D57EA0991168D4994637E8343E36"
-                    + "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1"));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0403F0EBA16286A2D57EA0991168D4994637E8343E3600D51FBC6C71A0094FA2CDD545B11C5C0C797324F1");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -762,9 +776,9 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.ValueOf(2);
 
                 ECCurve curve = new F2mCurve(m, k, a, b, n, h);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1"
-                    + "0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05"));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0401F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E10025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -792,9 +806,9 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.ValueOf(2);
 
                 ECCurve curve = new F2mCurve(m, k, a, b, n, h);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F"
-                    + "01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C"));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0400D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -822,9 +836,9 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.ValueOf(4);
 
                 ECCurve curve = new F2mCurve(m, k, a, b, n, h);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126"
-                    + "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3"));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "04017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD612601DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -852,9 +866,9 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.ValueOf(2);
 
                 ECCurve curve = new F2mCurve(m, k, a, b, n, h);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B"
-                    + "01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052"));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0400FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -882,9 +896,9 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.ValueOf(4);
 
                 ECCurve curve = new F2mCurve(m, k, a, b, n, h);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC"
-                    + "76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA"));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0429A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -914,9 +928,10 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.ValueOf(4);
 
                 ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+
+                X9ECPoint G = ConfigureBasepoint(curve, "04"
                     + "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836"
-                    + "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259"));
+                    + "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -946,9 +961,10 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.ValueOf(2);
 
                 ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+
+                X9ECPoint G = ConfigureBasepoint(curve, "04"
                     + "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053"
-                    + "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4"));
+                    + "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -976,9 +992,10 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.ValueOf(4);
 
                 ECCurve curve = new F2mCurve(m, k, a, b, n, h);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+
+                X9ECPoint G = ConfigureBasepoint(curve, "04"
                     + "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746"
-                    + "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B"));
+                    + "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -1006,9 +1023,10 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.ValueOf(2);
 
                 ECCurve curve = new F2mCurve(m, k, a, b, n, h);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+
+                X9ECPoint G = ConfigureBasepoint(curve, "04"
                     + "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7"
-                    + "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706"));
+                    + "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -1038,9 +1056,10 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.ValueOf(4);
 
                 ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+
+                X9ECPoint G = ConfigureBasepoint(curve, "04"
                     + "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972"
-                    + "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3"));
+                    + "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
@@ -1070,9 +1089,10 @@ namespace Org.BouncyCastle.Asn1.Sec
                 BigInteger h = BigInteger.ValueOf(2);
 
                 ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+
+                X9ECPoint G = ConfigureBasepoint(curve, "04"
                     + "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19"
-                    + "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B"));
+                    + "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B");
 
                 return new X9ECParameters(curve, G, n, h, S);
             }
diff --git a/crypto/src/asn1/teletrust/TeleTrusTNamedCurves.cs b/crypto/src/asn1/teletrust/TeleTrusTNamedCurves.cs
index 9a82db319..8393f3ea5 100644
--- a/crypto/src/asn1/teletrust/TeleTrusTNamedCurves.cs
+++ b/crypto/src/asn1/teletrust/TeleTrusTNamedCurves.cs
@@ -3,6 +3,7 @@ using System.Collections;
 using Org.BouncyCastle.Asn1.X9;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Math.EC.Multiplier;
 using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.Collections;
 using Org.BouncyCastle.Utilities.Encoders;
@@ -15,6 +16,13 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
     */
     public class TeleTrusTNamedCurves
     {
+        private static X9ECPoint ConfigureBasepoint(ECCurve curve, string encoding)
+        {
+            X9ECPoint G = new X9ECPoint(curve, Hex.Decode(encoding));
+            WNafUtilities.ConfigureBasepoint(G.Point);
+            return G;
+        }
+
         private static ECCurve ConfigureCurve(ECCurve curve)
         {
             return curve;
@@ -38,10 +46,10 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
                     new BigInteger("1E589A8595423412134FAA2DBDEC95C8D8675E58", 16), // b
                     n, h));
 
-                return new X9ECParameters(
-                    curve,
-                    new X9ECPoint(curve, Hex.Decode("04BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC31667CB477A1A8EC338F94741669C976316DA6321")), // G
-                    n, h);
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "04BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC31667CB477A1A8EC338F94741669C976316DA6321");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -58,16 +66,16 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
                 BigInteger h = new BigInteger("01", 16);
 
                 ECCurve curve = ConfigureCurve(new FpCurve(
-                    //   new BigInteger("24DBFF5DEC9B986BBFE5295A29BFBAE45E0F5D0B", 16), // Z
+                    //new BigInteger("24DBFF5DEC9B986BBFE5295A29BFBAE45E0F5D0B", 16), // Z
                     new BigInteger("E95E4A5F737059DC60DFC7AD95B3D8139515620F", 16), // q
                     new BigInteger("E95E4A5F737059DC60DFC7AD95B3D8139515620C", 16), // a'
                     new BigInteger("7A556B6DAE535B7B51ED2C4D7DAA7A0B5C55F380", 16), // b'
                     n, h));
 
-                return new X9ECParameters(
-                    curve,
-                    new X9ECPoint(curve, Hex.Decode("04B199B13B9B34EFC1397E64BAEB05ACC265FF2378ADD6718B7C7C1961F0991B842443772152C9E0AD")), // G
-                    n, h);
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "04B199B13B9B34EFC1397E64BAEB05ACC265FF2378ADD6718B7C7C1961F0991B842443772152C9E0AD");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -89,10 +97,10 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
                     new BigInteger("469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", 16), // b
                     n, h));
 
-                return new X9ECParameters(
-                    curve,
-                    new X9ECPoint(curve, Hex.Decode("04C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD614B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F")), // G
-                    n, h);
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "04C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD614B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -115,10 +123,10 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
                     new BigInteger("13D56FFAEC78681E68F9DEB43B35BEC2FB68542E27897B79", 16), // b'
                     n, h));
 
-                return new X9ECParameters(
-                    curve,
-                    new X9ECPoint(curve, Hex.Decode("043AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129097E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9")), // G'
-                    n, h);
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "043AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129097E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -140,10 +148,10 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
                     new BigInteger("2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", 16), // b
                     n, h));
 
-                return new X9ECParameters(
-                    curve,
-                    new X9ECPoint(curve, Hex.Decode("040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD")), // G
-                    n, h);
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -166,10 +174,10 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
                     new BigInteger("4B337D934104CD7BEF271BF60CED1ED20DA14C08B3BB64F18A60888D", 16), // b'
                     n, h));
 
-                return new X9ECParameters(
-                    curve,
-                    new X9ECPoint(curve, Hex.Decode("046AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D5800374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C")), // G'
-                    n, h);
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "046AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D5800374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -191,10 +199,10 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
                     new BigInteger("26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", 16), // b
                     n, h));
 
-                return new X9ECParameters(
-                    curve,
-                    new X9ECPoint(curve, Hex.Decode("048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997")), // G
-                    n, h);
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -217,10 +225,10 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
                     new BigInteger("662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04", 16), // b'
                     n, h));
 
-                return new X9ECParameters(
-                    curve,
-                    new X9ECPoint(curve, Hex.Decode("04A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F42D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE")), // G'
-                    n, h);
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "04A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F42D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -242,10 +250,10 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
                     new BigInteger("520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", 16), // b
                     n, h));
 
-                return new X9ECParameters(
-                    curve,
-                    new X9ECPoint(curve, Hex.Decode("0443BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E2061114FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1")), // G
-                    n, h);
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0443BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E2061114FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -268,10 +276,10 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
                     new BigInteger("A7F561E038EB1ED560B3D147DB782013064C19F27ED27C6780AAF77FB8A547CEB5B4FEF422340353", 16), // b'
                     n, h));
 
-                return new X9ECParameters(
-                    curve,
-                    new X9ECPoint(curve, Hex.Decode("04925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF3357F624A21BED5263BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B1B9BC0455FB0D2C3")), // G'
-                    n, h);
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "04925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF3357F624A21BED5263BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B1B9BC0455FB0D2C3");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -293,10 +301,10 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
                     new BigInteger("4A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", 16), // b
                     n, h));
 
-                return new X9ECParameters(
-                    curve,
-                    new X9ECPoint(curve, Hex.Decode("041D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315")), // G
-                    n, h);
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "041D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -319,10 +327,10 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
                     new BigInteger("7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE", 16), // b'
                     n, h));
 
-                return new X9ECParameters(
-                    curve,
-                    new X9ECPoint(curve, Hex.Decode("0418DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928")), // G'
-                    n, h);
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0418DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -344,10 +352,10 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
                     new BigInteger("3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", 16), // b
                     n, h));
 
-                return new X9ECParameters(
-                    curve,
-                    new X9ECPoint(curve, Hex.Decode("0481AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F8227DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892")), // G
-                    n, h);
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0481AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F8227DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -370,10 +378,10 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
                     new BigInteger("7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E", 16), // b'
                     n, h));
 
-                return new X9ECParameters(
-                    curve,
-                    new X9ECPoint(curve, Hex.Decode("04640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332")), // G'
-                    n, h);
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "04640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
diff --git a/crypto/src/asn1/tsp/Accuracy.cs b/crypto/src/asn1/tsp/Accuracy.cs
index c5a5ca119..31289db99 100644
--- a/crypto/src/asn1/tsp/Accuracy.cs
+++ b/crypto/src/asn1/tsp/Accuracy.cs
@@ -22,26 +22,22 @@ namespace Org.BouncyCastle.Asn1.Tsp
 			DerInteger millis,
 			DerInteger micros)
 		{
-			//Verifications
-			if (millis != null
-				&& (millis.Value.IntValue < MinMillis
-					|| millis.Value.IntValue > MaxMillis))
-			{
-				throw new ArgumentException(
-					"Invalid millis field : not in (1..999)");
-			}
-
-			if (micros != null
-				&& (micros.Value.IntValue < MinMicros
-					|| micros.Value.IntValue > MaxMicros))
-			{
-				throw new ArgumentException(
-					"Invalid micros field : not in (1..999)");
-			}
+            if (null != millis)
+            {
+                int millisValue = millis.IntValueExact;
+                if (millisValue < MinMillis || millisValue > MaxMillis)
+                    throw new ArgumentException("Invalid millis field : not in (1..999)");
+            }
+            if (null != micros)
+            {
+                int microsValue = micros.IntValueExact;
+                if (microsValue < MinMicros || microsValue > MaxMicros)
+                    throw new ArgumentException("Invalid micros field : not in (1..999)");
+            }
 
-			this.seconds = seconds;
-			this.millis = millis;
-			this.micros = micros;
+            this.seconds = seconds;
+            this.millis = millis;
+            this.micros = micros;
 		}
 
 		private Accuracy(
@@ -54,33 +50,27 @@ namespace Org.BouncyCastle.Asn1.Tsp
 				{
 					seconds = (DerInteger) seq[i];
 				}
-				else if (seq[i] is DerTaggedObject)
+                else if (seq[i] is Asn1TaggedObject)
 				{
-					DerTaggedObject extra = (DerTaggedObject) seq[i];
+                    Asn1TaggedObject extra = (Asn1TaggedObject)seq[i];
 
-					switch (extra.TagNo)
-					{
-						case 0:
-							millis = DerInteger.GetInstance(extra, false);
-							if (millis.Value.IntValue < MinMillis
-								|| millis.Value.IntValue > MaxMillis)
-							{
-								throw new ArgumentException(
-									"Invalid millis field : not in (1..999).");
-							}
-							break;
-						case 1:
-							micros = DerInteger.GetInstance(extra, false);
-							if (micros.Value.IntValue < MinMicros
-								|| micros.Value.IntValue > MaxMicros)
-							{
-								throw new ArgumentException(
-									"Invalid micros field : not in (1..999).");
-							}
-							break;
-						default:
-							throw new ArgumentException("Invalig tag number");
-					}
+                    switch (extra.TagNo)
+                    {
+                    case 0:
+                        millis = DerInteger.GetInstance(extra, false);
+                        int millisValue = millis.IntValueExact;
+                        if (millisValue < MinMillis || millisValue > MaxMillis)
+                            throw new ArgumentException("Invalid millis field : not in (1..999)");
+                        break;
+                    case 1:
+                        micros = DerInteger.GetInstance(extra, false);
+                        int microsValue = micros.IntValueExact;
+                        if (microsValue < MinMicros || microsValue > MaxMicros)
+                            throw new ArgumentException("Invalid micros field : not in (1..999)");
+                        break;
+                    default:
+                        throw new ArgumentException("Invalid tag number");
+                    }
 				}
 			}
 		}
diff --git a/crypto/src/asn1/util/Asn1Dump.cs b/crypto/src/asn1/util/Asn1Dump.cs
index 6a21ee2af..019041789 100644
--- a/crypto/src/asn1/util/Asn1Dump.cs
+++ b/crypto/src/asn1/util/Asn1Dump.cs
@@ -63,7 +63,7 @@ namespace Org.BouncyCastle.Asn1.Utilities
                     }
                 }
             }
-            else if (obj is DerTaggedObject)
+            else if (obj is Asn1TaggedObject)
             {
                 string tab = indent + Tab;
                 buf.Append(indent);
@@ -76,7 +76,7 @@ namespace Org.BouncyCastle.Asn1.Utilities
                     buf.Append("Tagged [");
                 }
 
-                DerTaggedObject o = (DerTaggedObject)obj;
+                Asn1TaggedObject o = (Asn1TaggedObject)obj;
 
                 buf.Append(((int)o.TagNo).ToString());
                 buf.Append(']');
diff --git a/crypto/src/asn1/x500/style/IetfUtilities.cs b/crypto/src/asn1/x500/style/IetfUtilities.cs
index e3236aaec..2c0ab45bc 100644
--- a/crypto/src/asn1/x500/style/IetfUtilities.cs
+++ b/crypto/src/asn1/x500/style/IetfUtilities.cs
@@ -33,7 +33,7 @@ namespace Org.BouncyCastle.Asn1.X500.Style
                 }
                 catch (IOException e)
                 {
-                    throw new ArgumentException("Other value has no encoded form", "value", e);
+                    throw new ArgumentException("Other value has no encoded form", e);
                 }
             }
 
@@ -85,7 +85,7 @@ namespace Org.BouncyCastle.Asn1.X500.Style
 
             while (endBuf >= 0 && vBuf[endBuf] == ' ')
             {
-                vBuf.Insert(endBuf, '\\');
+                vBuf.Insert(endBuf, "\\");
                 endBuf--;
             }
 
diff --git a/crypto/src/asn1/x509/CRLReason.cs b/crypto/src/asn1/x509/CRLReason.cs
index e8eb53a59..050ceb3bd 100644
--- a/crypto/src/asn1/x509/CRLReason.cs
+++ b/crypto/src/asn1/x509/CRLReason.cs
@@ -45,15 +45,14 @@ namespace Org.BouncyCastle.Asn1.X509
         {
         }
 
-		public CrlReason(
-			DerEnumerated reason)
-			: base(reason.Value.IntValue)
+		public CrlReason(DerEnumerated reason)
+			: base(reason.IntValueExact)
         {
         }
 
 		public override string ToString()
 		{
-			int reason = Value.IntValue;
+			int reason = IntValueExact;
 			string str = (reason < 0 || reason > 10) ? "Invalid" : ReasonString[reason];
 			return "CrlReason: " + str;
 		}    
diff --git a/crypto/src/asn1/x509/GeneralName.cs b/crypto/src/asn1/x509/GeneralName.cs
index b8794ea8f..fe00323ee 100644
--- a/crypto/src/asn1/x509/GeneralName.cs
+++ b/crypto/src/asn1/x509/GeneralName.cs
@@ -170,24 +170,25 @@ namespace Org.BouncyCastle.Asn1.X509
 
 				switch (tag)
 				{
-					case OtherName:
-						return new GeneralName(tag, Asn1Sequence.GetInstance(tagObj, false));
-					case Rfc822Name:
-						return new GeneralName(tag, DerIA5String.GetInstance(tagObj, false));
-					case DnsName:
-						return new GeneralName(tag, DerIA5String.GetInstance(tagObj, false));
-					case X400Address:
-						throw new ArgumentException("unknown tag: " + tag);
+                    case EdiPartyName:
+                    case OtherName:
+                    case X400Address:
+                        return new GeneralName(tag, Asn1Sequence.GetInstance(tagObj, false));
+
+                    case DnsName:
+                    case Rfc822Name:
+                    case UniformResourceIdentifier:
+                        return new GeneralName(tag, DerIA5String.GetInstance(tagObj, false));
+
 					case DirectoryName:
 						return new GeneralName(tag, X509Name.GetInstance(tagObj, true));
-					case EdiPartyName:
-						return new GeneralName(tag, Asn1Sequence.GetInstance(tagObj, false));
-					case UniformResourceIdentifier:
-						return new GeneralName(tag, DerIA5String.GetInstance(tagObj, false));
 					case IPAddress:
 						return new GeneralName(tag, Asn1OctetString.GetInstance(tagObj, false));
 					case RegisteredID:
 						return new GeneralName(tag, DerObjectIdentifier.GetInstance(tagObj, false));
+
+                    default:
+                        throw new ArgumentException("unknown tag: " + tag);
 				}
 	        }
 
@@ -412,8 +413,10 @@ namespace Org.BouncyCastle.Asn1.X509
 
 		public override Asn1Object ToAsn1Object()
         {
-			// Explicitly tagged if DirectoryName
-			return new DerTaggedObject(tag == DirectoryName, tag, obj);
+            // directoryName is explicitly tagged as it is a CHOICE
+            bool isExplicit = (tag == DirectoryName);
+
+            return new DerTaggedObject(isExplicit, tag, obj);
         }
     }
 }
diff --git a/crypto/src/asn1/x509/SubjectPublicKeyInfo.cs b/crypto/src/asn1/x509/SubjectPublicKeyInfo.cs
index 477329b7e..ae44a451f 100644
--- a/crypto/src/asn1/x509/SubjectPublicKeyInfo.cs
+++ b/crypto/src/asn1/x509/SubjectPublicKeyInfo.cs
@@ -66,6 +66,18 @@ namespace Org.BouncyCastle.Asn1.X509
 			get { return algID; }
         }
 
+        /**
+         * for when the public key is an encoded object - if the bitstring
+         * can't be decoded this routine raises an IOException.
+         *
+         * @exception IOException - if the bit string doesn't represent a Der
+         * encoded object.
+         */
+        public Asn1Object ParsePublicKey()
+        {
+            return Asn1Object.FromByteArray(keyData.GetOctets());
+        }
+
 		/**
          * for when the public key is an encoded object - if the bitstring
          * can't be decoded this routine raises an IOException.
@@ -73,6 +85,7 @@ namespace Org.BouncyCastle.Asn1.X509
          * @exception IOException - if the bit string doesn't represent a Der
          * encoded object.
          */
+        [Obsolete("Use 'ParsePublicKey' instead")]
         public Asn1Object GetPublicKey()
         {
 			return Asn1Object.FromByteArray(keyData.GetOctets());
diff --git a/crypto/src/asn1/x509/TBSCertList.cs b/crypto/src/asn1/x509/TBSCertList.cs
index 5767a7f21..a427ba2ba 100644
--- a/crypto/src/asn1/x509/TBSCertList.cs
+++ b/crypto/src/asn1/x509/TBSCertList.cs
@@ -193,13 +193,13 @@ namespace Org.BouncyCastle.Asn1.X509
             }
 
 			if (seqPos < seq.Count
-                && !(seq[seqPos] is DerTaggedObject))
+                && !(seq[seqPos] is Asn1TaggedObject))
             {
 				revokedCertificates = Asn1Sequence.GetInstance(seq[seqPos++]);
 			}
 
 			if (seqPos < seq.Count
-                && seq[seqPos] is DerTaggedObject)
+                && seq[seqPos] is Asn1TaggedObject)
             {
 				crlExtensions = X509Extensions.GetInstance(seq[seqPos]);
 			}
@@ -207,7 +207,7 @@ namespace Org.BouncyCastle.Asn1.X509
 
 		public int Version
         {
-            get { return version.Value.IntValue + 1; }
+            get { return version.IntValueExact + 1; }
         }
 
 		public DerInteger VersionNumber
diff --git a/crypto/src/asn1/x509/TBSCertificateStructure.cs b/crypto/src/asn1/x509/TBSCertificateStructure.cs
index e69e985f5..4e3c789e2 100644
--- a/crypto/src/asn1/x509/TBSCertificateStructure.cs
+++ b/crypto/src/asn1/x509/TBSCertificateStructure.cs
@@ -69,7 +69,7 @@ namespace Org.BouncyCastle.Asn1.X509
 			//
 			// some certficates don't include a version number - we assume v1
 			//
-			if (seq[0] is DerTaggedObject)
+			if (seq[0] is Asn1TaggedObject)
 			{
 				version = DerInteger.GetInstance((Asn1TaggedObject)seq[0], true);
 			}
@@ -121,8 +121,7 @@ namespace Org.BouncyCastle.Asn1.X509
 
             while (extras > 0)
 			{
-				DerTaggedObject extra = (DerTaggedObject)seq[seqStart + 6 + extras];
-
+                Asn1TaggedObject extra = Asn1TaggedObject.GetInstance(seq[seqStart + 6 + extras]);
 				switch (extra.TagNo)
 				{
 				case 1:
@@ -154,7 +153,7 @@ namespace Org.BouncyCastle.Asn1.X509
 
 		public int Version
 		{
-			get { return version.Value.IntValue + 1; }
+            get { return version.IntValueExact + 1; }
 		}
 
 		public DerInteger VersionNumber
diff --git a/crypto/src/asn1/x509/qualified/Iso4217CurrencyCode.cs b/crypto/src/asn1/x509/qualified/Iso4217CurrencyCode.cs
index 9ec88f5ed..a90a33ae2 100644
--- a/crypto/src/asn1/x509/qualified/Iso4217CurrencyCode.cs
+++ b/crypto/src/asn1/x509/qualified/Iso4217CurrencyCode.cs
@@ -35,7 +35,7 @@ namespace Org.BouncyCastle.Asn1.X509.Qualified
 			if (obj is DerInteger)
             {
                 DerInteger numericobj = DerInteger.GetInstance(obj);
-                int numeric = numericobj.Value.IntValue;
+                int numeric = numericobj.IntValueExact;
                 return new Iso4217CurrencyCode(numeric);
             }
 
@@ -74,7 +74,7 @@ namespace Org.BouncyCastle.Asn1.X509.Qualified
 
 		public string Alphabetic { get { return ((DerPrintableString) obj).GetString(); } }
 
-		public int Numeric { get { return ((DerInteger)obj).Value.IntValue; } }
+        public int Numeric { get { return ((DerInteger)obj).IntValueExact; } }
 
 		public override Asn1Object ToAsn1Object()
         {
diff --git a/crypto/src/asn1/x509/qualified/TypeOfBiometricData.cs b/crypto/src/asn1/x509/qualified/TypeOfBiometricData.cs
index 17b7841c3..a4e2e4555 100644
--- a/crypto/src/asn1/x509/qualified/TypeOfBiometricData.cs
+++ b/crypto/src/asn1/x509/qualified/TypeOfBiometricData.cs
@@ -35,7 +35,7 @@ namespace Org.BouncyCastle.Asn1.X509.Qualified
 			if (obj is DerInteger)
             {
                 DerInteger predefinedBiometricTypeObj = DerInteger.GetInstance(obj);
-                int predefinedBiometricType = predefinedBiometricTypeObj.Value.IntValue;
+                int predefinedBiometricType = predefinedBiometricTypeObj.IntValueExact;
 
 				return new TypeOfBiometricData(predefinedBiometricType);
             }
@@ -75,7 +75,7 @@ namespace Org.BouncyCastle.Asn1.X509.Qualified
 
 		public int PredefinedBiometricType
 		{
-			get { return ((DerInteger) obj).Value.IntValue; }
+            get { return ((DerInteger)obj).IntValueExact; }
 		}
 
 		public DerObjectIdentifier BiometricDataOid
diff --git a/crypto/src/asn1/x9/X962NamedCurves.cs b/crypto/src/asn1/x9/X962NamedCurves.cs
index 1609774f1..f8ba4144b 100644
--- a/crypto/src/asn1/x9/X962NamedCurves.cs
+++ b/crypto/src/asn1/x9/X962NamedCurves.cs
@@ -3,6 +3,7 @@ using System.Collections;
 
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Math.EC.Multiplier;
 using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.Collections;
 using Org.BouncyCastle.Utilities.Encoders;
@@ -18,6 +19,18 @@ namespace Org.BouncyCastle.Asn1.X9
         {
         }
 
+        private static X9ECPoint ConfigureBasepoint(ECCurve curve, string encoding)
+        {
+            X9ECPoint G = new X9ECPoint(curve, Hex.Decode(encoding));
+            WNafUtilities.ConfigureBasepoint(G.Point);
+            return G;
+        }
+
+        private static ECCurve ConfigureCurve(ECCurve curve)
+        {
+            return curve;
+        }
+
         internal class Prime192v1Holder
             : X9ECParametersHolder
         {
@@ -30,18 +43,16 @@ namespace Org.BouncyCastle.Asn1.X9
                 BigInteger n = new BigInteger("ffffffffffffffffffffffff99def836146bc9b1b4d22831", 16);
                 BigInteger h = BigInteger.One;
 
-                ECCurve cFp192v1 = new FpCurve(
+                ECCurve curve = ConfigureCurve(new FpCurve(
                     new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", 16),
                     new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
                     new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16),
-                    n, h);
-
-                return new X9ECParameters(
-                    cFp192v1,
-                    new X9ECPoint(cFp192v1,
-                        Hex.Decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")),
-                    n, h,
-                    Hex.Decode("3045AE6FC8422f64ED579528D38120EAE12196D5"));
+                    n, h));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012");
+
+                return new X9ECParameters(curve, G, n, h, Hex.Decode("3045AE6FC8422f64ED579528D38120EAE12196D5"));
             }
         }
 
@@ -57,18 +68,16 @@ namespace Org.BouncyCastle.Asn1.X9
                 BigInteger n = new BigInteger("fffffffffffffffffffffffe5fb1a724dc80418648d8dd31", 16);
                 BigInteger h = BigInteger.One;
 
-                ECCurve cFp192v2 = new FpCurve(
+                ECCurve curve = ConfigureCurve(new FpCurve(
                     new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", 16),
                     new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
                     new BigInteger("cc22d6dfb95c6b25e49c0d6364a4e5980c393aa21668d953", 16),
-                    n, h);
-
-                return new X9ECParameters(
-                    cFp192v2,
-                    new X9ECPoint(cFp192v2,
-                        Hex.Decode("03eea2bae7e1497842f2de7769cfe9c989c072ad696f48034a")),
-                    n, h,
-                    Hex.Decode("31a92ee2029fd10d901b113e990710f0d21ac6b6"));
+                    n, h));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "03eea2bae7e1497842f2de7769cfe9c989c072ad696f48034a");
+
+                return new X9ECParameters(curve, G, n, h, Hex.Decode("31a92ee2029fd10d901b113e990710f0d21ac6b6"));
             }
         }
 
@@ -84,18 +93,16 @@ namespace Org.BouncyCastle.Asn1.X9
                 BigInteger n = new BigInteger("ffffffffffffffffffffffff7a62d031c83f4294f640ec13", 16);
                 BigInteger h = BigInteger.One;
 
-                ECCurve cFp192v3 = new FpCurve(
+                ECCurve curve = ConfigureCurve(new FpCurve(
                     new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", 16),
                     new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
                     new BigInteger("22123dc2395a05caa7423daeccc94760a7d462256bd56916", 16),
-                    n, h);
-
-                return new X9ECParameters(
-                    cFp192v3,
-                    new X9ECPoint(cFp192v3,
-                        Hex.Decode("027d29778100c65a1da1783716588dce2b8b4aee8e228f1896")),
-                    n, h,
-                    Hex.Decode("c469684435deb378c4b65ca9591e2a5763059a2e"));
+                    n, h));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "027d29778100c65a1da1783716588dce2b8b4aee8e228f1896");
+
+                return new X9ECParameters(curve, G, n, h, Hex.Decode("c469684435deb378c4b65ca9591e2a5763059a2e"));
             }
         }
 
@@ -111,18 +118,16 @@ namespace Org.BouncyCastle.Asn1.X9
                 BigInteger n = new BigInteger("7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b", 16);
                 BigInteger h = BigInteger.One;
 
-                ECCurve cFp239v1 = new FpCurve(
+                ECCurve curve = ConfigureCurve(new FpCurve(
                     new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"),
                     new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16),
                     new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16),
-                    n, h);
-
-                return new X9ECParameters(
-                    cFp239v1,
-                    new X9ECPoint(cFp239v1,
-                        Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")),
-                    n, h,
-                    Hex.Decode("e43bb460f0b80cc0c0b075798e948060f8321b7d"));
+                    n, h));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf");
+
+                return new X9ECParameters(curve, G, n, h, Hex.Decode("e43bb460f0b80cc0c0b075798e948060f8321b7d"));
             }
         }
 
@@ -138,18 +143,16 @@ namespace Org.BouncyCastle.Asn1.X9
                 BigInteger n = new BigInteger("7fffffffffffffffffffffff800000cfa7e8594377d414c03821bc582063", 16);
                 BigInteger h = BigInteger.One;
 
-                ECCurve cFp239v2 = new FpCurve(
+                ECCurve curve = ConfigureCurve(new FpCurve(
                     new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"),
                     new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16),
                     new BigInteger("617fab6832576cbbfed50d99f0249c3fee58b94ba0038c7ae84c8c832f2c", 16),
-                    n, h);
-
-                return new X9ECParameters(
-                    cFp239v2,
-                    new X9ECPoint(cFp239v2,
-                        Hex.Decode("0238af09d98727705120c921bb5e9e26296a3cdcf2f35757a0eafd87b830e7")),
-                    n, h,
-                    Hex.Decode("e8b4011604095303ca3b8099982be09fcb9ae616"));
+                    n, h));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0238af09d98727705120c921bb5e9e26296a3cdcf2f35757a0eafd87b830e7");
+
+                return new X9ECParameters(curve, G, n, h, Hex.Decode("e8b4011604095303ca3b8099982be09fcb9ae616"));
             }
         }
 
@@ -165,18 +168,16 @@ namespace Org.BouncyCastle.Asn1.X9
                 BigInteger n = new BigInteger("7fffffffffffffffffffffff7fffff975deb41b3a6057c3c432146526551", 16);
                 BigInteger h = BigInteger.One;
 
-                ECCurve cFp239v3 = new FpCurve(
+                ECCurve curve = ConfigureCurve(new FpCurve(
                     new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"),
                     new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16),
                     new BigInteger("255705fa2a306654b1f4cb03d6a750a30c250102d4988717d9ba15ab6d3e", 16),
-                    n, h);
-
-                return new X9ECParameters(
-                    cFp239v3,
-                    new X9ECPoint(cFp239v3,
-                        Hex.Decode("036768ae8e18bb92cfcf005c949aa2c6d94853d0e660bbf854b1c9505fe95a")),
-                    n, h,
-                    Hex.Decode("7d7374168ffe3471b60a857686a19475d3bfa2ff"));
+                    n, h));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "036768ae8e18bb92cfcf005c949aa2c6d94853d0e660bbf854b1c9505fe95a");
+
+                return new X9ECParameters(curve, G, n, h, Hex.Decode("7d7374168ffe3471b60a857686a19475d3bfa2ff"));
             }
         }
 
@@ -192,18 +193,16 @@ namespace Org.BouncyCastle.Asn1.X9
                 BigInteger n = new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16);
                 BigInteger h = BigInteger.One;
 
-                ECCurve cFp256v1 = new FpCurve(
+                ECCurve curve = ConfigureCurve(new FpCurve(
                     new BigInteger("115792089210356248762697446949407573530086143415290314195533631308867097853951"),
                     new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16),
                     new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16),
-                    n, h);
-
-                return new X9ECParameters(
-                    cFp256v1,
-                    new X9ECPoint(cFp256v1,
-                        Hex.Decode("036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296")),
-                    n, h,
-                    Hex.Decode("c49d360886e704936a6678e1139d26b7819f7e90"));
+                    n, h));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296");
+
+                return new X9ECParameters(curve, G, n, h, Hex.Decode("c49d360886e704936a6678e1139d26b7819f7e90"));
             }
         }
 
@@ -222,19 +221,17 @@ namespace Org.BouncyCastle.Asn1.X9
                 BigInteger n = new BigInteger("0400000000000000000001E60FC8821CC74DAEAFC1", 16);
                 BigInteger h = BigInteger.Two;
 
-                ECCurve c2m163v1 = new F2mCurve(
+                ECCurve curve = ConfigureCurve(new F2mCurve(
                     163,
                     1, 2, 8,
                     new BigInteger("072546B5435234A422E0789675F432C89435DE5242", 16),
                     new BigInteger("00C9517D06D5240D3CFF38C74B20B6CD4D6F9DD4D9", 16),
-                    n, h);
-
-                return new X9ECParameters(
-                    c2m163v1,
-                    new X9ECPoint(c2m163v1,
-                        Hex.Decode("0307AF69989546103D79329FCC3D74880F33BBE803CB")),
-                    n, h,
-                    Hex.Decode("D2C0FB15760860DEF1EEF4D696E6768756151754"));
+                    n, h));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0307AF69989546103D79329FCC3D74880F33BBE803CB");
+
+                return new X9ECParameters(curve, G, n, h, Hex.Decode("D2C0FB15760860DEF1EEF4D696E6768756151754"));
             }
         }
 
@@ -250,19 +247,17 @@ namespace Org.BouncyCastle.Asn1.X9
                 BigInteger n = new BigInteger("03FFFFFFFFFFFFFFFFFFFDF64DE1151ADBB78F10A7", 16);
                 BigInteger h = BigInteger.Two;
 
-                ECCurve c2m163v2 = new F2mCurve(
+                ECCurve curve = ConfigureCurve(new F2mCurve(
                     163,
                     1, 2, 8,
                     new BigInteger("0108B39E77C4B108BED981ED0E890E117C511CF072", 16),
                     new BigInteger("0667ACEB38AF4E488C407433FFAE4F1C811638DF20", 16),
-                    n, h);
-
-                return new X9ECParameters(
-                    c2m163v2,
-                    new X9ECPoint(c2m163v2,
-                        Hex.Decode("030024266E4EB5106D0A964D92C4860E2671DB9B6CC5")),
-                    n, h,
-                    null);
+                    n, h));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "030024266E4EB5106D0A964D92C4860E2671DB9B6CC5");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -278,18 +273,17 @@ namespace Org.BouncyCastle.Asn1.X9
                 BigInteger n = new BigInteger("03FFFFFFFFFFFFFFFFFFFE1AEE140F110AFF961309", 16);
                 BigInteger h = BigInteger.Two;
 
-                ECCurve c2m163v3 = new F2mCurve(
+                ECCurve curve = ConfigureCurve(new F2mCurve(
                     163,
                     1, 2, 8,
                     new BigInteger("07A526C63D3E25A256A007699F5447E32AE456B50E", 16),
                     new BigInteger("03F7061798EB99E238FD6F1BF95B48FEEB4854252B", 16),
-                    n, h);
+                    n, h));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0202F9F87B7C574D0BDECF8A22E6524775F98CDEBDCB");
 
-                return new X9ECParameters(
-                    c2m163v3,
-                    new X9ECPoint(c2m163v3, Hex.Decode("0202F9F87B7C574D0BDECF8A22E6524775F98CDEBDCB")),
-                    n, h,
-                    null);
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -305,19 +299,17 @@ namespace Org.BouncyCastle.Asn1.X9
                 BigInteger n = new BigInteger("010092537397ECA4F6145799D62B0A19CE06FE26AD", 16);
                 BigInteger h = BigInteger.ValueOf(0xFF6E);
 
-                ECCurve c2m176w1 = new F2mCurve(
+                ECCurve curve = ConfigureCurve(new F2mCurve(
                     176,
                     1, 2, 43,
                     new BigInteger("00E4E6DB2995065C407D9D39B8D0967B96704BA8E9C90B", 16),
                     new BigInteger("005DDA470ABE6414DE8EC133AE28E9BBD7FCEC0AE0FFF2", 16),
-                    n, h);
-
-                return new X9ECParameters(
-                    c2m176w1,
-                    new X9ECPoint(c2m176w1,
-                        Hex.Decode("038D16C2866798B600F9F08BB4A8E860F3298CE04A5798")),
-                    n, h,
-                    null);
+                    n, h));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "038D16C2866798B600F9F08BB4A8E860F3298CE04A5798");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -333,19 +325,17 @@ namespace Org.BouncyCastle.Asn1.X9
                 BigInteger n = new BigInteger("40000000000000000000000004A20E90C39067C893BBB9A5", 16);
                 BigInteger h = BigInteger.Two;
 
-                ECCurve c2m191v1 = new F2mCurve(
+                ECCurve curve = ConfigureCurve(new F2mCurve(
                     191,
                     9,
                     new BigInteger("2866537B676752636A68F56554E12640276B649EF7526267", 16),
                     new BigInteger("2E45EF571F00786F67B0081B9495A3D95462F5DE0AA185EC", 16),
-                    n, h);
-
-                return new X9ECParameters(
-                    c2m191v1,
-                    new X9ECPoint(c2m191v1,
-                        Hex.Decode("0236B3DAF8A23206F9C4F299D7B21A9C369137F2C84AE1AA0D")),
-                    n, h,
-                    Hex.Decode("4E13CA542744D696E67687561517552F279A8C84"));
+                    n, h));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0236B3DAF8A23206F9C4F299D7B21A9C369137F2C84AE1AA0D");
+
+                return new X9ECParameters(curve, G, n, h, Hex.Decode("4E13CA542744D696E67687561517552F279A8C84"));
             }
         }
 
@@ -361,19 +351,17 @@ namespace Org.BouncyCastle.Asn1.X9
                 BigInteger n = new BigInteger("20000000000000000000000050508CB89F652824E06B8173", 16);
                 BigInteger h = BigInteger.ValueOf(4);
 
-                ECCurve c2m191v2 = new F2mCurve(
+                ECCurve curve = ConfigureCurve(new F2mCurve(
                     191,
                     9,
                     new BigInteger("401028774D7777C7B7666D1366EA432071274F89FF01E718", 16),
                     new BigInteger("0620048D28BCBD03B6249C99182B7C8CD19700C362C46A01", 16),
-                    n, h);
-
-                return new X9ECParameters(
-                    c2m191v2,
-                    new X9ECPoint(c2m191v2,
-                        Hex.Decode("023809B2B7CC1B28CC5A87926AAD83FD28789E81E2C9E3BF10")),
-                    n, h,
-                    null);
+                    n, h));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "023809B2B7CC1B28CC5A87926AAD83FD28789E81E2C9E3BF10");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -389,19 +377,17 @@ namespace Org.BouncyCastle.Asn1.X9
                 BigInteger n = new BigInteger("155555555555555555555555610C0B196812BFB6288A3EA3", 16);
                 BigInteger h = BigInteger.ValueOf(6);
 
-                ECCurve c2m191v3 = new F2mCurve(
+                ECCurve curve = ConfigureCurve(new F2mCurve(
                     191,
                     9,
                     new BigInteger("6C01074756099122221056911C77D77E77A777E7E7E77FCB", 16),
                     new BigInteger("71FE1AF926CF847989EFEF8DB459F66394D90F32AD3F15E8", 16),
-                    n, h);
-
-                return new X9ECParameters(
-                    c2m191v3,
-                    new X9ECPoint(c2m191v3,
-                        Hex.Decode("03375D4CE24FDE434489DE8746E71786015009E66E38A926DD")),
-                    n, h,
-                    null);
+                    n, h));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "03375D4CE24FDE434489DE8746E71786015009E66E38A926DD");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -417,19 +403,17 @@ namespace Org.BouncyCastle.Asn1.X9
                 BigInteger n = new BigInteger("0101BAF95C9723C57B6C21DA2EFF2D5ED588BDD5717E212F9D", 16);
                 BigInteger h = BigInteger.ValueOf(0xFE48);
 
-                ECCurve c2m208w1 = new F2mCurve(
+                ECCurve curve = ConfigureCurve(new F2mCurve(
                     208,
                     1, 2, 83,
                     new BigInteger("0", 16),
                     new BigInteger("00C8619ED45A62E6212E1160349E2BFA844439FAFC2A3FD1638F9E", 16),
-                    n, h);
-
-                return new X9ECParameters(
-                    c2m208w1,
-                    new X9ECPoint(c2m208w1,
-                        Hex.Decode("0289FDFBE4ABE193DF9559ECF07AC0CE78554E2784EB8C1ED1A57A")),
-                    n, h,
-                    null);
+                    n, h));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0289FDFBE4ABE193DF9559ECF07AC0CE78554E2784EB8C1ED1A57A");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -445,19 +429,17 @@ namespace Org.BouncyCastle.Asn1.X9
                 BigInteger n = new BigInteger("2000000000000000000000000000000F4D42FFE1492A4993F1CAD666E447", 16);
                 BigInteger h = BigInteger.ValueOf(4);
 
-                ECCurve c2m239v1 = new F2mCurve(
+                ECCurve curve = ConfigureCurve(new F2mCurve(
                     239,
                     36,
                     new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16),
                     new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16),
-                    n, h);
-
-                return new X9ECParameters(
-                    c2m239v1,
-                    new X9ECPoint(c2m239v1,
-                        Hex.Decode("0257927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D")),
-                    n, h,
-                    null);
+                    n, h));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0257927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -473,19 +455,17 @@ namespace Org.BouncyCastle.Asn1.X9
                 BigInteger n = new BigInteger("1555555555555555555555555555553C6F2885259C31E3FCDF154624522D", 16);
                 BigInteger h = BigInteger.ValueOf(6);
 
-                ECCurve c2m239v2 = new F2mCurve(
+                ECCurve curve = ConfigureCurve(new F2mCurve(
                     239,
                     36,
                     new BigInteger("4230017757A767FAE42398569B746325D45313AF0766266479B75654E65F", 16),
                     new BigInteger("5037EA654196CFF0CD82B2C14A2FCF2E3FF8775285B545722F03EACDB74B", 16),
-                    n, h);
-
-                return new X9ECParameters(
-                    c2m239v2,
-                    new X9ECPoint(c2m239v2,
-                        Hex.Decode("0228F9D04E900069C8DC47A08534FE76D2B900B7D7EF31F5709F200C4CA205")),
-                    n, h,
-                    null);
+                    n, h));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0228F9D04E900069C8DC47A08534FE76D2B900B7D7EF31F5709F200C4CA205");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -501,19 +481,17 @@ namespace Org.BouncyCastle.Asn1.X9
                 BigInteger n = new BigInteger("0CCCCCCCCCCCCCCCCCCCCCCCCCCCCCAC4912D2D9DF903EF9888B8A0E4CFF", 16);
                 BigInteger h = BigInteger.ValueOf(10);
 
-                ECCurve c2m239v3 = new F2mCurve(
+                ECCurve curve = ConfigureCurve(new F2mCurve(
                     239,
                     36,
                     new BigInteger("01238774666A67766D6676F778E676B66999176666E687666D8766C66A9F", 16),
                     new BigInteger("6A941977BA9F6A435199ACFC51067ED587F519C5ECB541B8E44111DE1D40", 16),
-                    n, h);
-
-                return new X9ECParameters(
-                    c2m239v3,
-                    new X9ECPoint(c2m239v3,
-                        Hex.Decode("0370F6E9D04D289C4E89913CE3530BFDE903977D42B146D539BF1BDE4E9C92")),
-                    n, h,
-                    null);
+                    n, h));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0370F6E9D04D289C4E89913CE3530BFDE903977D42B146D539BF1BDE4E9C92");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -529,19 +507,17 @@ namespace Org.BouncyCastle.Asn1.X9
                 BigInteger n = new BigInteger("0100FAF51354E0E39E4892DF6E319C72C8161603FA45AA7B998A167B8F1E629521", 16);
                 BigInteger h = BigInteger.ValueOf(0xFF06);
 
-                ECCurve c2m272w1 = new F2mCurve(
+                ECCurve curve = ConfigureCurve(new F2mCurve(
                     272,
                     1, 3, 56,
                     new BigInteger("0091A091F03B5FBA4AB2CCF49C4EDD220FB028712D42BE752B2C40094DBACDB586FB20", 16),
                     new BigInteger("7167EFC92BB2E3CE7C8AAAFF34E12A9C557003D7C73A6FAF003F99F6CC8482E540F7", 16),
-                    n, h);
-
-                return new X9ECParameters(
-                    c2m272w1,
-                    new X9ECPoint(c2m272w1,
-                        Hex.Decode("026108BABB2CEEBCF787058A056CBE0CFE622D7723A289E08A07AE13EF0D10D171DD8D")),
-                    n, h,
-                    null);
+                    n, h));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "026108BABB2CEEBCF787058A056CBE0CFE622D7723A289E08A07AE13EF0D10D171DD8D");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -557,19 +533,17 @@ namespace Org.BouncyCastle.Asn1.X9
                 BigInteger n = new BigInteger("0101D556572AABAC800101D556572AABAC8001022D5C91DD173F8FB561DA6899164443051D", 16);
                 BigInteger h = BigInteger.ValueOf(0xFE2E);
 
-                ECCurve c2m304w1 = new F2mCurve(
+                ECCurve curve = ConfigureCurve(new F2mCurve(
                     304,
                     1, 2, 11,
                     new BigInteger("00FD0D693149A118F651E6DCE6802085377E5F882D1B510B44160074C1288078365A0396C8E681", 16),
                     new BigInteger("00BDDB97E555A50A908E43B01C798EA5DAA6788F1EA2794EFCF57166B8C14039601E55827340BE", 16),
-                    n, h);
-
-                return new X9ECParameters(
-                    c2m304w1,
-                    new X9ECPoint(c2m304w1,
-                        Hex.Decode("02197B07845E9BE2D96ADB0F5F3C7F2CFFBD7A3EB8B6FEC35C7FD67F26DDF6285A644F740A2614")),
-                    n, h,
-                    null);
+                    n, h));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "02197B07845E9BE2D96ADB0F5F3C7F2CFFBD7A3EB8B6FEC35C7FD67F26DDF6285A644F740A2614");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -585,19 +559,17 @@ namespace Org.BouncyCastle.Asn1.X9
                 BigInteger n = new BigInteger("01AF286BCA1AF286BCA1AF286BCA1AF286BCA1AF286BC9FB8F6B85C556892C20A7EB964FE7719E74F490758D3B", 16);
                 BigInteger h = BigInteger.ValueOf(0x4C);
 
-                ECCurve c2m359v1 = new F2mCurve(
+                ECCurve curve = ConfigureCurve(new F2mCurve(
                     359,
                     68,
                     new BigInteger("5667676A654B20754F356EA92017D946567C46675556F19556A04616B567D223A5E05656FB549016A96656A557", 16),
                     new BigInteger("2472E2D0197C49363F1FE7F5B6DB075D52B6947D135D8CA445805D39BC345626089687742B6329E70680231988", 16),
-                    n, h);
-
-                return new X9ECParameters(
-                    c2m359v1,
-                    new X9ECPoint(c2m359v1,
-                        Hex.Decode("033C258EF3047767E7EDE0F1FDAA79DAEE3841366A132E163ACED4ED2401DF9C6BDCDE98E8E707C07A2239B1B097")),
-                    n, h,
-                    null);
+                    n, h));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "033C258EF3047767E7EDE0F1FDAA79DAEE3841366A132E163ACED4ED2401DF9C6BDCDE98E8E707C07A2239B1B097");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -613,19 +585,17 @@ namespace Org.BouncyCastle.Asn1.X9
                 BigInteger n = new BigInteger("010090512DA9AF72B08349D98A5DD4C7B0532ECA51CE03E2D10F3B7AC579BD87E909AE40A6F131E9CFCE5BD967", 16);
                 BigInteger h = BigInteger.ValueOf(0xFF70);
 
-                ECCurve c2m368w1 = new F2mCurve(
+                ECCurve curve = ConfigureCurve(new F2mCurve(
                     368,
                     1, 2, 85,
                     new BigInteger("00E0D2EE25095206F5E2A4F9ED229F1F256E79A0E2B455970D8D0D865BD94778C576D62F0AB7519CCD2A1A906AE30D", 16),
                     new BigInteger("00FC1217D4320A90452C760A58EDCD30C8DD069B3C34453837A34ED50CB54917E1C2112D84D164F444F8F74786046A", 16),
-                    n, h);
-
-                return new X9ECParameters(
-                    c2m368w1,
-                    new X9ECPoint(c2m368w1,
-                        Hex.Decode("021085E2755381DCCCE3C1557AFA10C2F0C0C2825646C5B34A394CBCFA8BC16B22E7E789E927BE216F02E1FB136A5F")),
-                    n, h,
-                    null);
+                    n, h));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "021085E2755381DCCCE3C1557AFA10C2F0C0C2825646C5B34A394CBCFA8BC16B22E7E789E927BE216F02E1FB136A5F");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
@@ -641,22 +611,21 @@ namespace Org.BouncyCastle.Asn1.X9
                 BigInteger n = new BigInteger("0340340340340340340340340340340340340340340340340340340323C313FAB50589703B5EC68D3587FEC60D161CC149C1AD4A91", 16);
                 BigInteger h = BigInteger.ValueOf(0x2760);
 
-                ECCurve c2m431r1 = new F2mCurve(
+                ECCurve curve = ConfigureCurve(new F2mCurve(
                     431,
                     120,
                     new BigInteger("1A827EF00DD6FC0E234CAF046C6A5D8A85395B236CC4AD2CF32A0CADBDC9DDF620B0EB9906D0957F6C6FEACD615468DF104DE296CD8F", 16),
                     new BigInteger("10D9B4A3D9047D8B154359ABFB1B7F5485B04CEB868237DDC9DEDA982A679A5A919B626D4E50A8DD731B107A9962381FB5D807BF2618", 16),
-                    n, h);
-
-                return new X9ECParameters(
-                    c2m431r1,
-                    new X9ECPoint(c2m431r1,
-                        Hex.Decode("02120FC05D3C67A99DE161D2F4092622FECA701BE4F50F4758714E8A87BBF2A658EF8C21E7C5EFE965361F6C2999C0C247B0DBD70CE6B7")),
-                    n, h,
-                    null);
+                    n, h));
+
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "02120FC05D3C67A99DE161D2F4092622FECA701BE4F50F4758714E8A87BBF2A658EF8C21E7C5EFE965361F6C2999C0C247B0DBD70CE6B7");
+
+                return new X9ECParameters(curve, G, n, h);
             }
         }
 
+
         private static readonly IDictionary objIds = Platform.CreateHashtable();
         private static readonly IDictionary curves = Platform.CreateHashtable();
         private static readonly IDictionary names = Platform.CreateHashtable();
diff --git a/crypto/src/asn1/x9/X9Curve.cs b/crypto/src/asn1/x9/X9Curve.cs
index eab94def8..0be9bf935 100644
--- a/crypto/src/asn1/x9/X9Curve.cs
+++ b/crypto/src/asn1/x9/X9Curve.cs
@@ -79,9 +79,8 @@ namespace Org.BouncyCastle.Asn1.X9
             {
                 // Characteristic two field
                 DerSequence parameters = (DerSequence)fieldID.Parameters;
-                int m = ((DerInteger)parameters[0]).Value.IntValue;
-                DerObjectIdentifier representation
-                    = (DerObjectIdentifier)parameters[1];
+                int m = ((DerInteger)parameters[0]).IntValueExact;
+                DerObjectIdentifier representation = (DerObjectIdentifier)parameters[1];
 
                 int k1 = 0;
                 int k2 = 0;
@@ -89,15 +88,15 @@ namespace Org.BouncyCastle.Asn1.X9
                 if (representation.Equals(X9ObjectIdentifiers.TPBasis)) 
                 {
                     // Trinomial basis representation
-                    k1 = ((DerInteger)parameters[2]).Value.IntValue;
+                    k1 = ((DerInteger)parameters[2]).IntValueExact;
                 }
                 else 
                 {
                     // Pentanomial basis representation
                     DerSequence pentanomial = (DerSequence) parameters[2];
-                    k1 = ((DerInteger) pentanomial[0]).Value.IntValue;
-                    k2 = ((DerInteger) pentanomial[1]).Value.IntValue;
-                    k3 = ((DerInteger) pentanomial[2]).Value.IntValue;
+                    k1 = ((DerInteger)pentanomial[0]).IntValueExact;
+                    k2 = ((DerInteger)pentanomial[1]).IntValueExact;
+                    k3 = ((DerInteger)pentanomial[2]).IntValueExact;
                 }
                 BigInteger A = new BigInteger(1, Asn1OctetString.GetInstance(seq[0]).GetOctets());
                 BigInteger B = new BigInteger(1, Asn1OctetString.GetInstance(seq[1]).GetOctets());
diff --git a/crypto/src/cmp/ProtectedPkiMessage.cs b/crypto/src/cmp/ProtectedPkiMessage.cs
index faddb0df1..770fe5443 100644
--- a/crypto/src/cmp/ProtectedPkiMessage.cs
+++ b/crypto/src/cmp/ProtectedPkiMessage.cs
@@ -120,11 +120,7 @@ namespace Org.BouncyCastle.Cmp
 
             streamCalculator.Stream.Write(enc, 0, enc.Length);
             streamCalculator.Stream.Flush();
-#if PORTABLE
-            streamCalculator.Stream.Dispose();
-#else
-            streamCalculator.Stream.Close();
-#endif
+            Platform.Dispose(streamCalculator.Stream);
 
             return streamCalculator.GetResult();
         }
diff --git a/crypto/src/cmp/ProtectedPkiMessageBuilder.cs b/crypto/src/cmp/ProtectedPkiMessageBuilder.cs
index 8ce0d48dc..5939e92df 100644
--- a/crypto/src/cmp/ProtectedPkiMessageBuilder.cs
+++ b/crypto/src/cmp/ProtectedPkiMessageBuilder.cs
@@ -90,6 +90,9 @@ namespace Org.BouncyCastle.Cmp
 
         public ProtectedPkiMessage Build(ISignatureFactory signatureFactory)
         {
+            if (null == body)
+                throw new InvalidOperationException("body must be set before building");
+
             IStreamCalculator calculator = signatureFactory.CreateCalculator();
 
             if (!(signatureFactory.AlgorithmDetails is AlgorithmIdentifier))
@@ -105,6 +108,9 @@ namespace Org.BouncyCastle.Cmp
 
         public ProtectedPkiMessage Build(IMacFactory factory)
         {
+            if (null == body)
+                throw new InvalidOperationException("body must be set before building");
+
             IStreamCalculator calculator = factory.CreateCalculator();
             FinalizeHeader((AlgorithmIdentifier)factory.AlgorithmDetails);
             PkiHeader header = hdrBuilBuilder.Build();
diff --git a/crypto/src/cms/CMSSignedData.cs b/crypto/src/cms/CMSSignedData.cs
index 237c1528e..979be6535 100644
--- a/crypto/src/cms/CMSSignedData.cs
+++ b/crypto/src/cms/CMSSignedData.cs
@@ -147,7 +147,7 @@ namespace Org.BouncyCastle.Cms
 		/// <summary>Return the version number for this object.</summary>
 		public int Version
 		{
-			get { return signedData.Version.Value.IntValue; }
+			get { return signedData.Version.IntValueExact; }
 		}
 
 		/**
diff --git a/crypto/src/cms/CMSSignedDataParser.cs b/crypto/src/cms/CMSSignedDataParser.cs
index fb51ab119..c25f0aad0 100644
--- a/crypto/src/cms/CMSSignedDataParser.cs
+++ b/crypto/src/cms/CMSSignedDataParser.cs
@@ -179,7 +179,7 @@ namespace Org.BouncyCastle.Cms
 		 */
 		public int Version
 		{
-			get { return _signedData.Version.Value.IntValue; }
+			get { return _signedData.Version.IntValueExact; }
 		}
 
 		public ISet DigestOids
diff --git a/crypto/src/cms/CMSSignedDataStreamGenerator.cs b/crypto/src/cms/CMSSignedDataStreamGenerator.cs
index 29411e132..e32f95d42 100644
--- a/crypto/src/cms/CMSSignedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSSignedDataStreamGenerator.cs
@@ -732,7 +732,7 @@ namespace Org.BouncyCastle.Cms
 			{
 				SignerInfo s = SignerInfo.GetInstance(si.ToSignerInfo());
 
-				if (s.Version.Value.IntValue == 3)
+				if (s.Version.IntValueExact == 3)
 				{
 					return true;
 				}
diff --git a/crypto/src/cms/SignerInformation.cs b/crypto/src/cms/SignerInformation.cs
index c262806a8..3643c6fe3 100644
--- a/crypto/src/cms/SignerInformation.cs
+++ b/crypto/src/cms/SignerInformation.cs
@@ -129,7 +129,7 @@ namespace Org.BouncyCastle.Cms
 		*/
 		public int Version
 		{
-			get { return info.Version.Value.IntValue; }
+			get { return info.Version.IntValueExact; }
 		}
 
 		public AlgorithmIdentifier DigestAlgorithmID
@@ -349,8 +349,8 @@ namespace Org.BouncyCastle.Cms
 						throw new CmsException("RSASSA-PSS signature parameters specified unknown MGF");
 
                     IDigest pssDigest = DigestUtilities.GetDigest(pss.HashAlgorithm.Algorithm);
-					int saltLength = pss.SaltLength.Value.IntValue;
-					byte trailerField = (byte) pss.TrailerField.Value.IntValue;
+                    int saltLength = pss.SaltLength.IntValueExact;
+                    byte trailerField = (byte)pss.TrailerField.IntValueExact;
 
 					// RFC 4055 3.1
 					// The value MUST be 1, which represents the trailer field with hexadecimal value 0xBC
diff --git a/crypto/src/crmf/EncryptedValueBuilder.cs b/crypto/src/crmf/EncryptedValueBuilder.cs
index 87ab0cd10..d95896959 100644
--- a/crypto/src/crmf/EncryptedValueBuilder.cs
+++ b/crypto/src/crmf/EncryptedValueBuilder.cs
@@ -121,11 +121,7 @@ namespace Org.BouncyCastle.Crmf
             try
             {
                 eOut.Write(data, 0, data.Length);
-#if PORTABLE
-                eOut.Dispose();
-#else
-                eOut.Close();
-#endif
+                Platform.Dispose(eOut);
             }
             catch (IOException e)
             {
diff --git a/crypto/src/crmf/PKMacBuilder.cs b/crypto/src/crmf/PKMacBuilder.cs
index b74eb6d18..156936eac 100644
--- a/crypto/src/crmf/PKMacBuilder.cs
+++ b/crypto/src/crmf/PKMacBuilder.cs
@@ -184,7 +184,7 @@ namespace Org.BouncyCastle.Crmf
         /// <returns>this</returns>
         public PKMacBuilder SetParameters(PbmParameter parameters)
         {
-            CheckIterationCountCeiling(parameters.IterationCount.Value.IntValue);
+            CheckIterationCountCeiling(parameters.IterationCount.IntValueExact);
 
             this.parameters = parameters;
 
@@ -257,7 +257,7 @@ namespace Org.BouncyCastle.Crmf
 
             IDigest digest = provider.CreateDigest(parameters.Owf);
 
-            int iter = parameters.IterationCount.Value.IntValue;
+            int iter = parameters.IterationCount.IntValueExact;
 
             digest.BlockUpdate(K, 0, K.Length);
 
diff --git a/crypto/src/crmf/ProofOfPossessionSigningKeyBuilder.cs b/crypto/src/crmf/ProofOfPossessionSigningKeyBuilder.cs
index 154b606da..b7a3ae01a 100644
--- a/crypto/src/crmf/ProofOfPossessionSigningKeyBuilder.cs
+++ b/crypto/src/crmf/ProofOfPossessionSigningKeyBuilder.cs
@@ -5,6 +5,7 @@ using Org.BouncyCastle.Asn1.Crmf;
 using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Crypto;
 using Org.BouncyCastle.Crypto.Operators;
+using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Crmf
 {
@@ -40,11 +41,7 @@ namespace Org.BouncyCastle.Crmf
             byte[] d = _pubKeyInfo.GetDerEncoded();
             calc.Stream.Write(d, 0, d.Length);
             calc.Stream.Flush();
-#if PORTABLE
-            calc.Stream.Dispose();
-#else
-            calc.Stream.Close();
-#endif
+            Platform.Dispose(calc.Stream);
 
             this._publicKeyMAC = new PKMacValue(
                 (AlgorithmIdentifier)fact.AlgorithmDetails,
@@ -84,11 +81,7 @@ namespace Org.BouncyCastle.Crmf
             }
 
             calc.Stream.Flush();
-#if PORTABLE
-            calc.Stream.Dispose();
-#else
-            calc.Stream.Close();
-#endif
+            Platform.Dispose(calc.Stream);
             DefaultSignatureResult res = (DefaultSignatureResult)calc.GetResult();
             return new PopoSigningKey(popo, (AlgorithmIdentifier)signer.AlgorithmDetails, new DerBitString(res.Collect()));
         }
diff --git a/crypto/src/crypto/digests/Sha256Digest.cs b/crypto/src/crypto/digests/Sha256Digest.cs
index 98e10a34d..63d5b8bee 100644
--- a/crypto/src/crypto/digests/Sha256Digest.cs
+++ b/crypto/src/crypto/digests/Sha256Digest.cs
@@ -230,63 +230,51 @@ namespace Org.BouncyCastle.Crypto.Digests
 			Array.Clear(X, 0, 16);
         }
 
-		private static uint Sum1Ch(
-            uint    x,
-            uint    y,
-            uint    z)
+		private static uint Sum1Ch(uint x, uint y, uint z)
 		{
 //			return Sum1(x) + Ch(x, y, z);
 	        return (((x >> 6) | (x << 26)) ^ ((x >> 11) | (x << 21)) ^ ((x >> 25) | (x << 7)))
-				+ ((x & y) ^ ((~x) & z));
-		}
+                //+ ((x & y) ^ ((~x) & z));
+                + (z ^ (x & (y ^ z)));
+        }
 
-		private static uint Sum0Maj(
-            uint	x,
-            uint    y,
-            uint    z)
+		private static uint Sum0Maj(uint x, uint y, uint z)
 		{
 //			return Sum0(x) + Maj(x, y, z);
 	        return (((x >> 2) | (x << 30)) ^ ((x >> 13) | (x << 19)) ^ ((x >> 22) | (x << 10)))
-				+ ((x & y) ^ (x & z) ^ (y & z));
-		}
+                //+ ((x & y) ^ (x & z) ^ (y & z));
+                + ((x & y) | (z & (x ^ y)));
+        }
 
 //		/* SHA-256 functions */
-//        private static uint Ch(
-//            uint    x,
-//            uint    y,
-//            uint    z)
+//        private static uint Ch(uint x, uint y, uint z)
 //        {
-//            return ((x & y) ^ ((~x) & z));
+//            return (x & y) ^ ((~x) & z);
+//            //return z ^ (x & (y ^ z));
 //        }
 //
-//        private static uint Maj(
-//            uint	x,
-//            uint    y,
-//            uint    z)
+//        private static uint Maj(uint x, uint y, uint z)
 //        {
-//            return ((x & y) ^ (x & z) ^ (y & z));
+//            //return (x & y) ^ (x & z) ^ (y & z);
+//            return (x & y) | (z & (x ^ y));
 //        }
 //
-//        private static uint Sum0(
-//            uint x)
+//        private static uint Sum0(uint x)
 //        {
 //	        return ((x >> 2) | (x << 30)) ^ ((x >> 13) | (x << 19)) ^ ((x >> 22) | (x << 10));
 //        }
 //
-//        private static uint Sum1(
-//            uint x)
+//        private static uint Sum1(uint x)
 //        {
 //	        return ((x >> 6) | (x << 26)) ^ ((x >> 11) | (x << 21)) ^ ((x >> 25) | (x << 7));
 //        }
 
-        private static uint Theta0(
-            uint x)
+        private static uint Theta0(uint x)
         {
 	        return ((x >> 7) | (x << 25)) ^ ((x >> 18) | (x << 14)) ^ (x >> 3);
         }
 
-        private static uint Theta1(
-            uint x)
+        private static uint Theta1(uint x)
         {
 	        return ((x >> 17) | (x << 15)) ^ ((x >> 19) | (x << 13)) ^ (x >> 10);
         }
diff --git a/crypto/src/crypto/ec/CustomNamedCurves.cs b/crypto/src/crypto/ec/CustomNamedCurves.cs
index 4b7600e09..a9f60dd8c 100644
--- a/crypto/src/crypto/ec/CustomNamedCurves.cs
+++ b/crypto/src/crypto/ec/CustomNamedCurves.cs
@@ -11,6 +11,7 @@ using Org.BouncyCastle.Math.EC.Custom.Djb;
 using Org.BouncyCastle.Math.EC.Custom.GM;
 using Org.BouncyCastle.Math.EC.Custom.Sec;
 using Org.BouncyCastle.Math.EC.Endo;
+using Org.BouncyCastle.Math.EC.Multiplier;
 using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.Collections;
 using Org.BouncyCastle.Utilities.Encoders;
@@ -23,9 +24,11 @@ namespace Org.BouncyCastle.Crypto.EC
         {
         }
 
-        private static BigInteger FromHex(string hex)
+        private static X9ECPoint ConfigureBasepoint(ECCurve curve, string encoding)
         {
-            return new BigInteger(1, Hex.Decode(hex));
+            X9ECPoint G = new X9ECPoint(curve, Hex.Decode(encoding));
+            WNafUtilities.ConfigureBasepoint(G.Point);
+            return G;
         }
 
         private static ECCurve ConfigureCurve(ECCurve curve)
@@ -38,6 +41,11 @@ namespace Org.BouncyCastle.Crypto.EC
             return c.Configure().SetEndomorphism(new GlvTypeBEndomorphism(c, p)).Create();
         }
 
+        private static BigInteger FromHex(string hex)
+        {
+            return new BigInteger(1, Hex.Decode(hex));
+        }
+
         /*
          * curve25519
          */
@@ -62,9 +70,8 @@ namespace Org.BouncyCastle.Crypto.EC
                  * 
                  * (The other possible y value is 5F51E65E475F794B1FE122D388B72EB36DC2B28192839E4DD6163A5D81312C14) 
                  */
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD245A"
-                    + "20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "042AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD245A20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9");
 
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
@@ -84,9 +91,8 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = Hex.Decode("000E0D4D696E6768756151750CC03A4473D03679");
                 ECCurve curve = ConfigureCurve(new SecP128R1Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "161FF7528B899B2D0C28607CA52C5B86"
-                    + "CF5AC8395BAFEB13C02DA292DDED7A83"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "04161FF7528B899B2D0C28607CA52C5B86CF5AC8395BAFEB13C02DA292DDED7A83"); 
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         };
@@ -107,19 +113,19 @@ namespace Org.BouncyCastle.Crypto.EC
                 GlvTypeBParameters glv = new GlvTypeBParameters(
                     new BigInteger("9ba48cba5ebcb9b6bd33b92830b2a2e0e192f10a", 16),
                     new BigInteger("c39c6c3b3a36d7701b9c71a1f5804ae5d0003f4", 16),
-                    new BigInteger[]{
-                        new BigInteger("9162fbe73984472a0a9e", 16),
-                        new BigInteger("-96341f1138933bc2f505", 16) },
-                    new BigInteger[]{
-                        new BigInteger("127971af8721782ecffa3", 16),
-                        new BigInteger("9162fbe73984472a0a9e", 16) },
-                    new BigInteger("9162fbe73984472a0a9d0590", 16),
-                    new BigInteger("96341f1138933bc2f503fd44", 16),
-                    176);
+                    new ScalarSplitParameters(
+                        new BigInteger[]{
+                            new BigInteger("9162fbe73984472a0a9e", 16),
+                            new BigInteger("-96341f1138933bc2f505", 16) },
+                        new BigInteger[]{
+                            new BigInteger("127971af8721782ecffa3", 16),
+                            new BigInteger("9162fbe73984472a0a9e", 16) },
+                        new BigInteger("9162fbe73984472a0a9d0590", 16),
+                        new BigInteger("96341f1138933bc2f503fd44", 16),
+                        176));
                 ECCurve curve = ConfigureCurveGlv(new SecP160K1Curve(), glv);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB"
-                    + "938CF935318FDCED6BC28286531733C3F03C4FEE"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "043B4C382CE37AA192A4019E763036F4F5DD4D7EBB938CF935318FDCED6BC28286531733C3F03C4FEE"); 
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         };
@@ -138,9 +144,8 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = Hex.Decode("1053CDE42C14D696E67687561517533BF3F83345");
                 ECCurve curve = ConfigureCurve(new SecP160R1Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "4A96B5688EF573284664698968C38BB913CBFC82"
-                    + "23A628553168947D59DCC912042351377AC5FB32"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "044A96B5688EF573284664698968C38BB913CBFC8223A628553168947D59DCC912042351377AC5FB32"); 
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         };
@@ -159,9 +164,8 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = Hex.Decode("B99B99B099B323E02709A4D696E6768756151751");
                 ECCurve curve = ConfigureCurve(new SecP160R2Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "52DCB034293A117E1F4FF11B30F7199D3144CE6D"
-                    + "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0452DCB034293A117E1F4FF11B30F7199D3144CE6DFEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E"); 
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         };
@@ -182,19 +186,19 @@ namespace Org.BouncyCastle.Crypto.EC
                 GlvTypeBParameters glv = new GlvTypeBParameters(
                     new BigInteger("bb85691939b869c1d087f601554b96b80cb4f55b35f433c2", 16),
                     new BigInteger("3d84f26c12238d7b4f3d516613c1759033b1a5800175d0b1", 16),
-                    new BigInteger[]{
-                        new BigInteger("71169be7330b3038edb025f1", 16),
-                        new BigInteger("-b3fb3400dec5c4adceb8655c", 16) },
-                    new BigInteger[]{
-                        new BigInteger("12511cfe811d0f4e6bc688b4d", 16),
-                        new BigInteger("71169be7330b3038edb025f1", 16) },
-                    new BigInteger("71169be7330b3038edb025f1d0f9", 16),
-                    new BigInteger("b3fb3400dec5c4adceb8655d4c94", 16),
-                    208);
+                    new ScalarSplitParameters(
+                        new BigInteger[]{
+                            new BigInteger("71169be7330b3038edb025f1", 16),
+                            new BigInteger("-b3fb3400dec5c4adceb8655c", 16) },
+                        new BigInteger[]{
+                            new BigInteger("12511cfe811d0f4e6bc688b4d", 16),
+                            new BigInteger("71169be7330b3038edb025f1", 16) },
+                        new BigInteger("71169be7330b3038edb025f1d0f9", 16),
+                        new BigInteger("b3fb3400dec5c4adceb8655d4c94", 16),
+                        208));
                 ECCurve curve = ConfigureCurveGlv(new SecP192K1Curve(), glv);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"
-                    + "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "04DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D"); 
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         }
@@ -213,9 +217,8 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = Hex.Decode("3045AE6FC8422F64ED579528D38120EAE12196D5");
                 ECCurve curve = ConfigureCurve(new SecP192R1Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"
-                    + "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "04188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF101207192B95FFC8DA78631011ED6B24CDD573F977A11E794811"); 
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         }
@@ -236,19 +239,19 @@ namespace Org.BouncyCastle.Crypto.EC
                 GlvTypeBParameters glv = new GlvTypeBParameters(
                     new BigInteger("fe0e87005b4e83761908c5131d552a850b3f58b749c37cf5b84d6768", 16),
                     new BigInteger("60dcd2104c4cbc0be6eeefc2bdd610739ec34e317f9b33046c9e4788", 16),
-                    new BigInteger[]{
-                        new BigInteger("6b8cf07d4ca75c88957d9d670591", 16),
-                        new BigInteger("-b8adf1378a6eb73409fa6c9c637d", 16) },
-                    new BigInteger[]{
-                        new BigInteger("1243ae1b4d71613bc9f780a03690e", 16),
-                        new BigInteger("6b8cf07d4ca75c88957d9d670591", 16) },
-                    new BigInteger("6b8cf07d4ca75c88957d9d67059037a4", 16),
-                    new BigInteger("b8adf1378a6eb73409fa6c9c637ba7f5", 16),
-                    240);
+                    new ScalarSplitParameters(
+                        new BigInteger[]{
+                            new BigInteger("6b8cf07d4ca75c88957d9d670591", 16),
+                            new BigInteger("-b8adf1378a6eb73409fa6c9c637d", 16) },
+                        new BigInteger[]{
+                            new BigInteger("1243ae1b4d71613bc9f780a03690e", 16),
+                            new BigInteger("6b8cf07d4ca75c88957d9d670591", 16) },
+                        new BigInteger("6b8cf07d4ca75c88957d9d67059037a4", 16),
+                        new BigInteger("b8adf1378a6eb73409fa6c9c637ba7f5", 16),
+                        240));
                 ECCurve curve = ConfigureCurveGlv(new SecP224K1Curve(), glv);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C"
-                    + "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "04A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5"); 
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         }
@@ -267,9 +270,8 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = Hex.Decode("BD71344799D5C7FCDC45B59FA3B9AB8F6A948BC5");
                 ECCurve curve = ConfigureCurve(new SecP224R1Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"
-                    + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "04B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"); 
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         }
@@ -290,19 +292,19 @@ namespace Org.BouncyCastle.Crypto.EC
                 GlvTypeBParameters glv = new GlvTypeBParameters(
                     new BigInteger("7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee", 16),
                     new BigInteger("5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72", 16),
-                    new BigInteger[]{
-                        new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16),
-                        new BigInteger("-e4437ed6010e88286f547fa90abfe4c3", 16) },
-                    new BigInteger[]{
-                        new BigInteger("114ca50f7a8e2f3f657c1108d9d44cfd8", 16),
-                        new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16) },
-                    new BigInteger("3086d221a7d46bcde86c90e49284eb153dab", 16),
-                    new BigInteger("e4437ed6010e88286f547fa90abfe4c42212", 16),
-                    272);
+                    new ScalarSplitParameters(
+                        new BigInteger[]{
+                            new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16),
+                            new BigInteger("-e4437ed6010e88286f547fa90abfe4c3", 16) },
+                        new BigInteger[]{
+                            new BigInteger("114ca50f7a8e2f3f657c1108d9d44cfd8", 16),
+                            new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16) },
+                        new BigInteger("3086d221a7d46bcde86c90e49284eb153dab", 16),
+                        new BigInteger("e4437ed6010e88286f547fa90abfe4c42212", 16),
+                        272));
                 ECCurve curve = ConfigureCurveGlv(new SecP256K1Curve(), glv);
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
-                    + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"); 
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         }
@@ -321,9 +323,8 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = Hex.Decode("C49D360886E704936A6678E1139D26B7819F7E90");
                 ECCurve curve = ConfigureCurve(new SecP256R1Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"
-                    + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"); 
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         }
@@ -342,9 +343,9 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = Hex.Decode("A335926AA319A27A1D00896A6773A4827ACDAC73");
                 ECCurve curve = ConfigureCurve(new SecP384R1Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+                X9ECPoint G = ConfigureBasepoint(curve, "04"
                     + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7"
-                    + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F"));
+                    + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F");
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         }
@@ -363,9 +364,9 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = Hex.Decode("D09E8800291CB85396CC6717393284AAA0DA64BA");
                 ECCurve curve = ConfigureCurve(new SecP521R1Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+                X9ECPoint G = ConfigureBasepoint(curve, "04"
                     + "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"
-                    + "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"));
+                    + "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650");
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         }
@@ -384,9 +385,8 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = Hex.Decode("10E723AB14D696E6768756151756FEBF8FCB49A9");
                 ECCurve curve = ConfigureCurve(new SecT113R1Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "009D73616F35F4AB1407D73562C10F"
-                    + "00A52830277958EE84D1315ED31886"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "04009D73616F35F4AB1407D73562C10F00A52830277958EE84D1315ED31886"); 
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         };
@@ -405,9 +405,8 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = Hex.Decode("10C0FB15760860DEF1EEF4D696E676875615175D");
                 ECCurve curve = ConfigureCurve(new SecT113R2Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "01A57A6A7B26CA5EF52FCDB8164797"
-                    + "00B3ADC94ED1FE674C06E695BABA1D"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0401A57A6A7B26CA5EF52FCDB816479700B3ADC94ED1FE674C06E695BABA1D"); 
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         };
@@ -426,9 +425,8 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = Hex.Decode("4D696E676875615175985BD3ADBADA21B43A97E2");
                 ECCurve curve = ConfigureCurve(new SecT131R1Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "0081BAF91FDF9833C40F9C181343638399"
-                    + "078C6E7EA38C001F73C8134B1B4EF9E150"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "040081BAF91FDF9833C40F9C181343638399078C6E7EA38C001F73C8134B1B4EF9E150"); 
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         };
@@ -447,9 +445,8 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = Hex.Decode("985BD3ADBAD4D696E676875615175A21B43A97E3");
                 ECCurve curve = ConfigureCurve(new SecT131R2Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "0356DCD8F2F95031AD652D23951BB366A8"
-                    + "0648F06D867940A5366D9E265DE9EB240F"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "040356DCD8F2F95031AD652D23951BB366A80648F06D867940A5366D9E265DE9EB240F"); 
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         };
@@ -468,9 +465,8 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = null;
                 ECCurve curve = ConfigureCurve(new SecT163K1Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8"
-                    + "0289070FB05D38FF58321F2E800536D538CCDAA3D9"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0402FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE80289070FB05D38FF58321F2E800536D538CCDAA3D9"); 
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         };
@@ -489,9 +485,8 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = Hex.Decode("24B7B137C8A14D696E6768756151756FD0DA2E5C");
                 ECCurve curve = ConfigureCurve(new SecT163R1Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "0369979697AB43897789566789567F787A7876A654"
-                    + "00435EDB42EFAFB2989D51FEFCE3C80988F41FF883"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "040369979697AB43897789566789567F787A7876A65400435EDB42EFAFB2989D51FEFCE3C80988F41FF883"); 
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         };
@@ -510,9 +505,8 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = Hex.Decode("85E25BFE5C86226CDB12016F7553F9D0E693A268");
                 ECCurve curve = ConfigureCurve(new SecT163R2Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "03F0EBA16286A2D57EA0991168D4994637E8343E36"
-                    + "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0403F0EBA16286A2D57EA0991168D4994637E8343E3600D51FBC6C71A0094FA2CDD545B11C5C0C797324F1"); 
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         };
@@ -531,9 +525,8 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = Hex.Decode("103FAEC74D696E676875615175777FC5B191EF30");
                 ECCurve curve = ConfigureCurve(new SecT193R1Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1"
-                    + "0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0401F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E10025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05"); 
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         };
@@ -552,9 +545,8 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = Hex.Decode("10B7B4D696E676875615175137C8A16FD0DA2211");
                 ECCurve curve = ConfigureCurve(new SecT193R2Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F"
-                    + "01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0400D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C"); 
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         };
@@ -573,9 +565,8 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = null;
                 ECCurve curve = ConfigureCurve(new SecT233K1Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126"
-                    + "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "04017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD612601DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3"); 
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         };
@@ -594,9 +585,8 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = Hex.Decode("74D59FF07F6B413D0EA14B344B20A2DB049B50C3");
                 ECCurve curve = ConfigureCurve(new SecT233R1Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B"
-                    + "01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0400FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052"); 
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         };
@@ -615,9 +605,8 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = null;
                 ECCurve curve = ConfigureCurve(new SecT239K1Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC"
-                    + "76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0429A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA"); 
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         };
@@ -636,9 +625,9 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = null;
                 ECCurve curve = ConfigureCurve(new SecT283K1Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+                X9ECPoint G = ConfigureBasepoint(curve, "04"
                     + "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836"
-                    + "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259"));
+                    + "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259");
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         };
@@ -657,9 +646,9 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = Hex.Decode("77E2B07370EB0F832A6DD5B62DFC88CD06BB84BE");
                 ECCurve curve = ConfigureCurve(new SecT283R1Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+                X9ECPoint G = ConfigureBasepoint(curve, "04"
                     + "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053"
-                    + "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4"));
+                    + "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4");
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         };
@@ -678,9 +667,9 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = null;
                 ECCurve curve = ConfigureCurve(new SecT409K1Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+                X9ECPoint G = ConfigureBasepoint(curve, "04"
                     + "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746"
-                    + "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B"));
+                    + "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B");
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         };
@@ -699,9 +688,9 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = Hex.Decode("4099B5A457F9D69F79213D094C4BCD4D4262210B");
                 ECCurve curve = ConfigureCurve(new SecT409R1Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+                X9ECPoint G = ConfigureBasepoint(curve, "04"
                     + "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7"
-                    + "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706"));
+                    + "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706");
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         };
@@ -720,9 +709,9 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = null;
                 ECCurve curve = ConfigureCurve(new SecT571K1Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+                X9ECPoint G = ConfigureBasepoint(curve, "04"
                     + "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972"
-                    + "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3"));
+                    + "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3");
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         };
@@ -741,9 +730,9 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = Hex.Decode("2AA058F73A0E33AB486B0F610410C53A7F132310");
                 ECCurve curve = ConfigureCurve(new SecT571R1Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+                X9ECPoint G = ConfigureBasepoint(curve, "04"
                     + "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19"
-                    + "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B"));
+                    + "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B");
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         };
@@ -762,9 +751,8 @@ namespace Org.BouncyCastle.Crypto.EC
             {
                 byte[] S = null;
                 ECCurve curve = ConfigureCurve(new SM2P256V1Curve());
-                X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
-                    + "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7"
-                    + "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"));
+                X9ECPoint G = ConfigureBasepoint(curve,
+                    "0432C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"); 
                 return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
             }
         }
diff --git a/crypto/src/crypto/engines/RSABlindedEngine.cs b/crypto/src/crypto/engines/RSABlindedEngine.cs
index 7b928c5fb..98108f9b4 100644
--- a/crypto/src/crypto/engines/RSABlindedEngine.cs
+++ b/crypto/src/crypto/engines/RSABlindedEngine.cs
@@ -49,13 +49,29 @@ namespace Org.BouncyCastle.Crypto.Engines
             {
                 ParametersWithRandom rParam = (ParametersWithRandom)param;
 
-                key = (RsaKeyParameters)rParam.Parameters;
-                random = rParam.Random;
+                this.key = (RsaKeyParameters)rParam.Parameters;
+
+                if (key is RsaPrivateCrtKeyParameters)
+                {
+                    this.random = rParam.Random;
+                }
+                else
+                {
+                    this.random = null;
+                }
             }
             else
             {
-                key = (RsaKeyParameters)param;
-                random = new SecureRandom();
+                this.key = (RsaKeyParameters)param;
+
+                if (key is RsaPrivateCrtKeyParameters)
+                {
+                    this.random = new SecureRandom();
+                }
+                else
+                {
+                    this.random = null;
+                }
             }
         }
 
diff --git a/crypto/src/crypto/generators/SCrypt.cs b/crypto/src/crypto/generators/SCrypt.cs
index 51dc50b81..9c204e786 100644
--- a/crypto/src/crypto/generators/SCrypt.cs
+++ b/crypto/src/crypto/generators/SCrypt.cs
@@ -118,7 +118,7 @@ namespace Org.BouncyCastle.Crypto.Generators
 				uint mask = (uint)N - 1;
 				for (int i = 0; i < N; ++i)
 				{
-					uint j = X[BCount - 16] & mask;
+					int j = (int)(X[BCount - 16] & mask);
                     Array.Copy(V, j * BCount, blockY, 0, BCount);
                     Xor(blockY, X, 0, blockY);
                     BlockMix(blockY, blockX1, blockX2, X, r);
diff --git a/crypto/src/crypto/parameters/MqvPrivateParameters.cs b/crypto/src/crypto/parameters/MqvPrivateParameters.cs
index 9159cac12..37145715f 100644
--- a/crypto/src/crypto/parameters/MqvPrivateParameters.cs
+++ b/crypto/src/crypto/parameters/MqvPrivateParameters.cs
@@ -1,5 +1,8 @@
 using System;
 
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Math.EC.Multiplier;
+
 namespace Org.BouncyCastle.Crypto.Parameters
 {
 	public class MqvPrivateParameters
@@ -32,9 +35,9 @@ namespace Org.BouncyCastle.Crypto.Parameters
 
             if (ephemeralPublicKey == null)
             {
-                ephemeralPublicKey = new ECPublicKeyParameters(
-                    parameters.G.Multiply(ephemeralPrivateKey.D),
-                    parameters);
+                ECPoint q = new FixedPointCombMultiplier().Multiply(parameters.G, ephemeralPrivateKey.D);
+
+                ephemeralPublicKey = new ECPublicKeyParameters(q, parameters);
             }
             else if (!parameters.Equals(ephemeralPublicKey.Parameters))
             {
diff --git a/crypto/src/crypto/parameters/SM2KeyExchangePrivateParameters.cs b/crypto/src/crypto/parameters/SM2KeyExchangePrivateParameters.cs
index 8afb61544..666566426 100644
--- a/crypto/src/crypto/parameters/SM2KeyExchangePrivateParameters.cs
+++ b/crypto/src/crypto/parameters/SM2KeyExchangePrivateParameters.cs
@@ -1,6 +1,7 @@
 using System;
 
 using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Math.EC.Multiplier;
 
 namespace Org.BouncyCastle.Crypto.Parameters
 {
@@ -29,11 +30,13 @@ namespace Org.BouncyCastle.Crypto.Parameters
             if (!parameters.Equals(ephemeralPrivateKey.Parameters))
                 throw new ArgumentException("Static and ephemeral private keys have different domain parameters");
 
+            ECMultiplier m = new FixedPointCombMultiplier();
+
             this.mInitiator = initiator;
             this.mStaticPrivateKey = staticPrivateKey;
-            this.mStaticPublicPoint = parameters.G.Multiply(staticPrivateKey.D).Normalize();
+            this.mStaticPublicPoint = m.Multiply(parameters.G, staticPrivateKey.D).Normalize(); 
             this.mEphemeralPrivateKey = ephemeralPrivateKey;
-            this.mEphemeralPublicPoint = parameters.G.Multiply(ephemeralPrivateKey.D).Normalize();
+            this.mEphemeralPublicPoint = m.Multiply(parameters.G, ephemeralPrivateKey.D).Normalize();
         }
 
         public virtual bool IsInitiator
diff --git a/crypto/src/crypto/signers/ECGOST3410Signer.cs b/crypto/src/crypto/signers/ECGOST3410Signer.cs
index f08d16551..ac6b080a5 100644
--- a/crypto/src/crypto/signers/ECGOST3410Signer.cs
+++ b/crypto/src/crypto/signers/ECGOST3410Signer.cs
@@ -6,6 +6,7 @@ using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Math.EC;
 using Org.BouncyCastle.Math.EC.Multiplier;
 using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Crypto.Signers
 {
@@ -78,12 +79,7 @@ namespace Org.BouncyCastle.Crypto.Signers
                 throw new InvalidOperationException("not initialized for signing");
             }
 
-            byte[] mRev = new byte[message.Length]; // conversion is little-endian
-            for (int i = 0; i != mRev.Length; i++)
-            {
-                mRev[i] = message[mRev.Length - 1 - i];
-            }
-
+            byte[] mRev = Arrays.Reverse(message); // conversion is little-endian
             BigInteger e = new BigInteger(1, mRev);
 
             ECDomainParameters ec = key.Parameters;
@@ -133,12 +129,7 @@ namespace Org.BouncyCastle.Crypto.Signers
                 throw new InvalidOperationException("not initialized for verification");
             }
 
-            byte[] mRev = new byte[message.Length]; // conversion is little-endian
-            for (int i = 0; i != mRev.Length; i++)
-            {
-                mRev[i] = message[mRev.Length - 1 - i];
-            }
-
+            byte[] mRev = Arrays.Reverse(message); // conversion is little-endian
             BigInteger e = new BigInteger(1, mRev);
             BigInteger n = key.Parameters.N;
 
diff --git a/crypto/src/crypto/signers/GOST3410Signer.cs b/crypto/src/crypto/signers/GOST3410Signer.cs
index c5f3bd5ef..bcc1125b1 100644
--- a/crypto/src/crypto/signers/GOST3410Signer.cs
+++ b/crypto/src/crypto/signers/GOST3410Signer.cs
@@ -3,6 +3,7 @@ using System;
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Crypto.Signers
 {
@@ -67,12 +68,7 @@ namespace Org.BouncyCastle.Crypto.Signers
         public virtual BigInteger[] GenerateSignature(
 			byte[] message)
 		{
-			byte[] mRev = new byte[message.Length]; // conversion is little-endian
-			for (int i = 0; i != mRev.Length; i++)
-			{
-				mRev[i] = message[mRev.Length - 1 - i];
-			}
-
+            byte[] mRev = Arrays.Reverse(message); // conversion is little-endian
 			BigInteger m = new BigInteger(1, mRev);
 			Gost3410Parameters parameters = key.Parameters;
 			BigInteger k;
@@ -102,13 +98,8 @@ namespace Org.BouncyCastle.Crypto.Signers
 			BigInteger	r,
 			BigInteger	s)
 		{
-			byte[] mRev = new byte[message.Length]; // conversion is little-endian
-			for (int i = 0; i != mRev.Length; i++)
-			{
-				mRev[i] = message[mRev.Length - 1 - i];
-			}
-
-			BigInteger m = new BigInteger(1, mRev);
+            byte[] mRev = Arrays.Reverse(message); // conversion is little-endian
+            BigInteger m = new BigInteger(1, mRev);
 			Gost3410Parameters parameters = key.Parameters;
 
 			if (r.SignValue < 0 || parameters.Q.CompareTo(r) <= 0)
diff --git a/crypto/src/math/BigInteger.cs b/crypto/src/math/BigInteger.cs
index 997f0bbea..3badb6d2c 100644
--- a/crypto/src/math/BigInteger.cs
+++ b/crypto/src/math/BigInteger.cs
@@ -249,7 +249,7 @@ namespace Org.BouncyCastle.Math
             return (nBits + BitsPerByte - 1) / BitsPerByte;
         }
 
-        internal static BigInteger Arbitrary(int sizeInBits)
+        public static BigInteger Arbitrary(int sizeInBits)
         {
             return new BigInteger(sizeInBits, RandomSource);
         }
@@ -1332,6 +1332,17 @@ namespace Org.BouncyCastle.Math
             }
         }
 
+        public int IntValueExact
+        {
+            get
+            {
+                if (BitLength > 31)
+                    throw new ArithmeticException("BigInteger out of int range");
+
+                return IntValue;
+            }
+        }
+
         /**
          * return whether or not a BigInteger is probably prime with a
          * probability of 1 - (1/2)**certainty.
@@ -1588,6 +1599,17 @@ namespace Org.BouncyCastle.Math
             }
         }
 
+        public long LongValueExact
+        {
+            get
+            {
+                if (BitLength > 63)
+                    throw new ArithmeticException("BigInteger out of long range");
+
+                return LongValue;
+            }
+        }
+
         public BigInteger Max(
             BigInteger value)
         {
diff --git a/crypto/src/math/ec/AbstractECLookupTable.cs b/crypto/src/math/ec/AbstractECLookupTable.cs
new file mode 100644
index 000000000..fbd272d0c
--- /dev/null
+++ b/crypto/src/math/ec/AbstractECLookupTable.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC
+{
+    public abstract class AbstractECLookupTable
+        : ECLookupTable
+    {
+        public abstract ECPoint Lookup(int index);
+        public abstract int Size { get; }
+
+        public virtual ECPoint LookupVar(int index)
+        {
+            return Lookup(index);
+        }
+    }
+}
diff --git a/crypto/src/math/ec/ECAlgorithms.cs b/crypto/src/math/ec/ECAlgorithms.cs
index b05c0201a..4976b73b0 100644
--- a/crypto/src/math/ec/ECAlgorithms.cs
+++ b/crypto/src/math/ec/ECAlgorithms.cs
@@ -3,6 +3,7 @@ using System;
 using Org.BouncyCastle.Math.EC.Endo;
 using Org.BouncyCastle.Math.EC.Multiplier;
 using Org.BouncyCastle.Math.Field;
+using Org.BouncyCastle.Math.Raw;
 
 namespace Org.BouncyCastle.Math.EC
 {
@@ -265,46 +266,63 @@ namespace Org.BouncyCastle.Math.EC
         {
             bool negK = k.SignValue < 0, negL = l.SignValue < 0;
 
-            k = k.Abs();
-            l = l.Abs();
+            BigInteger kAbs = k.Abs(), lAbs = l.Abs();
+
+            int minWidthP = WNafUtilities.GetWindowSize(kAbs.BitLength, 8);
+            int minWidthQ = WNafUtilities.GetWindowSize(lAbs.BitLength, 8);
 
-            int widthP = System.Math.Max(2, System.Math.Min(16, WNafUtilities.GetWindowSize(k.BitLength)));
-            int widthQ = System.Math.Max(2, System.Math.Min(16, WNafUtilities.GetWindowSize(l.BitLength)));
+            WNafPreCompInfo infoP = WNafUtilities.Precompute(P, minWidthP, true);
+            WNafPreCompInfo infoQ = WNafUtilities.Precompute(Q, minWidthQ, true);
+
+            // When P, Q are 'promoted' (i.e. reused several times), switch to fixed-point algorithm
+            {
+                ECCurve c = P.Curve;
+                int combSize = FixedPointUtilities.GetCombSize(c);
+                if (!negK && !negL
+                    && k.BitLength <= combSize && l.BitLength <= combSize
+                    && infoP.IsPromoted && infoQ.IsPromoted)
+                {
+                    return ImplShamirsTrickFixedPoint(P, k, Q, l);
+                }
+            }
 
-            WNafPreCompInfo infoP = WNafUtilities.Precompute(P, widthP, true);
-            WNafPreCompInfo infoQ = WNafUtilities.Precompute(Q, widthQ, true);
+            int widthP = System.Math.Min(8, infoP.Width);
+            int widthQ = System.Math.Min(8, infoQ.Width);
 
             ECPoint[] preCompP = negK ? infoP.PreCompNeg : infoP.PreComp;
             ECPoint[] preCompQ = negL ? infoQ.PreCompNeg : infoQ.PreComp;
             ECPoint[] preCompNegP = negK ? infoP.PreComp : infoP.PreCompNeg;
             ECPoint[] preCompNegQ = negL ? infoQ.PreComp : infoQ.PreCompNeg;
 
-            byte[] wnafP = WNafUtilities.GenerateWindowNaf(widthP, k);
-            byte[] wnafQ = WNafUtilities.GenerateWindowNaf(widthQ, l);
+            byte[] wnafP = WNafUtilities.GenerateWindowNaf(widthP, kAbs);
+            byte[] wnafQ = WNafUtilities.GenerateWindowNaf(widthQ, lAbs);
 
             return ImplShamirsTrickWNaf(preCompP, preCompNegP, wnafP, preCompQ, preCompNegQ, wnafQ);
         }
 
-        internal static ECPoint ImplShamirsTrickWNaf(ECPoint P, BigInteger k, ECPointMap pointMapQ, BigInteger l)
+        internal static ECPoint ImplShamirsTrickWNaf(ECEndomorphism endomorphism, ECPoint P, BigInteger k, BigInteger l)
         {
             bool negK = k.SignValue < 0, negL = l.SignValue < 0;
 
             k = k.Abs();
             l = l.Abs();
 
-            int width = System.Math.Max(2, System.Math.Min(16, WNafUtilities.GetWindowSize(System.Math.Max(k.BitLength, l.BitLength))));
+            int minWidth = WNafUtilities.GetWindowSize(System.Math.Max(k.BitLength, l.BitLength), 8);
+
+            WNafPreCompInfo infoP = WNafUtilities.Precompute(P, minWidth, true);
+            ECPoint Q = EndoUtilities.MapPoint(endomorphism, P);
+            WNafPreCompInfo infoQ = WNafUtilities.PrecomputeWithPointMap(Q, endomorphism.PointMap, infoP, true);
 
-            ECPoint Q = WNafUtilities.MapPointWithPrecomp(P, width, true, pointMapQ);
-            WNafPreCompInfo infoP = WNafUtilities.GetWNafPreCompInfo(P);
-            WNafPreCompInfo infoQ = WNafUtilities.GetWNafPreCompInfo(Q);
+            int widthP = System.Math.Min(8, infoP.Width);
+            int widthQ = System.Math.Min(8, infoQ.Width);
 
             ECPoint[] preCompP = negK ? infoP.PreCompNeg : infoP.PreComp;
             ECPoint[] preCompQ = negL ? infoQ.PreCompNeg : infoQ.PreComp;
             ECPoint[] preCompNegP = negK ? infoP.PreComp : infoP.PreCompNeg;
             ECPoint[] preCompNegQ = negL ? infoQ.PreComp : infoQ.PreCompNeg;
 
-            byte[] wnafP = WNafUtilities.GenerateWindowNaf(width, k);
-            byte[] wnafQ = WNafUtilities.GenerateWindowNaf(width, l);
+            byte[] wnafP = WNafUtilities.GenerateWindowNaf(widthP, k);
+            byte[] wnafQ = WNafUtilities.GenerateWindowNaf(widthQ, l);
 
             return ImplShamirsTrickWNaf(preCompP, preCompNegP, wnafP, preCompQ, preCompNegQ, wnafQ);
         }
@@ -373,8 +391,12 @@ namespace Org.BouncyCastle.Math.EC
             {
                 BigInteger ki = ks[i]; negs[i] = ki.SignValue < 0; ki = ki.Abs();
 
-                int width = System.Math.Max(2, System.Math.Min(16, WNafUtilities.GetWindowSize(ki.BitLength)));
-                infos[i] = WNafUtilities.Precompute(ps[i], width, true);
+                int minWidth = WNafUtilities.GetWindowSize(ki.BitLength, 8);
+                WNafPreCompInfo info = WNafUtilities.Precompute(ps[i], minWidth, true);
+
+                int width = System.Math.Min(8, info.Width);
+
+                infos[i] = info; 
                 wnafs[i] = WNafUtilities.GenerateWindowNaf(width, ki);
             }
 
@@ -395,24 +417,24 @@ namespace Org.BouncyCastle.Math.EC
                 abs[j++] = ab[1];
             }
 
-            ECPointMap pointMap = glvEndomorphism.PointMap;
             if (glvEndomorphism.HasEfficientPointMap)
             {
-                return ECAlgorithms.ImplSumOfMultiplies(ps, pointMap, abs);
+                return ImplSumOfMultiplies(glvEndomorphism, ps, abs);
             }
 
             ECPoint[] pqs = new ECPoint[len << 1];
             for (int i = 0, j = 0; i < len; ++i)
             {
-                ECPoint p = ps[i], q = pointMap.Map(p);
+                ECPoint p = ps[i];
+                ECPoint q = EndoUtilities.MapPoint(glvEndomorphism, p); 
                 pqs[j++] = p;
                 pqs[j++] = q;
             }
 
-            return ECAlgorithms.ImplSumOfMultiplies(pqs, abs);
+            return ImplSumOfMultiplies(pqs, abs);
         }
 
-        internal static ECPoint ImplSumOfMultiplies(ECPoint[] ps, ECPointMap pointMap, BigInteger[] ks)
+        internal static ECPoint ImplSumOfMultiplies(ECEndomorphism endomorphism, ECPoint[] ps, BigInteger[] ks)
         {
             int halfCount = ps.Length, fullCount = halfCount << 1;
 
@@ -420,6 +442,8 @@ namespace Org.BouncyCastle.Math.EC
             WNafPreCompInfo[] infos = new WNafPreCompInfo[fullCount];
             byte[][] wnafs = new byte[fullCount][];
 
+            ECPointMap pointMap = endomorphism.PointMap;
+
             for (int i = 0; i < halfCount; ++i)
             {
                 int j0 = i << 1, j1 = j0 + 1;
@@ -427,13 +451,20 @@ namespace Org.BouncyCastle.Math.EC
                 BigInteger kj0 = ks[j0]; negs[j0] = kj0.SignValue < 0; kj0 = kj0.Abs();
                 BigInteger kj1 = ks[j1]; negs[j1] = kj1.SignValue < 0; kj1 = kj1.Abs();
 
-                int width = System.Math.Max(2, System.Math.Min(16, WNafUtilities.GetWindowSize(System.Math.Max(kj0.BitLength, kj1.BitLength))));
+                int minWidth = WNafUtilities.GetWindowSize(System.Math.Max(kj0.BitLength, kj1.BitLength), 8);
+
+                ECPoint P = ps[i];
+                WNafPreCompInfo infoP = WNafUtilities.Precompute(P, minWidth, true);
+                ECPoint Q = EndoUtilities.MapPoint(endomorphism, P);
+                WNafPreCompInfo infoQ = WNafUtilities.PrecomputeWithPointMap(Q, pointMap, infoP, true);
+
+                int widthP = System.Math.Min(8, infoP.Width);
+                int widthQ = System.Math.Min(8, infoQ.Width);
 
-                ECPoint P = ps[i], Q = WNafUtilities.MapPointWithPrecomp(P, width, true, pointMap);
-                infos[j0] = WNafUtilities.GetWNafPreCompInfo(P);
-                infos[j1] = WNafUtilities.GetWNafPreCompInfo(Q);
-                wnafs[j0] = WNafUtilities.GenerateWindowNaf(width, kj0);
-                wnafs[j1] = WNafUtilities.GenerateWindowNaf(width, kj1);
+                infos[j0] = infoP;
+                infos[j1] = infoQ;
+                wnafs[j0] = WNafUtilities.GenerateWindowNaf(widthP, kj0);
+                wnafs[j1] = WNafUtilities.GenerateWindowNaf(widthQ, kj1);
             }
 
             return ImplSumOfMultiplies(negs, infos, wnafs);
@@ -492,5 +523,78 @@ namespace Org.BouncyCastle.Math.EC
 
             return R;
         }
+
+        private static ECPoint ImplShamirsTrickFixedPoint(ECPoint p, BigInteger k, ECPoint q, BigInteger l)
+        {
+            ECCurve c = p.Curve;
+            int combSize = FixedPointUtilities.GetCombSize(c);
+
+            if (k.BitLength > combSize || l.BitLength > combSize)
+            {
+                /*
+                 * TODO The comb works best when the scalars are less than the (possibly unknown) order.
+                 * Still, if we want to handle larger scalars, we could allow customization of the comb
+                 * size, or alternatively we could deal with the 'extra' bits either by running the comb
+                 * multiple times as necessary, or by using an alternative multiplier as prelude.
+                 */
+                throw new InvalidOperationException("fixed-point comb doesn't support scalars larger than the curve order");
+            }
+
+            FixedPointPreCompInfo infoP = FixedPointUtilities.Precompute(p);
+            FixedPointPreCompInfo infoQ = FixedPointUtilities.Precompute(q);
+
+            ECLookupTable lookupTableP = infoP.LookupTable;
+            ECLookupTable lookupTableQ = infoQ.LookupTable;
+
+            int widthP = infoP.Width;
+            int widthQ = infoQ.Width;
+
+            // TODO This shouldn't normally happen, but a better "solution" is desirable anyway
+            if (widthP != widthQ)
+            {
+                FixedPointCombMultiplier m = new FixedPointCombMultiplier();
+                ECPoint r1 = m.Multiply(p, k);
+                ECPoint r2 = m.Multiply(q, l);
+                return r1.Add(r2);
+            }
+
+            int width = widthP;
+
+            int d = (combSize + width - 1) / width;
+
+            ECPoint R = c.Infinity;
+
+            int fullComb = d * width;
+            uint[] K = Nat.FromBigInteger(fullComb, k);
+            uint[] L = Nat.FromBigInteger(fullComb, l);
+
+            int top = fullComb - 1; 
+            for (int i = 0; i < d; ++i)
+            {
+                uint secretIndexK = 0, secretIndexL = 0;
+
+                for (int j = top - i; j >= 0; j -= d)
+                {
+                    uint secretBitK = K[j >> 5] >> (j & 0x1F);
+                    secretIndexK ^= secretBitK >> 1;
+                    secretIndexK <<= 1;
+                    secretIndexK ^= secretBitK;
+
+                    uint secretBitL = L[j >> 5] >> (j & 0x1F);
+                    secretIndexL ^= secretBitL >> 1;
+                    secretIndexL <<= 1;
+                    secretIndexL ^= secretBitL;
+                }
+
+                ECPoint addP = lookupTableP.LookupVar((int)secretIndexK);
+                ECPoint addQ = lookupTableQ.LookupVar((int)secretIndexL);
+
+                ECPoint T = addP.Add(addQ);
+
+                R = R.TwicePlus(T);
+            }
+
+            return R.Add(infoP.Offset).Add(infoQ.Offset);
+        }
     }
 }
diff --git a/crypto/src/math/ec/ECCurve.cs b/crypto/src/math/ec/ECCurve.cs
index 993b69149..60fbc887a 100644
--- a/crypto/src/math/ec/ECCurve.cs
+++ b/crypto/src/math/ec/ECCurve.cs
@@ -521,7 +521,7 @@ namespace Org.BouncyCastle.Math.EC
         }
 
         private class DefaultLookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly ECCurve m_outer;
             private readonly byte[] m_table;
@@ -534,12 +534,12 @@ namespace Org.BouncyCastle.Math.EC
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 int FE_BYTES = (m_outer.FieldSize + 7) / 8;
                 byte[] x = new byte[FE_BYTES], y = new byte[FE_BYTES];
@@ -558,6 +558,26 @@ namespace Org.BouncyCastle.Math.EC
                     pos += (FE_BYTES * 2);
                 }
 
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                int FE_BYTES = (m_outer.FieldSize + 7) / 8;
+                byte[] x = new byte[FE_BYTES], y = new byte[FE_BYTES];
+                int pos = index * FE_BYTES * 2;
+
+                for (int j = 0; j < FE_BYTES; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + FE_BYTES + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(byte[] x, byte[] y)
+            {
                 ECFieldElement X = m_outer.FromBigInteger(new BigInteger(1, x));
                 ECFieldElement Y = m_outer.FromBigInteger(new BigInteger(1, y));
                 return m_outer.CreateRawPoint(X, Y, false);
@@ -862,12 +882,29 @@ namespace Org.BouncyCastle.Math.EC
          */
         internal ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
         {
+            AbstractF2mFieldElement betaF2m = (AbstractF2mFieldElement)beta;
+
+            bool fastTrace = betaF2m.HasFastTrace;
+            if (fastTrace && 0 != betaF2m.Trace())
+                return null;
+
+            int m = FieldSize;
+
+            // For odd m, use the half-trace 
+            if (0 != (m & 1))
+            {
+                ECFieldElement r = betaF2m.HalfTrace();
+                if (fastTrace || r.Square().Add(r).Add(beta).IsZero)
+                    return r;
+
+                return null;
+            }
+
             if (beta.IsZero)
                 return beta;
 
             ECFieldElement gamma, z, zeroElement = FromBigInteger(BigInteger.Zero);
 
-            int m = FieldSize;
             do
             {
                 ECFieldElement t = FromBigInteger(BigInteger.Arbitrary(m));
@@ -1234,7 +1271,7 @@ namespace Org.BouncyCastle.Math.EC
         }
 
         private class DefaultF2mLookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly F2mCurve m_outer;
             private readonly long[] m_table;
@@ -1247,16 +1284,13 @@ namespace Org.BouncyCastle.Math.EC
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
-                int m = m_outer.m;
-                int[] ks = m_outer.IsTrinomial() ? new int[]{ m_outer.k1 } : new int[]{ m_outer.k1, m_outer.k2, m_outer.k3 }; 
-
                 int FE_LONGS = (m_outer.m + 63) / 64;
                 long[] x = new long[FE_LONGS], y = new long[FE_LONGS];
                 int pos = 0;
@@ -1274,6 +1308,29 @@ namespace Org.BouncyCastle.Math.EC
                     pos += (FE_LONGS * 2);
                 }
 
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                int FE_LONGS = (m_outer.m + 63) / 64;
+                long[] x = new long[FE_LONGS], y = new long[FE_LONGS];
+                int pos = index * FE_LONGS * 2;
+
+                for (int j = 0; j < FE_LONGS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + FE_LONGS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(long[] x, long[] y)
+            {
+                int m = m_outer.m;
+                int[] ks = m_outer.IsTrinomial() ? new int[] { m_outer.k1 } : new int[] { m_outer.k1, m_outer.k2, m_outer.k3 }; 
+
                 ECFieldElement X = new F2mFieldElement(m, ks, new LongArray(x));
                 ECFieldElement Y = new F2mFieldElement(m, ks, new LongArray(y));
                 return m_outer.CreateRawPoint(X, Y, false);
diff --git a/crypto/src/math/ec/ECFieldElement.cs b/crypto/src/math/ec/ECFieldElement.cs
index 350e8c6d4..ef10dbf90 100644
--- a/crypto/src/math/ec/ECFieldElement.cs
+++ b/crypto/src/math/ec/ECFieldElement.cs
@@ -550,32 +550,63 @@ namespace Org.BouncyCastle.Math.EC
             if ((m & 1) == 0)
                 throw new InvalidOperationException("Half-trace only defined for odd m");
 
-            ECFieldElement fe = this;
-            ECFieldElement ht = fe;
-            for (int i = 2; i < m; i += 2)
+            //ECFieldElement ht = this;
+            //for (int i = 1; i < m; i += 2)
+            //{
+            //    ht = ht.SquarePow(2).Add(this);
+            //}
+
+            int n = (m + 1) >> 1;
+            int k = 31 - Integers.NumberOfLeadingZeros(n);
+            int nk = 1;
+
+            ECFieldElement ht = this;
+            while (k > 0)
             {
-                fe = fe.SquarePow(2);
-                ht = ht.Add(fe);
+                ht = ht.SquarePow(nk << 1).Add(ht);
+                nk = n >> --k;
+                if (0 != (nk & 1))
+                {
+                    ht = ht.SquarePow(2).Add(this);
+                }
             }
 
             return ht;
         }
 
+        public virtual bool HasFastTrace
+        {
+            get { return false; }
+        }
+
         public virtual int Trace()
         {
             int m = FieldSize;
-            ECFieldElement fe = this;
-            ECFieldElement tr = fe;
-            for (int i = 1; i < m; ++i)
+
+            //ECFieldElement tr = this;
+            //for (int i = 1; i < m; ++i)
+            //{
+            //    tr = tr.Square().Add(this);
+            //}
+
+            int k = 31 - Integers.NumberOfLeadingZeros(m);
+            int mk = 1;
+
+            ECFieldElement tr = this;
+            while (k > 0)
             {
-                fe = fe.Square();
-                tr = tr.Add(fe);
+                tr = tr.SquarePow(mk).Add(tr);
+                mk = m >> --k;
+                if (0 != (mk & 1))
+                {
+                    tr = tr.Square().Add(this);
+                }
             }
+
             if (tr.IsZero)
                 return 0;
             if (tr.IsOne)
                 return 1;
-
             throw new InvalidOperationException("Internal error in trace calculation");
         }
     }
diff --git a/crypto/src/math/ec/ECLookupTable.cs b/crypto/src/math/ec/ECLookupTable.cs
index 35995d426..c14087d3b 100644
--- a/crypto/src/math/ec/ECLookupTable.cs
+++ b/crypto/src/math/ec/ECLookupTable.cs
@@ -6,5 +6,6 @@ namespace Org.BouncyCastle.Math.EC
     {
         int Size { get; }
         ECPoint Lookup(int index);
+        ECPoint LookupVar(int index);
     }
 }
diff --git a/crypto/src/math/ec/ECPoint.cs b/crypto/src/math/ec/ECPoint.cs
index 2acc9f5c0..6a7c3ecf0 100644
--- a/crypto/src/math/ec/ECPoint.cs
+++ b/crypto/src/math/ec/ECPoint.cs
@@ -306,6 +306,13 @@ namespace Org.BouncyCastle.Math.EC
                 : Curve.CreateRawPoint(RawXCoord.Multiply(scale), RawYCoord, RawZCoords, IsCompressed);
         }
 
+        public virtual ECPoint ScaleXNegateY(ECFieldElement scale)
+        {
+            return IsInfinity
+                ? this
+                : Curve.CreateRawPoint(RawXCoord.Multiply(scale), RawYCoord.Negate(), RawZCoords, IsCompressed);
+        }
+
         public virtual ECPoint ScaleY(ECFieldElement scale)
         {
             return IsInfinity
@@ -313,6 +320,13 @@ namespace Org.BouncyCastle.Math.EC
                 : Curve.CreateRawPoint(RawXCoord, RawYCoord.Multiply(scale), RawZCoords, IsCompressed);
         }
 
+        public virtual ECPoint ScaleYNegateX(ECFieldElement scale)
+        {
+            return IsInfinity
+                ? this
+                : Curve.CreateRawPoint(RawXCoord.Negate(), RawYCoord.Multiply(scale), RawZCoords, IsCompressed);
+        }
+
         public override bool Equals(object obj)
         {
             return Equals(obj as ECPoint);
@@ -1421,34 +1435,44 @@ namespace Org.BouncyCastle.Math.EC
             if (BigInteger.Two.Equals(cofactor))
             {
                 /*
-                 *  Check that the trace of (X + A) is 0, then there exists a solution to L^2 + L = X + A,
-                 *  and so a halving is possible, so this point is the double of another.  
+                 * Check that 0 == Tr(X + A); then there exists a solution to L^2 + L = X + A, and
+                 * so a halving is possible, so this point is the double of another.
+                 * 
+                 * Note: Tr(A) == 1 for cofactor 2 curves.
                  */
                 ECPoint N = this.Normalize();
                 ECFieldElement X = N.AffineXCoord;
-                ECFieldElement rhs = X.Add(curve.A);
-                return ((AbstractF2mFieldElement)rhs).Trace() == 0;
+                return 0 != ((AbstractF2mFieldElement)X).Trace();
             }
             if (BigInteger.ValueOf(4).Equals(cofactor))
             {
                 /*
                  * Solve L^2 + L = X + A to find the half of this point, if it exists (fail if not).
-                 * Generate both possibilities for the square of the half-point's x-coordinate (w),
-                 * and check if Tr(w + A) == 0 for at least one; then a second halving is possible
-                 * (see comments for cofactor 2 above), so this point is four times another.
                  * 
-                 * Note: Tr(x^2) == Tr(x). 
+                 * Note: Tr(A) == 0 for cofactor 4 curves.
                  */
                 ECPoint N = this.Normalize();
                 ECFieldElement X = N.AffineXCoord;
-                ECFieldElement lambda = ((AbstractF2mCurve)curve).SolveQuadraticEquation(X.Add(curve.A));
-                if (lambda == null)
+                ECFieldElement L = ((AbstractF2mCurve)curve).SolveQuadraticEquation(X.Add(curve.A));
+                if (null == L)
                     return false;
 
-                ECFieldElement w = X.Multiply(lambda).Add(N.AffineYCoord);
-                ECFieldElement t = w.Add(curve.A);
-                return ((AbstractF2mFieldElement)t).Trace() == 0
-                    || ((AbstractF2mFieldElement)(t.Add(X))).Trace() == 0;
+                /*
+                 * A solution exists, therefore 0 == Tr(X + A) == Tr(X).
+                 */
+                ECFieldElement Y = N.AffineYCoord;
+                ECFieldElement T = X.Multiply(L).Add(Y);
+
+                /*
+                 * Either T or (T + X) is the square of a half-point's x coordinate (hx). In either
+                 * case, the half-point can be halved again when 0 == Tr(hx + A).
+                 * 
+                 * Note: Tr(hx + A) == Tr(hx) == Tr(hx^2) == Tr(T) == Tr(T + X)
+                 *
+                 * Check that 0 == Tr(T); then there exists a solution to L^2 + L = hx + A, and so a
+                 * second halving is possible and this point is four times some other.
+                 */
+                return 0 == ((AbstractF2mFieldElement)T).Trace();
             }
 
             return base.SatisfiesOrder();
@@ -1490,6 +1514,11 @@ namespace Org.BouncyCastle.Math.EC
             }
         }
 
+        public override ECPoint ScaleXNegateY(ECFieldElement scale)
+        {
+            return ScaleX(scale);
+        }
+
         public override ECPoint ScaleY(ECFieldElement scale)
         {
             if (this.IsInfinity)
@@ -1514,6 +1543,11 @@ namespace Org.BouncyCastle.Math.EC
             }
         }
 
+        public override ECPoint ScaleYNegateX(ECFieldElement scale)
+        {
+            return ScaleY(scale);
+        }
+
         public override ECPoint Subtract(ECPoint b)
         {
             if (b.IsInfinity)
diff --git a/crypto/src/math/ec/ScaleXNegateYPointMap.cs b/crypto/src/math/ec/ScaleXNegateYPointMap.cs
new file mode 100644
index 000000000..b0466a633
--- /dev/null
+++ b/crypto/src/math/ec/ScaleXNegateYPointMap.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC
+{
+    public class ScaleXNegateYPointMap
+        : ECPointMap
+    {
+        protected readonly ECFieldElement scale;
+
+        public ScaleXNegateYPointMap(ECFieldElement scale)
+        {
+            this.scale = scale;
+        }
+
+        public virtual ECPoint Map(ECPoint p)
+        {
+            return p.ScaleXNegateY(scale);
+        }
+    }
+}
diff --git a/crypto/src/math/ec/ScaleYNegateXPointMap.cs b/crypto/src/math/ec/ScaleYNegateXPointMap.cs
new file mode 100644
index 000000000..6a7fed12e
--- /dev/null
+++ b/crypto/src/math/ec/ScaleYNegateXPointMap.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC
+{
+    public class ScaleYNegateXPointMap
+        : ECPointMap
+    {
+        protected readonly ECFieldElement scale;
+
+        public ScaleYNegateXPointMap(ECFieldElement scale)
+        {
+            this.scale = scale;
+        }
+
+        public virtual ECPoint Map(ECPoint p)
+        {
+            return p.ScaleYNegateX(scale);
+        }
+    }
+}
diff --git a/crypto/src/math/ec/SimpleLookupTable.cs b/crypto/src/math/ec/SimpleLookupTable.cs
index f1e32f215..ed300baaa 100644
--- a/crypto/src/math/ec/SimpleLookupTable.cs
+++ b/crypto/src/math/ec/SimpleLookupTable.cs
@@ -3,7 +3,7 @@
 namespace Org.BouncyCastle.Math.EC
 {
     public class SimpleLookupTable
-        : ECLookupTable
+        : AbstractECLookupTable
     {
         private static ECPoint[] Copy(ECPoint[] points, int off, int len)
         {
@@ -22,12 +22,17 @@ namespace Org.BouncyCastle.Math.EC
             this.points = Copy(points, off, len);
         }
 
-        public virtual int Size
+        public override int Size
         {
             get { return points.Length; }
         }
 
-        public virtual ECPoint Lookup(int index)
+        public override ECPoint Lookup(int index)
+        {
+            throw new NotSupportedException("Constant-time lookup not supported");
+        }
+
+        public override ECPoint LookupVar(int index)
         {
             return points[index];
         }
diff --git a/crypto/src/math/ec/custom/djb/Curve25519.cs b/crypto/src/math/ec/custom/djb/Curve25519.cs
index c0f911a9c..190edf6ec 100644
--- a/crypto/src/math/ec/custom/djb/Curve25519.cs
+++ b/crypto/src/math/ec/custom/djb/Curve25519.cs
@@ -8,11 +8,15 @@ namespace Org.BouncyCastle.Math.EC.Custom.Djb
     internal class Curve25519
         : AbstractFpCurve
     {
-        public static readonly BigInteger q = Nat256.ToBigInteger(Curve25519Field.P);
+        public static readonly BigInteger q = Curve25519FieldElement.Q;
 
-        private const int Curve25519_DEFAULT_COORDS = COORD_JACOBIAN_MODIFIED;
-        private const int CURVE25519_FE_INTS = 8;
+        private static readonly BigInteger C_a = new BigInteger(1, Hex.Decode("2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA984914A144"));
+        private static readonly BigInteger C_b = new BigInteger(1, Hex.Decode("7B425ED097B425ED097B425ED097B425ED097B425ED097B4260B5E9C7710C864"));
 
+        private const int CURVE25519_DEFAULT_COORDS = COORD_JACOBIAN_MODIFIED;
+        private const int CURVE25519_FE_INTS = 8;
+        private static readonly ECFieldElement[] CURVE25519_AFFINE_ZS = new ECFieldElement[] {
+            new Curve25519FieldElement(BigInteger.One), new Curve25519FieldElement(C_a) }; 
         protected readonly Curve25519Point m_infinity;
 
         public Curve25519()
@@ -20,13 +24,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Djb
         {
             this.m_infinity = new Curve25519Point(this, null, null);
 
-            this.m_a = FromBigInteger(new BigInteger(1,
-                Hex.Decode("2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA984914A144")));
-            this.m_b = FromBigInteger(new BigInteger(1,
-                Hex.Decode("7B425ED097B425ED097B425ED097B425ED097B425ED097B4260B5E9C7710C864")));
+            this.m_a = FromBigInteger(C_a);
+            this.m_b = FromBigInteger(C_b);
             this.m_order = new BigInteger(1, Hex.Decode("1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED"));
             this.m_cofactor = BigInteger.ValueOf(8);
-            this.m_coord = Curve25519_DEFAULT_COORDS;
+            this.m_coord = CURVE25519_DEFAULT_COORDS;
         }
 
         protected override ECCurve CloneCurve()
@@ -92,7 +94,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Djb
         }
 
         private class Curve25519LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly Curve25519 m_outer;
             private readonly uint[] m_table;
@@ -105,12 +107,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Djb
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 uint[] x = Nat256.Create(), y = Nat256.Create();
                 int pos = 0;
@@ -128,7 +130,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Djb
                     pos += (CURVE25519_FE_INTS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new Curve25519FieldElement(x), new Curve25519FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                uint[] x = Nat256.Create(), y = Nat256.Create();
+                int pos = index * CURVE25519_FE_INTS * 2;
+
+                for (int j = 0; j < CURVE25519_FE_INTS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + CURVE25519_FE_INTS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(uint[] x, uint[] y)
+            {
+                return m_outer.CreateRawPoint(new Curve25519FieldElement(x), new Curve25519FieldElement(y), CURVE25519_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/djb/Curve25519FieldElement.cs b/crypto/src/math/ec/custom/djb/Curve25519FieldElement.cs
index 37256a550..5d82df547 100644
--- a/crypto/src/math/ec/custom/djb/Curve25519FieldElement.cs
+++ b/crypto/src/math/ec/custom/djb/Curve25519FieldElement.cs
@@ -8,7 +8,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Djb
     internal class Curve25519FieldElement
         : AbstractFpFieldElement
     {
-        public static readonly BigInteger Q = Curve25519.q;
+        public static readonly BigInteger Q = Nat256.ToBigInteger(Curve25519Field.P);
 
         // Calculated as ECConstants.TWO.modPow(Q.shiftRight(2), Q)
         private static readonly uint[] PRECOMP_POW2 = new uint[]{ 0x4a0ea0b0, 0xc4ee1b27, 0xad2fe478, 0x2f431806,
diff --git a/crypto/src/math/ec/custom/gm/SM2P256V1Curve.cs b/crypto/src/math/ec/custom/gm/SM2P256V1Curve.cs
index 2c5d8f3a3..4978a2beb 100644
--- a/crypto/src/math/ec/custom/gm/SM2P256V1Curve.cs
+++ b/crypto/src/math/ec/custom/gm/SM2P256V1Curve.cs
@@ -8,11 +8,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.GM
     internal class SM2P256V1Curve
         : AbstractFpCurve
     {
-        public static readonly BigInteger q = new BigInteger(1,
-            Hex.Decode("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF"));
+        public static readonly BigInteger q = SM2P256V1FieldElement.Q;
 
         private const int SM2P256V1_DEFAULT_COORDS = COORD_JACOBIAN;
         private const int SM2P256V1_FE_INTS = 8;
+        private static readonly ECFieldElement[] SM2P256V1_AFFINE_ZS = new ECFieldElement[] { new SM2P256V1FieldElement(BigInteger.One) }; 
 
         protected readonly SM2P256V1Point m_infinity;
 
@@ -93,7 +93,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.GM
         }
 
         private class SM2P256V1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SM2P256V1Curve m_outer;
             private readonly uint[] m_table;
@@ -106,12 +106,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.GM
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 uint[] x = Nat256.Create(), y = Nat256.Create();
                 int pos = 0;
@@ -129,7 +129,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.GM
                     pos += (SM2P256V1_FE_INTS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SM2P256V1FieldElement(x), new SM2P256V1FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                uint[] x = Nat256.Create(), y = Nat256.Create();
+                int pos = index * SM2P256V1_FE_INTS * 2;
+
+                for (int j = 0; j < SM2P256V1_FE_INTS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SM2P256V1_FE_INTS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(uint[] x, uint[] y)
+            {
+                return m_outer.CreateRawPoint(new SM2P256V1FieldElement(x), new SM2P256V1FieldElement(y), SM2P256V1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/gm/SM2P256V1FieldElement.cs b/crypto/src/math/ec/custom/gm/SM2P256V1FieldElement.cs
index 087a040f2..a1f675f90 100644
--- a/crypto/src/math/ec/custom/gm/SM2P256V1FieldElement.cs
+++ b/crypto/src/math/ec/custom/gm/SM2P256V1FieldElement.cs
@@ -2,13 +2,15 @@
 
 using Org.BouncyCastle.Math.Raw;
 using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
 
 namespace Org.BouncyCastle.Math.EC.Custom.GM
 {
     internal class SM2P256V1FieldElement
         : AbstractFpFieldElement
     {
-        public static readonly BigInteger Q = SM2P256V1Curve.q;
+        public static readonly BigInteger Q = new BigInteger(1,
+            Hex.Decode("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF"));
 
         protected internal readonly uint[] x;
 
diff --git a/crypto/src/math/ec/custom/sec/SecP128R1Curve.cs b/crypto/src/math/ec/custom/sec/SecP128R1Curve.cs
index cc50f50d2..58bff2390 100644
--- a/crypto/src/math/ec/custom/sec/SecP128R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecP128R1Curve.cs
@@ -8,11 +8,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     internal class SecP128R1Curve
         : AbstractFpCurve
     {
-        public static readonly BigInteger q = new BigInteger(1,
-            Hex.Decode("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF"));
+        public static readonly BigInteger q = SecP128R1FieldElement.Q;
 
         private const int SECP128R1_DEFAULT_COORDS = COORD_JACOBIAN;
         private const int SECP128R1_FE_INTS = 4;
+        private static readonly ECFieldElement[] SECP128R1_AFFINE_ZS = new ECFieldElement[] { new SecP128R1FieldElement(BigInteger.One) }; 
 
         protected readonly SecP128R1Point m_infinity;
 
@@ -94,7 +94,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecP128R1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecP128R1Curve m_outer;
             private readonly uint[] m_table;
@@ -107,12 +107,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 uint[] x = Nat128.Create(), y = Nat128.Create();
                 int pos = 0;
@@ -130,7 +130,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECP128R1_FE_INTS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecP128R1FieldElement(x), new SecP128R1FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                uint[] x = Nat128.Create(), y = Nat128.Create();
+                int pos = index * SECP128R1_FE_INTS * 2;
+
+                for (int j = 0; j < SECP128R1_FE_INTS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECP128R1_FE_INTS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(uint[] x, uint[] y)
+            {
+                return m_outer.CreateRawPoint(new SecP128R1FieldElement(x), new SecP128R1FieldElement(y), SECP128R1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecP128R1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP128R1FieldElement.cs
index 5912a87e8..04f432ced 100644
--- a/crypto/src/math/ec/custom/sec/SecP128R1FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecP128R1FieldElement.cs
@@ -2,13 +2,15 @@
 
 using Org.BouncyCastle.Math.Raw;
 using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
 
 namespace Org.BouncyCastle.Math.EC.Custom.Sec
 {
     internal class SecP128R1FieldElement
         : AbstractFpFieldElement
     {
-        public static readonly BigInteger Q = SecP128R1Curve.q;
+        public static readonly BigInteger Q = new BigInteger(1,
+            Hex.Decode("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF"));
 
         protected internal readonly uint[] x;
 
diff --git a/crypto/src/math/ec/custom/sec/SecP160K1Curve.cs b/crypto/src/math/ec/custom/sec/SecP160K1Curve.cs
index 234c86b87..1b5bbfe96 100644
--- a/crypto/src/math/ec/custom/sec/SecP160K1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecP160K1Curve.cs
@@ -8,10 +8,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     internal class SecP160K1Curve
         : AbstractFpCurve
     {
-        public static readonly BigInteger q = SecP160R2Curve.q;
+        public static readonly BigInteger q = SecP160R2FieldElement.Q;
 
         private const int SECP160K1_DEFAULT_COORDS = COORD_JACOBIAN;
         private const int SECP160K1_FE_INTS = 5;
+        private static readonly ECFieldElement[] SECP160K1_AFFINE_ZS = new ECFieldElement[] { new SecP160R2FieldElement(BigInteger.One) };
 
         protected readonly SecP160K1Point m_infinity;
 
@@ -90,7 +91,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecP160K1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecP160K1Curve m_outer;
             private readonly uint[] m_table;
@@ -103,12 +104,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 uint[] x = Nat256.Create(), y = Nat256.Create();
                 int pos = 0;
@@ -126,7 +127,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECP160K1_FE_INTS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecP160R2FieldElement(x), new SecP160R2FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                uint[] x = Nat256.Create(), y = Nat256.Create();
+                int pos = index * SECP160K1_FE_INTS * 2;
+
+                for (int j = 0; j < SECP160K1_FE_INTS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECP160K1_FE_INTS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(uint[] x, uint[] y)
+            {
+                return m_outer.CreateRawPoint(new SecP160R2FieldElement(x), new SecP160R2FieldElement(y), SECP160K1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecP160R1Curve.cs b/crypto/src/math/ec/custom/sec/SecP160R1Curve.cs
index 958eb2765..42f2f467b 100644
--- a/crypto/src/math/ec/custom/sec/SecP160R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecP160R1Curve.cs
@@ -8,11 +8,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     internal class SecP160R1Curve
         : AbstractFpCurve
     {
-        public static readonly BigInteger q = new BigInteger(1,
-            Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF"));
+        public static readonly BigInteger q = SecP160R1FieldElement.Q;
 
         private const int SECP160R1_DEFAULT_COORDS = COORD_JACOBIAN;
         private const int SECP160R1_FE_INTS = 5;
+        private static readonly ECFieldElement[] SECP160R1_AFFINE_ZS = new ECFieldElement[] { new SecP160R1FieldElement(BigInteger.One) }; 
 
         protected readonly SecP160R1Point m_infinity;
 
@@ -94,7 +94,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecP160R1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecP160R1Curve m_outer;
             private readonly uint[] m_table;
@@ -107,12 +107,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 uint[] x = Nat160.Create(), y = Nat160.Create();
                 int pos = 0;
@@ -130,7 +130,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECP160R1_FE_INTS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecP160R1FieldElement(x), new SecP160R1FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                uint[] x = Nat160.Create(), y = Nat160.Create();
+                int pos = index * SECP160R1_FE_INTS * 2;
+
+                for (int j = 0; j < SECP160R1_FE_INTS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECP160R1_FE_INTS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(uint[] x, uint[] y)
+            {
+                return m_outer.CreateRawPoint(new SecP160R1FieldElement(x), new SecP160R1FieldElement(y), SECP160R1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecP160R1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP160R1FieldElement.cs
index 3ab11bdae..5365d7cd0 100644
--- a/crypto/src/math/ec/custom/sec/SecP160R1FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecP160R1FieldElement.cs
@@ -2,13 +2,15 @@
 
 using Org.BouncyCastle.Math.Raw;
 using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
 
 namespace Org.BouncyCastle.Math.EC.Custom.Sec
 {
     internal class SecP160R1FieldElement
         : AbstractFpFieldElement
     {
-        public static readonly BigInteger Q = SecP160R1Curve.q;
+        public static readonly BigInteger Q = new BigInteger(1,
+            Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF"));
 
         protected internal readonly uint[] x;
 
diff --git a/crypto/src/math/ec/custom/sec/SecP160R2Curve.cs b/crypto/src/math/ec/custom/sec/SecP160R2Curve.cs
index 252312e62..17f73d7ce 100644
--- a/crypto/src/math/ec/custom/sec/SecP160R2Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecP160R2Curve.cs
@@ -8,11 +8,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     internal class SecP160R2Curve
         : AbstractFpCurve
     {
-        public static readonly BigInteger q = new BigInteger(1,
-            Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73"));
+        public static readonly BigInteger q = SecP160R2FieldElement.Q;
 
         private const int SECP160R2_DEFAULT_COORDS = COORD_JACOBIAN;
         private const int SECP160R2_FE_INTS = 5;
+        private static readonly ECFieldElement[] SECP160R2_AFFINE_ZS = new ECFieldElement[] { new SecP160R2FieldElement(BigInteger.One) };
 
         protected readonly SecP160R2Point m_infinity;
 
@@ -94,7 +94,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecP160R2LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecP160R2Curve m_outer;
             private readonly uint[] m_table;
@@ -107,12 +107,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 uint[] x = Nat160.Create(), y = Nat160.Create();
                 int pos = 0;
@@ -130,7 +130,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECP160R2_FE_INTS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecP160R2FieldElement(x), new SecP160R2FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                uint[] x = Nat160.Create(), y = Nat160.Create();
+                int pos = index * SECP160R2_FE_INTS * 2;
+
+                for (int j = 0; j < SECP160R2_FE_INTS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECP160R2_FE_INTS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(uint[] x, uint[] y)
+            {
+                return m_outer.CreateRawPoint(new SecP160R2FieldElement(x), new SecP160R2FieldElement(y), SECP160R2_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecP160R2FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP160R2FieldElement.cs
index 9d8131857..95d3c0b31 100644
--- a/crypto/src/math/ec/custom/sec/SecP160R2FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecP160R2FieldElement.cs
@@ -2,13 +2,15 @@
 
 using Org.BouncyCastle.Math.Raw;
 using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
 
 namespace Org.BouncyCastle.Math.EC.Custom.Sec
 {
     internal class SecP160R2FieldElement
         : AbstractFpFieldElement
     {
-        public static readonly BigInteger Q = SecP160R2Curve.q;
+        public static readonly BigInteger Q = new BigInteger(1,
+            Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73"));
 
         protected internal readonly uint[] x;
 
diff --git a/crypto/src/math/ec/custom/sec/SecP192K1Curve.cs b/crypto/src/math/ec/custom/sec/SecP192K1Curve.cs
index 518e0a131..6647ebab9 100644
--- a/crypto/src/math/ec/custom/sec/SecP192K1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecP192K1Curve.cs
@@ -8,11 +8,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     internal class SecP192K1Curve
         : AbstractFpCurve
     {
-        public static readonly BigInteger q = new BigInteger(1,
-            Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37"));
+        public static readonly BigInteger q = SecP192K1FieldElement.Q;
 
         private const int SECP192K1_DEFAULT_COORDS = COORD_JACOBIAN;
         private const int SECP192K1_FE_INTS = 6;
+        private static readonly ECFieldElement[] SECP192K1_AFFINE_ZS = new ECFieldElement[] { new SecP192K1FieldElement(BigInteger.One) };
 
         protected readonly SecP192K1Point m_infinity;
 
@@ -91,7 +91,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecP192K1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecP192K1Curve m_outer;
             private readonly uint[] m_table;
@@ -104,12 +104,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 uint[] x = Nat192.Create(), y = Nat192.Create();
                 int pos = 0;
@@ -127,7 +127,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECP192K1_FE_INTS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecP192K1FieldElement(x), new SecP192K1FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                uint[] x = Nat192.Create(), y = Nat192.Create();
+                int pos = index * SECP192K1_FE_INTS * 2;
+
+                for (int j = 0; j < SECP192K1_FE_INTS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECP192K1_FE_INTS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(uint[] x, uint[] y)
+            {
+                return m_outer.CreateRawPoint(new SecP192K1FieldElement(x), new SecP192K1FieldElement(y), SECP192K1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecP192K1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP192K1FieldElement.cs
index 54b72573c..d3de532d9 100644
--- a/crypto/src/math/ec/custom/sec/SecP192K1FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecP192K1FieldElement.cs
@@ -3,13 +3,15 @@ using System.Diagnostics;
 
 using Org.BouncyCastle.Math.Raw;
 using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
 
 namespace Org.BouncyCastle.Math.EC.Custom.Sec
 {
     internal class SecP192K1FieldElement
         : AbstractFpFieldElement
     {
-        public static readonly BigInteger Q = SecP192K1Curve.q;
+        public static readonly BigInteger Q = new BigInteger(1,
+            Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37"));
 
         protected internal readonly uint[] x;
 
diff --git a/crypto/src/math/ec/custom/sec/SecP192R1Curve.cs b/crypto/src/math/ec/custom/sec/SecP192R1Curve.cs
index 91d31932a..a65afd0b0 100644
--- a/crypto/src/math/ec/custom/sec/SecP192R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecP192R1Curve.cs
@@ -8,11 +8,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     internal class SecP192R1Curve
         : AbstractFpCurve
     {
-        public static readonly BigInteger q = new BigInteger(1,
-            Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF"));
+        public static readonly BigInteger q = SecP192R1FieldElement.Q;
 
         private const int SECP192R1_DEFAULT_COORDS = COORD_JACOBIAN;
         private const int SECP192R1_FE_INTS = 6;
+        private static readonly ECFieldElement[] SECP192R1_AFFINE_ZS = new ECFieldElement[] { new SecP192R1FieldElement(BigInteger.One) };
 
         protected readonly SecP192R1Point m_infinity;
 
@@ -94,7 +94,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecP192R1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecP192R1Curve m_outer;
             private readonly uint[] m_table;
@@ -107,12 +107,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 uint[] x = Nat192.Create(), y = Nat192.Create();
                 int pos = 0;
@@ -130,7 +130,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECP192R1_FE_INTS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecP192R1FieldElement(x), new SecP192R1FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                uint[] x = Nat192.Create(), y = Nat192.Create();
+                int pos = index * SECP192R1_FE_INTS * 2;
+
+                for (int j = 0; j < SECP192R1_FE_INTS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECP192R1_FE_INTS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(uint[] x, uint[] y)
+            {
+                return m_outer.CreateRawPoint(new SecP192R1FieldElement(x), new SecP192R1FieldElement(y), SECP192R1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecP192R1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP192R1FieldElement.cs
index f3e12b542..65a1aadb3 100644
--- a/crypto/src/math/ec/custom/sec/SecP192R1FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecP192R1FieldElement.cs
@@ -2,13 +2,15 @@
 
 using Org.BouncyCastle.Math.Raw;
 using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
 
 namespace Org.BouncyCastle.Math.EC.Custom.Sec
 {
     internal class SecP192R1FieldElement
         : AbstractFpFieldElement
     {
-        public static readonly BigInteger Q = SecP192R1Curve.q;
+        public static readonly BigInteger Q = new BigInteger(1,
+            Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF"));
 
         protected internal readonly uint[] x;
 
diff --git a/crypto/src/math/ec/custom/sec/SecP224K1Curve.cs b/crypto/src/math/ec/custom/sec/SecP224K1Curve.cs
index a9c55090f..ce56fbf52 100644
--- a/crypto/src/math/ec/custom/sec/SecP224K1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecP224K1Curve.cs
@@ -8,11 +8,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     internal class SecP224K1Curve
         : AbstractFpCurve
     {
-        public static readonly BigInteger q = new BigInteger(1,
-            Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D"));
+        public static readonly BigInteger q = SecP224K1FieldElement.Q;
 
         private const int SECP224K1_DEFAULT_COORDS = COORD_JACOBIAN;
         private const int SECP224K1_FE_INTS = 7;
+        private static readonly ECFieldElement[] SECP224K1_AFFINE_ZS = new ECFieldElement[] { new SecP224K1FieldElement(BigInteger.One) };
 
         protected readonly SecP224K1Point m_infinity;
 
@@ -91,7 +91,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecP224K1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecP224K1Curve m_outer;
             private readonly uint[] m_table;
@@ -104,12 +104,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 uint[] x = Nat224.Create(), y = Nat224.Create();
                 int pos = 0;
@@ -127,7 +127,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECP224K1_FE_INTS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecP224K1FieldElement(x), new SecP224K1FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                uint[] x = Nat224.Create(), y = Nat224.Create();
+                int pos = index * SECP224K1_FE_INTS * 2;
+
+                for (int j = 0; j < SECP224K1_FE_INTS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECP224K1_FE_INTS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(uint[] x, uint[] y)
+            {
+                return m_outer.CreateRawPoint(new SecP224K1FieldElement(x), new SecP224K1FieldElement(y), SECP224K1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecP224K1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP224K1FieldElement.cs
index ef53a88d6..0614b7def 100644
--- a/crypto/src/math/ec/custom/sec/SecP224K1FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecP224K1FieldElement.cs
@@ -3,13 +3,15 @@ using System.Diagnostics;
 
 using Org.BouncyCastle.Math.Raw;
 using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
 
 namespace Org.BouncyCastle.Math.EC.Custom.Sec
 {
     internal class SecP224K1FieldElement
         : AbstractFpFieldElement
     {
-        public static readonly BigInteger Q = SecP224K1Curve.q;
+        public static readonly BigInteger Q = new BigInteger(1,
+            Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D"));
 
         // Calculated as BigInteger.Two.ModPow(Q.ShiftRight(2), Q)
         private static readonly uint[] PRECOMP_POW2 = new uint[]{ 0x33bfd202, 0xdcfad133, 0x2287624a, 0xc3811ba8,
diff --git a/crypto/src/math/ec/custom/sec/SecP224R1Curve.cs b/crypto/src/math/ec/custom/sec/SecP224R1Curve.cs
index ec34390aa..a37fc282f 100644
--- a/crypto/src/math/ec/custom/sec/SecP224R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecP224R1Curve.cs
@@ -8,11 +8,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     internal class SecP224R1Curve
         : AbstractFpCurve
     {
-        public static readonly BigInteger q = new BigInteger(1,
-            Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001"));
+        public static readonly BigInteger q = SecP224R1FieldElement.Q;
 
         private const int SECP224R1_DEFAULT_COORDS = COORD_JACOBIAN;
         private const int SECP224R1_FE_INTS = 7;
+        private static readonly ECFieldElement[] SECP224R1_AFFINE_ZS = new ECFieldElement[] { new SecP224R1FieldElement(BigInteger.One) };
 
         protected readonly SecP224R1Point m_infinity;
 
@@ -94,7 +94,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecP224R1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecP224R1Curve m_outer;
             private readonly uint[] m_table;
@@ -107,12 +107,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 uint[] x = Nat224.Create(), y = Nat224.Create();
                 int pos = 0;
@@ -130,7 +130,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECP224R1_FE_INTS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecP224R1FieldElement(x), new SecP224R1FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                uint[] x = Nat224.Create(), y = Nat224.Create();
+                int pos = index * SECP224R1_FE_INTS * 2;
+
+                for (int j = 0; j < SECP224R1_FE_INTS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECP224R1_FE_INTS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(uint[] x, uint[] y)
+            {
+                return m_outer.CreateRawPoint(new SecP224R1FieldElement(x), new SecP224R1FieldElement(y), SECP224R1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecP224R1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP224R1FieldElement.cs
index 5780b7481..968bc0baa 100644
--- a/crypto/src/math/ec/custom/sec/SecP224R1FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecP224R1FieldElement.cs
@@ -2,13 +2,15 @@
 
 using Org.BouncyCastle.Math.Raw;
 using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
 
 namespace Org.BouncyCastle.Math.EC.Custom.Sec
 {
     internal class SecP224R1FieldElement
         : AbstractFpFieldElement
     {
-        public static readonly BigInteger Q = SecP224R1Curve.q;
+        public static readonly BigInteger Q = new BigInteger(1,
+            Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001"));
 
         protected internal readonly uint[] x;
 
diff --git a/crypto/src/math/ec/custom/sec/SecP256K1Curve.cs b/crypto/src/math/ec/custom/sec/SecP256K1Curve.cs
index b3a5dd646..26c788b5f 100644
--- a/crypto/src/math/ec/custom/sec/SecP256K1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecP256K1Curve.cs
@@ -8,11 +8,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     internal class SecP256K1Curve
         : AbstractFpCurve
     {
-        public static readonly BigInteger q = new BigInteger(1,
-            Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F"));
+        public static readonly BigInteger q = SecP256K1FieldElement.Q;
 
         private const int SECP256K1_DEFAULT_COORDS = COORD_JACOBIAN;
         private const int SECP256K1_FE_INTS = 8;
+        private static readonly ECFieldElement[] SECP256K1_AFFINE_ZS = new ECFieldElement[] { new SecP256K1FieldElement(BigInteger.One) };
 
         protected readonly SecP256K1Point m_infinity;
 
@@ -91,7 +91,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecP256K1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecP256K1Curve m_outer;
             private readonly uint[] m_table;
@@ -104,12 +104,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 uint[] x = Nat256.Create(), y = Nat256.Create();
                 int pos = 0;
@@ -127,7 +127,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECP256K1_FE_INTS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecP256K1FieldElement(x), new SecP256K1FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                uint[] x = Nat256.Create(), y = Nat256.Create();
+                int pos = index * SECP256K1_FE_INTS * 2;
+
+                for (int j = 0; j < SECP256K1_FE_INTS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECP256K1_FE_INTS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(uint[] x, uint[] y)
+            {
+                return m_outer.CreateRawPoint(new SecP256K1FieldElement(x), new SecP256K1FieldElement(y), SECP256K1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecP256K1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP256K1FieldElement.cs
index 9a604bdb7..d24f8d0df 100644
--- a/crypto/src/math/ec/custom/sec/SecP256K1FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecP256K1FieldElement.cs
@@ -3,13 +3,15 @@ using System.Diagnostics;
 
 using Org.BouncyCastle.Math.Raw;
 using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
 
 namespace Org.BouncyCastle.Math.EC.Custom.Sec
 {
     internal class SecP256K1FieldElement
         : AbstractFpFieldElement
     {
-        public static readonly BigInteger Q = SecP256K1Curve.q;
+        public static readonly BigInteger Q = new BigInteger(1,
+            Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F"));
 
         protected internal readonly uint[] x;
 
diff --git a/crypto/src/math/ec/custom/sec/SecP256R1Curve.cs b/crypto/src/math/ec/custom/sec/SecP256R1Curve.cs
index 2d9a88b72..504d7edc6 100644
--- a/crypto/src/math/ec/custom/sec/SecP256R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecP256R1Curve.cs
@@ -8,11 +8,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     internal class SecP256R1Curve
         : AbstractFpCurve
     {
-        public static readonly BigInteger q = new BigInteger(1,
-            Hex.Decode("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF"));
+        public static readonly BigInteger q = SecP256R1FieldElement.Q;
 
         private const int SECP256R1_DEFAULT_COORDS = COORD_JACOBIAN;
         private const int SECP256R1_FE_INTS = 8;
+        private static readonly ECFieldElement[] SECP256R1_AFFINE_ZS = new ECFieldElement[] { new SecP256R1FieldElement(BigInteger.One) }; 
 
         protected readonly SecP256R1Point m_infinity;
 
@@ -93,7 +93,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecP256R1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecP256R1Curve m_outer;
             private readonly uint[] m_table;
@@ -106,12 +106,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 uint[] x = Nat256.Create(), y = Nat256.Create();
                 int pos = 0;
@@ -129,7 +129,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECP256R1_FE_INTS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecP256R1FieldElement(x), new SecP256R1FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                uint[] x = Nat256.Create(), y = Nat256.Create();
+                int pos = index * SECP256R1_FE_INTS * 2;
+
+                for (int j = 0; j < SECP256R1_FE_INTS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECP256R1_FE_INTS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(uint[] x, uint[] y)
+            {
+                return m_outer.CreateRawPoint(new SecP256R1FieldElement(x), new SecP256R1FieldElement(y), SECP256R1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecP256R1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP256R1FieldElement.cs
index 808e99ea6..be4021485 100644
--- a/crypto/src/math/ec/custom/sec/SecP256R1FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecP256R1FieldElement.cs
@@ -2,13 +2,15 @@
 
 using Org.BouncyCastle.Math.Raw;
 using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
 
 namespace Org.BouncyCastle.Math.EC.Custom.Sec
 {
     internal class SecP256R1FieldElement
         : AbstractFpFieldElement
     {
-        public static readonly BigInteger Q = SecP256R1Curve.q;
+        public static readonly BigInteger Q = new BigInteger(1,
+            Hex.Decode("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF"));
 
         protected internal readonly uint[] x;
 
diff --git a/crypto/src/math/ec/custom/sec/SecP384R1Curve.cs b/crypto/src/math/ec/custom/sec/SecP384R1Curve.cs
index 26b057198..5c6afc2e5 100644
--- a/crypto/src/math/ec/custom/sec/SecP384R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecP384R1Curve.cs
@@ -8,11 +8,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     internal class SecP384R1Curve
         : AbstractFpCurve
     {
-        public static readonly BigInteger q = new BigInteger(1,
-            Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF"));
+        public static readonly BigInteger q = SecP384R1FieldElement.Q;
 
         private const int SECP384R1_DEFAULT_COORDS = COORD_JACOBIAN;
         private const int SECP384R1_FE_INTS = 12;
+        private static readonly ECFieldElement[] SECP384R1_AFFINE_ZS = new ECFieldElement[] { new SecP384R1FieldElement(BigInteger.One) };
 
         protected readonly SecP384R1Point m_infinity;
 
@@ -93,7 +93,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecP384R1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecP384R1Curve m_outer;
             private readonly uint[] m_table;
@@ -106,12 +106,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 uint[] x = Nat.Create(SECP384R1_FE_INTS), y = Nat.Create(SECP384R1_FE_INTS);
                 int pos = 0;
@@ -129,7 +129,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECP384R1_FE_INTS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecP384R1FieldElement(x), new SecP384R1FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                uint[] x = Nat.Create(SECP384R1_FE_INTS), y = Nat.Create(SECP384R1_FE_INTS);
+                int pos = index * SECP384R1_FE_INTS * 2;
+
+                for (int j = 0; j < SECP384R1_FE_INTS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECP384R1_FE_INTS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(uint[] x, uint[] y)
+            {
+                return m_outer.CreateRawPoint(new SecP384R1FieldElement(x), new SecP384R1FieldElement(y), SECP384R1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecP384R1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP384R1FieldElement.cs
index 7eedccae6..9d3f51d87 100644
--- a/crypto/src/math/ec/custom/sec/SecP384R1FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecP384R1FieldElement.cs
@@ -2,13 +2,15 @@
 
 using Org.BouncyCastle.Math.Raw;
 using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
 
 namespace Org.BouncyCastle.Math.EC.Custom.Sec
 {
     internal class SecP384R1FieldElement
         : AbstractFpFieldElement
     {
-        public static readonly BigInteger Q = SecP384R1Curve.q;
+        public static readonly BigInteger Q = new BigInteger(1,
+            Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF"));
 
         protected internal readonly uint[] x;
 
diff --git a/crypto/src/math/ec/custom/sec/SecP521R1Curve.cs b/crypto/src/math/ec/custom/sec/SecP521R1Curve.cs
index 810be85b5..cca86e2cb 100644
--- a/crypto/src/math/ec/custom/sec/SecP521R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecP521R1Curve.cs
@@ -8,11 +8,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     internal class SecP521R1Curve
         : AbstractFpCurve
     {
-        public static readonly BigInteger q = new BigInteger(1,
-            Hex.Decode("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"));
+        public static readonly BigInteger q = SecP521R1FieldElement.Q;
 
         private const int SECP521R1_DEFAULT_COORDS = COORD_JACOBIAN;
         private const int SECP521R1_FE_INTS = 17;
+        private static readonly ECFieldElement[] SECP521R1_AFFINE_ZS = new ECFieldElement[] { new SecP521R1FieldElement(BigInteger.One) };
 
         protected readonly SecP521R1Point m_infinity;
 
@@ -93,7 +93,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecP521R1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecP521R1Curve m_outer;
             private readonly uint[] m_table;
@@ -106,12 +106,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 uint[] x = Nat.Create(SECP521R1_FE_INTS), y = Nat.Create(SECP521R1_FE_INTS);
                 int pos = 0;
@@ -129,7 +129,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECP521R1_FE_INTS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecP521R1FieldElement(x), new SecP521R1FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                uint[] x = Nat.Create(SECP521R1_FE_INTS), y = Nat.Create(SECP521R1_FE_INTS);
+                int pos = index * SECP521R1_FE_INTS * 2;
+
+                for (int j = 0; j < SECP521R1_FE_INTS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECP521R1_FE_INTS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(uint[] x, uint[] y)
+            {
+                return m_outer.CreateRawPoint(new SecP521R1FieldElement(x), new SecP521R1FieldElement(y), SECP521R1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecP521R1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP521R1FieldElement.cs
index 96658a8e5..a428a1243 100644
--- a/crypto/src/math/ec/custom/sec/SecP521R1FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecP521R1FieldElement.cs
@@ -2,13 +2,15 @@
 
 using Org.BouncyCastle.Math.Raw;
 using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
 
 namespace Org.BouncyCastle.Math.EC.Custom.Sec
 {
     internal class SecP521R1FieldElement
         : AbstractFpFieldElement
     {
-        public static readonly BigInteger Q = SecP521R1Curve.q;
+        public static readonly BigInteger Q = new BigInteger(1,
+            Hex.Decode("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"));
 
         protected internal readonly uint[] x;
 
diff --git a/crypto/src/math/ec/custom/sec/SecT113Field.cs b/crypto/src/math/ec/custom/sec/SecT113Field.cs
index 49773b66d..3c9e0938d 100644
--- a/crypto/src/math/ec/custom/sec/SecT113Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT113Field.cs
@@ -30,11 +30,30 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             z[1] = x[1];
         }
 
+        private static void AddTo(ulong[] x, ulong[] z)
+        {
+            z[0] ^= x[0];
+            z[1] ^= x[1];
+        }
+
         public static ulong[] FromBigInteger(BigInteger x)
         {
-            ulong[] z = Nat128.FromBigInteger64(x);
-            Reduce15(z, 0);
-            return z;
+            return Nat.FromBigInteger64(113, x);
+        }
+
+        public static void HalfTrace(ulong[] x, ulong[] z)
+        {
+            ulong[] tt = Nat128.CreateExt64();
+
+            Nat128.Copy64(x, z);
+            for (int i = 1; i < 113; i += 2)
+            {
+                ImplSquare(z, tt);
+                Reduce(tt, z);
+                ImplSquare(z, tt);
+                Reduce(tt, z);
+                AddTo(x, z);
+            }
         }
 
         public static void Invert(ulong[] x, ulong[] z)
diff --git a/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs
index bb87b00fc..63de2b88c 100644
--- a/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs
@@ -150,6 +150,18 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             return new SecT113FieldElement(z);
         }
 
+        public override ECFieldElement HalfTrace()
+        {
+            ulong[] z = Nat128.Create64();
+            SecT113Field.HalfTrace(x, z);
+            return new SecT113FieldElement(z);
+        }
+
+        public override bool HasFastTrace
+        {
+            get { return true; }
+        }
+
         public override int Trace()
         {
             return (int)SecT113Field.Trace(x);
diff --git a/crypto/src/math/ec/custom/sec/SecT113R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT113R1Curve.cs
index e85f68e60..ea9ea0b0c 100644
--- a/crypto/src/math/ec/custom/sec/SecT113R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT113R1Curve.cs
@@ -10,6 +10,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     {
         private const int SECT113R1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
         private const int SECT113R1_FE_LONGS = 2;
+        private static readonly ECFieldElement[] SECT113R1_AFFINE_ZS = new ECFieldElement[] { new SecT113FieldElement(BigInteger.One) };
 
         protected readonly SecT113R1Point m_infinity;
 
@@ -114,7 +115,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecT113R1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecT113R1Curve m_outer;
             private readonly ulong[] m_table;
@@ -127,12 +128,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 ulong[] x = Nat128.Create64(), y = Nat128.Create64();
                 int pos = 0;
@@ -150,7 +151,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECT113R1_FE_LONGS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecT113FieldElement(x), new SecT113FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                ulong[] x = Nat128.Create64(), y = Nat128.Create64();
+                int pos = index * SECT113R1_FE_LONGS * 2;
+
+                for (int j = 0; j < SECT113R1_FE_LONGS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECT113R1_FE_LONGS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(ulong[] x, ulong[] y)
+            {
+                return m_outer.CreateRawPoint(new SecT113FieldElement(x), new SecT113FieldElement(y), SECT113R1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecT113R2Curve.cs b/crypto/src/math/ec/custom/sec/SecT113R2Curve.cs
index efe422806..84b20e026 100644
--- a/crypto/src/math/ec/custom/sec/SecT113R2Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT113R2Curve.cs
@@ -10,6 +10,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     {
         private const int SECT113R2_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
         private const int SECT113R2_FE_LONGS = 2;
+        private static readonly ECFieldElement[] SECT113R2_AFFINE_ZS = new ECFieldElement[] { new SecT113FieldElement(BigInteger.One) };
 
         protected readonly SecT113R2Point m_infinity;
 
@@ -114,7 +115,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecT113R2LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecT113R2Curve m_outer;
             private readonly ulong[] m_table;
@@ -127,12 +128,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 ulong[] x = Nat128.Create64(), y = Nat128.Create64();
                 int pos = 0;
@@ -150,7 +151,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECT113R2_FE_LONGS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecT113FieldElement(x), new SecT113FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                ulong[] x = Nat128.Create64(), y = Nat128.Create64();
+                int pos = index * SECT113R2_FE_LONGS * 2;
+
+                for (int j = 0; j < SECT113R2_FE_LONGS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECT113R2_FE_LONGS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(ulong[] x, ulong[] y)
+            {
+                return m_outer.CreateRawPoint(new SecT113FieldElement(x), new SecT113FieldElement(y), SECT113R2_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecT131Field.cs b/crypto/src/math/ec/custom/sec/SecT131Field.cs
index 1b6697afe..db703d9e0 100644
--- a/crypto/src/math/ec/custom/sec/SecT131Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT131Field.cs
@@ -35,11 +35,31 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             z[2] = x[2];
         }
 
+        private static void AddTo(ulong[] x, ulong[] z)
+        {
+            z[0] ^= x[0];
+            z[1] ^= x[1];
+            z[2] ^= x[2];
+        }
+
         public static ulong[] FromBigInteger(BigInteger x)
         {
-            ulong[] z = Nat192.FromBigInteger64(x);
-            Reduce61(z, 0);
-            return z;
+            return Nat.FromBigInteger64(131, x);
+        }
+
+        public static void HalfTrace(ulong[] x, ulong[] z)
+        {
+            ulong[] tt = Nat.Create64(5);
+
+            Nat192.Copy64(x, z);
+            for (int i = 1; i < 131; i += 2)
+            {
+                ImplSquare(z, tt);
+                Reduce(tt, z);
+                ImplSquare(z, tt);
+                Reduce(tt, z);
+                AddTo(x, z);
+            }
         }
 
         public static void Invert(ulong[] x, ulong[] z)
@@ -323,7 +343,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         {
             Interleave.Expand64To128(x[0], zz, 0);
             Interleave.Expand64To128(x[1], zz, 2);
-
             zz[4] = Interleave.Expand8to16((uint)x[2]);
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs
index f96c7ca39..4884e7152 100644
--- a/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs
@@ -150,6 +150,18 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             return new SecT131FieldElement(z);
         }
 
+        public override ECFieldElement HalfTrace()
+        {
+            ulong[] z = Nat192.Create64();
+            SecT131Field.HalfTrace(x, z);
+            return new SecT131FieldElement(z);
+        }
+
+        public override bool HasFastTrace
+        {
+            get { return true; }
+        }
+
         public override int Trace()
         {
             return (int)SecT131Field.Trace(x);
diff --git a/crypto/src/math/ec/custom/sec/SecT131R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT131R1Curve.cs
index 06f0a79ae..1a8c01670 100644
--- a/crypto/src/math/ec/custom/sec/SecT131R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT131R1Curve.cs
@@ -10,6 +10,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     {
         private const int SECT131R1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
         private const int SECT131R1_FE_LONGS = 3;
+        private static readonly ECFieldElement[] SECT131R1_AFFINE_ZS = new ECFieldElement[] { new SecT131FieldElement(BigInteger.One) };
 
         protected readonly SecT131R1Point m_infinity;
 
@@ -114,7 +115,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecT131R1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecT131R1Curve m_outer;
             private readonly ulong[] m_table;
@@ -127,12 +128,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 ulong[] x = Nat192.Create64(), y = Nat192.Create64();
                 int pos = 0;
@@ -150,7 +151,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECT131R1_FE_LONGS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecT131FieldElement(x), new SecT131FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                ulong[] x = Nat192.Create64(), y = Nat192.Create64();
+                int pos = index * SECT131R1_FE_LONGS * 2;
+
+                for (int j = 0; j < SECT131R1_FE_LONGS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECT131R1_FE_LONGS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(ulong[] x, ulong[] y)
+            {
+                return m_outer.CreateRawPoint(new SecT131FieldElement(x), new SecT131FieldElement(y), SECT131R1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecT131R2Curve.cs b/crypto/src/math/ec/custom/sec/SecT131R2Curve.cs
index 0120b3059..4a90a74f3 100644
--- a/crypto/src/math/ec/custom/sec/SecT131R2Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT131R2Curve.cs
@@ -10,6 +10,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     {
         private const int SECT131R2_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
         private const int SECT131R2_FE_LONGS = 3;
+        private static readonly ECFieldElement[] SECT131R2_AFFINE_ZS = new ECFieldElement[] { new SecT131FieldElement(BigInteger.One) };
 
         protected readonly SecT131R2Point m_infinity;
 
@@ -114,7 +115,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecT131R2LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecT131R2Curve m_outer;
             private readonly ulong[] m_table;
@@ -127,12 +128,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 ulong[] x = Nat192.Create64(), y = Nat192.Create64();
                 int pos = 0;
@@ -150,7 +151,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECT131R2_FE_LONGS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecT131FieldElement(x), new SecT131FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                ulong[] x = Nat192.Create64(), y = Nat192.Create64();
+                int pos = index * SECT131R2_FE_LONGS * 2;
+
+                for (int j = 0; j < SECT131R2_FE_LONGS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECT131R2_FE_LONGS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(ulong[] x, ulong[] y)
+            {
+                return m_outer.CreateRawPoint(new SecT131FieldElement(x), new SecT131FieldElement(y), SECT131R2_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecT163Field.cs b/crypto/src/math/ec/custom/sec/SecT163Field.cs
index b1e9aa725..b7f60d860 100644
--- a/crypto/src/math/ec/custom/sec/SecT163Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT163Field.cs
@@ -36,11 +36,31 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             z[2] = x[2];
         }
 
+        private static void AddTo(ulong[] x, ulong[] z)
+        {
+            z[0] ^= x[0];
+            z[1] ^= x[1];
+            z[2] ^= x[2];
+        }
+
         public static ulong[] FromBigInteger(BigInteger x)
         {
-            ulong[] z = Nat192.FromBigInteger64(x);
-            Reduce29(z, 0);
-            return z;
+            return Nat.FromBigInteger64(163, x);
+        }
+
+        public static void HalfTrace(ulong[] x, ulong[] z)
+        {
+            ulong[] tt = Nat192.CreateExt64();
+
+            Nat192.Copy64(x, z);
+            for (int i = 1; i < 163; i += 2)
+            {
+                ImplSquare(z, tt);
+                Reduce(tt, z);
+                ImplSquare(z, tt);
+                Reduce(tt, z);
+                AddTo(x, z);
+            }
         }
 
         public static void Invert(ulong[] x, ulong[] z)
@@ -331,10 +351,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         {
             Interleave.Expand64To128(x[0], zz, 0);
             Interleave.Expand64To128(x[1], zz, 2);
-
-            ulong x2 = x[2];
-            zz[4] = Interleave.Expand32to64((uint)x2);
-            zz[5] = Interleave.Expand8to16((uint)(x2 >> 32));
+            Interleave.Expand64To128(x[2], zz, 4);
         }
     }
 }
diff --git a/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs
index 903645999..214a56343 100644
--- a/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs
@@ -150,6 +150,18 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             return new SecT163FieldElement(z);
         }
 
+        public override ECFieldElement HalfTrace()
+        {
+            ulong[] z = Nat192.Create64();
+            SecT163Field.HalfTrace(x, z);
+            return new SecT163FieldElement(z);
+        }
+
+        public override bool HasFastTrace
+        {
+            get { return true; }
+        }
+
         public override int Trace()
         {
             return (int)SecT163Field.Trace(x);
diff --git a/crypto/src/math/ec/custom/sec/SecT163K1Curve.cs b/crypto/src/math/ec/custom/sec/SecT163K1Curve.cs
index 5e1431f46..6cdb7bdd6 100644
--- a/crypto/src/math/ec/custom/sec/SecT163K1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT163K1Curve.cs
@@ -11,6 +11,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     {
         private const int SECT163K1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
         private const int SECT163K1_FE_LONGS = 3;
+        private static readonly ECFieldElement[] SECT163K1_AFFINE_ZS = new ECFieldElement[] { new SecT163FieldElement(BigInteger.One) };
 
         protected readonly SecT163K1Point m_infinity;
 
@@ -120,7 +121,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecT163K1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecT163K1Curve m_outer;
             private readonly ulong[] m_table;
@@ -133,12 +134,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 ulong[] x = Nat192.Create64(), y = Nat192.Create64();
                 int pos = 0;
@@ -156,7 +157,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECT163K1_FE_LONGS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecT163FieldElement(x), new SecT163FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                ulong[] x = Nat192.Create64(), y = Nat192.Create64();
+                int pos = index * SECT163K1_FE_LONGS * 2;
+
+                for (int j = 0; j < SECT163K1_FE_LONGS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECT163K1_FE_LONGS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(ulong[] x, ulong[] y)
+            {
+                return m_outer.CreateRawPoint(new SecT163FieldElement(x), new SecT163FieldElement(y), SECT163K1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecT163R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT163R1Curve.cs
index e212ad4ea..bee0d3c80 100644
--- a/crypto/src/math/ec/custom/sec/SecT163R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT163R1Curve.cs
@@ -10,6 +10,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     {
         private const int SECT163R1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
         private const int SECT163R1_FE_LONGS = 3;
+        private static readonly ECFieldElement[] SECT163R1_AFFINE_ZS = new ECFieldElement[] { new SecT163FieldElement(BigInteger.One) };
 
         protected readonly SecT163R1Point m_infinity;
 
@@ -114,7 +115,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecT163R1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecT163R1Curve m_outer;
             private readonly ulong[] m_table;
@@ -127,12 +128,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 ulong[] x = Nat192.Create64(), y = Nat192.Create64();
                 int pos = 0;
@@ -150,7 +151,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECT163R1_FE_LONGS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecT163FieldElement(x), new SecT163FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                ulong[] x = Nat192.Create64(), y = Nat192.Create64();
+                int pos = index * SECT163R1_FE_LONGS * 2;
+
+                for (int j = 0; j < SECT163R1_FE_LONGS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECT163R1_FE_LONGS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(ulong[] x, ulong[] y)
+            {
+                return m_outer.CreateRawPoint(new SecT163FieldElement(x), new SecT163FieldElement(y), SECT163R1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecT163R2Curve.cs b/crypto/src/math/ec/custom/sec/SecT163R2Curve.cs
index b0365388a..35e91ddf1 100644
--- a/crypto/src/math/ec/custom/sec/SecT163R2Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT163R2Curve.cs
@@ -10,6 +10,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     {
         private const int SECT163R2_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
         private const int SECT163R2_FE_LONGS = 3;
+        private static readonly ECFieldElement[] SECT163R2_AFFINE_ZS = new ECFieldElement[] { new SecT163FieldElement(BigInteger.One) };
 
         protected readonly SecT163R2Point m_infinity;
 
@@ -114,7 +115,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecT163R2LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecT163R2Curve m_outer;
             private readonly ulong[] m_table;
@@ -127,12 +128,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 ulong[] x = Nat192.Create64(), y = Nat192.Create64();
                 int pos = 0;
@@ -150,7 +151,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECT163R2_FE_LONGS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecT163FieldElement(x), new SecT163FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                ulong[] x = Nat192.Create64(), y = Nat192.Create64();
+                int pos = index * SECT163R2_FE_LONGS * 2;
+
+                for (int j = 0; j < SECT163R2_FE_LONGS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECT163R2_FE_LONGS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(ulong[] x, ulong[] y)
+            {
+                return m_outer.CreateRawPoint(new SecT163FieldElement(x), new SecT163FieldElement(y), SECT163R2_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecT193Field.cs b/crypto/src/math/ec/custom/sec/SecT193Field.cs
index 41acb4f94..3ad9b0af2 100644
--- a/crypto/src/math/ec/custom/sec/SecT193Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT193Field.cs
@@ -37,11 +37,32 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             z[3] = x[3];
         }
 
+        private static void AddTo(ulong[] x, ulong[] z)
+        {
+            z[0] ^= x[0];
+            z[1] ^= x[1];
+            z[2] ^= x[2];
+            z[3] ^= x[3];
+        }
+
         public static ulong[] FromBigInteger(BigInteger x)
         {
-            ulong[] z = Nat256.FromBigInteger64(x);
-            Reduce63(z, 0);
-            return z;
+            return Nat.FromBigInteger64(193, x);
+        }
+
+        public static void HalfTrace(ulong[] x, ulong[] z)
+        {
+            ulong[] tt = Nat256.CreateExt64();
+
+            Nat256.Copy64(x, z);
+            for (int i = 1; i < 193; i += 2)
+            {
+                ImplSquare(z, tt);
+                Reduce(tt, z);
+                ImplSquare(z, tt);
+                Reduce(tt, z);
+                AddTo(x, z);
+            }
         }
 
         public static void Invert(ulong[] x, ulong[] z)
diff --git a/crypto/src/math/ec/custom/sec/SecT193FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT193FieldElement.cs
index 9813bcb01..3a3ed09ce 100644
--- a/crypto/src/math/ec/custom/sec/SecT193FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT193FieldElement.cs
@@ -150,6 +150,18 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             return new SecT193FieldElement(z);
         }
 
+        public override ECFieldElement HalfTrace()
+        {
+            ulong[] z = Nat256.Create64();
+            SecT193Field.HalfTrace(x, z);
+            return new SecT193FieldElement(z);
+        }
+
+        public override bool HasFastTrace
+        {
+            get { return true; }
+        }
+
         public override int Trace()
         {
             return (int)SecT193Field.Trace(x);
diff --git a/crypto/src/math/ec/custom/sec/SecT193R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT193R1Curve.cs
index e6cb3b4d8..8ba83689e 100644
--- a/crypto/src/math/ec/custom/sec/SecT193R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT193R1Curve.cs
@@ -10,6 +10,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     {
         private const int SECT193R1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
         private const int SECT193R1_FE_LONGS = 4;
+        private static readonly ECFieldElement[] SECT193R1_AFFINE_ZS = new ECFieldElement[] { new SecT193FieldElement(BigInteger.One) };
 
         protected readonly SecT193R1Point m_infinity;
 
@@ -114,7 +115,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecT193R1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecT193R1Curve m_outer;
             private readonly ulong[] m_table;
@@ -127,12 +128,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 ulong[] x = Nat256.Create64(), y = Nat256.Create64();
                 int pos = 0;
@@ -150,7 +151,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECT193R1_FE_LONGS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecT193FieldElement(x), new SecT193FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                ulong[] x = Nat256.Create64(), y = Nat256.Create64();
+                int pos = index * SECT193R1_FE_LONGS * 2;
+
+                for (int j = 0; j < SECT193R1_FE_LONGS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECT193R1_FE_LONGS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(ulong[] x, ulong[] y)
+            {
+                return m_outer.CreateRawPoint(new SecT193FieldElement(x), new SecT193FieldElement(y), SECT193R1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecT193R2Curve.cs b/crypto/src/math/ec/custom/sec/SecT193R2Curve.cs
index cfd690c65..46790e7e4 100644
--- a/crypto/src/math/ec/custom/sec/SecT193R2Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT193R2Curve.cs
@@ -10,6 +10,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     {
         private const int SECT193R2_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
         private const int SECT193R2_FE_LONGS = 4;
+        private static readonly ECFieldElement[] SECT193R2_AFFINE_ZS = new ECFieldElement[] { new SecT193FieldElement(BigInteger.One) };
 
         protected readonly SecT193R2Point m_infinity;
 
@@ -114,7 +115,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecT193R2LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecT193R2Curve m_outer;
             private readonly ulong[] m_table;
@@ -127,12 +128,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 ulong[] x = Nat256.Create64(), y = Nat256.Create64();
                 int pos = 0;
@@ -150,7 +151,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECT193R2_FE_LONGS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecT193FieldElement(x), new SecT193FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                ulong[] x = Nat256.Create64(), y = Nat256.Create64();
+                int pos = index * SECT193R2_FE_LONGS * 2;
+
+                for (int j = 0; j < SECT193R2_FE_LONGS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECT193R2_FE_LONGS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(ulong[] x, ulong[] y)
+            {
+                return m_outer.CreateRawPoint(new SecT193FieldElement(x), new SecT193FieldElement(y), SECT193R2_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecT233Field.cs b/crypto/src/math/ec/custom/sec/SecT233Field.cs
index 870dade50..d7916c57d 100644
--- a/crypto/src/math/ec/custom/sec/SecT233Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT233Field.cs
@@ -38,11 +38,32 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             z[3] = x[3];
         }
 
+        private static void AddTo(ulong[] x, ulong[] z)
+        {
+            z[0] ^= x[0];
+            z[1] ^= x[1];
+            z[2] ^= x[2];
+            z[3] ^= x[3];
+        }
+
         public static ulong[] FromBigInteger(BigInteger x)
         {
-            ulong[] z = Nat256.FromBigInteger64(x);
-            Reduce23(z, 0);
-            return z;
+            return Nat.FromBigInteger64(233, x);
+        }
+
+        public static void HalfTrace(ulong[] x, ulong[] z)
+        {
+            ulong[] tt = Nat256.CreateExt64();
+
+            Nat256.Copy64(x, z);
+            for (int i = 1; i < 233; i += 2)
+            {
+                ImplSquare(z, tt);
+                Reduce(tt, z);
+                ImplSquare(z, tt);
+                Reduce(tt, z);
+                AddTo(x, z);
+            }
         }
 
         public static void Invert(ulong[] x, ulong[] z)
@@ -308,10 +329,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             Interleave.Expand64To128(x[0], zz, 0);
             Interleave.Expand64To128(x[1], zz, 2);
             Interleave.Expand64To128(x[2], zz, 4);
-
-            ulong x3 = x[3];
-            zz[6] = Interleave.Expand32to64((uint)x3);
-            zz[7] = Interleave.Expand16to32((uint)(x3 >> 32));
+            Interleave.Expand64To128(x[3], zz, 6);
         }
     }
 }
diff --git a/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs
index fbfe35e13..8aff8c87a 100644
--- a/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs
@@ -150,6 +150,18 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             return new SecT233FieldElement(z);
         }
 
+        public override ECFieldElement HalfTrace()
+        {
+            ulong[] z = Nat256.Create64();
+            SecT233Field.HalfTrace(x, z);
+            return new SecT233FieldElement(z);
+        }
+
+        public override bool HasFastTrace
+        {
+            get { return true; }
+        }
+
         public override int Trace()
         {
             return (int)SecT233Field.Trace(x);
diff --git a/crypto/src/math/ec/custom/sec/SecT233K1Curve.cs b/crypto/src/math/ec/custom/sec/SecT233K1Curve.cs
index 07eae1564..c01247446 100644
--- a/crypto/src/math/ec/custom/sec/SecT233K1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT233K1Curve.cs
@@ -11,6 +11,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     {
         private const int SECT233K1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
         private const int SECT233K1_FE_LONGS = 4;
+        private static readonly ECFieldElement[] SECT233K1_AFFINE_ZS = new ECFieldElement[] { new SecT233FieldElement(BigInteger.One) };
 
         protected readonly SecT233K1Point m_infinity;
 
@@ -120,7 +121,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecT233K1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecT233K1Curve m_outer;
             private readonly ulong[] m_table;
@@ -133,12 +134,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 ulong[] x = Nat256.Create64(), y = Nat256.Create64();
                 int pos = 0;
@@ -156,7 +157,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECT233K1_FE_LONGS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecT233FieldElement(x), new SecT233FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                ulong[] x = Nat256.Create64(), y = Nat256.Create64();
+                int pos = index * SECT233K1_FE_LONGS * 2;
+
+                for (int j = 0; j < SECT233K1_FE_LONGS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECT233K1_FE_LONGS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(ulong[] x, ulong[] y)
+            {
+                return m_outer.CreateRawPoint(new SecT233FieldElement(x), new SecT233FieldElement(y), SECT233K1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecT233R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT233R1Curve.cs
index 5e8dee875..a5d3b86fd 100644
--- a/crypto/src/math/ec/custom/sec/SecT233R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT233R1Curve.cs
@@ -10,6 +10,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     {
         private const int SECT233R1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
         private const int SECT233R1_FE_LONGS = 4;
+        private static readonly ECFieldElement[] SECT233R1_AFFINE_ZS = new ECFieldElement[] { new SecT233FieldElement(BigInteger.One) };
 
         protected readonly SecT233R1Point m_infinity;
 
@@ -114,7 +115,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecT233R1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecT233R1Curve m_outer;
             private readonly ulong[] m_table;
@@ -127,12 +128,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 ulong[] x = Nat256.Create64(), y = Nat256.Create64();
                 int pos = 0;
@@ -150,7 +151,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECT233R1_FE_LONGS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecT233FieldElement(x), new SecT233FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                ulong[] x = Nat256.Create64(), y = Nat256.Create64();
+                int pos = index * SECT233R1_FE_LONGS * 2;
+
+                for (int j = 0; j < SECT233R1_FE_LONGS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECT233R1_FE_LONGS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(ulong[] x, ulong[] y)
+            {
+                return m_outer.CreateRawPoint(new SecT233FieldElement(x), new SecT233FieldElement(y), SECT233R1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecT239Field.cs b/crypto/src/math/ec/custom/sec/SecT239Field.cs
index 2e6ed2ad6..eab929359 100644
--- a/crypto/src/math/ec/custom/sec/SecT239Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT239Field.cs
@@ -38,11 +38,32 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             z[3] = x[3];
         }
 
+        private static void AddTo(ulong[] x, ulong[] z)
+        {
+            z[0] ^= x[0];
+            z[1] ^= x[1];
+            z[2] ^= x[2];
+            z[3] ^= x[3];
+        }
+
         public static ulong[] FromBigInteger(BigInteger x)
         {
-            ulong[] z = Nat256.FromBigInteger64(x);
-            Reduce17(z, 0);
-            return z;
+            return Nat.FromBigInteger64(239, x);
+        }
+
+        public static void HalfTrace(ulong[] x, ulong[] z)
+        {
+            ulong[] tt = Nat256.CreateExt64();
+
+            Nat256.Copy64(x, z);
+            for (int i = 1; i < 239; i += 2)
+            {
+                ImplSquare(z, tt);
+                Reduce(tt, z);
+                ImplSquare(z, tt);
+                Reduce(tt, z);
+                AddTo(x, z);
+            }
         }
 
         public static void Invert(ulong[] x, ulong[] z)
@@ -319,10 +340,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             Interleave.Expand64To128(x[0], zz, 0);
             Interleave.Expand64To128(x[1], zz, 2);
             Interleave.Expand64To128(x[2], zz, 4);
-
-            ulong x3 = x[3];
-            zz[6] = Interleave.Expand32to64((uint)x3);
-            zz[7] = Interleave.Expand16to32((uint)(x3 >> 32));
+            Interleave.Expand64To128(x[3], zz, 6);
         }
     }
 }
diff --git a/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs
index b1b58e89b..9f1bf671c 100644
--- a/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs
@@ -150,6 +150,18 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             return new SecT239FieldElement(z);
         }
 
+        public override ECFieldElement HalfTrace()
+        {
+            ulong[] z = Nat256.Create64();
+            SecT239Field.HalfTrace(x, z);
+            return new SecT239FieldElement(z);
+        }
+
+        public override bool HasFastTrace
+        {
+            get { return true; }
+        }
+
         public override int Trace()
         {
             return (int)SecT239Field.Trace(x);
diff --git a/crypto/src/math/ec/custom/sec/SecT239K1Curve.cs b/crypto/src/math/ec/custom/sec/SecT239K1Curve.cs
index 33792e631..5748942e2 100644
--- a/crypto/src/math/ec/custom/sec/SecT239K1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT239K1Curve.cs
@@ -11,6 +11,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     {
         private const int SECT239K1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
         private const int SECT239K1_FE_LONGS = 4;
+        private static readonly ECFieldElement[] SECT239K1_AFFINE_ZS = new ECFieldElement[] { new SecT239FieldElement(BigInteger.One) };
 
         protected readonly SecT239K1Point m_infinity;
 
@@ -120,7 +121,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecT239K1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecT239K1Curve m_outer;
             private readonly ulong[] m_table;
@@ -133,12 +134,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 ulong[] x = Nat256.Create64(), y = Nat256.Create64();
                 int pos = 0;
@@ -156,7 +157,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECT239K1_FE_LONGS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecT239FieldElement(x), new SecT239FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                ulong[] x = Nat256.Create64(), y = Nat256.Create64();
+                int pos = index * SECT239K1_FE_LONGS * 2;
+
+                for (int j = 0; j < SECT239K1_FE_LONGS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECT239K1_FE_LONGS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(ulong[] x, ulong[] y)
+            {
+                return m_outer.CreateRawPoint(new SecT239FieldElement(x), new SecT239FieldElement(y), SECT239K1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecT283Field.cs b/crypto/src/math/ec/custom/sec/SecT283Field.cs
index 22b7eaaab..4e2cee0f8 100644
--- a/crypto/src/math/ec/custom/sec/SecT283Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT283Field.cs
@@ -43,11 +43,33 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             z[4] = x[4];
         }
 
+        private static void AddTo(ulong[] x, ulong[] z)
+        {
+            z[0] ^= x[0];
+            z[1] ^= x[1];
+            z[2] ^= x[2];
+            z[3] ^= x[3];
+            z[4] ^= x[4];
+        }
+
         public static ulong[] FromBigInteger(BigInteger x)
         {
-            ulong[] z = Nat320.FromBigInteger64(x);
-            Reduce37(z, 0);
-            return z;
+            return Nat.FromBigInteger64(283, x);
+        }
+
+        public static void HalfTrace(ulong[] x, ulong[] z)
+        {
+            ulong[] tt = Nat.Create64(9);
+
+            Nat320.Copy64(x, z);
+            for (int i = 1; i < 283; i += 2)
+            {
+                ImplSquare(z, tt);
+                Reduce(tt, z);
+                ImplSquare(z, tt);
+                Reduce(tt, z);
+                AddTo(x, z);
+            }
         }
 
         public static void Invert(ulong[] x, ulong[] z)
@@ -392,10 +414,10 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
 
         protected static void ImplSquare(ulong[] x, ulong[] zz)
         {
-            for (int i = 0; i < 4; ++i)
-            {
-                Interleave.Expand64To128(x[i], zz, i << 1);
-            }
+            Interleave.Expand64To128(x[0], zz, 0);
+            Interleave.Expand64To128(x[1], zz, 2);
+            Interleave.Expand64To128(x[2], zz, 4);
+            Interleave.Expand64To128(x[3], zz, 6);
             zz[8] = Interleave.Expand32to64((uint)x[4]);
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs
index c1bb2e30c..6bd720acd 100644
--- a/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs
@@ -150,6 +150,18 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             return new SecT283FieldElement(z);
         }
 
+        public override ECFieldElement HalfTrace()
+        {
+            ulong[] z = Nat320.Create64();
+            SecT283Field.HalfTrace(x, z);
+            return new SecT283FieldElement(z);
+        }
+
+        public override bool HasFastTrace
+        {
+            get { return true; }
+        }
+
         public override int Trace()
         {
             return (int)SecT283Field.Trace(x);
diff --git a/crypto/src/math/ec/custom/sec/SecT283K1Curve.cs b/crypto/src/math/ec/custom/sec/SecT283K1Curve.cs
index 51725bc20..e97a0f01d 100644
--- a/crypto/src/math/ec/custom/sec/SecT283K1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT283K1Curve.cs
@@ -11,6 +11,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     {
         private const int SECT283K1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
         private const int SECT283K1_FE_LONGS = 5;
+        private static readonly ECFieldElement[] SECT283K1_AFFINE_ZS = new ECFieldElement[] { new SecT283FieldElement(BigInteger.One) };
 
         protected readonly SecT283K1Point m_infinity;
 
@@ -120,7 +121,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecT283K1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecT283K1Curve m_outer;
             private readonly ulong[] m_table;
@@ -133,12 +134,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 ulong[] x = Nat320.Create64(), y = Nat320.Create64();
                 int pos = 0;
@@ -156,7 +157,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECT283K1_FE_LONGS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecT283FieldElement(x), new SecT283FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                ulong[] x = Nat320.Create64(), y = Nat320.Create64();
+                int pos = index * SECT283K1_FE_LONGS * 2;
+
+                for (int j = 0; j < SECT283K1_FE_LONGS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECT283K1_FE_LONGS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(ulong[] x, ulong[] y)
+            {
+                return m_outer.CreateRawPoint(new SecT283FieldElement(x), new SecT283FieldElement(y), SECT283K1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecT283R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT283R1Curve.cs
index 567df7686..a8a50c22a 100644
--- a/crypto/src/math/ec/custom/sec/SecT283R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT283R1Curve.cs
@@ -10,6 +10,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     {
         private const int SECT283R1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
         private const int SECT283R1_FE_LONGS = 5;
+        private static readonly ECFieldElement[] SECT283R1_AFFINE_ZS = new ECFieldElement[] { new SecT283FieldElement(BigInteger.One) };
 
         protected readonly SecT283R1Point m_infinity;
 
@@ -114,7 +115,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecT283R1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecT283R1Curve m_outer;
             private readonly ulong[] m_table;
@@ -127,12 +128,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 ulong[] x = Nat320.Create64(), y = Nat320.Create64();
                 int pos = 0;
@@ -150,7 +151,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECT283R1_FE_LONGS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecT283FieldElement(x), new SecT283FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                ulong[] x = Nat320.Create64(), y = Nat320.Create64();
+                int pos = index * SECT283R1_FE_LONGS * 2;
+
+                for (int j = 0; j < SECT283R1_FE_LONGS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECT283R1_FE_LONGS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(ulong[] x, ulong[] y)
+            {
+                return m_outer.CreateRawPoint(new SecT283FieldElement(x), new SecT283FieldElement(y), SECT283R1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecT409Field.cs b/crypto/src/math/ec/custom/sec/SecT409Field.cs
index 861b77aa1..2e5609542 100644
--- a/crypto/src/math/ec/custom/sec/SecT409Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT409Field.cs
@@ -40,11 +40,35 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             z[6] = x[6];
         }
 
+        private static void AddTo(ulong[] x, ulong[] z)
+        {
+            z[0] ^= x[0];
+            z[1] ^= x[1];
+            z[2] ^= x[2];
+            z[3] ^= x[3];
+            z[4] ^= x[4];
+            z[5] ^= x[5];
+            z[6] ^= x[6];
+        }
+
         public static ulong[] FromBigInteger(BigInteger x)
         {
-            ulong[] z = Nat448.FromBigInteger64(x);
-            Reduce39(z, 0);
-            return z;
+            return Nat.FromBigInteger64(409, x);
+        }
+
+        public static void HalfTrace(ulong[] x, ulong[] z)
+        {
+            ulong[] tt = Nat.Create64(13);
+
+            Nat448.Copy64(x, z);
+            for (int i = 1; i < 409; i += 2)
+            {
+                ImplSquare(z, tt);
+                Reduce(tt, z);
+                ImplSquare(z, tt);
+                Reduce(tt, z);
+                AddTo(x, z);
+            }
         }
 
         public static void Invert(ulong[] x, ulong[] z)
@@ -321,10 +345,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
 
         protected static void ImplSquare(ulong[] x, ulong[] zz)
         {
-            for (int i = 0; i < 6; ++i)
-            {
-                Interleave.Expand64To128(x[i], zz, i << 1);
-            }
+            Interleave.Expand64To128(x[0], zz, 0);
+            Interleave.Expand64To128(x[1], zz, 2);
+            Interleave.Expand64To128(x[2], zz, 4);
+            Interleave.Expand64To128(x[3], zz, 6);
+            Interleave.Expand64To128(x[4], zz, 8);
+            Interleave.Expand64To128(x[5], zz, 10);
             zz[12] = Interleave.Expand32to64((uint)x[6]);
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs
index 68a63312d..a9b08526a 100644
--- a/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs
@@ -150,6 +150,18 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             return new SecT409FieldElement(z);
         }
 
+        public override ECFieldElement HalfTrace()
+        {
+            ulong[] z = Nat448.Create64();
+            SecT409Field.HalfTrace(x, z);
+            return new SecT409FieldElement(z);
+        }
+
+        public override bool HasFastTrace
+        {
+            get { return true; }
+        }
+
         public override int Trace()
         {
             return (int)SecT409Field.Trace(x);
diff --git a/crypto/src/math/ec/custom/sec/SecT409K1Curve.cs b/crypto/src/math/ec/custom/sec/SecT409K1Curve.cs
index 839ec8059..2f6503692 100644
--- a/crypto/src/math/ec/custom/sec/SecT409K1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT409K1Curve.cs
@@ -11,6 +11,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     {
         private const int SECT409K1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
         private const int SECT409K1_FE_LONGS = 7;
+        private static readonly ECFieldElement[] SECT409K1_AFFINE_ZS = new ECFieldElement[] { new SecT409FieldElement(BigInteger.One) };
 
         protected readonly SecT409K1Point m_infinity;
 
@@ -120,7 +121,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecT409K1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecT409K1Curve m_outer;
             private readonly ulong[] m_table;
@@ -133,12 +134,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 ulong[] x = Nat448.Create64(), y = Nat448.Create64();
                 int pos = 0;
@@ -156,7 +157,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECT409K1_FE_LONGS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecT409FieldElement(x), new SecT409FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                ulong[] x = Nat448.Create64(), y = Nat448.Create64();
+                int pos = index * SECT409K1_FE_LONGS * 2;
+
+                for (int j = 0; j < SECT409K1_FE_LONGS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECT409K1_FE_LONGS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(ulong[] x, ulong[] y)
+            {
+                return m_outer.CreateRawPoint(new SecT409FieldElement(x), new SecT409FieldElement(y), SECT409K1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecT409R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT409R1Curve.cs
index f70dd5f8e..0e767504b 100644
--- a/crypto/src/math/ec/custom/sec/SecT409R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT409R1Curve.cs
@@ -10,6 +10,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     {
         private const int SECT409R1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
         private const int SECT409R1_FE_LONGS = 7;
+        private static readonly ECFieldElement[] SECT409R1_AFFINE_ZS = new ECFieldElement[] { new SecT409FieldElement(BigInteger.One) };
 
         protected readonly SecT409R1Point m_infinity;
 
@@ -114,7 +115,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecT409R1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecT409R1Curve m_outer;
             private readonly ulong[] m_table;
@@ -127,12 +128,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 ulong[] x = Nat448.Create64(), y = Nat448.Create64();
                 int pos = 0;
@@ -150,7 +151,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECT409R1_FE_LONGS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecT409FieldElement(x), new SecT409FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                ulong[] x = Nat448.Create64(), y = Nat448.Create64();
+                int pos = index * SECT409R1_FE_LONGS * 2;
+
+                for (int j = 0; j < SECT409R1_FE_LONGS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECT409R1_FE_LONGS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(ulong[] x, ulong[] y)
+            {
+                return m_outer.CreateRawPoint(new SecT409FieldElement(x), new SecT409FieldElement(y), SECT409R1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecT571Field.cs b/crypto/src/math/ec/custom/sec/SecT571Field.cs
index 98f4f7fc2..0d9b337fc 100644
--- a/crypto/src/math/ec/custom/sec/SecT571Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT571Field.cs
@@ -55,11 +55,32 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             }
         }
 
+        private static void AddTo(ulong[] x, ulong[] z)
+        {
+            for (int i = 0; i < 9; ++i)
+            {
+                z[i] ^= x[i];
+            }
+        }
+
         public static ulong[] FromBigInteger(BigInteger x)
         {
-            ulong[] z = Nat576.FromBigInteger64(x);
-            Reduce5(z, 0);
-            return z;
+            return Nat.FromBigInteger64(571, x);
+        }
+
+        public static void HalfTrace(ulong[] x, ulong[] z)
+        {
+            ulong[] tt = Nat576.CreateExt64();
+
+            Nat576.Copy64(x, z);
+            for (int i = 1; i < 571; i += 2)
+            {
+                ImplSquare(z, tt);
+                Reduce(tt, z);
+                ImplSquare(z, tt);
+                Reduce(tt, z);
+                AddTo(x, z);
+            }
         }
 
         public static void Invert(ulong[] x, ulong[] z)
@@ -324,10 +345,15 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
 
         protected static void ImplSquare(ulong[] x, ulong[] zz)
         {
-            for (int i = 0; i < 9; ++i)
-            {
-                Interleave.Expand64To128(x[i], zz, i << 1);
-            }
+            Interleave.Expand64To128(x[0], zz, 0);
+            Interleave.Expand64To128(x[1], zz, 2);
+            Interleave.Expand64To128(x[2], zz, 4);
+            Interleave.Expand64To128(x[3], zz, 6);
+            Interleave.Expand64To128(x[4], zz, 8);
+            Interleave.Expand64To128(x[5], zz, 10);
+            Interleave.Expand64To128(x[6], zz, 12);
+            Interleave.Expand64To128(x[7], zz, 14);
+            Interleave.Expand64To128(x[8], zz, 16);
         }
     }
 }
diff --git a/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs
index c9f3aa5c0..22edfe0a2 100644
--- a/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs
@@ -150,6 +150,18 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             return new SecT571FieldElement(z);
         }
 
+        public override ECFieldElement HalfTrace()
+        {
+            ulong[] z = Nat576.Create64();
+            SecT571Field.HalfTrace(x, z);
+            return new SecT571FieldElement(z);
+        }
+
+        public override bool HasFastTrace
+        {
+            get { return true; }
+        }
+
         public override int Trace()
         {
             return (int)SecT571Field.Trace(x);
diff --git a/crypto/src/math/ec/custom/sec/SecT571K1Curve.cs b/crypto/src/math/ec/custom/sec/SecT571K1Curve.cs
index 3d84797f7..1ab3b0941 100644
--- a/crypto/src/math/ec/custom/sec/SecT571K1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT571K1Curve.cs
@@ -11,6 +11,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     {
         private const int SECT571K1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
         private const int SECT571K1_FE_LONGS = 9;
+        private static readonly ECFieldElement[] SECT571K1_AFFINE_ZS = new ECFieldElement[] { new SecT571FieldElement(BigInteger.One) };
 
         protected readonly SecT571K1Point m_infinity;
 
@@ -120,7 +121,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecT571K1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecT571K1Curve m_outer;
             private readonly ulong[] m_table;
@@ -133,12 +134,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 ulong[] x = Nat576.Create64(), y = Nat576.Create64();
                 int pos = 0;
@@ -156,7 +157,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECT571K1_FE_LONGS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecT571FieldElement(x), new SecT571FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                ulong[] x = Nat576.Create64(), y = Nat576.Create64();
+                int pos = index * SECT571K1_FE_LONGS * 2;
+
+                for (int j = 0; j < SECT571K1_FE_LONGS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECT571K1_FE_LONGS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(ulong[] x, ulong[] y)
+            {
+                return m_outer.CreateRawPoint(new SecT571FieldElement(x), new SecT571FieldElement(y), SECT571K1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/custom/sec/SecT571R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT571R1Curve.cs
index 7ebf90856..840c29638 100644
--- a/crypto/src/math/ec/custom/sec/SecT571R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT571R1Curve.cs
@@ -10,6 +10,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
     {
         private const int SECT571R1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
         private const int SECT571R1_FE_LONGS = 9;
+        private static readonly ECFieldElement[] SECT571R1_AFFINE_ZS = new ECFieldElement[] { new SecT571FieldElement(BigInteger.One) };
 
         protected readonly SecT571R1Point m_infinity;
 
@@ -118,7 +119,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         }
 
         private class SecT571R1LookupTable
-            : ECLookupTable
+            : AbstractECLookupTable
         {
             private readonly SecT571R1Curve m_outer;
             private readonly ulong[] m_table;
@@ -131,12 +132,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                 this.m_size = size;
             }
 
-            public virtual int Size
+            public override int Size
             {
                 get { return m_size; }
             }
 
-            public virtual ECPoint Lookup(int index)
+            public override ECPoint Lookup(int index)
             {
                 ulong[] x = Nat576.Create64(), y = Nat576.Create64();
                 int pos = 0;
@@ -154,7 +155,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
                     pos += (SECT571R1_FE_LONGS * 2);
                 }
 
-                return m_outer.CreateRawPoint(new SecT571FieldElement(x), new SecT571FieldElement(y), false);
+                return CreatePoint(x, y);
+            }
+
+            public override ECPoint LookupVar(int index)
+            {
+                ulong[] x = Nat576.Create64(), y = Nat576.Create64();
+                int pos = index * SECT571R1_FE_LONGS * 2;
+
+                for (int j = 0; j < SECT571R1_FE_LONGS; ++j)
+                {
+                    x[j] = m_table[pos + j];
+                    y[j] = m_table[pos + SECT571R1_FE_LONGS + j];
+                }
+
+                return CreatePoint(x, y);
+            }
+
+            private ECPoint CreatePoint(ulong[] x, ulong[] y)
+            {
+                return m_outer.CreateRawPoint(new SecT571FieldElement(x), new SecT571FieldElement(y), SECT571R1_AFFINE_ZS, false);
             }
         }
     }
diff --git a/crypto/src/math/ec/endo/EndoPreCompInfo.cs b/crypto/src/math/ec/endo/EndoPreCompInfo.cs
new file mode 100644
index 000000000..cb926fc98
--- /dev/null
+++ b/crypto/src/math/ec/endo/EndoPreCompInfo.cs
@@ -0,0 +1,26 @@
+using System;
+
+using Org.BouncyCastle.Math.EC.Multiplier;
+
+namespace Org.BouncyCastle.Math.EC.Endo
+{
+    public class EndoPreCompInfo
+        : PreCompInfo
+    {
+        protected ECEndomorphism m_endomorphism;
+
+        protected ECPoint m_mappedPoint;
+
+        public virtual ECEndomorphism Endomorphism
+        {
+            get { return m_endomorphism; }
+            set { this.m_endomorphism = value; }
+        }
+
+        public virtual ECPoint MappedPoint
+        {
+            get { return m_mappedPoint; }
+            set { this.m_mappedPoint = value; }
+        }
+    }
+}
diff --git a/crypto/src/math/ec/endo/EndoUtilities.cs b/crypto/src/math/ec/endo/EndoUtilities.cs
new file mode 100644
index 000000000..843103bca
--- /dev/null
+++ b/crypto/src/math/ec/endo/EndoUtilities.cs
@@ -0,0 +1,79 @@
+using System;
+
+using Org.BouncyCastle.Math.EC.Multiplier;
+
+namespace Org.BouncyCastle.Math.EC.Endo
+{
+    public abstract class EndoUtilities
+    {
+        public static readonly string PRECOMP_NAME = "bc_endo";
+
+        public static BigInteger[] DecomposeScalar(ScalarSplitParameters p, BigInteger k)
+        {
+            int bits = p.Bits;
+            BigInteger b1 = CalculateB(k, p.G1, bits);
+            BigInteger b2 = CalculateB(k, p.G2, bits);
+
+            BigInteger a = k.Subtract((b1.Multiply(p.V1A)).Add(b2.Multiply(p.V2A)));
+            BigInteger b = (b1.Multiply(p.V1B)).Add(b2.Multiply(p.V2B)).Negate();
+
+            return new BigInteger[]{ a, b };
+        }
+
+        public static ECPoint MapPoint(ECEndomorphism endomorphism, ECPoint p)
+        {
+            EndoPreCompInfo precomp = (EndoPreCompInfo)p.Curve.Precompute(p, PRECOMP_NAME,
+                new MapPointCallback(endomorphism, p));
+            return precomp.MappedPoint;
+        }
+
+        private static BigInteger CalculateB(BigInteger k, BigInteger g, int t)
+        {
+            bool negative = (g.SignValue < 0);
+            BigInteger b = k.Multiply(g.Abs());
+            bool extra = b.TestBit(t - 1);
+            b = b.ShiftRight(t);
+            if (extra)
+            {
+                b = b.Add(BigInteger.One);
+            }
+            return negative ? b.Negate() : b;
+        }
+
+        private class MapPointCallback
+            : IPreCompCallback
+        {
+            private readonly ECEndomorphism m_endomorphism;
+            private readonly ECPoint m_point;
+
+            internal MapPointCallback(ECEndomorphism endomorphism, ECPoint point)
+            {
+                this.m_endomorphism = endomorphism;
+                this.m_point = point;
+            }
+
+            public PreCompInfo Precompute(PreCompInfo existing)
+            {
+                EndoPreCompInfo existingEndo = existing as EndoPreCompInfo;
+
+                if (CheckExisting(existingEndo, m_endomorphism))
+                    return existingEndo;
+
+                ECPoint mappedPoint = m_endomorphism.PointMap.Map(m_point);
+
+                EndoPreCompInfo result = new EndoPreCompInfo();
+                result.Endomorphism = m_endomorphism;
+                result.MappedPoint = mappedPoint;
+                return result;
+            }
+
+            private bool CheckExisting(EndoPreCompInfo existingEndo, ECEndomorphism endomorphism)
+            {
+                return null != existingEndo
+                    && existingEndo.Endomorphism == endomorphism
+                    && existingEndo.MappedPoint != null;
+            }
+
+        }
+    }
+}
diff --git a/crypto/src/math/ec/endo/GlvTypeAEndomorphism.cs b/crypto/src/math/ec/endo/GlvTypeAEndomorphism.cs
new file mode 100644
index 000000000..fda8f154c
--- /dev/null
+++ b/crypto/src/math/ec/endo/GlvTypeAEndomorphism.cs
@@ -0,0 +1,38 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Endo
+{
+    public class GlvTypeAEndomorphism
+        :   GlvEndomorphism
+    {
+        protected readonly GlvTypeAParameters m_parameters;
+        protected readonly ECPointMap m_pointMap;
+
+        public GlvTypeAEndomorphism(ECCurve curve, GlvTypeAParameters parameters)
+        {
+            /*
+             * NOTE: 'curve' MUST only be used to create a suitable ECFieldElement. Due to the way
+             * ECCurve configuration works, 'curve' will not be the actual instance of ECCurve that the
+             * endomorphism is being used with.
+             */
+
+            this.m_parameters = parameters;
+            this.m_pointMap = new ScaleYNegateXPointMap(curve.FromBigInteger(parameters.I));
+        }
+
+        public virtual BigInteger[] DecomposeScalar(BigInteger k)
+        {
+            return EndoUtilities.DecomposeScalar(m_parameters.SplitParams, k);
+        }
+
+        public virtual ECPointMap PointMap
+        {
+            get { return m_pointMap; }
+        }
+
+        public virtual bool HasEfficientPointMap
+        {
+            get { return true; }
+        }
+    }
+}
diff --git a/crypto/src/math/ec/endo/GlvTypeAParameters.cs b/crypto/src/math/ec/endo/GlvTypeAParameters.cs
new file mode 100644
index 000000000..68464c530
--- /dev/null
+++ b/crypto/src/math/ec/endo/GlvTypeAParameters.cs
@@ -0,0 +1,32 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Endo
+{
+    public class GlvTypeAParameters
+    {
+        protected readonly BigInteger m_i, m_lambda;
+        protected readonly ScalarSplitParameters m_splitParams;
+
+        public GlvTypeAParameters(BigInteger i, BigInteger lambda, ScalarSplitParameters splitParams)
+        {
+            this.m_i = i;
+            this.m_lambda = lambda;
+            this.m_splitParams = splitParams;
+        }
+
+        public virtual BigInteger I
+        {
+            get { return m_i; }
+        }
+
+        public virtual BigInteger Lambda
+        {
+            get { return m_lambda; }
+        }
+
+        public virtual ScalarSplitParameters SplitParams
+        {
+            get { return m_splitParams; }
+        }
+    }
+}
diff --git a/crypto/src/math/ec/endo/GlvTypeBEndomorphism.cs b/crypto/src/math/ec/endo/GlvTypeBEndomorphism.cs
index d234d88bf..e4f12fed9 100644
--- a/crypto/src/math/ec/endo/GlvTypeBEndomorphism.cs
+++ b/crypto/src/math/ec/endo/GlvTypeBEndomorphism.cs
@@ -5,28 +5,24 @@ namespace Org.BouncyCastle.Math.EC.Endo
     public class GlvTypeBEndomorphism
         :   GlvEndomorphism
     {
-        protected readonly ECCurve m_curve;
         protected readonly GlvTypeBParameters m_parameters;
         protected readonly ECPointMap m_pointMap;
 
         public GlvTypeBEndomorphism(ECCurve curve, GlvTypeBParameters parameters)
         {
-            this.m_curve = curve;
+            /*
+             * NOTE: 'curve' MUST only be used to create a suitable ECFieldElement. Due to the way
+             * ECCurve configuration works, 'curve' will not be the actual instance of ECCurve that the
+             * endomorphism is being used with.
+             */
+
             this.m_parameters = parameters;
             this.m_pointMap = new ScaleXPointMap(curve.FromBigInteger(parameters.Beta));
         }
 
         public virtual BigInteger[] DecomposeScalar(BigInteger k)
         {
-            int bits = m_parameters.Bits;
-            BigInteger b1 = CalculateB(k, m_parameters.G1, bits);
-            BigInteger b2 = CalculateB(k, m_parameters.G2, bits);
-
-            BigInteger[] v1 = m_parameters.V1, v2 = m_parameters.V2;
-            BigInteger a = k.Subtract((b1.Multiply(v1[0])).Add(b2.Multiply(v2[0])));
-            BigInteger b = (b1.Multiply(v1[1])).Add(b2.Multiply(v2[1])).Negate();
-
-            return new BigInteger[]{ a, b };
+            return EndoUtilities.DecomposeScalar(m_parameters.SplitParams, k);
         }
 
         public virtual ECPointMap PointMap
@@ -38,18 +34,5 @@ namespace Org.BouncyCastle.Math.EC.Endo
         {
             get { return true; }
         }
-
-        protected virtual BigInteger CalculateB(BigInteger k, BigInteger g, int t)
-        {
-            bool negative = (g.SignValue < 0);
-            BigInteger b = k.Multiply(g.Abs());
-            bool extra = b.TestBit(t - 1);
-            b = b.ShiftRight(t);
-            if (extra)
-            {
-                b = b.Add(BigInteger.One);
-            }
-            return negative ? b.Negate() : b;
-        }
     }
 }
diff --git a/crypto/src/math/ec/endo/GlvTypeBParameters.cs b/crypto/src/math/ec/endo/GlvTypeBParameters.cs
index f93dfaf2b..5e2937be8 100644
--- a/crypto/src/math/ec/endo/GlvTypeBParameters.cs
+++ b/crypto/src/math/ec/endo/GlvTypeBParameters.cs
@@ -4,22 +4,23 @@ namespace Org.BouncyCastle.Math.EC.Endo
 {
     public class GlvTypeBParameters
     {
-        protected readonly BigInteger m_beta;
-        protected readonly BigInteger m_lambda;
-        protected readonly BigInteger[] m_v1, m_v2;
-        protected readonly BigInteger m_g1, m_g2;
-        protected readonly int m_bits;
+        protected readonly BigInteger m_beta, m_lambda;
+        protected readonly ScalarSplitParameters m_splitParams;
 
+        [Obsolete("Use constructor taking a ScalarSplitParameters instead")]
         public GlvTypeBParameters(BigInteger beta, BigInteger lambda, BigInteger[] v1, BigInteger[] v2,
             BigInteger g1, BigInteger g2, int bits)
         {
             this.m_beta = beta;
             this.m_lambda = lambda;
-            this.m_v1 = v1;
-            this.m_v2 = v2;
-            this.m_g1 = g1;
-            this.m_g2 = g2;
-            this.m_bits = bits;
+            this.m_splitParams = new ScalarSplitParameters(v1, v2, g1, g2, bits);
+        }
+
+        public GlvTypeBParameters(BigInteger beta, BigInteger lambda, ScalarSplitParameters splitParams)
+        {
+            this.m_beta = beta;
+            this.m_lambda = lambda;
+            this.m_splitParams = splitParams;
         }
 
         public virtual BigInteger Beta
@@ -32,29 +33,39 @@ namespace Org.BouncyCastle.Math.EC.Endo
             get { return m_lambda; }
         }
 
+        public virtual ScalarSplitParameters SplitParams
+        {
+            get { return m_splitParams; }
+        }
+
+        [Obsolete("Access via SplitParams instead")]
         public virtual BigInteger[] V1
         {
-            get { return m_v1; }
+            get { return new BigInteger[] { m_splitParams.V1A, m_splitParams.V1B }; }
         }
 
+        [Obsolete("Access via SplitParams instead")]
         public virtual BigInteger[] V2
         {
-            get { return m_v2; }
+            get { return new BigInteger[] { m_splitParams.V2A, m_splitParams.V2B }; }
         }
 
+        [Obsolete("Access via SplitParams instead")]
         public virtual BigInteger G1
         {
-            get { return m_g1; }
+            get { return m_splitParams.G1; }
         }
 
+        [Obsolete("Access via SplitParams instead")]
         public virtual BigInteger G2
         {
-            get { return m_g2; }
+            get { return m_splitParams.G2; }
         }
 
+        [Obsolete("Access via SplitParams instead")]
         public virtual int Bits
         {
-            get { return m_bits; }
+            get { return m_splitParams.Bits; }
         }
     }
 }
diff --git a/crypto/src/math/ec/endo/ScalarSplitParameters.cs b/crypto/src/math/ec/endo/ScalarSplitParameters.cs
new file mode 100644
index 000000000..18d0bdb9e
--- /dev/null
+++ b/crypto/src/math/ec/endo/ScalarSplitParameters.cs
@@ -0,0 +1,69 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Math.EC.Endo
+{
+    public class ScalarSplitParameters
+    {
+        private static void CheckVector(BigInteger[] v, string name)
+        {
+            if (v == null || v.Length != 2 || v[0] == null || v[1] == null)
+                throw new ArgumentException("Must consist of exactly 2 (non-null) values", name);
+        }
+
+        protected readonly BigInteger m_v1A, m_v1B, m_v2A, m_v2B;
+        protected readonly BigInteger m_g1, m_g2;
+        protected readonly int m_bits;
+
+        public ScalarSplitParameters(BigInteger[] v1, BigInteger[] v2, BigInteger g1,
+            BigInteger g2, int bits)
+        {
+            CheckVector(v1, "v1");
+            CheckVector(v2, "v2");
+
+            this.m_v1A = v1[0];
+            this.m_v1B = v1[1];
+            this.m_v2A = v2[0];
+            this.m_v2B = v2[1];
+            this.m_g1 = g1;
+            this.m_g2 = g2;
+            this.m_bits = bits;
+        }
+
+        public virtual BigInteger V1A
+        {
+            get { return m_v1A; }
+        }
+
+        public virtual BigInteger V1B
+        {
+            get { return m_v1B; }
+        }
+
+        public virtual BigInteger V2A
+        {
+            get { return m_v2A; }
+        }
+
+        public virtual BigInteger V2B
+        {
+            get { return m_v2B; }
+        }
+
+        public virtual BigInteger G1
+        {
+            get { return m_g1; }
+        }
+
+        public virtual BigInteger G2
+        {
+            get { return m_g2; }
+        }
+
+        public virtual int Bits
+        {
+            get { return m_bits; }
+        }
+    }
+}
diff --git a/crypto/src/math/ec/multiplier/GlvMultiplier.cs b/crypto/src/math/ec/multiplier/GlvMultiplier.cs
index f19049474..9ef7d6e24 100644
--- a/crypto/src/math/ec/multiplier/GlvMultiplier.cs
+++ b/crypto/src/math/ec/multiplier/GlvMultiplier.cs
@@ -28,13 +28,14 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
             BigInteger[] ab = glvEndomorphism.DecomposeScalar(k.Mod(n));
             BigInteger a = ab[0], b = ab[1];
 
-            ECPointMap pointMap = glvEndomorphism.PointMap;
             if (glvEndomorphism.HasEfficientPointMap)
             {
-                return ECAlgorithms.ImplShamirsTrickWNaf(p, a, pointMap, b);
+                return ECAlgorithms.ImplShamirsTrickWNaf(glvEndomorphism, p, a, b);
             }
 
-            return ECAlgorithms.ImplShamirsTrickWNaf(p, a, pointMap.Map(p), b);
+            ECPoint q = EndoUtilities.MapPoint(glvEndomorphism, p);
+
+            return ECAlgorithms.ImplShamirsTrickWNaf(p, a, q, b);
         }
     }
 }
diff --git a/crypto/src/math/ec/multiplier/WNafL2RMultiplier.cs b/crypto/src/math/ec/multiplier/WNafL2RMultiplier.cs
index f671f6a5c..833bbb5ea 100644
--- a/crypto/src/math/ec/multiplier/WNafL2RMultiplier.cs
+++ b/crypto/src/math/ec/multiplier/WNafL2RMultiplier.cs
@@ -1,5 +1,7 @@
 using System;
 
+using Org.BouncyCastle.Utilities;
+
 namespace Org.BouncyCastle.Math.EC.Multiplier
 {
     /**
@@ -18,12 +20,12 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
          */
         protected override ECPoint MultiplyPositive(ECPoint p, BigInteger k)
         {
-            // Clamp the window width in the range [2, 16]
-            int width = System.Math.Max(2, System.Math.Min(16, GetWindowSize(k.BitLength)));
+            int minWidth = WNafUtilities.GetWindowSize(k.BitLength);
 
-            WNafPreCompInfo wnafPreCompInfo = WNafUtilities.Precompute(p, width, true);
-            ECPoint[] preComp = wnafPreCompInfo.PreComp;
-            ECPoint[] preCompNeg = wnafPreCompInfo.PreCompNeg;
+            WNafPreCompInfo info = WNafUtilities.Precompute(p, minWidth, true);
+            ECPoint[] preComp = info.PreComp;
+            ECPoint[] preCompNeg = info.PreCompNeg;
+            int width = info.Width;
 
             int[] wnaf = WNafUtilities.GenerateCompactWindowNaf(width, k);
 
@@ -46,7 +48,7 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
                 // Optimization can only be used for values in the lower half of the table
                 if ((n << 2) < (1 << width))
                 {
-                    int highest = LongArray.BitLengths[n];
+                    int highest = 32 - Integers.NumberOfLeadingZeros(n);
 
                     // TODO Get addition/doubling cost ratio from curve and compare to 'scale' to see if worth substituting?
                     int scale = width - highest;
@@ -83,16 +85,5 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
 
             return R;
         }
-
-        /**
-         * Determine window width to use for a scalar multiplication of the given size.
-         * 
-         * @param bits the bit-length of the scalar to multiply by
-         * @return the window size to use
-         */
-        protected virtual int GetWindowSize(int bits)
-        {
-            return WNafUtilities.GetWindowSize(bits);
-        }
     }
 }
diff --git a/crypto/src/math/ec/multiplier/WNafPreCompInfo.cs b/crypto/src/math/ec/multiplier/WNafPreCompInfo.cs
index 7e0a73154..f979f33d9 100644
--- a/crypto/src/math/ec/multiplier/WNafPreCompInfo.cs
+++ b/crypto/src/math/ec/multiplier/WNafPreCompInfo.cs
@@ -5,8 +5,12 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
     * algorithm.
     */
     public class WNafPreCompInfo
-        : PreCompInfo 
+        : PreCompInfo
     {
+        internal volatile int m_promotionCountdown = 4;
+
+        protected int m_confWidth = -1;
+
         /**
          * Array holding the precomputed <code>ECPoint</code>s used for a Window
          * NAF multiplication.
@@ -25,6 +29,35 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
          */
         protected ECPoint m_twice = null;
 
+        protected int m_width = -1;
+
+        internal int DecrementPromotionCountdown()
+        {
+            int t = m_promotionCountdown;
+            if (t > 0)
+            {
+                m_promotionCountdown = --t;
+            }
+            return t;
+        }
+
+        internal int PromotionCountdown
+        {
+            get { return m_promotionCountdown; }
+            set { this.m_promotionCountdown = value; }
+        }
+
+        public virtual bool IsPromoted
+        {
+            get { return m_promotionCountdown <= 0; }
+        }
+
+        public virtual int ConfWidth
+        {
+            get { return m_confWidth; }
+            set { this.m_confWidth = value; }
+        }
+
         public virtual ECPoint[] PreComp
         {
             get { return m_preComp; }
@@ -42,5 +75,11 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
             get { return m_twice; }
             set { this.m_twice = value; }
         }
+
+        public virtual int Width
+        {
+            get { return m_width; }
+            set { this.m_width = value; }
+        }
     }
 }
diff --git a/crypto/src/math/ec/multiplier/WNafUtilities.cs b/crypto/src/math/ec/multiplier/WNafUtilities.cs
index 24646deb2..42265b2d6 100644
--- a/crypto/src/math/ec/multiplier/WNafUtilities.cs
+++ b/crypto/src/math/ec/multiplier/WNafUtilities.cs
@@ -9,9 +9,23 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
         public static readonly string PRECOMP_NAME = "bc_wnaf";
 
         private static readonly int[] DEFAULT_WINDOW_SIZE_CUTOFFS = new int[]{ 13, 41, 121, 337, 897, 2305 };
+        private static readonly int MAX_WIDTH = 16;
 
         private static readonly ECPoint[] EMPTY_POINTS = new ECPoint[0];
 
+        public static void ConfigureBasepoint(ECPoint p)
+        {
+            ECCurve c = p.Curve;
+            if (null == c)
+                return;
+
+            BigInteger n = c.Order;
+            int bits = (null == n) ? c.FieldSize + 1 : n.BitLength;
+            int confWidth = System.Math.Min(MAX_WIDTH, GetWindowSize(bits) + 3);
+
+            c.Precompute(p, PRECOMP_NAME, new ConfigureBasepointCallback(c, confWidth));
+        }
+
         public static int[] GenerateCompactNaf(BigInteger k)
         {
             if ((k.BitLength >> 16) != 0)
@@ -298,7 +312,19 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
          */
         public static int GetWindowSize(int bits)
         {
-            return GetWindowSize(bits, DEFAULT_WINDOW_SIZE_CUTOFFS);
+            return GetWindowSize(bits, DEFAULT_WINDOW_SIZE_CUTOFFS, MAX_WIDTH);
+        }
+
+        /**
+         * Determine window width to use for a scalar multiplication of the given size.
+         * 
+         * @param bits the bit-length of the scalar to multiply by
+         * @param maxWidth the maximum window width to return 
+         * @return the window size to use
+         */
+        public static int GetWindowSize(int bits, int maxWidth)
+        {
+            return GetWindowSize(bits, DEFAULT_WINDOW_SIZE_CUTOFFS, maxWidth);
         }
 
         /**
@@ -310,6 +336,19 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
          */
         public static int GetWindowSize(int bits, int[] windowSizeCutoffs)
         {
+            return GetWindowSize(bits, windowSizeCutoffs, MAX_WIDTH);
+        }
+
+        /**
+         * Determine window width to use for a scalar multiplication of the given size.
+         * 
+         * @param bits the bit-length of the scalar to multiply by
+         * @param windowSizeCutoffs a monotonically increasing list of bit sizes at which to increment the window width
+         * @param maxWidth the maximum window width to return 
+         * @return the window size to use
+         */
+        public static int GetWindowSize(int bits, int[] windowSizeCutoffs, int maxWidth)
+        {
             int w = 0;
             for (; w < windowSizeCutoffs.Length; ++w)
             {
@@ -318,23 +357,33 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
                     break;
                 }
             }
-            return w + 2;
+
+            return System.Math.Max(2, System.Math.Min(maxWidth, w + 2));
         }
 
-        public static ECPoint MapPointWithPrecomp(ECPoint p, int width, bool includeNegated,
+        [Obsolete]
+        public static ECPoint MapPointWithPrecomp(ECPoint p, int minWidth, bool includeNegated,
             ECPointMap pointMap)
         {
             ECCurve c = p.Curve;
-            WNafPreCompInfo wnafPreCompP = Precompute(p, width, includeNegated);
+            WNafPreCompInfo infoP = Precompute(p, minWidth, includeNegated);
 
             ECPoint q = pointMap.Map(p);
-            c.Precompute(q, PRECOMP_NAME, new MapPointCallback(wnafPreCompP, includeNegated, pointMap));
+            c.Precompute(q, PRECOMP_NAME, new MapPointCallback(infoP, includeNegated, pointMap));
             return q;
         }
 
-        public static WNafPreCompInfo Precompute(ECPoint p, int width, bool includeNegated)
+        public static WNafPreCompInfo Precompute(ECPoint p, int minWidth, bool includeNegated)
         {
-            return (WNafPreCompInfo)p.Curve.Precompute(p, PRECOMP_NAME, new WNafCallback(p, width, includeNegated));
+            return (WNafPreCompInfo)p.Curve.Precompute(p, PRECOMP_NAME,
+                new PrecomputeCallback(p, minWidth, includeNegated));
+        }
+
+        public static WNafPreCompInfo PrecomputeWithPointMap(ECPoint p, ECPointMap pointMap, WNafPreCompInfo fromWNaf,
+            bool includeNegated)
+        {
+            return (WNafPreCompInfo)p.Curve.Precompute(p, PRECOMP_NAME,
+                new PrecomputeWithPointMapCallback(p, pointMap, fromWNaf, includeNegated));
         }
 
         private static byte[] Trim(byte[] a, int length)
@@ -358,16 +407,55 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
             return result;
         }
 
+        private class ConfigureBasepointCallback
+            : IPreCompCallback
+        {
+            private readonly ECCurve m_curve;
+            private readonly int m_confWidth;
+
+            internal ConfigureBasepointCallback(ECCurve curve, int confWidth)
+            {
+                this.m_curve = curve;
+                this.m_confWidth = confWidth;
+            }
+
+            public PreCompInfo Precompute(PreCompInfo existing)
+            {
+                WNafPreCompInfo existingWNaf = existing as WNafPreCompInfo;
+
+                if (null != existingWNaf && existingWNaf.ConfWidth == m_confWidth)
+                {
+                    existingWNaf.PromotionCountdown = 0;
+                    return existingWNaf;
+                }
+
+                WNafPreCompInfo result = new WNafPreCompInfo();
+
+                result.PromotionCountdown = 0;
+                result.ConfWidth = m_confWidth;
+
+                if (null != existingWNaf)
+                {
+                    result.PreComp = existingWNaf.PreComp;
+                    result.PreCompNeg = existingWNaf.PreCompNeg;
+                    result.Twice = existingWNaf.Twice;
+                    result.Width = existingWNaf.Width;
+                }
+
+                return result;
+            }
+        }
+
         private class MapPointCallback
             : IPreCompCallback
         {
-            private readonly WNafPreCompInfo m_wnafPreCompP;
+            private readonly WNafPreCompInfo m_infoP;
             private readonly bool m_includeNegated;
             private readonly ECPointMap m_pointMap;
 
-            internal MapPointCallback(WNafPreCompInfo wnafPreCompP, bool includeNegated, ECPointMap pointMap)
+            internal MapPointCallback(WNafPreCompInfo infoP, bool includeNegated, ECPointMap pointMap)
             {
-                this.m_wnafPreCompP = wnafPreCompP;
+                this.m_infoP = infoP;
                 this.m_includeNegated = includeNegated;
                 this.m_pointMap = pointMap;
             }
@@ -376,20 +464,23 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
             {
                 WNafPreCompInfo result = new WNafPreCompInfo();
 
-                ECPoint twiceP = m_wnafPreCompP.Twice;
-                if (twiceP != null)
+                result.ConfWidth = m_infoP.ConfWidth;
+
+                ECPoint twiceP = m_infoP.Twice;
+                if (null != twiceP)
                 {
                     ECPoint twiceQ = m_pointMap.Map(twiceP);
                     result.Twice = twiceQ;
                 }
 
-                ECPoint[] preCompP = m_wnafPreCompP.PreComp;
+                ECPoint[] preCompP = m_infoP.PreComp;
                 ECPoint[] preCompQ = new ECPoint[preCompP.Length];
                 for (int i = 0; i < preCompP.Length; ++i)
                 {
                     preCompQ[i] = m_pointMap.Map(preCompP[i]);
                 }
                 result.PreComp = preCompQ;
+                result.Width = m_infoP.Width;
 
                 if (m_includeNegated)
                 {
@@ -405,17 +496,17 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
             }
         }
 
-        private class WNafCallback
+        private class PrecomputeCallback
             : IPreCompCallback
         {
             private readonly ECPoint m_p;
-            private readonly int m_width;
+            private readonly int m_minWidth;
             private readonly bool m_includeNegated;
 
-            internal WNafCallback(ECPoint p, int width, bool includeNegated)
+            internal PrecomputeCallback(ECPoint p, int minWidth, bool includeNegated)
             {
                 this.m_p = p;
-                this.m_width = width;
+                this.m_minWidth = minWidth;
                 this.m_includeNegated = includeNegated;
             }
 
@@ -423,24 +514,39 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
             {
                 WNafPreCompInfo existingWNaf = existing as WNafPreCompInfo;
 
-                int reqPreCompLen = 1 << System.Math.Max(0, m_width - 2);
+                int width = System.Math.Max(2, System.Math.Min(MAX_WIDTH, m_minWidth));
+                int reqPreCompLen = 1 << (width - 2);
 
-                if (CheckExisting(existingWNaf, reqPreCompLen, m_includeNegated))
+                if (CheckExisting(existingWNaf, width, reqPreCompLen, m_includeNegated))
+                {
+                    existingWNaf.DecrementPromotionCountdown();
                     return existingWNaf;
+                }
+
+                WNafPreCompInfo result = new WNafPreCompInfo();
 
                 ECCurve c = m_p.Curve;
                 ECPoint[] preComp = null, preCompNeg = null;
                 ECPoint twiceP = null;
 
-                if (existingWNaf != null)
+                if (null != existingWNaf)
                 {
+                    int promotionCountdown = existingWNaf.DecrementPromotionCountdown();
+                    result.PromotionCountdown = promotionCountdown;
+
+                    int confWidth = existingWNaf.ConfWidth;
+                    result.ConfWidth = confWidth;
+
                     preComp = existingWNaf.PreComp;
                     preCompNeg = existingWNaf.PreCompNeg;
                     twiceP = existingWNaf.Twice;
                 }
 
+                width = System.Math.Min(MAX_WIDTH, System.Math.Max(result.ConfWidth, width));
+                reqPreCompLen = 1 << (width - 2);
+
                 int iniPreCompLen = 0;
-                if (preComp == null)
+                if (null == preComp)
                 {
                     preComp = EMPTY_POINTS;
                 }
@@ -475,7 +581,7 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
                         else
                         {
                             ECPoint isoTwiceP = twiceP, last = preComp[curPreCompLen - 1];
-                            if (isoTwiceP == null)
+                            if (null == isoTwiceP)
                             {
                                 isoTwiceP = preComp[0].Twice();
                                 twiceP = isoTwiceP;
@@ -535,7 +641,7 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
                 if (m_includeNegated)
                 {
                     int pos;
-                    if (preCompNeg == null)
+                    if (null == preCompNeg)
                     {
                         pos = 0;
                         preCompNeg = new ECPoint[reqPreCompLen]; 
@@ -556,23 +662,105 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
                     }
                 }
 
-                WNafPreCompInfo result = new WNafPreCompInfo();
                 result.PreComp = preComp;
                 result.PreCompNeg = preCompNeg;
                 result.Twice = twiceP;
+                result.Width = width;
+                return result;
+            }
+
+            private bool CheckExisting(WNafPreCompInfo existingWNaf, int width, int reqPreCompLen, bool includeNegated)
+            {
+                return null != existingWNaf
+                    && existingWNaf.Width >= System.Math.Max(existingWNaf.ConfWidth, width) 
+                    && CheckTable(existingWNaf.PreComp, reqPreCompLen)
+                    && (!includeNegated || CheckTable(existingWNaf.PreCompNeg, reqPreCompLen));
+            }
+
+            private bool CheckTable(ECPoint[] table, int reqLen)
+            {
+                return null != table && table.Length >= reqLen;
+            }
+        }
+
+        private class PrecomputeWithPointMapCallback
+            : IPreCompCallback
+        {
+            private readonly ECPoint m_point;
+            private readonly ECPointMap m_pointMap;
+            private readonly WNafPreCompInfo m_fromWNaf;
+            private readonly bool m_includeNegated;
+
+            internal PrecomputeWithPointMapCallback(ECPoint point, ECPointMap pointMap, WNafPreCompInfo fromWNaf,
+                bool includeNegated)
+            {
+                this.m_point = point;
+                this.m_pointMap = pointMap;
+                this.m_fromWNaf = fromWNaf;
+                this.m_includeNegated = includeNegated;
+            }
+
+            public PreCompInfo Precompute(PreCompInfo existing)
+            {
+                WNafPreCompInfo existingWNaf = existing as WNafPreCompInfo;
+
+                int width = m_fromWNaf.Width;
+                int reqPreCompLen = m_fromWNaf.PreComp.Length;
+
+                if (CheckExisting(existingWNaf, width, reqPreCompLen, m_includeNegated))
+                {
+                    existingWNaf.DecrementPromotionCountdown();
+                    return existingWNaf;
+                }
+
+                /*
+                 * TODO Ideally this method would support incremental calculation, but given the
+                 * existing use-cases it would be of little-to-no benefit.
+                 */
+                WNafPreCompInfo result = new WNafPreCompInfo();
+
+                result.PromotionCountdown = m_fromWNaf.PromotionCountdown;
+
+                ECPoint twiceFrom = m_fromWNaf.Twice;
+                if (null != twiceFrom)
+                {
+                    ECPoint twice = m_pointMap.Map(twiceFrom);
+                    result.Twice = twice;
+                }
+
+                ECPoint[] preCompFrom = m_fromWNaf.PreComp;
+                ECPoint[] preComp = new ECPoint[preCompFrom.Length];
+                for (int i = 0; i < preCompFrom.Length; ++i)
+                {
+                    preComp[i] = m_pointMap.Map(preCompFrom[i]);
+                }
+                result.PreComp = preComp;
+                result.Width = width;
+
+                if (m_includeNegated)
+                {
+                    ECPoint[] preCompNeg = new ECPoint[preComp.Length];
+                    for (int i = 0; i < preCompNeg.Length; ++i)
+                    {
+                        preCompNeg[i] = preComp[i].Negate();
+                    }
+                    result.PreCompNeg = preCompNeg;
+                }
+
                 return result;
             }
 
-            private bool CheckExisting(WNafPreCompInfo existingWNaf, int reqPreCompLen, bool includeNegated)
+            private bool CheckExisting(WNafPreCompInfo existingWNaf, int width, int reqPreCompLen, bool includeNegated)
             {
-                return existingWNaf != null
+                return null != existingWNaf
+                    && existingWNaf.Width >= width
                     && CheckTable(existingWNaf.PreComp, reqPreCompLen)
                     && (!includeNegated || CheckTable(existingWNaf.PreCompNeg, reqPreCompLen));
             }
 
             private bool CheckTable(ECPoint[] table, int reqLen)
             {
-                return table != null && table.Length >= reqLen;
+                return null != table && table.Length >= reqLen;
             }
         }
     }
diff --git a/crypto/src/math/ec/rfc7748/X25519Field.cs b/crypto/src/math/ec/rfc7748/X25519Field.cs
index fd5599657..3a06941dd 100644
--- a/crypto/src/math/ec/rfc7748/X25519Field.cs
+++ b/crypto/src/math/ec/rfc7748/X25519Field.cs
@@ -14,7 +14,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
         private static readonly int[] RootNegOne = { 0x020EA0B0, 0x0386C9D2, 0x00478C4E, 0x0035697F, 0x005E8630,
             0x01FBD7A7, 0x0340264F, 0x01F0B2B4, 0x00027E0E, 0x00570649 };
 
-        private X25519Field() {}
+        protected X25519Field() {}
 
         public static void Add(int[] x, int[] y, int[] z)
         {
@@ -67,6 +67,18 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
             z[5] = z5; z[6] = z6; z[7] = z7; z[8] = z8; z[9] = z9;
         }
 
+        public static void CMov(int cond, int[] x, int xOff, int[] z, int zOff)
+        {
+            Debug.Assert(0 == cond || -1 == cond);
+
+            for (int i = 0; i < Size; ++i)
+            {
+                int z_i = z[zOff + i], diff = z_i ^ x[xOff + i];
+                z_i ^= (diff & cond);
+                z[zOff + i] = z_i;
+            }
+        }
+
         public static void CNegate(int negate, int[] z)
         {
             Debug.Assert(negate >> 1 == 0);
@@ -179,14 +191,21 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
             Mul(t, x2, z);
         }
 
-        public static bool IsZeroVar(int[] x)
+        public static int IsZero(int[] x)
         {
             int d = 0;
             for (int i = 0; i < Size; ++i)
             {
                 d |= x[i];
             }
-            return d == 0;
+            d |= d >> 16;
+            d &= 0xFFFF;
+            return (d - 1) >> 31;
+        }
+
+        public static bool IsZeroVar(int[] x)
+        {
+            return 0 != IsZero(x);
         }
 
         public static void Mul(int[] x, int y, int[] z)
diff --git a/crypto/src/math/ec/rfc7748/X448Field.cs b/crypto/src/math/ec/rfc7748/X448Field.cs
index 5a682714d..f1e89e520 100644
--- a/crypto/src/math/ec/rfc7748/X448Field.cs
+++ b/crypto/src/math/ec/rfc7748/X448Field.cs
@@ -1,8 +1,6 @@
 using System;
 using System.Diagnostics;
 
-using Org.BouncyCastle.Math.Raw;
-
 namespace Org.BouncyCastle.Math.EC.Rfc7748
 {
     [CLSCompliantAttribute(false)]
@@ -12,7 +10,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
 
         private const uint M28 = 0x0FFFFFFFU;
 
-        private X448Field() {}
+        protected X448Field() {}
 
         public static void Add(uint[] x, uint[] y, uint[] z)
         {
@@ -74,6 +72,20 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
             z[8] = z8; z[9] = z9; z[10] = z10; z[11] = z11; z[12] = z12; z[13] = z13; z[14] = z14; z[15] = z15;
         }
 
+        public static void CMov(int cond, uint[] x, int xOff, uint[] z, int zOff)
+        {
+            Debug.Assert(0 == cond || -1 == cond);
+
+            uint MASK = (uint)cond;
+
+            for (int i = 0; i < Size; ++i)
+            {
+                uint z_i = z[zOff + i], diff = z_i ^ x[xOff + i];
+                z_i ^= (diff & MASK);
+                z[zOff + i] = z_i;
+            }
+        }
+
         public static void CNegate(int negate, uint[] z)
         {
             Debug.Assert(negate >> 1 == 0);
@@ -81,7 +93,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
             uint[] t = Create();
             Sub(t, z, t);
 
-            Nat.CMov(Size, negate, t, 0, z, 0);
+            CMov(-negate, t, 0, z, 0);
         }
 
         public static void Copy(uint[] x, int xOff, uint[] z, int zOff)
@@ -195,14 +207,21 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
             Mul(t, x, z);
         }
 
-        public static bool IsZeroVar(uint[] x)
+        public static int IsZero(uint[] x)
         {
             uint d = 0;
             for (int i = 0; i < Size; ++i)
             {
                 d |= x[i];
             }
-            return d == 0U;
+            d |= d >> 16;
+            d &= 0xFFFF;
+            return ((int)d - 1) >> 31;
+        }
+
+        public static bool IsZeroVar(uint[] x)
+        {
+            return 0U != IsZero(x);
         }
 
         public static void Mul(uint[] x, uint y, uint[] z)
diff --git a/crypto/src/math/ec/rfc8032/Ed25519.cs b/crypto/src/math/ec/rfc8032/Ed25519.cs
index 702c48dd3..b798bdf2d 100644
--- a/crypto/src/math/ec/rfc8032/Ed25519.cs
+++ b/crypto/src/math/ec/rfc8032/Ed25519.cs
@@ -270,7 +270,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
 
         private static sbyte[] GetWnaf(uint[] n, int width)
         {
-            Debug.Assert(n[ScalarUints - 1] >> 31 == 0);
+            Debug.Assert(n[ScalarUints - 1] >> 28 == 0);
 
             uint[] t = new uint[ScalarUints * 2];
             {
@@ -284,7 +284,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
                 }
             }
 
-            sbyte[] ws = new sbyte[256];
+            sbyte[] ws = new sbyte[253];
 
             uint pow2 = 1U << width;
             uint mask = pow2 - 1U;
@@ -423,7 +423,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             DecodeScalar(k, 0, nA);
 
             PointAccum pR = new PointAccum();
-            ScalarMultStraussVar(nS, nA, pA, pR);
+            ScalarMultStrausVar(nS, nA, pA, pR);
 
             byte[] check = new byte[PointBytes];
             EncodePoint(pR, check, 0);
@@ -597,10 +597,10 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
 
             for (int i = 0; i < PrecompPoints; ++i)
             {
-                int mask = ((i ^ index) - 1) >> 31;
-                Nat.CMov(X25519Field.Size, mask, precompBase, off, p.ypx_h, 0); off += X25519Field.Size;
-                Nat.CMov(X25519Field.Size, mask, precompBase, off, p.ymx_h, 0); off += X25519Field.Size;
-                Nat.CMov(X25519Field.Size, mask, precompBase, off, p.xyd, 0);   off += X25519Field.Size;
+                int cond = ((i ^ index) - 1) >> 31;
+                X25519Field.CMov(cond, precompBase, off, p.ypx_h, 0);   off += X25519Field.Size;
+                X25519Field.CMov(cond, precompBase, off, p.ymx_h, 0);   off += X25519Field.Size;
+                X25519Field.CMov(cond, precompBase, off, p.xyd, 0);     off += X25519Field.Size;
             }
         }
 
@@ -945,7 +945,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             X25519Field.Copy(p.z, 0, z, 0);
         }
 
-        private static void ScalarMultStraussVar(uint[] nb, uint[] np, PointExt p, PointAccum r)
+        private static void ScalarMultStrausVar(uint[] nb, uint[] np, PointExt p, PointAccum r)
         {
             Precompute();
 
@@ -958,13 +958,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
 
             PointSetNeutral(r);
 
-            int bit = 255;
-            while (bit > 0 && ((byte)ws_b[bit] | (byte)ws_p[bit]) == 0)
-            {
-                --bit;
-            }
-
-            for (; ; )
+            for (int bit = 252;;)
             {
                 int wb = ws_b[bit];
                 if (wb != 0)
diff --git a/crypto/src/math/ec/rfc8032/Ed448.cs b/crypto/src/math/ec/rfc8032/Ed448.cs
index 597062269..842839396 100644
--- a/crypto/src/math/ec/rfc8032/Ed448.cs
+++ b/crypto/src/math/ec/rfc8032/Ed448.cs
@@ -279,7 +279,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
 
         private static sbyte[] GetWnaf(uint[] n, int width)
         {
-            Debug.Assert(n[ScalarUints - 1] >> 31 == 0U);
+            Debug.Assert(n[ScalarUints - 1] >> 30 == 0U);
 
             uint[] t = new uint[ScalarUints * 2];
             {
@@ -293,7 +293,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
                 }
             }
 
-            sbyte[] ws = new sbyte[448];
+            sbyte[] ws = new sbyte[447];
 
             uint pow2 = 1U << width;
             uint mask = pow2 - 1U;
@@ -432,7 +432,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             DecodeScalar(k, 0, nA);
 
             PointExt pR = new PointExt();
-            ScalarMultStraussVar(nS, nA, pA, pR);
+            ScalarMultStrausVar(nS, nA, pA, pR);
 
             byte[] check = new byte[PointBytes];
             EncodePoint(pR, check, 0);
@@ -568,9 +568,9 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
 
             for (int i = 0; i < PrecompPoints; ++i)
             {
-                int mask = ((i ^ index) - 1) >> 31;
-                Nat.CMov(X448Field.Size, mask, precompBase, off, p.x, 0);   off += X448Field.Size;
-                Nat.CMov(X448Field.Size, mask, precompBase, off, p.y, 0);   off += X448Field.Size;
+                int cond = ((i ^ index) - 1) >> 31;
+                X448Field.CMov(cond, precompBase, off, p.x, 0);     off += X448Field.Size;
+                X448Field.CMov(cond, precompBase, off, p.y, 0);     off += X448Field.Size;
             }
         }
 
@@ -1032,7 +1032,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             X448Field.Copy(p.y, 0, y, 0);
         }
 
-        private static void ScalarMultStraussVar(uint[] nb, uint[] np, PointExt p, PointExt r)
+        private static void ScalarMultStrausVar(uint[] nb, uint[] np, PointExt p, PointExt r)
         {
             Precompute();
 
@@ -1045,13 +1045,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
 
             PointSetNeutral(r);
 
-            int bit = 447;
-            while (bit > 0 && ((byte)ws_b[bit] | (byte)ws_p[bit]) == 0)
-            {
-                --bit;
-            }
-
-            for (;;)
+            for (int bit = 446;;)
             {
                 int wb = ws_b[bit];
                 if (wb != 0)
diff --git a/crypto/src/math/raw/Nat.cs b/crypto/src/math/raw/Nat.cs
index f9e4e6714..9786d3ecf 100644
--- a/crypto/src/math/raw/Nat.cs
+++ b/crypto/src/math/raw/Nat.cs
@@ -161,6 +161,31 @@ namespace Org.BouncyCastle.Math.Raw
             return (uint)c;
         }
 
+        public static uint AddTo(int len, uint[] x, int xOff, uint[] z, int zOff, uint cIn)
+        {
+            ulong c = cIn;
+            for (int i = 0; i < len; ++i)
+            {
+                c += (ulong)x[xOff + i] + z[zOff + i];
+                z[zOff + i] = (uint)c;
+                c >>= 32;
+            }
+            return (uint)c;
+        }
+
+        public static uint AddToEachOther(int len, uint[] u, int uOff, uint[] v, int vOff)
+        {
+            ulong c = 0;
+            for (int i = 0; i < len; ++i)
+            {
+                c += (ulong)u[uOff + i] + v[vOff + i];
+                u[uOff + i] = (uint)c;
+                v[vOff + i] = (uint)c;
+                c >>= 32;
+            }
+            return (uint)c;
+        }
+
         public static uint AddWordAt(int len, uint x, uint[] z, int zPos)
         {
             Debug.Assert(zPos <= (len - 1));
@@ -297,6 +322,32 @@ namespace Org.BouncyCastle.Math.Raw
             return new ulong[len];
         }
 
+        public static int CSub(int len, int mask, uint[] x, uint[] y, uint[] z)
+        {
+            long MASK = (uint)-(mask & 1);
+            long c = 0;
+            for (int i = 0; i < len; ++i)
+            {
+                c += (long)x[i] - (y[i] & MASK);
+                z[i] = (uint)c;
+                c >>= 32;
+            }
+            return (int)c;
+        }
+
+        public static int CSub(int len, int mask, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
+        {
+            long MASK = (uint)-(mask & 1);
+            long c = 0;
+            for (int i = 0; i < len; ++i)
+            {
+                c += (long)x[xOff + i] - (y[yOff + i] & MASK);
+                z[zOff + i] = (uint)c;
+                c >>= 32;
+            }
+            return (int)c;
+        }
+
         public static int Dec(int len, uint[] z)
         {
             for (int i = 0; i < len; ++i)
@@ -384,6 +435,22 @@ namespace Org.BouncyCastle.Math.Raw
             return z;
         }
 
+        public static ulong[] FromBigInteger64(int bits, BigInteger x)
+        {
+            if (x.SignValue < 0 || x.BitLength > bits)
+                throw new ArgumentException();
+
+            int len = (bits + 63) >> 6;
+            ulong[] z = Create64(len);
+            int i = 0;
+            while (x.SignValue != 0)
+            {
+                z[i++] = (ulong)x.LongValue;
+                x = x.ShiftRight(64);
+            }
+            return z;
+        }
+
         public static uint GetBit(uint[] x, int bit)
         {
             if (bit == 0)
@@ -538,10 +605,10 @@ namespace Org.BouncyCastle.Math.Raw
             ulong zc = 0;
             for (int i = 0; i < len; ++i)
             {
-                ulong c = MulWordAddTo(len, x[i], y, 0, zz, i) & M;
-                c += zc + (zz[i + len] & M);
-                zz[i + len] = (uint)c;
-                zc = c >> 32;
+                zc += MulWordAddTo(len, x[i], y, 0, zz, i) & M;
+                zc += zz[i + len] & M;
+                zz[i + len] = (uint)zc;
+                zc >>= 32;
             }
             return (uint)zc;
         }
@@ -551,10 +618,10 @@ namespace Org.BouncyCastle.Math.Raw
             ulong zc = 0;
             for (int i = 0; i < len; ++i)
             {
-                ulong c = MulWordAddTo(len, x[xOff + i], y, yOff, zz, zzOff) & M;
-                c += zc + (zz[zzOff + len] & M);
-                zz[zzOff + len] = (uint)c;
-                zc = c >> 32;
+                zc += MulWordAddTo(len, x[xOff + i], y, yOff, zz, zzOff) & M;
+                zc += zz[zzOff + len] & M;
+                zz[zzOff + len] = (uint)zc;
+                zc >>= 32;
                 ++zzOff;
             }
             return (uint)zc;
@@ -886,11 +953,18 @@ namespace Org.BouncyCastle.Math.Raw
             }
             while (j > 0);
 
+            ulong d = 0UL;
+            int zzPos = 2;
+
             for (int i = 1; i < len; ++i)
             {
-                c = SquareWordAdd(x, i, zz);
-                AddWordAt(extLen, c, zz, i << 1);
+                d += SquareWordAddTo(x, i, zz);
+                d += zz[zzPos];
+                zz[zzPos++] = (uint)d; d >>= 32;
+                d += zz[zzPos];
+                zz[zzPos++] = (uint)d; d >>= 32;
             }
+            Debug.Assert(0UL == d);
 
             ShiftUpBit(extLen, zz, x[0] << 31);
         }
@@ -910,15 +984,23 @@ namespace Org.BouncyCastle.Math.Raw
             }
             while (j > 0);
 
+            ulong d = 0UL;
+            int zzPos = zzOff + 2;
+
             for (int i = 1; i < len; ++i)
             {
-                c = SquareWordAdd(x, xOff, i, zz, zzOff);
-                AddWordAt(extLen, c, zz, zzOff, i << 1);
+                d += SquareWordAddTo(x, xOff, i, zz, zzOff);
+                d += zz[zzPos];
+                zz[zzPos++] = (uint)d; d >>= 32;
+                d += zz[zzPos];
+                zz[zzPos++] = (uint)d; d >>= 32;
             }
+            Debug.Assert(0UL == d);
 
             ShiftUpBit(extLen, zz, zzOff, x[xOff] << 31);
         }
 
+        [Obsolete("Use 'SquareWordAddTo' instead")]
         public static uint SquareWordAdd(uint[] x, int xPos, uint[] z)
         {
             ulong c = 0, xVal = (ulong)x[xPos];
@@ -933,6 +1015,7 @@ namespace Org.BouncyCastle.Math.Raw
             return (uint)c;
         }
 
+        [Obsolete("Use 'SquareWordAddTo' instead")]
         public static uint SquareWordAdd(uint[] x, int xOff, int xPos, uint[] z, int zOff)
         {
             ulong c = 0, xVal = (ulong)x[xOff + xPos];
@@ -948,6 +1031,35 @@ namespace Org.BouncyCastle.Math.Raw
             return (uint)c;
         }
 
+        public static uint SquareWordAddTo(uint[] x, int xPos, uint[] z)
+        {
+            ulong c = 0, xVal = (ulong)x[xPos];
+            int i = 0;
+            do
+            {
+                c += xVal * x[i] + z[xPos + i];
+                z[xPos + i] = (uint)c;
+                c >>= 32;
+            }
+            while (++i < xPos);
+            return (uint)c;
+        }
+
+        public static uint SquareWordAddTo(uint[] x, int xOff, int xPos, uint[] z, int zOff)
+        {
+            ulong c = 0, xVal = (ulong)x[xOff + xPos];
+            int i = 0;
+            do
+            {
+                c += xVal * (x[xOff + i] & M) + (z[xPos + zOff] & M);
+                z[xPos + zOff] = (uint)c;
+                c >>= 32;
+                ++zOff;
+            }
+            while (++i < xPos);
+            return (uint)c;
+        }
+
         public static int Sub(int len, uint[] x, uint[] y, uint[] z)
         {
             long c = 0;
diff --git a/crypto/src/math/raw/Nat128.cs b/crypto/src/math/raw/Nat128.cs
index 27ed5abe4..7617a9ee9 100644
--- a/crypto/src/math/raw/Nat128.cs
+++ b/crypto/src/math/raw/Nat128.cs
@@ -422,9 +422,10 @@ namespace Org.BouncyCastle.Math.Raw
                 c += x_i * y_3 + zz[i + 3];
                 zz[i + 3] = (uint)c;
                 c >>= 32;
-                c += zc + zz[i + 4];
-                zz[i + 4] = (uint)c;
-                zc = c >> 32;
+
+                zc += c + zz[i + 4];
+                zz[i + 4] = (uint)zc;
+                zc >>= 32;
             }
             return (uint)zc;
         }
@@ -452,9 +453,10 @@ namespace Org.BouncyCastle.Math.Raw
                 c += x_i * y_3 + zz[zzOff + 3];
                 zz[zzOff + 3] = (uint)c;
                 c >>= 32;
-                c += zc + zz[zzOff + 4];
-                zz[zzOff + 4] = (uint)c;
-                zc = c >> 32;
+
+                zc += c + zz[zzOff + 4];
+                zz[zzOff + 4] = (uint)zc;
+                zc >>= 32;
                 ++zzOff;
             }
             return (uint)zc;
diff --git a/crypto/src/math/raw/Nat160.cs b/crypto/src/math/raw/Nat160.cs
index 57212cae0..f5514d7b4 100644
--- a/crypto/src/math/raw/Nat160.cs
+++ b/crypto/src/math/raw/Nat160.cs
@@ -384,9 +384,10 @@ namespace Org.BouncyCastle.Math.Raw
                 c += x_i * y_4 + zz[i + 4];
                 zz[i + 4] = (uint)c;
                 c >>= 32;
-                c += zc + zz[i + 5];
-                zz[i + 5] = (uint)c;
-                zc = c >> 32;
+
+                zc += c + zz[i + 5];
+                zz[i + 5] = (uint)zc;
+                zc >>= 32;
             }
             return (uint)zc;
         }
@@ -418,9 +419,10 @@ namespace Org.BouncyCastle.Math.Raw
                 c += x_i * y_4 + zz[zzOff + 4];
                 zz[zzOff + 4] = (uint)c;
                 c >>= 32;
-                c += zc + zz[zzOff + 5];
-                zz[zzOff + 5] = (uint)c;
-                zc = c >> 32;
+
+                zc += c + zz[zzOff + 5];
+                zz[zzOff + 5] = (uint)zc;
+                zc >>= 32;
                 ++zzOff;
             }
             return (uint)zc;
diff --git a/crypto/src/math/raw/Nat192.cs b/crypto/src/math/raw/Nat192.cs
index 06c75aa54..1311dee04 100644
--- a/crypto/src/math/raw/Nat192.cs
+++ b/crypto/src/math/raw/Nat192.cs
@@ -498,9 +498,10 @@ namespace Org.BouncyCastle.Math.Raw
                 c += x_i * y_5 + zz[i + 5];
                 zz[i + 5] = (uint)c;
                 c >>= 32;
-                c += zc + zz[i + 6];
-                zz[i + 6] = (uint)c;
-                zc = c >> 32;
+
+                zc += c + zz[i + 6];
+                zz[i + 6] = (uint)zc;
+                zc >>= 32;
             }
             return (uint)zc;
         }
@@ -536,9 +537,10 @@ namespace Org.BouncyCastle.Math.Raw
                 c += x_i * y_5 + zz[zzOff + 5];
                 zz[zzOff + 5] = (uint)c;
                 c >>= 32;
-                c += zc + zz[zzOff + 6];
-                zz[zzOff + 6] = (uint)c;
-                zc = c >> 32;
+
+                zc += c + zz[zzOff + 6];
+                zz[zzOff + 6] = (uint)zc;
+                zc >>= 32;
                 ++zzOff;
             }
             return (uint)zc;
diff --git a/crypto/src/math/raw/Nat224.cs b/crypto/src/math/raw/Nat224.cs
index ff1eb6306..565abcb9c 100644
--- a/crypto/src/math/raw/Nat224.cs
+++ b/crypto/src/math/raw/Nat224.cs
@@ -509,9 +509,10 @@ namespace Org.BouncyCastle.Math.Raw
                 c += x_i * y_6 + zz[i + 6];
                 zz[i + 6] = (uint)c;
                 c >>= 32;
-                c += zc + zz[i + 7];
-                zz[i + 7] = (uint)c;
-                zc = c >> 32;
+
+                zc += c + zz[i + 7];
+                zz[i + 7] = (uint)zc;
+                zc >>= 32;
             }
             return (uint)zc;
         }
@@ -551,9 +552,10 @@ namespace Org.BouncyCastle.Math.Raw
                 c += x_i * y_6 + zz[zzOff + 6];
                 zz[zzOff + 6] = (uint)c;
                 c >>= 32;
-                c += zc + zz[zzOff + 7];
-                zz[zzOff + 7] = (uint)c;
-                zc = c >> 32;
+
+                zc += c + zz[zzOff + 7];
+                zz[zzOff + 7] = (uint)zc;
+                zc >>= 32;
                 ++zzOff;
             }
             return (uint)zc;
diff --git a/crypto/src/math/raw/Nat256.cs b/crypto/src/math/raw/Nat256.cs
index 2be03d642..5c473c405 100644
--- a/crypto/src/math/raw/Nat256.cs
+++ b/crypto/src/math/raw/Nat256.cs
@@ -632,9 +632,10 @@ namespace Org.BouncyCastle.Math.Raw
                 c += x_i * y_7 + zz[i + 7];
                 zz[i + 7] = (uint)c;
                 c >>= 32;
-                c += zc + zz[i + 8];
-                zz[i + 8] = (uint)c;
-                zc = c >> 32;
+
+                zc += c + zz[i + 8];
+                zz[i + 8] = (uint)zc;
+                zc >>= 32;
             }
             return (uint)zc;
         }
@@ -678,9 +679,10 @@ namespace Org.BouncyCastle.Math.Raw
                 c += x_i * y_7 + zz[zzOff + 7];
                 zz[zzOff + 7] = (uint)c;
                 c >>= 32;
-                c += zc + zz[zzOff + 8];
-                zz[zzOff + 8] = (uint)c;
-                zc = c >> 32;
+
+                zc += c + zz[zzOff + 8];
+                zz[zzOff + 8] = (uint)zc;
+                zc >>= 32;
                 ++zzOff;
             }
             return (uint)zc;
diff --git a/crypto/src/ocsp/BasicOCSPResp.cs b/crypto/src/ocsp/BasicOCSPResp.cs
index 63ab8921e..e79d556bd 100644
--- a/crypto/src/ocsp/BasicOCSPResp.cs
+++ b/crypto/src/ocsp/BasicOCSPResp.cs
@@ -54,7 +54,7 @@ namespace Org.BouncyCastle.Ocsp
 
 		public int Version
 		{
-			get { return data.Version.Value.IntValue + 1; }
+            get { return data.Version.IntValueExact + 1; }
 		}
 
 		public RespID ResponderId
diff --git a/crypto/src/ocsp/OCSPReq.cs b/crypto/src/ocsp/OCSPReq.cs
index 0cd95c6d6..5408f068f 100644
--- a/crypto/src/ocsp/OCSPReq.cs
+++ b/crypto/src/ocsp/OCSPReq.cs
@@ -103,7 +103,7 @@ namespace Org.BouncyCastle.Ocsp
 
 		public int Version
 		{
-			get { return req.TbsRequest.Version.Value.IntValue + 1; }
+            get { return req.TbsRequest.Version.IntValueExact + 1; }
 		}
 
 		public GeneralName RequestorName
diff --git a/crypto/src/ocsp/OCSPResp.cs b/crypto/src/ocsp/OCSPResp.cs
index dc99c6a9a..1e65b2f7a 100644
--- a/crypto/src/ocsp/OCSPResp.cs
+++ b/crypto/src/ocsp/OCSPResp.cs
@@ -43,7 +43,7 @@ namespace Org.BouncyCastle.Ocsp
 
 		public int Status
 		{
-			get { return this.resp.ResponseStatus.Value.IntValue; }
+            get { return this.resp.ResponseStatus.IntValueExact; }
 		}
 
 		public object GetResponseObject()
diff --git a/crypto/src/ocsp/RespData.cs b/crypto/src/ocsp/RespData.cs
index 105726ca7..7ec0e4b68 100644
--- a/crypto/src/ocsp/RespData.cs
+++ b/crypto/src/ocsp/RespData.cs
@@ -21,7 +21,7 @@ namespace Org.BouncyCastle.Ocsp
 
 		public int Version
 		{
-			get { return data.Version.Value.IntValue + 1; }
+            get { return data.Version.IntValueExact + 1; }
 		}
 
 		public RespID GetResponderId()
diff --git a/crypto/src/ocsp/RevokedStatus.cs b/crypto/src/ocsp/RevokedStatus.cs
index 6e5ad1b26..edbeb57da 100644
--- a/crypto/src/ocsp/RevokedStatus.cs
+++ b/crypto/src/ocsp/RevokedStatus.cs
@@ -51,7 +51,7 @@ namespace Org.BouncyCastle.Ocsp
 					throw new InvalidOperationException("attempt to get a reason where none is available");
 				}
 
-				return info.RevocationReason.Value.IntValue;
+                return info.RevocationReason.IntValueExact;
 			}
 		}
 	}
diff --git a/crypto/src/pkix/Rfc3280CertPathUtilities.cs b/crypto/src/pkix/Rfc3280CertPathUtilities.cs
index cdb69b7e0..c703194a4 100644
--- a/crypto/src/pkix/Rfc3280CertPathUtilities.cs
+++ b/crypto/src/pkix/Rfc3280CertPathUtilities.cs
@@ -1620,7 +1620,7 @@ namespace Org.BouncyCastle.Pkix
 						Asn1TaggedObject constraint = Asn1TaggedObject.GetInstance(policyConstraints.Current);
 						if (constraint.TagNo == 0)
 						{
-							tmpInt = DerInteger.GetInstance(constraint, false).Value.IntValue;
+                            tmpInt = DerInteger.GetInstance(constraint, false).IntValueExact;
 							if (tmpInt < explicitPolicy)
 							{
 								return tmpInt;
@@ -1675,7 +1675,7 @@ namespace Org.BouncyCastle.Pkix
 						Asn1TaggedObject constraint = Asn1TaggedObject.GetInstance(policyConstraints.Current);
 						if (constraint.TagNo == 1)
 						{
-							tmpInt = DerInteger.GetInstance(constraint, false).Value.IntValue;
+                            tmpInt = DerInteger.GetInstance(constraint, false).IntValueExact;
 							if (tmpInt < policyMapping)
 							{
 								return tmpInt;
@@ -1789,7 +1789,7 @@ namespace Org.BouncyCastle.Pkix
 
 			if (iap != null)
 			{
-				int _inhibitAnyPolicy = iap.Value.IntValue;
+                int _inhibitAnyPolicy = iap.IntValueExact;
 
 				if (_inhibitAnyPolicy < inhibitAnyPolicy)
 					return _inhibitAnyPolicy;
@@ -2062,7 +2062,7 @@ namespace Org.BouncyCastle.Pkix
 						case 0:
 							try
 							{
-								tmpInt = DerInteger.GetInstance(constraint, false).Value.IntValue;
+                                tmpInt = DerInteger.GetInstance(constraint, false).IntValueExact;
 							}
 							catch (Exception e)
 							{
diff --git a/crypto/src/security/PrivateKeyFactory.cs b/crypto/src/security/PrivateKeyFactory.cs
index f7709160d..ddcb88992 100644
--- a/crypto/src/security/PrivateKeyFactory.cs
+++ b/crypto/src/security/PrivateKeyFactory.cs
@@ -213,18 +213,9 @@ namespace Org.BouncyCastle.Security
                     }
                     else
                     {
-                        byte[] encVal = Asn1OctetString.GetInstance(privKey).GetOctets();
-                        byte[] dVal = new byte[encVal.Length];
-
-                        for (int i = 0; i != encVal.Length; i++)
-                        {
-                            dVal[i] = encVal[encVal.Length - 1 - i];
-                        }
-
+                        byte[] dVal = Arrays.Reverse(Asn1OctetString.GetInstance(privKey).GetOctets());
                         d = new BigInteger(1, dVal);
                     }
-
-
                 }
                 else
                 {
diff --git a/crypto/src/security/PublicKeyFactory.cs b/crypto/src/security/PublicKeyFactory.cs
index 7a34d71df..7b19f1c0f 100644
--- a/crypto/src/security/PublicKeyFactory.cs
+++ b/crypto/src/security/PublicKeyFactory.cs
@@ -17,6 +17,7 @@ using Org.BouncyCastle.Crypto.Generators;
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.Encoders;
 
 namespace Org.BouncyCastle.Security
@@ -56,7 +57,7 @@ namespace Org.BouncyCastle.Security
                 || algOid.Equals(PkcsObjectIdentifiers.IdRsaesOaep))
             {
                 RsaPublicKeyStructure pubKey = RsaPublicKeyStructure.GetInstance(
-                    keyInfo.GetPublicKey());
+                    keyInfo.ParsePublicKey());
 
                 return new RsaKeyParameters(false, pubKey.Modulus, pubKey.PublicExponent);
             }
@@ -64,7 +65,7 @@ namespace Org.BouncyCastle.Security
             {
                 Asn1Sequence seq = Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object());
 
-                DHPublicKey dhPublicKey = DHPublicKey.GetInstance(keyInfo.GetPublicKey());
+                DHPublicKey dhPublicKey = DHPublicKey.GetInstance(keyInfo.ParsePublicKey());
 
                 BigInteger y = dhPublicKey.Y.Value;
 
@@ -101,7 +102,7 @@ namespace Org.BouncyCastle.Security
             {
                 Asn1Sequence seq = Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object());
 
-                DerInteger derY = (DerInteger) keyInfo.GetPublicKey();
+                DerInteger derY = (DerInteger)keyInfo.ParsePublicKey();
 
                 return ReadPkcsDHParam(algOid, derY.Value, seq);
             }
@@ -109,7 +110,7 @@ namespace Org.BouncyCastle.Security
             {
                 ElGamalParameter para = new ElGamalParameter(
                     Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
-                DerInteger derY = (DerInteger) keyInfo.GetPublicKey();
+                DerInteger derY = (DerInteger)keyInfo.ParsePublicKey();
 
                 return new ElGamalPublicKeyParameters(
                     derY.Value,
@@ -118,7 +119,7 @@ namespace Org.BouncyCastle.Security
             else if (algOid.Equals(X9ObjectIdentifiers.IdDsa)
                 || algOid.Equals(OiwObjectIdentifiers.DsaWithSha1))
             {
-                DerInteger derY = (DerInteger) keyInfo.GetPublicKey();
+                DerInteger derY = (DerInteger)keyInfo.ParsePublicKey();
                 Asn1Encodable ae = algID.Parameters;
 
                 DsaParameters parameters = null;
@@ -158,64 +159,57 @@ namespace Org.BouncyCastle.Security
             }
             else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x2001))
             {
-                Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters(
-                    (Asn1Sequence) algID.Parameters);
+                Gost3410PublicKeyAlgParameters gostParams = Gost3410PublicKeyAlgParameters.GetInstance(algID.Parameters);
+                DerObjectIdentifier publicKeyParamSet = gostParams.PublicKeyParamSet;
+
+                ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(publicKeyParamSet);
+                if (ecP == null)
+                    return null;
 
                 Asn1OctetString key;
                 try
                 {
-                    key = (Asn1OctetString) keyInfo.GetPublicKey();
+                    key = (Asn1OctetString)keyInfo.ParsePublicKey();
                 }
-                catch (IOException)
+                catch (IOException e)
                 {
-                    throw new ArgumentException("invalid info structure in GOST3410 public key");
+                    throw new ArgumentException("error recovering GOST3410_2001 public key", e);
                 }
 
-                byte[] keyEnc = key.GetOctets();
-                byte[] x = new byte[32];
-                byte[] y = new byte[32];
+                int fieldSize = 32;
+                int keySize = 2 * fieldSize;
 
-                for (int i = 0; i != y.Length; i++)
-                {
-                    x[i] = keyEnc[32 - 1 - i];
-                }
+                byte[] keyEnc = key.GetOctets();
+                if (keyEnc.Length != keySize)
+                    throw new ArgumentException("invalid length for GOST3410_2001 public key");
 
-                for (int i = 0; i != x.Length; i++)
+                byte[] x9Encoding = new byte[1 + keySize];
+                x9Encoding[0] = 0x04;
+                for (int i = 1; i <= fieldSize; ++i)
                 {
-                    y[i] = keyEnc[64 - 1 - i];
+                    x9Encoding[i] = keyEnc[fieldSize - i];
+                    x9Encoding[i + fieldSize] = keyEnc[keySize - i];
                 }
 
-                ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet);
-
-                if (ecP == null)
-                    return null;
-
-                ECPoint q = ecP.Curve.CreatePoint(new BigInteger(1, x), new BigInteger(1, y));
+                ECPoint q = ecP.Curve.DecodePoint(x9Encoding);
 
-                return new ECPublicKeyParameters("ECGOST3410", q, gostParams.PublicKeyParamSet);
+                return new ECPublicKeyParameters("ECGOST3410", q, publicKeyParamSet);
             }
             else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x94))
             {
-                Gost3410PublicKeyAlgParameters algParams = new Gost3410PublicKeyAlgParameters(
-                    (Asn1Sequence) algID.Parameters);
+                Gost3410PublicKeyAlgParameters algParams = Gost3410PublicKeyAlgParameters.GetInstance(algID.Parameters);
 
-                DerOctetString derY;
+                Asn1OctetString key;
                 try
                 {
-                    derY = (DerOctetString) keyInfo.GetPublicKey();
+                    key = (Asn1OctetString)keyInfo.ParsePublicKey();
                 }
-                catch (IOException)
+                catch (IOException e)
                 {
-                    throw new ArgumentException("invalid info structure in GOST3410 public key");
+                    throw new ArgumentException("error recovering GOST3410_94 public key", e);
                 }
 
-                byte[] keyEnc = derY.GetOctets();
-                byte[] keyBytes = new byte[keyEnc.Length];
-
-                for (int i = 0; i != keyEnc.Length; i++)
-                {
-                    keyBytes[i] = keyEnc[keyEnc.Length - 1 - i]; // was little endian
-                }
+                byte[] keyBytes = Arrays.Reverse(key.GetOctets()); // was little endian
 
                 BigInteger y = new BigInteger(1, keyBytes);
 
@@ -236,21 +230,40 @@ namespace Org.BouncyCastle.Security
             else if (algOid.Equals(EdECObjectIdentifiers.id_Ed448))
             {
                 return new Ed448PublicKeyParameters(GetRawKey(keyInfo, Ed448PublicKeyParameters.KeySize), 0);
-            } else if (
-                algOid.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256) ||
-                algOid.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512))
+            }
+            else if (algOid.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256)
+                ||   algOid.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512))
             {
+                Gost3410PublicKeyAlgParameters gostParams = Gost3410PublicKeyAlgParameters.GetInstance(algID.Parameters);
+                DerObjectIdentifier publicKeyParamSet = gostParams.PublicKeyParamSet;
 
-                byte[] keyEnc = ((DerOctetString)Asn1Object.FromByteArray(keyInfo.PublicKeyData.GetOctets())).str;
+                ECGost3410Parameters ecDomainParameters =new ECGost3410Parameters(
+                    new ECNamedDomainParameters(publicKeyParamSet, ECGost3410NamedCurves.GetByOid(publicKeyParamSet)),
+                    publicKeyParamSet,
+                    gostParams.DigestParamSet,
+                    gostParams.EncryptionParamSet);
+
+                Asn1OctetString key;
+                try
+                {
+                    key = (Asn1OctetString)keyInfo.ParsePublicKey();
+                }
+                catch (IOException e)
+                {
+                    throw new ArgumentException("error recovering GOST3410_2012 public key", e);
+                }
 
                 int fieldSize = 32;
                 if (algOid.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512))
                 {
                     fieldSize = 64;
                 }
-
                 int keySize = 2 * fieldSize;
 
+                byte[] keyEnc = key.GetOctets();
+                if (keyEnc.Length != keySize)
+                    throw new ArgumentException("invalid length for GOST3410_2012 public key");
+
                 byte[] x9Encoding = new byte[1 + keySize];
                 x9Encoding[0] = 0x04;
                 for (int i = 1; i <= fieldSize; ++i)
@@ -259,17 +272,9 @@ namespace Org.BouncyCastle.Security
                     x9Encoding[i + fieldSize] = keyEnc[keySize - i];
                 }
 
-                Gost3410PublicKeyAlgParameters gostParams = Gost3410PublicKeyAlgParameters.GetInstance(keyInfo.AlgorithmID.Parameters);
-
-                ECGost3410Parameters ecDomainParameters =
-                    new ECGost3410Parameters(
-                        new ECNamedDomainParameters(gostParams.PublicKeyParamSet, ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet)),
-                        gostParams.PublicKeyParamSet,
-                        gostParams.DigestParamSet,
-                        gostParams.EncryptionParamSet);
-              
-                return new ECPublicKeyParameters(ecDomainParameters.Curve.DecodePoint(x9Encoding), ecDomainParameters);
+                ECPoint q = ecDomainParameters.Curve.DecodePoint(x9Encoding);
 
+                return new ECPublicKeyParameters(q, ecDomainParameters);
             }
             else
             {
diff --git a/crypto/src/tsp/GenTimeAccuracy.cs b/crypto/src/tsp/GenTimeAccuracy.cs
index 8a2f29989..400bf6f9e 100644
--- a/crypto/src/tsp/GenTimeAccuracy.cs
+++ b/crypto/src/tsp/GenTimeAccuracy.cs
@@ -22,7 +22,7 @@ namespace Org.BouncyCastle.Tsp
 		private int GetTimeComponent(
 			DerInteger time)
 		{
-			return time == null ? 0 : time.Value.IntValue;
+            return time == null ? 0 : time.IntValueExact;
 		}
 
 		public override string ToString()
diff --git a/crypto/src/tsp/TimeStampRequest.cs b/crypto/src/tsp/TimeStampRequest.cs
index 0b41adef7..f5c6a09e6 100644
--- a/crypto/src/tsp/TimeStampRequest.cs
+++ b/crypto/src/tsp/TimeStampRequest.cs
@@ -72,7 +72,7 @@ namespace Org.BouncyCastle.Tsp
 
 		public int Version
 		{
-			get { return req.Version.Value.IntValue; }
+            get { return req.Version.IntValueExact; }
 		}
 
 		public string MessageImprintAlgOid
diff --git a/crypto/src/util/Arrays.cs b/crypto/src/util/Arrays.cs
index aa8d31df4..7b060bf3c 100644
--- a/crypto/src/util/Arrays.cs
+++ b/crypto/src/util/Arrays.cs
@@ -366,35 +366,23 @@ namespace Org.BouncyCastle.Utilities
             return hc;
         }
 
-        public static byte[] Clone(
-            byte[] data)
+        public static bool[] Clone(bool[] data)
         {
-            return data == null ? null : (byte[])data.Clone();
+            return data == null ? null : (bool[])data.Clone();
         }
 
-        public static byte[] Clone(
-            byte[] data, 
-            byte[] existing)
+        public static byte[] Clone(byte[] data)
         {
-            if (data == null)
-            {
-                return null;
-            }
-            if ((existing == null) || (existing.Length != data.Length))
-            {
-                return Clone(data);
-            }
-            Array.Copy(data, 0, existing, 0, existing.Length);
-            return existing;
+            return data == null ? null : (byte[])data.Clone();
         }
 
-        public static int[] Clone(
-            int[] data)
+        public static int[] Clone(int[] data)
         {
             return data == null ? null : (int[])data.Clone();
         }
 
-        internal static uint[] Clone(uint[] data)
+        [CLSCompliantAttribute(false)]
+        public static uint[] Clone(uint[] data)
         {
             return data == null ? null : (uint[])data.Clone();
         }
@@ -405,25 +393,28 @@ namespace Org.BouncyCastle.Utilities
         }
 
         [CLSCompliantAttribute(false)]
-        public static ulong[] Clone(
-            ulong[] data)
+        public static ulong[] Clone(ulong[] data)
         {
-            return data == null ? null : (ulong[]) data.Clone();
+            return data == null ? null : (ulong[])data.Clone();
+        }
+
+        public static byte[] Clone(byte[] data, byte[] existing)
+        {
+            if (data == null)
+                return null;
+            if (existing == null || existing.Length != data.Length)
+                return Clone(data);
+            Array.Copy(data, 0, existing, 0, existing.Length);
+            return existing;
         }
 
         [CLSCompliantAttribute(false)]
-        public static ulong[] Clone(
-            ulong[] data, 
-            ulong[] existing)
+        public static ulong[] Clone(ulong[] data, ulong[] existing)
         {
             if (data == null)
-            {
                 return null;
-            }
-            if ((existing == null) || (existing.Length != data.Length))
-            {
+            if (existing == null || existing.Length != data.Length)
                 return Clone(data);
-            }
             Array.Copy(data, 0, existing, 0, existing.Length);
             return existing;
         }
@@ -721,5 +712,19 @@ namespace Org.BouncyCastle.Utilities
 
             return result;
         }
+
+        public static bool IsNullOrContainsNull(object[] array)
+        {
+            if (null == array)
+                return true;
+
+            int count = array.Length;
+            for (int i = 0; i < count; ++i)
+            {
+                if (null == array[i])
+                    return true;
+            }
+            return false;
+        }
     }
 }
diff --git a/crypto/src/util/Integers.cs b/crypto/src/util/Integers.cs
index e746b0ef4..bd05a053e 100644
--- a/crypto/src/util/Integers.cs
+++ b/crypto/src/util/Integers.cs
@@ -4,6 +4,21 @@ namespace Org.BouncyCastle.Utilities
 {
     public abstract class Integers
     {
+        public static int NumberOfLeadingZeros(int i)
+        {
+            if (i <= 0)
+                return (~i >> (31 - 5)) & (1 << 5);
+
+            uint u = (uint)i;
+            int n = 1;
+            if (0 == (u >> 16)) { n += 16; u <<= 16; }
+            if (0 == (u >> 24)) { n +=  8; u <<=  8; }
+            if (0 == (u >> 28)) { n +=  4; u <<=  4; }
+            if (0 == (u >> 30)) { n +=  2; u <<=  2; }
+            n -= (int)(u >> 31);
+            return n;
+        }
+
         public static int RotateLeft(int i, int distance)
         {
             return (i << distance) ^ (int)((uint)i >> -distance);
diff --git a/crypto/src/util/collections/CollectionUtilities.cs b/crypto/src/util/collections/CollectionUtilities.cs
index cac158226..e0c79bdf4 100644
--- a/crypto/src/util/collections/CollectionUtilities.cs
+++ b/crypto/src/util/collections/CollectionUtilities.cs
@@ -49,23 +49,18 @@ namespace Org.BouncyCastle.Utilities.Collections
 
         public static string ToString(IEnumerable c)
         {
-            StringBuilder sb = new StringBuilder("[");
-
             IEnumerator e = c.GetEnumerator();
+            if (!e.MoveNext())
+                return "[]";
 
-            if (e.MoveNext())
+            StringBuilder sb = new StringBuilder("[");
+            sb.Append(e.Current.ToString());
+            while (e.MoveNext())
             {
+                sb.Append(", ");
                 sb.Append(e.Current.ToString());
-
-                while (e.MoveNext())
-                {
-                    sb.Append(", ");
-                    sb.Append(e.Current.ToString());
-                }
             }
-
             sb.Append(']');
-
             return sb.ToString();
         }
     }
diff --git a/crypto/src/x509/AttributeCertificateHolder.cs b/crypto/src/x509/AttributeCertificateHolder.cs
index 04460cd59..8ea90c24d 100644
--- a/crypto/src/x509/AttributeCertificateHolder.cs
+++ b/crypto/src/x509/AttributeCertificateHolder.cs
@@ -128,8 +128,8 @@ namespace Org.BouncyCastle.X509
 				ObjectDigestInfo odi = holder.ObjectDigestInfo;
 
 				return odi == null
-					?	-1
-					:	odi.DigestedObjectType.Value.IntValue;
+					?   -1
+                    :   odi.DigestedObjectType.IntValueExact;
 			}
 		}
 
diff --git a/crypto/src/x509/X509Certificate.cs b/crypto/src/x509/X509Certificate.cs
index 6f2f40411..fd156e487 100644
--- a/crypto/src/x509/X509Certificate.cs
+++ b/crypto/src/x509/X509Certificate.cs
@@ -32,8 +32,11 @@ namespace Org.BouncyCastle.X509
 		private readonly BasicConstraints basicConstraints;
 		private readonly bool[] keyUsage;
 
-		private bool hashValueSet;
-		private int hashValue;
+        private readonly object cacheLock = new object();
+        private AsymmetricKeyParameter publicKeyValue;
+
+		private volatile bool hashValueSet;
+        private volatile int hashValue;
 
 		protected X509Certificate()
 		{
@@ -295,7 +298,7 @@ namespace Org.BouncyCastle.X509
 		/// </summary>
 		public virtual bool[] GetKeyUsage()
 		{
-			return keyUsage == null ? null : (bool[]) keyUsage.Clone();
+            return Arrays.Clone(keyUsage);
 		}
 
 		// TODO Replace with something that returns a list of DerObjectIdentifier
@@ -387,7 +390,24 @@ namespace Org.BouncyCastle.X509
 		/// <returns>The public key parameters.</returns>
 		public virtual AsymmetricKeyParameter GetPublicKey()
 		{
-			return PublicKeyFactory.CreateKey(c.SubjectPublicKeyInfo);
+            // Cache the public key to support repeated-use optimizations
+            lock (cacheLock)
+            {
+                if (null != publicKeyValue)
+                    return publicKeyValue;
+            }
+
+			AsymmetricKeyParameter temp = PublicKeyFactory.CreateKey(c.SubjectPublicKeyInfo);
+
+            lock (cacheLock)
+            {
+                if (null == publicKeyValue)
+                {
+                    publicKeyValue = temp;
+                }
+
+                return publicKeyValue;
+            }
 		}
 
 		/// <summary>
@@ -399,35 +419,40 @@ namespace Org.BouncyCastle.X509
 			return c.GetDerEncoded();
 		}
 
-		public override bool Equals(
-			object obj)
+        public override bool Equals(object other)
 		{
-			if (obj == this)
+			if (this == other)
 				return true;
 
-			X509Certificate other = obj as X509Certificate;
-
-			if (other == null)
+			X509Certificate that = other as X509Certificate;
+			if (null == that)
 				return false;
 
-			return c.Equals(other.c);
+            if (this.hashValueSet && that.hashValueSet)
+            {
+                if (this.hashValue != that.hashValue)
+                    return false;
+            }
+            else if (!this.c.Signature.Equals(that.c.Signature))
+            {
+                return false;
+            }
+
+			return this.c.Equals(that.c);
 
 			// NB: May prefer this implementation of Equals if more than one certificate implementation in play
-//			return Arrays.AreEqual(this.GetEncoded(), other.GetEncoded());
+            //return Arrays.AreEqual(this.GetEncoded(), that.GetEncoded());
 		}
 
 		public override int GetHashCode()
 		{
-			lock (this)
+			if (!hashValueSet)
 			{
-				if (!hashValueSet)
-				{
-					hashValue = c.GetHashCode();
-					hashValueSet = true;
-				}
+				hashValue = this.c.GetHashCode();
+				hashValueSet = true;
 			}
 
-			return hashValue;
+            return hashValue;
 		}
 
 //		public void setBagAttribute(
diff --git a/crypto/src/x509/X509Crl.cs b/crypto/src/x509/X509Crl.cs
index ecfb14132..8903e69d0 100644
--- a/crypto/src/x509/X509Crl.cs
+++ b/crypto/src/x509/X509Crl.cs
@@ -6,6 +6,7 @@ using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.Utilities;
 using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Operators;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Security;
 using Org.BouncyCastle.Security.Certificates;
@@ -14,7 +15,6 @@ using Org.BouncyCastle.Utilities.Collections;
 using Org.BouncyCastle.Utilities.Date;
 using Org.BouncyCastle.Utilities.Encoders;
 using Org.BouncyCastle.X509.Extension;
-using Org.BouncyCastle.Crypto.Operators;
 
 namespace Org.BouncyCastle.X509
 {
@@ -36,6 +36,9 @@ namespace Org.BouncyCastle.X509
 		private readonly byte[] sigAlgParams;
 		private readonly bool isIndirect;
 
+        private volatile bool hashValueSet;
+        private volatile int hashValue;
+
 		public X509Crl(
 			CertificateList c)
 		{
@@ -229,27 +232,41 @@ namespace Org.BouncyCastle.X509
 			return Arrays.Clone(sigAlgParams);
 		}
 
-		public override bool Equals(
-			object obj)
+		public override bool Equals(object other)
 		{
-			if (obj == this)
-				return true;
+            if (this == other)
+                return true;
 
-			X509Crl other = obj as X509Crl;
+            X509Crl that = other as X509Crl;
+            if (null == that)
+                return false;
 
-			if (other == null)
-				return false;
+            if (this.hashValueSet && that.hashValueSet)
+            {
+                if (this.hashValue != that.hashValue)
+                    return false;
+            }
+            else if (!this.c.Signature.Equals(that.c.Signature))
+            {
+                return false;
+            }
 
-			return c.Equals(other.c);
+            return this.c.Equals(that.c);
 
-			// NB: May prefer this implementation of Equals if more than one certificate implementation in play
-			//return Arrays.AreEqual(this.GetEncoded(), other.GetEncoded());
+            // NB: May prefer this implementation of Equals if more than one CRL implementation in play
+			//return Arrays.AreEqual(this.GetEncoded(), that.GetEncoded());
 		}
 
-		public override int GetHashCode()
-		{
-			return c.GetHashCode();
-		}
+        public override int GetHashCode()
+        {
+            if (!hashValueSet)
+            {
+                hashValue = this.c.GetHashCode();
+                hashValueSet = true;
+            }
+
+            return hashValue;
+        }
 
 		/**
 		 * Returns a string representation of this CRL.
diff --git a/crypto/src/x509/X509CrlEntry.cs b/crypto/src/x509/X509CrlEntry.cs
index caca29470..9e3608c18 100644
--- a/crypto/src/x509/X509CrlEntry.cs
+++ b/crypto/src/x509/X509CrlEntry.cs
@@ -1,6 +1,5 @@
 using System;
 using System.Collections;
-using System.IO;
 using System.Text;
 
 using Org.BouncyCastle.Asn1;
@@ -27,6 +26,9 @@ namespace Org.BouncyCastle.X509
 		private X509Name	previousCertificateIssuer;
 		private X509Name	certificateIssuer;
 
+        private volatile bool hashValueSet;
+        private volatile int hashValue;
+
 		public X509CrlEntry(
 			CrlEntry c)
 		{
@@ -132,6 +134,35 @@ namespace Org.BouncyCastle.X509
 			get { return c.Extensions != null; }
 		}
 
+        public override bool Equals(object other)
+        {
+            if (this == other)
+                return true;
+
+            X509CrlEntry that = other as X509CrlEntry;
+            if (null == that)
+                return false;
+
+            if (this.hashValueSet && that.hashValueSet)
+            {
+                if (this.hashValue != that.hashValue)
+                    return false;
+            }
+
+            return this.c.Equals(that.c);
+        }
+
+        public override int GetHashCode()
+        {
+            if (!hashValueSet)
+            {
+                hashValue = this.c.GetHashCode();
+                hashValueSet = true;
+            }
+
+            return hashValue;
+        }
+
 		public override string ToString()
 		{
 			StringBuilder buf = new StringBuilder();
diff --git a/crypto/src/x509/X509V2AttributeCertificate.cs b/crypto/src/x509/X509V2AttributeCertificate.cs
index c41b31239..1ceba101e 100644
--- a/crypto/src/x509/X509V2AttributeCertificate.cs
+++ b/crypto/src/x509/X509V2AttributeCertificate.cs
@@ -67,7 +67,7 @@ namespace Org.BouncyCastle.X509
 
 		public virtual int Version
 		{
-			get { return cert.ACInfo.Version.Value.IntValue + 1; }
+            get { return cert.ACInfo.Version.IntValueExact + 1; }
 		}
 
 		public virtual BigInteger SerialNumber
diff --git a/crypto/test/src/asn1/test/ASN1IntegerTest.cs b/crypto/test/src/asn1/test/ASN1IntegerTest.cs
index 0937a7844..355b408eb 100644
--- a/crypto/test/src/asn1/test/ASN1IntegerTest.cs
+++ b/crypto/test/src/asn1/test/ASN1IntegerTest.cs
@@ -48,7 +48,7 @@ namespace Org.BouncyCastle.Asn1.Tests
 
             new DerInteger(Hex.Decode("ffda47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b0e"));
 
-            new DerEnumerated(Hex.Decode("ffda47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b0e"));
+            new DerEnumerated(Hex.Decode("005a47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b0e"));
 
             SetAllowUnsafeProperty(false);
 
@@ -102,6 +102,17 @@ namespace Org.BouncyCastle.Asn1.Tests
             {
                 IsEquals("malformed enumerated", e.Message);
             }
+
+            try
+            {
+                new DerEnumerated(Hex.Decode("005a47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b0e"));
+
+                Fail("no exception");
+            }
+            catch (ArgumentException e)
+            {
+                IsEquals("malformed enumerated", e.Message);
+            }
 #endif
         }
 
@@ -173,7 +184,7 @@ namespace Org.BouncyCastle.Asn1.Tests
             try
             {
                 byte[] rawInt = Hex.Decode("FF81FF");
-                DerInteger i = new DerInteger(rawInt);
+                new DerInteger(rawInt);
                 Fail("Expecting illegal argument exception.");
             }
             catch (ArgumentException e)
@@ -212,7 +223,7 @@ namespace Org.BouncyCastle.Asn1.Tests
             try
             {
                 byte[] rawInt = Hex.Decode("FFFFFFFF01FF");
-                DerInteger i = new DerInteger(rawInt);
+                new DerInteger(rawInt);
                 Fail("Expecting illegal argument exception.");
             }
             catch (ArgumentException e)
@@ -235,7 +246,7 @@ namespace Org.BouncyCastle.Asn1.Tests
             {
                 SetAllowUnsafeProperty(true);
                 byte[] rawInt = Hex.Decode("0000000010FF");
-                DerInteger i = new DerInteger(rawInt);
+                new DerInteger(rawInt);
                 Fail("Expecting illegal argument exception.");
             }
             catch (ArgumentException e)
@@ -254,7 +265,7 @@ namespace Org.BouncyCastle.Asn1.Tests
             {
                 SetAllowUnsafeProperty(true);
                 byte[] rawInt = Hex.Decode("FFFFFFFF10FF");
-                DerInteger i = new DerInteger(rawInt);
+                new DerInteger(rawInt);
                 Fail("Expecting illegal argument exception.");
             }
             catch (ArgumentException e)
diff --git a/crypto/test/src/asn1/test/DeclarationOfMajorityUnitTest.cs b/crypto/test/src/asn1/test/DeclarationOfMajorityUnitTest.cs
index 37c6fb519..2097a68b6 100644
--- a/crypto/test/src/asn1/test/DeclarationOfMajorityUnitTest.cs
+++ b/crypto/test/src/asn1/test/DeclarationOfMajorityUnitTest.cs
@@ -20,11 +20,11 @@ namespace Org.BouncyCastle.Asn1.Tests
 			DerGeneralizedTime dateOfBirth = new DerGeneralizedTime("20070315173729Z");
 			DeclarationOfMajority decl = new DeclarationOfMajority(dateOfBirth);
 
-			checkConstruction(decl, DeclarationOfMajority.Choice.DateOfBirth, dateOfBirth, -1);
+			CheckConstruction(decl, DeclarationOfMajority.Choice.DateOfBirth, dateOfBirth, -1);
 
 			decl = new DeclarationOfMajority(6);
 
-			checkConstruction(decl, DeclarationOfMajority.Choice.NotYoungerThan, null, 6);
+			CheckConstruction(decl, DeclarationOfMajority.Choice.NotYoungerThan, null, 6);
 
 			decl = DeclarationOfMajority.GetInstance(null);
 
@@ -45,28 +45,24 @@ namespace Org.BouncyCastle.Asn1.Tests
 			}
 		}
 
-		private void checkConstruction(
+		private void CheckConstruction(
 			DeclarationOfMajority			decl,
 			DeclarationOfMajority.Choice	type,
 			DerGeneralizedTime				dateOfBirth,
 			int								notYoungerThan)
 		{
-			checkValues(decl, type, dateOfBirth, notYoungerThan);
+			CheckValues(decl, type, dateOfBirth, notYoungerThan);
 
 			decl = DeclarationOfMajority.GetInstance(decl);
 
-			checkValues(decl, type, dateOfBirth, notYoungerThan);
+			CheckValues(decl, type, dateOfBirth, notYoungerThan);
 
-			Asn1InputStream aIn = new Asn1InputStream(decl.ToAsn1Object().GetEncoded());
+            decl = DeclarationOfMajority.GetInstance(Asn1Object.FromByteArray(decl.GetEncoded()));
 
-			DerTaggedObject info = (DerTaggedObject) aIn.ReadObject();
-
-			decl = DeclarationOfMajority.GetInstance(info);
-
-			checkValues(decl, type, dateOfBirth, notYoungerThan);
+			CheckValues(decl, type, dateOfBirth, notYoungerThan);
 		}
 
-		private void checkValues(
+		private void CheckValues(
 			DeclarationOfMajority			decl,
 			DeclarationOfMajority.Choice	type,
 			DerGeneralizedTime				dateOfBirth,
diff --git a/crypto/test/src/asn1/test/LinkedCertificateTest.cs b/crypto/test/src/asn1/test/LinkedCertificateTest.cs
index 0eca5fda2..88ea5a07d 100644
--- a/crypto/test/src/asn1/test/LinkedCertificateTest.cs
+++ b/crypto/test/src/asn1/test/LinkedCertificateTest.cs
@@ -48,7 +48,7 @@ namespace Org.BouncyCastle.Asn1.Tests
 
                 Fail("getInstance() failed to detect bad object.");
             }
-            catch (ArgumentException e)
+            catch (ArgumentException)
             {
                 // expected
             }
diff --git a/crypto/test/src/asn1/test/MiscTest.cs b/crypto/test/src/asn1/test/MiscTest.cs
index 553a72ef4..d33a16a3e 100644
--- a/crypto/test/src/asn1/test/MiscTest.cs
+++ b/crypto/test/src/asn1/test/MiscTest.cs
@@ -46,7 +46,7 @@ namespace Org.BouncyCastle.Asn1.Tests
             }
             catch (ArgumentException e)
             {
-                IsTrue("wrong exc", "malformed integer".Equals(e.Message));
+                IsTrue("wrong exc", e.Message.StartsWith("malformed integer"));
             }
 
             try
@@ -55,7 +55,7 @@ namespace Org.BouncyCastle.Asn1.Tests
             }
             catch (ArgumentException e)
             {
-                IsTrue("wrong exc", "malformed integer".Equals(e.Message));
+                IsTrue("wrong exc", e.Message.StartsWith("malformed integer"));
             }
 
             try
@@ -64,7 +64,7 @@ namespace Org.BouncyCastle.Asn1.Tests
             }
             catch (ArgumentException e)
             {
-                IsTrue("wrong exc", "malformed enumerated".Equals(e.Message));
+                IsTrue("wrong exc", e.Message.StartsWith("malformed enumerated"));
             }
 
             try
@@ -73,7 +73,7 @@ namespace Org.BouncyCastle.Asn1.Tests
             }
             catch (ArgumentException e)
             {
-                IsTrue("wrong exc", "malformed enumerated".Equals(e.Message));
+                IsTrue("wrong exc", e.Message.StartsWith("malformed enumerated"));
             }
         }
 
diff --git a/crypto/test/src/cmp/test/ProtectedMessageTest.cs b/crypto/test/src/cmp/test/ProtectedMessageTest.cs
index 70bf670da..034463310 100644
--- a/crypto/test/src/cmp/test/ProtectedMessageTest.cs
+++ b/crypto/test/src/cmp/test/ProtectedMessageTest.cs
@@ -220,8 +220,9 @@ namespace Org.BouncyCastle.Cmp.Tests
             GeneralName sender = new GeneralName(new X509Name("CN=Sender"));
             GeneralName recipient = new GeneralName(new X509Name("CN=Recip"));
 
-            ProtectedPkiMessageBuilder msgBuilder = new ProtectedPkiMessageBuilder(sender, recipient);
-            msgBuilder.AddCmpCertificate(cert);
+            ProtectedPkiMessageBuilder msgBuilder = new ProtectedPkiMessageBuilder(sender, recipient)
+                .SetBody(new PkiBody(PkiBody.TYPE_INIT_REP, CertRepMessage.GetInstance(new DerSequence(new DerSequence()))))
+                .AddCmpCertificate(cert);
 
             ISignatureFactory sigFact = new Asn1SignatureFactory("MD5WithRSA", rsaKeyPair.Private);
 
@@ -254,8 +255,9 @@ namespace Org.BouncyCastle.Cmp.Tests
             GeneralName sender = new GeneralName(new X509Name("CN=Sender"));
             GeneralName recipient = new GeneralName(new X509Name("CN=Recip"));
 
-            ProtectedPkiMessageBuilder msgBuilder = new ProtectedPkiMessageBuilder(sender, recipient);
-            msgBuilder.AddCmpCertificate(cert);
+            ProtectedPkiMessageBuilder msgBuilder = new ProtectedPkiMessageBuilder(sender, recipient)
+                .SetBody(new PkiBody(PkiBody.TYPE_INIT_REP, CertRepMessage.GetInstance(new DerSequence(new DerSequence()))))
+                .AddCmpCertificate(cert);
 
             //
             // Default instance.
diff --git a/crypto/test/src/crypto/test/OAEPTest.cs b/crypto/test/src/crypto/test/OAEPTest.cs
index 781e92ba5..4903ea09b 100644
--- a/crypto/test/src/crypto/test/OAEPTest.cs
+++ b/crypto/test/src/crypto/test/OAEPTest.cs
@@ -310,7 +310,7 @@ namespace Org.BouncyCastle.Crypto.Tests
             //
             Asn1Object pubKeyObj = Asn1Object.FromByteArray(pubKeyEnc);
             RsaPublicKeyStructure pubStruct = RsaPublicKeyStructure.GetInstance(
-                SubjectPublicKeyInfo.GetInstance(pubKeyObj).GetPublicKey());
+                SubjectPublicKeyInfo.GetInstance(pubKeyObj).ParsePublicKey());
 
             //
             // extract the private key info.
diff --git a/crypto/test/src/crypto/test/SCryptTest.cs b/crypto/test/src/crypto/test/SCryptTest.cs
index ea9dda9b1..5d2cae8be 100644
--- a/crypto/test/src/crypto/test/SCryptTest.cs
+++ b/crypto/test/src/crypto/test/SCryptTest.cs
@@ -65,7 +65,7 @@ namespace Org.BouncyCastle.Crypto.Tests
                 SCrypt.Generate(pass, salt, N, r, p, len);
                 Fail(msg);
             }
-            catch (ArgumentException e)
+            catch (ArgumentException)
             {
                 //Console.Error.WriteLine(e.StackTrace);
             }
diff --git a/crypto/test/src/math/ec/test/ECPointTest.cs b/crypto/test/src/math/ec/test/ECPointTest.cs
index dbd739023..e1a2b8a6a 100644
--- a/crypto/test/src/math/ec/test/ECPointTest.cs
+++ b/crypto/test/src/math/ec/test/ECPointTest.cs
@@ -5,9 +5,11 @@ using NUnit.Framework;
 
 using Org.BouncyCastle.Asn1.X9;
 using Org.BouncyCastle.Crypto.EC;
+using Org.BouncyCastle.Math.EC.Multiplier;
 using Org.BouncyCastle.Security;
 using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Encoders;
 
 namespace Org.BouncyCastle.Math.EC.Tests
 {
@@ -399,10 +401,15 @@ namespace Org.BouncyCastle.Math.EC.Tests
             ImplTestMultiply(q, n.BitLength);
             ImplTestMultiply(infinity, n.BitLength);
 
+            int logSize = 32 - Integers.NumberOfLeadingZeros(curve.FieldSize - 1);
+            int rounds = System.Math.Max(2, System.Math.Min(10, 32 - 3 * logSize));
+
             ECPoint p = q;
-            for (int i = 0; i < 10; ++i)
+            for (int i = 0; ; )
             {
                 ImplTestEncoding(p);
+                if (++i == rounds)
+                    break;
                 p = p.Twice();
             }
         }
@@ -446,14 +453,42 @@ namespace Org.BouncyCastle.Math.EC.Tests
         {
             Assert.IsTrue(g.IsValid());
 
-            BigInteger h = c.Cofactor;
-            if (h != null && h.CompareTo(BigInteger.One) > 0)
+            if (ECAlgorithms.IsF2mCurve(c))
             {
-                if (ECAlgorithms.IsF2mCurve(c))
+                BigInteger h = c.Cofactor;
+                if (null != h)
                 {
-                    ECPoint order2 = c.CreatePoint(BigInteger.Zero, c.B.Sqrt().ToBigInteger());
-                    ECPoint bad = g.Add(order2);
-                    Assert.IsFalse(bad.IsValid());
+                    if (!h.TestBit(0))
+                    {
+                        ECFieldElement sqrtB = c.B.Sqrt();
+                        ECPoint order2 = c.CreatePoint(BigInteger.Zero, sqrtB.ToBigInteger());
+                        Assert.IsTrue(order2.Twice().IsInfinity);
+                        Assert.IsFalse(order2.IsValid());
+                        ECPoint bad2 = g.Add(order2);
+                        Assert.IsFalse(bad2.IsValid());
+                        ECPoint good2 = bad2.Add(order2);
+                        Assert.IsTrue(good2.IsValid());
+
+                        if (!h.TestBit(1))
+                        {
+                            ECFieldElement L = SolveQuadraticEquation(c, c.A);
+                            Assert.IsNotNull(L);
+                            ECFieldElement T = sqrtB;
+                            ECFieldElement x = T.Sqrt();
+                            ECFieldElement y = T.Add(x.Multiply(L));
+                            ECPoint order4 = c.CreatePoint(x.ToBigInteger(), y.ToBigInteger());
+                            Assert.IsTrue(order4.Twice().Equals(order2));
+                            Assert.IsFalse(order4.IsValid());
+                            ECPoint bad4_1 = g.Add(order4);
+                            Assert.IsFalse(bad4_1.IsValid());
+                            ECPoint bad4_2 = bad4_1.Add(order4);
+                            Assert.IsFalse(bad4_2.IsValid());
+                            ECPoint bad4_3 = bad4_2.Add(order4);
+                            Assert.IsFalse(bad4_3.IsValid());
+                            ECPoint good4 = bad4_3.Add(order4);
+                            Assert.IsTrue(good4.IsValid());
+                        }
+                    }
                 }
             }
         }
@@ -543,6 +578,55 @@ namespace Org.BouncyCastle.Math.EC.Tests
             }
         }
 
+        [Test]
+        public void TestExampleFpB0()
+        {
+            /*
+             * The supersingular curve y^2 = x^3 - 3.x (i.e. with 'B' == 0) from RFC 6508 2.1, with
+             * curve parameters from RFC 6509 Appendix A.
+             */
+            BigInteger p = FromHex(
+                  "997ABB1F0A563FDA65C61198DAD0657A"
+                + "416C0CE19CB48261BE9AE358B3E01A2E"
+                + "F40AAB27E2FC0F1B228730D531A59CB0"
+                + "E791B39FF7C88A19356D27F4A666A6D0"
+                + "E26C6487326B4CD4512AC5CD65681CE1"
+                + "B6AFF4A831852A82A7CF3C521C3C09AA"
+                + "9F94D6AF56971F1FFCE3E82389857DB0"
+                + "80C5DF10AC7ACE87666D807AFEA85FEB");
+            BigInteger a = p.Subtract(BigInteger.ValueOf(3));
+            BigInteger b = BigInteger.Zero;
+            byte[] S = null;
+            BigInteger n = p.Add(BigInteger.One).ShiftRight(2);
+            BigInteger h = BigInteger.ValueOf(4);
+
+            ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
+
+            X9ECPoint G = ConfigureBasepoint(curve, "04"
+                // Px
+                + "53FC09EE332C29AD0A7990053ED9B52A"
+                + "2B1A2FD60AEC69C698B2F204B6FF7CBF"
+                + "B5EDB6C0F6CE2308AB10DB9030B09E10"
+                + "43D5F22CDB9DFA55718BD9E7406CE890"
+                + "9760AF765DD5BCCB337C86548B72F2E1"
+                + "A702C3397A60DE74A7C1514DBA66910D"
+                + "D5CFB4CC80728D87EE9163A5B63F73EC"
+                + "80EC46C4967E0979880DC8ABEAE63895"
+                // Py
+                + "0A8249063F6009F1F9F1F0533634A135"
+                + "D3E82016029906963D778D821E141178"
+                + "F5EA69F4654EC2B9E7F7F5E5F0DE55F6"
+                + "6B598CCF9A140B2E416CFF0CA9E032B9"
+                + "70DAE117AD547C6CCAD696B5B7652FE0"
+                + "AC6F1E80164AA989492D979FC5A4D5F2"
+                + "13515AD7E9CB99A980BDAD5AD5BB4636"
+                + "ADB9B5706A67DCDE75573FD71BEF16D7");
+
+            X9ECParameters x9 = new X9ECParameters(curve, G, n, h, S);
+
+            ImplAddSubtractMultiplyTwiceEncodingTestAllCoords(x9);
+        }
+
         private void AssertPointsEqual(string message, ECPoint a, ECPoint b)
         {
             // NOTE: We intentionally test points for equality in both directions
@@ -565,5 +649,52 @@ namespace Org.BouncyCastle.Math.EC.Tests
                 Assert.IsTrue(Arrays.AreEqual(a, b));
             }
         }
+
+        private static X9ECPoint ConfigureBasepoint(ECCurve curve, string encoding)
+        {
+            X9ECPoint G = new X9ECPoint(curve, Hex.Decode(encoding));
+            //WNafUtilities.ConfigureBasepoint(G.Point);
+            return G;
+        }
+
+        private static ECCurve ConfigureCurve(ECCurve curve)
+        {
+            return curve;
+        }
+
+        private static BigInteger FromHex(string hex)
+        {
+            return new BigInteger(1, Hex.Decode(hex));
+        }
+
+        private static ECFieldElement SolveQuadraticEquation(ECCurve c, ECFieldElement rhs)
+        {
+            if (rhs.IsZero)
+                return rhs;
+
+            ECFieldElement gamma, z, zeroElement = c.FromBigInteger(BigInteger.Zero);
+
+            int m = c.FieldSize;
+            do
+            {
+                ECFieldElement t = c.FromBigInteger(BigInteger.Arbitrary(m));
+                z = zeroElement;
+                ECFieldElement w = rhs;
+                for (int i = 1; i < m; i++)
+                {
+                    ECFieldElement w2 = w.Square();
+                    z = z.Square().Add(w2.Multiply(t));
+                    w = w2.Add(rhs);
+                }
+                if (!w.IsZero)
+                {
+                    return null;
+                }
+                gamma = z.Square().Add(z);
+            }
+            while (gamma.IsZero);
+
+            return z;
+        }
     }
 }
diff --git a/crypto/test/src/test/NamedCurveTest.cs b/crypto/test/src/test/NamedCurveTest.cs
index 5b29a4152..2273d2fd1 100644
--- a/crypto/test/src/test/NamedCurveTest.cs
+++ b/crypto/test/src/test/NamedCurveTest.cs
@@ -251,15 +251,15 @@ namespace Org.BouncyCastle.Tests
                 // Current test cases don't work for GOST34.10 2012
                 return;
 
-                keyAlgorithm = "ECGOST3410-2012";
-                if (name.IndexOf("256") > 0)
-                {
-                    sgr = SignerUtilities.GetSigner("ECGOST3410-2012-256");
-                }
-                else
-                {
-                    sgr = SignerUtilities.GetSigner("ECGOST3410-2012-512");
-                }
+                //keyAlgorithm = "ECGOST3410-2012";
+                //if (name.IndexOf("256") > 0)
+                //{
+                //    sgr = SignerUtilities.GetSigner("ECGOST3410-2012-256");
+                //}
+                //else
+                //{
+                //    sgr = SignerUtilities.GetSigner("ECGOST3410-2012-512");
+                //}
             }
             else
             {