diff --git a/src/Renci.SshNet/Compression/Zlib.cs b/src/Renci.SshNet/Compression/Zlib.cs index f7da2eb15..20346c900 100644 --- a/src/Renci.SshNet/Compression/Zlib.cs +++ b/src/Renci.SshNet/Compression/Zlib.cs @@ -7,7 +7,9 @@ namespace Renci.SshNet.Compression /// /// Represents the "zlib" compression algorithm. /// +#pragma warning disable CA1724 // Type names should not match namespaces public class Zlib : Compressor +#pragma warning restore CA1724 // Type names should not match namespaces { private readonly ZLibStream _compressor; private readonly ZLibStream _decompressor; diff --git a/src/Renci.SshNet/Renci.SshNet.csproj b/src/Renci.SshNet/Renci.SshNet.csproj index 197f83194..7634c3f81 100644 --- a/src/Renci.SshNet/Renci.SshNet.csproj +++ b/src/Renci.SshNet/Renci.SshNet.csproj @@ -40,6 +40,10 @@ + + + + True diff --git a/src/Renci.SshNet/Security/BouncyCastle/.editorconfig b/src/Renci.SshNet/Security/BouncyCastle/.editorconfig deleted file mode 100644 index 7b2f03592..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/.editorconfig +++ /dev/null @@ -1,10 +0,0 @@ -[*.cs] - -generated_code = true - -# Do not reported any diagnostics for "imported" code -dotnet_analyzer_diagnostic.severity = none - -# IDE0005: Remove unnecessary using directives -# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0005 -dotnet_diagnostic.IDE0005.severity = none diff --git a/src/Renci.SshNet/Security/BouncyCastle/asn1/sec/SECNamedCurves.cs b/src/Renci.SshNet/Security/BouncyCastle/asn1/sec/SECNamedCurves.cs deleted file mode 100644 index dc9462b3a..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/asn1/sec/SECNamedCurves.cs +++ /dev/null @@ -1,121 +0,0 @@ -using Renci.SshNet.Security.Org.BouncyCastle.Asn1.X9; -using Renci.SshNet.Security.Org.BouncyCastle.Math; -using Renci.SshNet.Security.Org.BouncyCastle.Math.EC; -using Renci.SshNet.Security.Org.BouncyCastle.Utilities.Encoders; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Asn1.Sec -{ - internal sealed class SecNamedCurves - { - /* - * secp256r1 - */ - internal class Secp256r1Holder - : X9ECParametersHolder - { - private Secp256r1Holder() {} - - internal static readonly X9ECParametersHolder Instance = new Secp256r1Holder(); - - protected override X9ECParameters CreateParameters() - { - // p = 2^224 (2^32 - 1) + 2^192 + 2^96 - 1 - BigInteger p = FromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF"); - BigInteger a = FromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC"); - BigInteger b = FromHex("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B"); - byte[] S = Hex.Decode("C49D360886E704936A6678E1139D26B7819F7E90"); - BigInteger n = FromHex("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551"); - BigInteger h = BigInteger.One; - - ECCurve curve = new FpCurve(p, a, b, n, h); - X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04" - + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296" - + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5")); - - return new X9ECParameters(curve, G, n, h, S); - } - } - - /* - * secp384r1 - */ - internal class Secp384r1Holder - : X9ECParametersHolder - { - private Secp384r1Holder() {} - - internal static readonly X9ECParametersHolder Instance = new Secp384r1Holder(); - - protected override X9ECParameters CreateParameters() - { - // p = 2^384 - 2^128 - 2^96 + 2^32 - 1 - BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF"); - BigInteger a = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC"); - BigInteger b = FromHex("B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF"); - byte[] S = Hex.Decode("A335926AA319A27A1D00896A6773A4827ACDAC73"); - BigInteger n = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973"); - BigInteger h = BigInteger.One; - - ECCurve curve = new FpCurve(p, a, b, n, h); - X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04" - + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7" - + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F")); - - return new X9ECParameters(curve, G, n, h, S); - } - } - - /* - * secp521r1 - */ - internal class Secp521r1Holder - : X9ECParametersHolder - { - private Secp521r1Holder() {} - - internal static readonly X9ECParametersHolder Instance = new Secp521r1Holder(); - - protected override X9ECParameters CreateParameters() - { - // p = 2^521 - 1 - BigInteger p = FromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); - BigInteger a = FromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC"); - BigInteger b = FromHex("0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00"); - byte[] S = Hex.Decode("D09E8800291CB85396CC6717393284AAA0DA64BA"); - BigInteger n = FromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409"); - BigInteger h = BigInteger.One; - - ECCurve curve = new FpCurve(p, a, b, n, h); - X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04" - + "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66" - + "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650")); - - return new X9ECParameters(curve, G, n, h, S); - } - } - - public static X9ECParameters GetByName( - string name) - { - switch(name) - { - case "P-256": - case "secp256r1": - return Secp256r1Holder.Instance.Parameters; - case "P-384": - case "secp384r1": - return Secp384r1Holder.Instance.Parameters; - case "P-521": - case "secp521r1": - return Secp521r1Holder.Instance.Parameters; - } - - return null; - } - - private static BigInteger FromHex(string hex) - { - return new BigInteger(1, Hex.Decode(hex)); - } - } -} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/BouncyCastle/asn1/x9/X9Curve.cs b/src/Renci.SshNet/Security/BouncyCastle/asn1/x9/X9Curve.cs deleted file mode 100644 index 1faf777a8..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/asn1/x9/X9Curve.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; - -using Renci.SshNet.Security.Org.BouncyCastle.Math.EC; -using Renci.SshNet.Security.Org.BouncyCastle.Utilities; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Asn1.X9 -{ - internal class X9Curve - { - private readonly ECCurve curve; - private readonly byte[] seed; - - public X9Curve( - ECCurve curve) - : this(curve, null) - { - } - - public X9Curve( - ECCurve curve, - byte[] seed) - { - if (curve == null) - throw new ArgumentNullException("curve"); - - this.curve = curve; - this.seed = Arrays.Clone(seed); - } - - public ECCurve Curve - { - get { return curve; } - } - - public byte[] GetSeed() - { - return Arrays.Clone(seed); - } - } -} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/BouncyCastle/asn1/x9/X9ECParameters.cs b/src/Renci.SshNet/Security/BouncyCastle/asn1/x9/X9ECParameters.cs deleted file mode 100644 index f8234b963..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/asn1/x9/X9ECParameters.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System; - -using Renci.SshNet.Security.Org.BouncyCastle.Math; -using Renci.SshNet.Security.Org.BouncyCastle.Math.EC; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Asn1.X9 -{ - internal class X9ECParameters - { - private byte[] seed; - - public static X9ECParameters GetInstance(Object obj) - { - if (obj is X9ECParameters) - return (X9ECParameters)obj; - - return null; - } - - public X9ECParameters( - ECCurve curve, - ECPoint g, - BigInteger n) - : this(curve, g, n, null, null) - { - } - - public X9ECParameters( - ECCurve curve, - X9ECPoint g, - BigInteger n, - BigInteger h) - : this(curve, g, n, h, null) - { - } - - public X9ECParameters( - ECCurve curve, - ECPoint g, - BigInteger n, - BigInteger h) - : this(curve, g, n, h, null) - { - } - - public X9ECParameters( - ECCurve curve, - ECPoint g, - BigInteger n, - BigInteger h, - byte[] seed) - : this(curve, new X9ECPoint(g), n, h, seed) - { - } - - public X9ECParameters( - ECCurve curve, - X9ECPoint g, - BigInteger n, - BigInteger h, - byte[] seed) - { - this.Curve = curve; - this.BaseEntry = g; - this.N = n; - this.H = h; - this.seed = seed; - } - - public ECCurve Curve { get; private set; } - - public ECPoint G - { - get { return BaseEntry.Point; } - } - - public BigInteger N { get; private set; } - - public BigInteger H { get; private set; } - - public byte[] GetSeed() - { - return seed; - } - - public X9Curve CurveEntry - { - get { return new X9Curve(Curve, seed); } - } - - public X9ECPoint BaseEntry { get; private set; } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/asn1/x9/X9ECParametersHolder.cs b/src/Renci.SshNet/Security/BouncyCastle/asn1/x9/X9ECParametersHolder.cs deleted file mode 100644 index 8574cb035..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/asn1/x9/X9ECParametersHolder.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace Renci.SshNet.Security.Org.BouncyCastle.Asn1.X9 -{ - internal abstract class X9ECParametersHolder - { - private X9ECParameters parameters; - - public X9ECParameters Parameters - { - get - { - lock (this) - { - if (parameters == null) - { - parameters = CreateParameters(); - } - - return parameters; - } - } - } - - protected abstract X9ECParameters CreateParameters(); - } -} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/BouncyCastle/asn1/x9/X9ECPoint.cs b/src/Renci.SshNet/Security/BouncyCastle/asn1/x9/X9ECPoint.cs deleted file mode 100644 index f4db71063..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/asn1/x9/X9ECPoint.cs +++ /dev/null @@ -1,57 +0,0 @@ -using Renci.SshNet.Security.Org.BouncyCastle.Math.EC; -using Renci.SshNet.Security.Org.BouncyCastle.Utilities; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Asn1.X9 -{ - internal class X9ECPoint - { - private readonly byte[] encoding; - - private ECCurve c; - private ECPoint p; - - public X9ECPoint(ECPoint p) - : this(p, false) - { - } - - public X9ECPoint(ECPoint p, bool compressed) - { - this.p = p.Normalize(); - this.encoding = p.GetEncoded(compressed); - } - - public X9ECPoint(ECCurve c, byte[] encoding) - { - this.c = c; - this.encoding = Arrays.Clone(encoding); - } - - public byte[] GetPointEncoding() - { - return Arrays.Clone(encoding); - } - - public ECPoint Point - { - get - { - if (p == null) - { - p = c.DecodePoint(encoding).Normalize(); - } - - return p; - } - } - - public bool IsPointCompressed - { - get - { - byte[] octets = encoding; - return octets != null && octets.Length > 0 && (octets[0] == 2 || octets[0] == 3); - } - } - } -} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/BouncyCastle/crypto/AsymmetricCipherKeyPair.cs b/src/Renci.SshNet/Security/BouncyCastle/crypto/AsymmetricCipherKeyPair.cs deleted file mode 100644 index e53a66fe3..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/crypto/AsymmetricCipherKeyPair.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Crypto -{ - internal class AsymmetricCipherKeyPair - { - private readonly AsymmetricKeyParameter publicParameter; - private readonly AsymmetricKeyParameter privateParameter; - - public AsymmetricCipherKeyPair( - AsymmetricKeyParameter publicParameter, - AsymmetricKeyParameter privateParameter) - { - if (publicParameter.IsPrivate) - throw new ArgumentException("Expected a public key", "publicParameter"); - if (!privateParameter.IsPrivate) - throw new ArgumentException("Expected a private key", "privateParameter"); - - this.publicParameter = publicParameter; - this.privateParameter = privateParameter; - } - - public AsymmetricKeyParameter Public - { - get { return publicParameter; } - } - - public AsymmetricKeyParameter Private - { - get { return privateParameter; } - } - } -} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/BouncyCastle/crypto/AsymmetricKeyParameter.cs b/src/Renci.SshNet/Security/BouncyCastle/crypto/AsymmetricKeyParameter.cs deleted file mode 100644 index fb66739f3..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/crypto/AsymmetricKeyParameter.cs +++ /dev/null @@ -1,42 +0,0 @@ -namespace Renci.SshNet.Security.Org.BouncyCastle.Crypto -{ - internal abstract class AsymmetricKeyParameter - { - private readonly bool privateKey; - - protected AsymmetricKeyParameter( - bool privateKey) - { - this.privateKey = privateKey; - } - - public bool IsPrivate - { - get { return privateKey; } - } - - public override bool Equals( - object obj) - { - AsymmetricKeyParameter other = obj as AsymmetricKeyParameter; - - if (other == null) - { - return false; - } - - return Equals(other); - } - - protected bool Equals( - AsymmetricKeyParameter other) - { - return privateKey == other.privateKey; - } - - public override int GetHashCode() - { - return privateKey.GetHashCode(); - } - } -} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/BouncyCastle/crypto/IAsymmetricCipherKeyPairGenerator.cs b/src/Renci.SshNet/Security/BouncyCastle/crypto/IAsymmetricCipherKeyPairGenerator.cs deleted file mode 100644 index 6c19d1ea0..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/crypto/IAsymmetricCipherKeyPairGenerator.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Renci.SshNet.Security.Org.BouncyCastle.Crypto -{ - internal interface IAsymmetricCipherKeyPairGenerator - { - void Init(KeyGenerationParameters parameters); - - AsymmetricCipherKeyPair GenerateKeyPair(); - } -} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/BouncyCastle/crypto/IDigest.cs b/src/Renci.SshNet/Security/BouncyCastle/crypto/IDigest.cs deleted file mode 100644 index 2ff19e3a3..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/crypto/IDigest.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Crypto -{ - /** - * interface that a message digest conforms to. - */ - internal interface IDigest - { - /** - * return the algorithm name - * - * @return the algorithm name - */ - string AlgorithmName { get; } - - /** - * return the size, in bytes, of the digest produced by this message digest. - * - * @return the size, in bytes, of the digest produced by this message digest. - */ - int GetDigestSize(); - - /** - * return the size, in bytes, of the internal buffer used by this digest. - * - * @return the size, in bytes, of the internal buffer used by this digest. - */ - int GetByteLength(); - - /** - * update the message digest with a single byte. - * - * @param inByte the input byte to be entered. - */ - void Update(byte input); - - /** - * update the message digest with a block of bytes. - * - * @param input the byte array containing the data. - * @param inOff the offset into the byte array where the data starts. - * @param len the length of the data. - */ - void BlockUpdate(byte[] input, int inOff, int length); - - /** - * Close the digest, producing the final digest value. The doFinal - * call leaves the digest reset. - * - * @param output the array the digest is to be copied into. - * @param outOff the offset into the out array the digest is to start at. - */ - int DoFinal(byte[] output, int outOff); - - /** - * reset the digest back to it's initial state. - */ - void Reset(); - } -} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/BouncyCastle/crypto/KeyGenerationParameters.cs b/src/Renci.SshNet/Security/BouncyCastle/crypto/KeyGenerationParameters.cs deleted file mode 100644 index 3be654e49..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/crypto/KeyGenerationParameters.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; - -using Renci.SshNet.Security.Org.BouncyCastle.Security; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Crypto -{ - /** - * The base class for parameters to key generators. - */ - internal class KeyGenerationParameters - { - private SecureRandom random; - private int strength; - - /** - * initialise the generator with a source of randomness - * and a strength (in bits). - * - * @param random the random byte source. - * @param strength the size, in bits, of the keys we want to produce. - */ - public KeyGenerationParameters( - SecureRandom random, - int strength) - { - if (random == null) - throw new ArgumentNullException("random"); - if (strength < 1) - throw new ArgumentException("strength must be a positive value", "strength"); - - this.random = random; - this.strength = strength; - } - - /** - * return the random source associated with this - * generator. - * - * @return the generators random source. - */ - public SecureRandom Random - { - get { return random; } - } - - /** - * return the bit strength for keys produced by this generator, - * - * @return the strength of the keys this generator produces (in bits). - */ - public int Strength - { - get { return strength; } - } - } -} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/BouncyCastle/crypto/License.html b/src/Renci.SshNet/Security/BouncyCastle/crypto/License.html deleted file mode 100644 index 829aa6ba3..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/crypto/License.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - License - - -The Bouncy Castle Cryptographic C#® API -License: -The Bouncy Castle License -Copyright (c) 2000-2018 The Legion of the Bouncy Castle Inc. -(https://www.bouncycastle.org) -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), to deal in the -Software without restriction, including without limitation the rights to use, copy, modify, merge, -publish, distribute, sub license, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", -WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -INCLUDING BUT NOT LIMITED TO THE -WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE AND NONINFRINGEMENT. IN NO -EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - - - - diff --git a/src/Renci.SshNet/Security/BouncyCastle/crypto/agreement/ECDHCBasicAgreement.cs b/src/Renci.SshNet/Security/BouncyCastle/crypto/agreement/ECDHCBasicAgreement.cs deleted file mode 100644 index 6814cb176..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/crypto/agreement/ECDHCBasicAgreement.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; - -using Renci.SshNet.Security.Org.BouncyCastle.Math; -using Renci.SshNet.Security.Org.BouncyCastle.Math.EC; -using Renci.SshNet.Security.Org.BouncyCastle.Crypto.Parameters; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Crypto.Agreement -{ - internal class ECDHCBasicAgreement - { - private ECPrivateKeyParameters privKey; - - public virtual void Init( - AsymmetricKeyParameter parameters) - { - this.privKey = (ECPrivateKeyParameters)parameters; - } - - public virtual int GetFieldSize() - { - return (privKey.Parameters.Curve.FieldSize + 7) / 8; - } - - public virtual BigInteger CalculateAgreement( - ECPublicKeyParameters pubKey) - { - ECPublicKeyParameters pub = pubKey; - ECDomainParameters dp = privKey.Parameters; - if (!dp.Equals(pub.Parameters)) - throw new InvalidOperationException("ECDHC public key has wrong domain parameters"); - - BigInteger hd = dp.H.Multiply(privKey.D).Mod(dp.N); - - // Always perform calculations on the exact curve specified by our private key's parameters - ECPoint pubPoint = ECAlgorithms.CleanPoint(dp.Curve, pub.Q); - if (pubPoint.IsInfinity) - throw new InvalidOperationException("Infinity is not a valid public key for ECDHC"); - - ECPoint P = pubPoint.Multiply(hd).Normalize(); - if (P.IsInfinity) - throw new InvalidOperationException("Infinity is not a valid agreement value for ECDHC"); - - return P.AffineXCoord.ToBigInteger(); - } - } -} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/BouncyCastle/crypto/digests/GeneralDigest.cs b/src/Renci.SshNet/Security/BouncyCastle/crypto/digests/GeneralDigest.cs deleted file mode 100644 index 718f34ae8..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/crypto/digests/GeneralDigest.cs +++ /dev/null @@ -1,129 +0,0 @@ -using System; - -using Renci.SshNet.Security.Org.BouncyCastle.Utilities; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Crypto.Digests -{ - internal abstract class GeneralDigest - : IDigest, IMemoable - { - private const int BYTE_LENGTH = 64; - - private byte[] xBuf; - private int xBufOff; - - private long byteCount; - - internal GeneralDigest() - { - xBuf = new byte[4]; - } - - internal GeneralDigest(GeneralDigest t) - { - xBuf = new byte[t.xBuf.Length]; - CopyIn(t); - } - - protected void CopyIn(GeneralDigest t) - { - Array.Copy(t.xBuf, 0, xBuf, 0, t.xBuf.Length); - - xBufOff = t.xBufOff; - byteCount = t.byteCount; - } - - public void Update(byte input) - { - xBuf[xBufOff++] = input; - - if (xBufOff == xBuf.Length) - { - ProcessWord(xBuf, 0); - xBufOff = 0; - } - - byteCount++; - } - - public void BlockUpdate( - byte[] input, - int inOff, - int length) - { - length = System.Math.Max(0, length); - - // - // fill the current word - // - int i = 0; - if (xBufOff != 0) - { - while (i < length) - { - xBuf[xBufOff++] = input[inOff + i++]; - if (xBufOff == 4) - { - ProcessWord(xBuf, 0); - xBufOff = 0; - break; - } - } - } - - // - // process whole words. - // - int limit = ((length - i) & ~3) + i; - for (; i < limit; i += 4) - { - ProcessWord(input, inOff + i); - } - - // - // load in the remainder. - // - while (i < length) - { - xBuf[xBufOff++] = input[inOff + i++]; - } - - byteCount += length; - } - - public void Finish() - { - long bitLength = (byteCount << 3); - - // - // add the pad bytes. - // - Update((byte)128); - - while (xBufOff != 0) Update((byte)0); - ProcessLength(bitLength); - ProcessBlock(); - } - - public virtual void Reset() - { - byteCount = 0; - xBufOff = 0; - Array.Clear(xBuf, 0, xBuf.Length); - } - - public int GetByteLength() - { - return BYTE_LENGTH; - } - - internal abstract void ProcessWord(byte[] input, int inOff); - internal abstract void ProcessLength(long bitLength); - internal abstract void ProcessBlock(); - public abstract string AlgorithmName { get; } - public abstract int GetDigestSize(); - public abstract int DoFinal(byte[] output, int outOff); - public abstract IMemoable Copy(); - public abstract void Reset(IMemoable t); - } -} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/BouncyCastle/crypto/digests/Sha256Digest.cs b/src/Renci.SshNet/Security/BouncyCastle/crypto/digests/Sha256Digest.cs deleted file mode 100644 index da700fcf2..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/crypto/digests/Sha256Digest.cs +++ /dev/null @@ -1,280 +0,0 @@ -using System; - -using Renci.SshNet.Security.Org.BouncyCastle.Crypto.Utilities; -using Renci.SshNet.Security.Org.BouncyCastle.Utilities; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Crypto.Digests -{ - internal class Sha256Digest - : GeneralDigest - { - private const int DigestLength = 32; - - private uint H1, H2, H3, H4, H5, H6, H7, H8; - private uint[] X = new uint[64]; - private int xOff; - - public Sha256Digest() - { - initHs(); - } - - /** - * Copy constructor. This will copy the state of the provided - * message digest. - */ - public Sha256Digest(Sha256Digest t) : base(t) - { - CopyIn(t); - } - - private void CopyIn(Sha256Digest t) - { - base.CopyIn(t); - - H1 = t.H1; - H2 = t.H2; - H3 = t.H3; - H4 = t.H4; - H5 = t.H5; - H6 = t.H6; - H7 = t.H7; - H8 = t.H8; - - Array.Copy(t.X, 0, X, 0, t.X.Length); - xOff = t.xOff; - } - - public override string AlgorithmName - { - get { return "SHA-256"; } - } - - public override int GetDigestSize() - { - return DigestLength; - } - - internal override void ProcessWord( - byte[] input, - int inOff) - { - X[xOff] = Pack.BE_To_UInt32(input, inOff); - - if (++xOff == 16) - { - ProcessBlock(); - } - } - - internal override void ProcessLength( - long bitLength) - { - if (xOff > 14) - { - ProcessBlock(); - } - - X[14] = (uint)((ulong)bitLength >> 32); - X[15] = (uint)((ulong)bitLength); - } - - public override int DoFinal( - byte[] output, - int outOff) - { - Finish(); - - Pack.UInt32_To_BE((uint)H1, output, outOff); - Pack.UInt32_To_BE((uint)H2, output, outOff + 4); - Pack.UInt32_To_BE((uint)H3, output, outOff + 8); - Pack.UInt32_To_BE((uint)H4, output, outOff + 12); - Pack.UInt32_To_BE((uint)H5, output, outOff + 16); - Pack.UInt32_To_BE((uint)H6, output, outOff + 20); - Pack.UInt32_To_BE((uint)H7, output, outOff + 24); - Pack.UInt32_To_BE((uint)H8, output, outOff + 28); - - Reset(); - - return DigestLength; - } - - public override void Reset() - { - base.Reset(); - - initHs(); - - xOff = 0; - Array.Clear(X, 0, X.Length); - } - - private void initHs() - { - /* SHA-256 initial hash value - * The first 32 bits of the fractional parts of the square roots - * of the first eight prime numbers - */ - H1 = 0x6a09e667; - H2 = 0xbb67ae85; - H3 = 0x3c6ef372; - H4 = 0xa54ff53a; - H5 = 0x510e527f; - H6 = 0x9b05688c; - H7 = 0x1f83d9ab; - H8 = 0x5be0cd19; - } - - internal override void ProcessBlock() - { - // - // expand 16 word block into 64 word blocks. - // - for (int ti = 16; ti <= 63; ti++) - { - X[ti] = Theta1(X[ti - 2]) + X[ti - 7] + Theta0(X[ti - 15]) + X[ti - 16]; - } - - // - // set up working variables. - // - uint a = H1; - uint b = H2; - uint c = H3; - uint d = H4; - uint e = H5; - uint f = H6; - uint g = H7; - uint h = H8; - - int t = 0; - for(int i = 0; i < 8; ++i) - { - // t = 8 * i - h += Sum1Ch(e, f, g) + K[t] + X[t]; - d += h; - h += Sum0Maj(a, b, c); - ++t; - - // t = 8 * i + 1 - g += Sum1Ch(d, e, f) + K[t] + X[t]; - c += g; - g += Sum0Maj(h, a, b); - ++t; - - // t = 8 * i + 2 - f += Sum1Ch(c, d, e) + K[t] + X[t]; - b += f; - f += Sum0Maj(g, h, a); - ++t; - - // t = 8 * i + 3 - e += Sum1Ch(b, c, d) + K[t] + X[t]; - a += e; - e += Sum0Maj(f, g, h); - ++t; - - // t = 8 * i + 4 - d += Sum1Ch(a, b, c) + K[t] + X[t]; - h += d; - d += Sum0Maj(e, f, g); - ++t; - - // t = 8 * i + 5 - c += Sum1Ch(h, a, b) + K[t] + X[t]; - g += c; - c += Sum0Maj(d, e, f); - ++t; - - // t = 8 * i + 6 - b += Sum1Ch(g, h, a) + K[t] + X[t]; - f += b; - b += Sum0Maj(c, d, e); - ++t; - - // t = 8 * i + 7 - a += Sum1Ch(f, g, h) + K[t] + X[t]; - e += a; - a += Sum0Maj(b, c, d); - ++t; - } - - H1 += a; - H2 += b; - H3 += c; - H4 += d; - H5 += e; - H6 += f; - H7 += g; - H8 += h; - - // - // reset the offset and clean out the word buffer. - // - xOff = 0; - Array.Clear(X, 0, 16); - } - - private static uint Sum1Ch( - uint x, - uint y, - uint z) - { - return (((x >> 6) | (x << 26)) ^ ((x >> 11) | (x << 21)) ^ ((x >> 25) | (x << 7))) - + ((x & y) ^ ((~x) & z)); - } - - private static uint Sum0Maj( - uint x, - uint y, - uint z) - { - return (((x >> 2) | (x << 30)) ^ ((x >> 13) | (x << 19)) ^ ((x >> 22) | (x << 10))) - + ((x & y) ^ (x & z) ^ (y & z)); - } - - private static uint Theta0( - uint x) - { - return ((x >> 7) | (x << 25)) ^ ((x >> 18) | (x << 14)) ^ (x >> 3); - } - - private static uint Theta1( - uint x) - { - return ((x >> 17) | (x << 15)) ^ ((x >> 19) | (x << 13)) ^ (x >> 10); - } - - private static readonly uint[] K = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 - }; - - public override IMemoable Copy() - { - return new Sha256Digest(this); - } - - public override void Reset(IMemoable other) - { - Sha256Digest d = (Sha256Digest)other; - - CopyIn(d); - } - - } -} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/BouncyCastle/crypto/generators/ECKeyPairGenerator.cs b/src/Renci.SshNet/Security/BouncyCastle/crypto/generators/ECKeyPairGenerator.cs deleted file mode 100644 index 446c279cd..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/crypto/generators/ECKeyPairGenerator.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; - -using Renci.SshNet.Security.Org.BouncyCastle.Crypto.Parameters; -using Renci.SshNet.Security.Org.BouncyCastle.Math; -using Renci.SshNet.Security.Org.BouncyCastle.Math.EC; -using Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Multiplier; -using Renci.SshNet.Security.Org.BouncyCastle.Security; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Crypto.Generators -{ - internal class ECKeyPairGenerator - : IAsymmetricCipherKeyPairGenerator - { - private readonly string algorithm; - - private ECDomainParameters parameters; - private SecureRandom random; - - public ECKeyPairGenerator() - : this("EC") - { - } - - public ECKeyPairGenerator( - string algorithm) - { - if (algorithm == null) - throw new ArgumentNullException("algorithm"); - - this.algorithm = ECKeyParameters.VerifyAlgorithmName(algorithm); - } - - public void Init( - KeyGenerationParameters parameters) - { - if (parameters is ECKeyGenerationParameters) - { - ECKeyGenerationParameters ecP = (ECKeyGenerationParameters) parameters; - - this.parameters = ecP.DomainParameters; - } - - this.random = parameters.Random; - - if (this.random == null) - { - this.random = new SecureRandom(); - } - } - - public AsymmetricCipherKeyPair GenerateKeyPair() - { - BigInteger n = parameters.N; - BigInteger d; - int minWeight = n.BitLength >> 2; - - for (;;) - { - d = new BigInteger(n.BitLength, random); - - if (d.CompareTo(BigInteger.Two) < 0 || d.CompareTo(n) >= 0) - continue; - - if (WNafUtilities.GetNafWeight(d) < minWeight) - continue; - - break; - } - - ECPoint q = CreateBasePointMultiplier().Multiply(parameters.G, d); - - return new AsymmetricCipherKeyPair( - new ECPublicKeyParameters(algorithm, q, parameters), - new ECPrivateKeyParameters(algorithm, d, parameters)); - } - - protected virtual ECMultiplier CreateBasePointMultiplier() - { - return new FixedPointCombMultiplier(); - } - - internal static ECPublicKeyParameters GetCorrespondingPublicKey( - ECPrivateKeyParameters privKey) - { - ECDomainParameters ec = privKey.Parameters; - ECPoint q = new FixedPointCombMultiplier().Multiply(ec.G, privKey.D); - - return new ECPublicKeyParameters(privKey.AlgorithmName, q, ec); - } - } -} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/BouncyCastle/crypto/parameters/ECDomainParameters.cs b/src/Renci.SshNet/Security/BouncyCastle/crypto/parameters/ECDomainParameters.cs deleted file mode 100644 index 1d1b037f2..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/crypto/parameters/ECDomainParameters.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; - -using Renci.SshNet.Security.Org.BouncyCastle.Math; -using Renci.SshNet.Security.Org.BouncyCastle.Math.EC; -using Renci.SshNet.Security.Org.BouncyCastle.Utilities; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Crypto.Parameters -{ - internal class ECDomainParameters - { - internal ECCurve curve; - internal byte[] seed; - internal ECPoint g; - internal BigInteger n; - internal BigInteger h; - internal BigInteger hInv; - - public ECDomainParameters( - ECCurve curve, - ECPoint g, - BigInteger n, - BigInteger h, - byte[] seed) - { - if (curve == null) - throw new ArgumentNullException("curve"); - if (g == null) - throw new ArgumentNullException("g"); - if (n == null) - throw new ArgumentNullException("n"); - // we can't check for h == null here as h is optional in X9.62 as it is not required for ECDSA - - this.curve = curve; - this.g = Validate(curve, g); - this.n = n; - this.h = h; - this.seed = Arrays.Clone(seed); - } - - public ECCurve Curve - { - get { return curve; } - } - - public ECPoint G - { - get { return g; } - } - - public BigInteger N - { - get { return n; } - } - - public BigInteger H - { - get { return h; } - } - - public BigInteger HInv - { - get - { - lock (this) - { - if (hInv == null) - { - hInv = h.ModInverse(n); - } - return hInv; - } - } - } - - internal static ECPoint Validate(ECCurve c, ECPoint q) - { - if (q == null) - throw new ArgumentException("Point has null value", "q"); - - q = ECAlgorithms.ImportPoint(c, q).Normalize(); - - if (q.IsInfinity) - throw new ArgumentException("Point at infinity", "q"); - - if (!q.IsValid()) - throw new ArgumentException("Point not on curve", "q"); - - return q; - } - } -} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/BouncyCastle/crypto/parameters/ECKeyGenerationParameters.cs b/src/Renci.SshNet/Security/BouncyCastle/crypto/parameters/ECKeyGenerationParameters.cs deleted file mode 100644 index 88e33e3d3..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/crypto/parameters/ECKeyGenerationParameters.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Renci.SshNet.Security.Org.BouncyCastle.Security; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Crypto.Parameters -{ - internal class ECKeyGenerationParameters - : KeyGenerationParameters - { - private readonly ECDomainParameters domainParams; - - public ECKeyGenerationParameters( - ECDomainParameters domainParameters, - SecureRandom random) - : base(random, domainParameters.N.BitLength) - { - this.domainParams = domainParameters; - } - - public ECDomainParameters DomainParameters - { - get { return domainParams; } - } - } -} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/BouncyCastle/crypto/parameters/ECKeyParameters.cs b/src/Renci.SshNet/Security/BouncyCastle/crypto/parameters/ECKeyParameters.cs deleted file mode 100644 index 50426c54e..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/crypto/parameters/ECKeyParameters.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System; - -using Renci.SshNet.Security.Org.BouncyCastle.Security; -using Renci.SshNet.Security.Org.BouncyCastle.Utilities; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Crypto.Parameters -{ - internal abstract class ECKeyParameters - : AsymmetricKeyParameter - { - private static readonly string[] algorithms = { "EC", "ECDH" }; - - private readonly string algorithm; - private readonly ECDomainParameters parameters; - - protected ECKeyParameters( - string algorithm, - bool isPrivate, - ECDomainParameters parameters) - : base(isPrivate) - { - if (algorithm == null) - throw new ArgumentNullException("algorithm"); - if (parameters == null) - throw new ArgumentNullException("parameters"); - - this.algorithm = VerifyAlgorithmName(algorithm); - this.parameters = parameters; - } - - public string AlgorithmName - { - get { return algorithm; } - } - - public ECDomainParameters Parameters - { - get { return parameters; } - } - - public override bool Equals( - object obj) - { - if (obj == this) - return true; - - ECDomainParameters other = obj as ECDomainParameters; - - if (other == null) - return false; - - return Equals(other); - } - - protected bool Equals( - ECKeyParameters other) - { - return parameters.Equals(other.parameters) && base.Equals(other); - } - - public override int GetHashCode() - { - return parameters.GetHashCode() ^ base.GetHashCode(); - } - - internal ECKeyGenerationParameters CreateKeyGenerationParameters( - SecureRandom random) - { - return new ECKeyGenerationParameters(parameters, random); - } - - internal static string VerifyAlgorithmName(string algorithm) - { - if (Array.IndexOf(algorithms, algorithm, 0, algorithms.Length) < 0) - throw new ArgumentException("unrecognised algorithm: " + algorithm, "algorithm"); - return algorithm.ToUpper(); - } - } -} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/BouncyCastle/crypto/parameters/ECPrivateKeyParameters.cs b/src/Renci.SshNet/Security/BouncyCastle/crypto/parameters/ECPrivateKeyParameters.cs deleted file mode 100644 index a11233c8d..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/crypto/parameters/ECPrivateKeyParameters.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; - -using Renci.SshNet.Security.Org.BouncyCastle.Math; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Crypto.Parameters -{ - internal class ECPrivateKeyParameters - : ECKeyParameters - { - private readonly BigInteger d; - - public ECPrivateKeyParameters( - BigInteger d, - ECDomainParameters parameters) - : this("EC", d, parameters) - { - } - - public ECPrivateKeyParameters( - string algorithm, - BigInteger d, - ECDomainParameters parameters) - : base(algorithm, true, parameters) - { - if (d == null) - throw new ArgumentNullException("d"); - - this.d = d; - } - - public BigInteger D - { - get { return d; } - } - - public override bool Equals( - object obj) - { - if (obj == this) - return true; - - ECPrivateKeyParameters other = obj as ECPrivateKeyParameters; - - if (other == null) - return false; - - return Equals(other); - } - - protected bool Equals( - ECPrivateKeyParameters other) - { - return d.Equals(other.d) && base.Equals(other); - } - - public override int GetHashCode() - { - return d.GetHashCode() ^ base.GetHashCode(); - } - } -} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/BouncyCastle/crypto/parameters/ECPublicKeyParameters.cs b/src/Renci.SshNet/Security/BouncyCastle/crypto/parameters/ECPublicKeyParameters.cs deleted file mode 100644 index 6b1f3ec5c..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/crypto/parameters/ECPublicKeyParameters.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; - -using Renci.SshNet.Security.Org.BouncyCastle.Math.EC; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Crypto.Parameters -{ - internal class ECPublicKeyParameters - : ECKeyParameters - { - private readonly ECPoint q; - - public ECPublicKeyParameters( - ECPoint q, - ECDomainParameters parameters) - : this("EC", q, parameters) - { - } - - public ECPublicKeyParameters( - string algorithm, - ECPoint q, - ECDomainParameters parameters) - : base(algorithm, false, parameters) - { - if (q == null) - throw new ArgumentNullException("q"); - - this.q = ECDomainParameters.Validate(Parameters.Curve, q); - } - - public ECPoint Q - { - get { return q; } - } - - public override bool Equals(object obj) - { - if (obj == this) - return true; - - ECPublicKeyParameters other = obj as ECPublicKeyParameters; - - if (other == null) - return false; - - return Equals(other); - } - - protected bool Equals( - ECPublicKeyParameters other) - { - return q.Equals(other.q) && base.Equals(other); - } - - public override int GetHashCode() - { - return q.GetHashCode() ^ base.GetHashCode(); - } - } -} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/BouncyCastle/crypto/prng/CryptoApiRandomGenerator.cs b/src/Renci.SshNet/Security/BouncyCastle/crypto/prng/CryptoApiRandomGenerator.cs deleted file mode 100644 index 50ae6f38d..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/crypto/prng/CryptoApiRandomGenerator.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Security.Cryptography; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Crypto.Prng -{ - internal class CryptoApiRandomGenerator - : IRandomGenerator - { - private readonly RandomNumberGenerator rndProv; - - public CryptoApiRandomGenerator() - : this(Abstractions.CryptoAbstraction.CreateRandomNumberGenerator()) - { - } - - public CryptoApiRandomGenerator(RandomNumberGenerator rng) - { - this.rndProv = rng; - } - - #region IRandomGenerator Members - - public virtual void AddSeedMaterial(byte[] seed) - { - // We don't care about the seed - } - - public virtual void AddSeedMaterial(long seed) - { - // We don't care about the seed - } - - public virtual void NextBytes(byte[] bytes) - { - rndProv.GetBytes(bytes); - } - - public virtual void NextBytes(byte[] bytes, int start, int len) - { - if (start < 0) - throw new ArgumentException("Start offset cannot be negative", "start"); - if (bytes.Length < (start + len)) - throw new ArgumentException("Byte array too small for requested offset and length"); - - if (bytes.Length == len && start == 0) - { - NextBytes(bytes); - } - else - { - byte[] tmpBuf = new byte[len]; - NextBytes(tmpBuf); - Array.Copy(tmpBuf, 0, bytes, start, len); - } - } - - #endregion - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/crypto/prng/DigestRandomGenerator.cs b/src/Renci.SshNet/Security/BouncyCastle/crypto/prng/DigestRandomGenerator.cs deleted file mode 100644 index b0b69b7bc..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/crypto/prng/DigestRandomGenerator.cs +++ /dev/null @@ -1,117 +0,0 @@ -using Renci.SshNet.Security.Org.BouncyCastle.Crypto.Utilities; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Crypto.Prng -{ - internal class DigestRandomGenerator - : IRandomGenerator - { - private const long CYCLE_COUNT = 10; - - private long stateCounter; - private long seedCounter; - private IDigest digest; - private byte[] state; - private byte[] seed; - - public DigestRandomGenerator( - IDigest digest) - { - this.digest = digest; - - this.seed = new byte[digest.GetDigestSize()]; - this.seedCounter = 1; - - this.state = new byte[digest.GetDigestSize()]; - this.stateCounter = 1; - } - - public void AddSeedMaterial( - byte[] inSeed) - { - lock (this) - { - DigestUpdate(inSeed); - DigestUpdate(seed); - DigestDoFinal(seed); - } - } - - public void AddSeedMaterial( - long rSeed) - { - lock (this) - { - DigestAddCounter(rSeed); - DigestUpdate(seed); - DigestDoFinal(seed); - } - } - - public void NextBytes( - byte[] bytes) - { - NextBytes(bytes, 0, bytes.Length); - } - - public void NextBytes( - byte[] bytes, - int start, - int len) - { - lock (this) - { - int stateOff = 0; - - GenerateState(); - - int end = start + len; - for (int i = start; i < end; ++i) - { - if (stateOff == state.Length) - { - GenerateState(); - stateOff = 0; - } - bytes[i] = state[stateOff++]; - } - } - } - - private void CycleSeed() - { - DigestUpdate(seed); - DigestAddCounter(seedCounter++); - DigestDoFinal(seed); - } - - private void GenerateState() - { - DigestAddCounter(stateCounter++); - DigestUpdate(state); - DigestUpdate(seed); - DigestDoFinal(state); - - if ((stateCounter % CYCLE_COUNT) == 0) - { - CycleSeed(); - } - } - - private void DigestAddCounter(long seedVal) - { - byte[] bytes = new byte[8]; - Pack.UInt64_To_LE((ulong)seedVal, bytes); - digest.BlockUpdate(bytes, 0, bytes.Length); - } - - private void DigestUpdate(byte[] inSeed) - { - digest.BlockUpdate(inSeed, 0, inSeed.Length); - } - - private void DigestDoFinal(byte[] result) - { - digest.DoFinal(result, 0); - } - } -} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/BouncyCastle/crypto/prng/IRandomGenerator.cs b/src/Renci.SshNet/Security/BouncyCastle/crypto/prng/IRandomGenerator.cs deleted file mode 100644 index 57e49ea71..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/crypto/prng/IRandomGenerator.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Crypto.Prng -{ - /// Generic interface for objects generating random bytes. - internal interface IRandomGenerator - { - /// Add more seed material to the generator. - /// A byte array to be mixed into the generator's state. - void AddSeedMaterial(byte[] seed); - - /// Add more seed material to the generator. - /// A long value to be mixed into the generator's state. - void AddSeedMaterial(long seed); - - /// Fill byte array with random values. - /// Array to be filled. - void NextBytes(byte[] bytes); - - /// Fill byte array with random values. - /// Array to receive bytes. - /// Index to start filling at. - /// Length of segment to fill. - void NextBytes(byte[] bytes, int start, int len); - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/crypto/util/Pack.cs b/src/Renci.SshNet/Security/BouncyCastle/crypto/util/Pack.cs deleted file mode 100644 index 594959eb2..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/crypto/util/Pack.cs +++ /dev/null @@ -1,345 +0,0 @@ -using System; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Crypto.Utilities -{ - internal sealed class Pack - { - private Pack() - { - } - - internal static void UInt16_To_BE(ushort n, byte[] bs) - { - bs[0] = (byte)(n >> 8); - bs[1] = (byte)(n); - } - - internal static void UInt16_To_BE(ushort n, byte[] bs, int off) - { - bs[off] = (byte)(n >> 8); - bs[off + 1] = (byte)(n); - } - - internal static ushort BE_To_UInt16(byte[] bs) - { - uint n = (uint)bs[0] << 8 - | (uint)bs[1]; - return (ushort)n; - } - - internal static ushort BE_To_UInt16(byte[] bs, int off) - { - uint n = (uint)bs[off] << 8 - | (uint)bs[off + 1]; - return (ushort)n; - } - - internal static byte[] UInt32_To_BE(uint n) - { - byte[] bs = new byte[4]; - UInt32_To_BE(n, bs, 0); - return bs; - } - - internal static void UInt32_To_BE(uint n, byte[] bs) - { - bs[0] = (byte)(n >> 24); - bs[1] = (byte)(n >> 16); - bs[2] = (byte)(n >> 8); - bs[3] = (byte)(n); - } - - internal static void UInt32_To_BE(uint n, byte[] bs, int off) - { - bs[off] = (byte)(n >> 24); - bs[off + 1] = (byte)(n >> 16); - bs[off + 2] = (byte)(n >> 8); - bs[off + 3] = (byte)(n); - } - - internal static byte[] UInt32_To_BE(uint[] ns) - { - byte[] bs = new byte[4 * ns.Length]; - UInt32_To_BE(ns, bs, 0); - return bs; - } - - internal static void UInt32_To_BE(uint[] ns, byte[] bs, int off) - { - for (int i = 0; i < ns.Length; ++i) - { - UInt32_To_BE(ns[i], bs, off); - off += 4; - } - } - - internal static uint BE_To_UInt32(byte[] bs) - { - return (uint)bs[0] << 24 - | (uint)bs[1] << 16 - | (uint)bs[2] << 8 - | (uint)bs[3]; - } - - internal static uint BE_To_UInt32(byte[] bs, int off) - { - return (uint)bs[off] << 24 - | (uint)bs[off + 1] << 16 - | (uint)bs[off + 2] << 8 - | (uint)bs[off + 3]; - } - - internal static void BE_To_UInt32(byte[] bs, int off, uint[] ns) - { - for (int i = 0; i < ns.Length; ++i) - { - ns[i] = BE_To_UInt32(bs, off); - off += 4; - } - } - - internal static byte[] UInt64_To_BE(ulong n) - { - byte[] bs = new byte[8]; - UInt64_To_BE(n, bs, 0); - return bs; - } - - internal static void UInt64_To_BE(ulong n, byte[] bs) - { - UInt32_To_BE((uint)(n >> 32), bs); - UInt32_To_BE((uint)(n), bs, 4); - } - - internal static void UInt64_To_BE(ulong n, byte[] bs, int off) - { - UInt32_To_BE((uint)(n >> 32), bs, off); - UInt32_To_BE((uint)(n), bs, off + 4); - } - - internal static byte[] UInt64_To_BE(ulong[] ns) - { - byte[] bs = new byte[8 * ns.Length]; - UInt64_To_BE(ns, bs, 0); - return bs; - } - - internal static void UInt64_To_BE(ulong[] ns, byte[] bs, int off) - { - for (int i = 0; i < ns.Length; ++i) - { - UInt64_To_BE(ns[i], bs, off); - off += 8; - } - } - - internal static ulong BE_To_UInt64(byte[] bs) - { - uint hi = BE_To_UInt32(bs); - uint lo = BE_To_UInt32(bs, 4); - return ((ulong)hi << 32) | (ulong)lo; - } - - internal static ulong BE_To_UInt64(byte[] bs, int off) - { - uint hi = BE_To_UInt32(bs, off); - uint lo = BE_To_UInt32(bs, off + 4); - return ((ulong)hi << 32) | (ulong)lo; - } - - internal static void BE_To_UInt64(byte[] bs, int off, ulong[] ns) - { - for (int i = 0; i < ns.Length; ++i) - { - ns[i] = BE_To_UInt64(bs, off); - off += 8; - } - } - - internal static void UInt16_To_LE(ushort n, byte[] bs) - { - bs[0] = (byte)(n); - bs[1] = (byte)(n >> 8); - } - - internal static void UInt16_To_LE(ushort n, byte[] bs, int off) - { - bs[off] = (byte)(n); - bs[off + 1] = (byte)(n >> 8); - } - - internal static ushort LE_To_UInt16(byte[] bs) - { - uint n = (uint)bs[0] - | (uint)bs[1] << 8; - return (ushort)n; - } - - internal static ushort LE_To_UInt16(byte[] bs, int off) - { - uint n = (uint)bs[off] - | (uint)bs[off + 1] << 8; - return (ushort)n; - } - - internal static byte[] UInt32_To_LE(uint n) - { - byte[] bs = new byte[4]; - UInt32_To_LE(n, bs, 0); - return bs; - } - - internal static void UInt32_To_LE(uint n, byte[] bs) - { - bs[0] = (byte)(n); - bs[1] = (byte)(n >> 8); - bs[2] = (byte)(n >> 16); - bs[3] = (byte)(n >> 24); - } - - internal static void UInt32_To_LE(uint n, byte[] bs, int off) - { - bs[off] = (byte)(n); - bs[off + 1] = (byte)(n >> 8); - bs[off + 2] = (byte)(n >> 16); - bs[off + 3] = (byte)(n >> 24); - } - - internal static byte[] UInt32_To_LE(uint[] ns) - { - byte[] bs = new byte[4 * ns.Length]; - UInt32_To_LE(ns, bs, 0); - return bs; - } - - internal static void UInt32_To_LE(uint[] ns, byte[] bs, int off) - { - for (int i = 0; i < ns.Length; ++i) - { - UInt32_To_LE(ns[i], bs, off); - off += 4; - } - } - - internal static uint LE_To_UInt32(byte[] bs) - { - return (uint)bs[0] - | (uint)bs[1] << 8 - | (uint)bs[2] << 16 - | (uint)bs[3] << 24; - } - - internal static uint LE_To_UInt32(byte[] bs, int off) - { - return (uint)bs[off] - | (uint)bs[off + 1] << 8 - | (uint)bs[off + 2] << 16 - | (uint)bs[off + 3] << 24; - } - - internal static void LE_To_UInt32(byte[] bs, int off, uint[] ns) - { - for (int i = 0; i < ns.Length; ++i) - { - ns[i] = LE_To_UInt32(bs, off); - off += 4; - } - } - - internal static void LE_To_UInt32(byte[] bs, int bOff, uint[] ns, int nOff, int count) - { - for (int i = 0; i < count; ++i) - { - ns[nOff + i] = LE_To_UInt32(bs, bOff); - bOff += 4; - } - } - - internal static uint[] LE_To_UInt32(byte[] bs, int off, int count) - { - uint[] ns = new uint[count]; - for (int i = 0; i < ns.Length; ++i) - { - ns[i] = LE_To_UInt32(bs, off); - off += 4; - } - return ns; - } - - internal static byte[] UInt64_To_LE(ulong n) - { - byte[] bs = new byte[8]; - UInt64_To_LE(n, bs, 0); - return bs; - } - - internal static void UInt64_To_LE(ulong n, byte[] bs) - { - UInt32_To_LE((uint)(n), bs); - UInt32_To_LE((uint)(n >> 32), bs, 4); - } - - internal static void UInt64_To_LE(ulong n, byte[] bs, int off) - { - UInt32_To_LE((uint)(n), bs, off); - UInt32_To_LE((uint)(n >> 32), bs, off + 4); - } - - internal static byte[] UInt64_To_LE(ulong[] ns) - { - byte[] bs = new byte[8 * ns.Length]; - UInt64_To_LE(ns, bs, 0); - return bs; - } - - internal static void UInt64_To_LE(ulong[] ns, byte[] bs, int off) - { - for (int i = 0; i < ns.Length; ++i) - { - UInt64_To_LE(ns[i], bs, off); - off += 8; - } - } - - internal static void UInt64_To_LE(ulong[] ns, int nsOff, int nsLen, byte[] bs, int bsOff) - { - for (int i = 0; i < nsLen; ++i) - { - UInt64_To_LE(ns[nsOff + i], bs, bsOff); - bsOff += 8; - } - } - - internal static ulong LE_To_UInt64(byte[] bs) - { - uint lo = LE_To_UInt32(bs); - uint hi = LE_To_UInt32(bs, 4); - return ((ulong)hi << 32) | (ulong)lo; - } - - internal static ulong LE_To_UInt64(byte[] bs, int off) - { - uint lo = LE_To_UInt32(bs, off); - uint hi = LE_To_UInt32(bs, off + 4); - return ((ulong)hi << 32) | (ulong)lo; - } - - internal static void LE_To_UInt64(byte[] bs, int off, ulong[] ns) - { - for (int i = 0; i < ns.Length; ++i) - { - ns[i] = LE_To_UInt64(bs, off); - off += 8; - } - } - - internal static void LE_To_UInt64(byte[] bs, int bsOff, ulong[] ns, int nsOff, int nsLen) - { - for (int i = 0; i < nsLen; ++i) - { - ns[nsOff + i] = LE_To_UInt64(bs, bsOff); - bsOff += 8; - } - } - } -} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/BigInteger.cs b/src/Renci.SshNet/Security/BouncyCastle/math/BigInteger.cs deleted file mode 100644 index a947d590d..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/BigInteger.cs +++ /dev/null @@ -1,3605 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.Text; - -using Renci.SshNet.Security.Org.BouncyCastle.Security; -using Renci.SshNet.Security.Org.BouncyCastle.Utilities; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math -{ -#if NETFRAMEWORK - [Serializable] -#endif - internal class BigInteger - { - // The first few odd primes - /* - 3 5 7 11 13 17 19 23 29 - 31 37 41 43 47 53 59 61 67 71 - 73 79 83 89 97 101 103 107 109 113 - 127 131 137 139 149 151 157 163 167 173 - 179 181 191 193 197 199 211 223 227 229 - 233 239 241 251 257 263 269 271 277 281 - 283 293 307 311 313 317 331 337 347 349 - 353 359 367 373 379 383 389 397 401 409 - 419 421 431 433 439 443 449 457 461 463 - 467 479 487 491 499 503 509 521 523 541 - 547 557 563 569 571 577 587 593 599 601 - 607 613 617 619 631 641 643 647 653 659 - 661 673 677 683 691 701 709 719 727 733 - 739 743 751 757 761 769 773 787 797 809 - 811 821 823 827 829 839 853 857 859 863 - 877 881 883 887 907 911 919 929 937 941 - 947 953 967 971 977 983 991 997 1009 - 1013 1019 1021 1031 1033 1039 1049 1051 - 1061 1063 1069 1087 1091 1093 1097 1103 - 1109 1117 1123 1129 1151 1153 1163 1171 - 1181 1187 1193 1201 1213 1217 1223 1229 - 1231 1237 1249 1259 1277 1279 1283 1289 - */ - - // Each list has a product < 2^31 - internal static readonly int[][] primeLists = new int[][] - { - new int[]{ 3, 5, 7, 11, 13, 17, 19, 23 }, - new int[]{ 29, 31, 37, 41, 43 }, - new int[]{ 47, 53, 59, 61, 67 }, - new int[]{ 71, 73, 79, 83 }, - new int[]{ 89, 97, 101, 103 }, - - new int[]{ 107, 109, 113, 127 }, - new int[]{ 131, 137, 139, 149 }, - new int[]{ 151, 157, 163, 167 }, - new int[]{ 173, 179, 181, 191 }, - new int[]{ 193, 197, 199, 211 }, - - new int[]{ 223, 227, 229 }, - new int[]{ 233, 239, 241 }, - new int[]{ 251, 257, 263 }, - new int[]{ 269, 271, 277 }, - new int[]{ 281, 283, 293 }, - - new int[]{ 307, 311, 313 }, - new int[]{ 317, 331, 337 }, - new int[]{ 347, 349, 353 }, - new int[]{ 359, 367, 373 }, - new int[]{ 379, 383, 389 }, - - new int[]{ 397, 401, 409 }, - new int[]{ 419, 421, 431 }, - new int[]{ 433, 439, 443 }, - new int[]{ 449, 457, 461 }, - new int[]{ 463, 467, 479 }, - - new int[]{ 487, 491, 499 }, - new int[]{ 503, 509, 521 }, - new int[]{ 523, 541, 547 }, - new int[]{ 557, 563, 569 }, - new int[]{ 571, 577, 587 }, - - new int[]{ 593, 599, 601 }, - new int[]{ 607, 613, 617 }, - new int[]{ 619, 631, 641 }, - new int[]{ 643, 647, 653 }, - new int[]{ 659, 661, 673 }, - - new int[]{ 677, 683, 691 }, - new int[]{ 701, 709, 719 }, - new int[]{ 727, 733, 739 }, - new int[]{ 743, 751, 757 }, - new int[]{ 761, 769, 773 }, - - new int[]{ 787, 797, 809 }, - new int[]{ 811, 821, 823 }, - new int[]{ 827, 829, 839 }, - new int[]{ 853, 857, 859 }, - new int[]{ 863, 877, 881 }, - - new int[]{ 883, 887, 907 }, - new int[]{ 911, 919, 929 }, - new int[]{ 937, 941, 947 }, - new int[]{ 953, 967, 971 }, - new int[]{ 977, 983, 991 }, - - new int[]{ 997, 1009, 1013 }, - new int[]{ 1019, 1021, 1031 }, - new int[]{ 1033, 1039, 1049 }, - new int[]{ 1051, 1061, 1063 }, - new int[]{ 1069, 1087, 1091 }, - - new int[]{ 1093, 1097, 1103 }, - new int[]{ 1109, 1117, 1123 }, - new int[]{ 1129, 1151, 1153 }, - new int[]{ 1163, 1171, 1181 }, - new int[]{ 1187, 1193, 1201 }, - - new int[]{ 1213, 1217, 1223 }, - new int[]{ 1229, 1231, 1237 }, - new int[]{ 1249, 1259, 1277 }, - new int[]{ 1279, 1283, 1289 }, - }; - - internal static readonly int[] primeProducts; - - private const long IMASK = 0xFFFFFFFFL; - private const ulong UIMASK = 0xFFFFFFFFUL; - - private static readonly int[] ZeroMagnitude = new int[0]; - private static readonly byte[] ZeroEncoding = new byte[0]; - - private static readonly BigInteger[] SMALL_CONSTANTS = new BigInteger[17]; - public static readonly BigInteger Zero; - public static readonly BigInteger One; - public static readonly BigInteger Two; - public static readonly BigInteger Three; - public static readonly BigInteger Ten; - - //private readonly static byte[] BitCountTable = - //{ - // 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, - // 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - // 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - // 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - // 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - // 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - // 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - // 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - // 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - // 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - // 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - // 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - // 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - // 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - // 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - // 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 - //}; - - private readonly static byte[] BitLengthTable = - { - 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 - }; - - // TODO Parse radix-2 64 bits at a time and radix-8 63 bits at a time - private const int chunk2 = 1, chunk8 = 1, chunk10 = 19, chunk16 = 16; - private static readonly BigInteger radix2, radix2E, radix8, radix8E, radix10, radix10E, radix16, radix16E; - - private static readonly SecureRandom RandomSource = new SecureRandom(); - - /* - * These are the threshold bit-lengths (of an exponent) where we increase the window size. - * They are calculated according to the expected savings in multiplications. - * Some squares will also be saved on average, but we offset these against the extra storage costs. - */ - private static readonly int[] ExpWindowThresholds = { 7, 25, 81, 241, 673, 1793, 4609, Int32.MaxValue }; - - private const int BitsPerByte = 8; - private const int BitsPerInt = 32; - private const int BytesPerInt = 4; - - static BigInteger() - { - Zero = new BigInteger(0, ZeroMagnitude, false); - Zero.nBits = 0; Zero.nBitLength = 0; - - SMALL_CONSTANTS[0] = Zero; - for (uint i = 1; i < SMALL_CONSTANTS.Length; ++i) - { - SMALL_CONSTANTS[i] = CreateUValueOf(i); - } - - One = SMALL_CONSTANTS[1]; - Two = SMALL_CONSTANTS[2]; - Three = SMALL_CONSTANTS[3]; - Ten = SMALL_CONSTANTS[10]; - - radix2 = ValueOf(2); - radix2E = radix2.Pow(chunk2); - - radix8 = ValueOf(8); - radix8E = radix8.Pow(chunk8); - - radix10 = ValueOf(10); - radix10E = radix10.Pow(chunk10); - - radix16 = ValueOf(16); - radix16E = radix16.Pow(chunk16); - - primeProducts = new int[primeLists.Length]; - - for (int i = 0; i < primeLists.Length; ++i) - { - int[] primeList = primeLists[i]; - int product = primeList[0]; - for (int j = 1; j < primeList.Length; ++j) - { - product *= primeList[j]; - } - primeProducts[i] = product; - } - } - - private int[] magnitude; // array of ints with [0] being the most significant - private int sign; // -1 means -ve; +1 means +ve; 0 means 0; - private int nBits = -1; // cache BitCount() value - private int nBitLength = -1; // cache BitLength() value - private int mQuote = 0; // -m^(-1) mod b, b = 2^32 (see Montgomery mult.), 0 when uninitialised - - private static int GetByteLength( - int nBits) - { - return (nBits + BitsPerByte - 1) / BitsPerByte; - } - - internal static BigInteger Arbitrary(int sizeInBits) - { - return new BigInteger(sizeInBits, RandomSource); - } - - private BigInteger( - int signum, - int[] mag, - bool checkMag) - { - if (checkMag) - { - int i = 0; - while (i < mag.Length && mag[i] == 0) - { - ++i; - } - - if (i == mag.Length) - { - this.sign = 0; - this.magnitude = ZeroMagnitude; - } - else - { - this.sign = signum; - - if (i == 0) - { - this.magnitude = mag; - } - else - { - // strip leading 0 words - this.magnitude = new int[mag.Length - i]; - Array.Copy(mag, i, this.magnitude, 0, this.magnitude.Length); - } - } - } - else - { - this.sign = signum; - this.magnitude = mag; - } - } - - public BigInteger( - string value) - : this(value, 10) - { - } - - public BigInteger( - string str, - int radix) - { - if (str.Length == 0) - throw new FormatException("Zero length BigInteger"); - - NumberStyles style; - int chunk; - BigInteger r; - BigInteger rE; - - switch (radix) - { - case 2: - // Is there anyway to restrict to binary digits? - style = NumberStyles.Integer; - chunk = chunk2; - r = radix2; - rE = radix2E; - break; - case 8: - // Is there anyway to restrict to octal digits? - style = NumberStyles.Integer; - chunk = chunk8; - r = radix8; - rE = radix8E; - break; - case 10: - // This style seems to handle spaces and minus sign already (our processing redundant?) - style = NumberStyles.Integer; - chunk = chunk10; - r = radix10; - rE = radix10E; - break; - case 16: - // TODO Should this be HexNumber? - style = NumberStyles.AllowHexSpecifier; - chunk = chunk16; - r = radix16; - rE = radix16E; - break; - default: - throw new FormatException("Only bases 2, 8, 10, or 16 allowed"); - } - - - int index = 0; - sign = 1; - - if (str[0] == '-') - { - if (str.Length == 1) - throw new FormatException("Zero length BigInteger"); - - sign = -1; - index = 1; - } - - // strip leading zeros from the string str - while (index < str.Length && Int32.Parse(str[index].ToString(), style) == 0) - { - index++; - } - - if (index >= str.Length) - { - // zero value - we're done - sign = 0; - magnitude = ZeroMagnitude; - return; - } - - ////// - // could we work out the max number of ints required to store - // str.Length digits in the given base, then allocate that - // storage in one hit?, then Generate the magnitude in one hit too? - ////// - - BigInteger b = Zero; - - - int next = index + chunk; - - if (next <= str.Length) - { - do - { - string s = str.Substring(index, chunk); - ulong i = ulong.Parse(s, style); - BigInteger bi = CreateUValueOf(i); - - switch (radix) - { - case 2: - // TODO Need this because we are parsing in radix 10 above - if (i >= 2) - throw new FormatException("Bad character in radix 2 string: " + s); - - // TODO Parse 64 bits at a time - b = b.ShiftLeft(1); - break; - case 8: - // TODO Need this because we are parsing in radix 10 above - if (i >= 8) - throw new FormatException("Bad character in radix 8 string: " + s); - - // TODO Parse 63 bits at a time - b = b.ShiftLeft(3); - break; - case 16: - b = b.ShiftLeft(64); - break; - default: - b = b.Multiply(rE); - break; - } - - b = b.Add(bi); - - index = next; - next += chunk; - } - while (next <= str.Length); - } - - if (index < str.Length) - { - string s = str.Substring(index); - ulong i = ulong.Parse(s, style); - BigInteger bi = CreateUValueOf(i); - - if (b.sign > 0) - { - if (radix == 2) - { - // NB: Can't reach here since we are parsing one char at a time - Debug.Assert(false); - - // TODO Parse all bits at once -// b = b.ShiftLeft(s.Length); - } - else if (radix == 8) - { - // NB: Can't reach here since we are parsing one char at a time - Debug.Assert(false); - - // TODO Parse all bits at once -// b = b.ShiftLeft(s.Length * 3); - } - else if (radix == 16) - { - b = b.ShiftLeft(s.Length << 2); - } - else - { - b = b.Multiply(r.Pow(s.Length)); - } - - b = b.Add(bi); - } - else - { - b = bi; - } - } - - // Note: This is the previous (slower) algorithm -// while (index < value.Length) -// { -// char c = value[index]; -// string s = c.ToString(); -// int i = Int32.Parse(s, style); -// -// b = b.Multiply(r).Add(ValueOf(i)); -// index++; -// } - - magnitude = b.magnitude; - } - - public BigInteger( - byte[] bytes) - : this(bytes, 0, bytes.Length) - { - } - - public BigInteger( - byte[] bytes, - int offset, - int length) - { - if (length == 0) - throw new FormatException("Zero length BigInteger"); - - // TODO Move this processing into MakeMagnitude (provide sign argument) - if ((sbyte)bytes[offset] < 0) - { - this.sign = -1; - - int end = offset + length; - - int iBval; - // strip leading sign bytes - for (iBval = offset; iBval < end && ((sbyte)bytes[iBval] == -1); iBval++) - { - } - - if (iBval >= end) - { - this.magnitude = One.magnitude; - } - else - { - int numBytes = end - iBval; - byte[] inverse = new byte[numBytes]; - - int index = 0; - while (index < numBytes) - { - inverse[index++] = (byte)~bytes[iBval++]; - } - - Debug.Assert(iBval == end); - - while (inverse[--index] == byte.MaxValue) - { - inverse[index] = byte.MinValue; - } - - inverse[index]++; - - this.magnitude = MakeMagnitude(inverse, 0, inverse.Length); - } - } - else - { - // strip leading zero bytes and return magnitude bytes - this.magnitude = MakeMagnitude(bytes, offset, length); - this.sign = this.magnitude.Length > 0 ? 1 : 0; - } - } - - private static int[] MakeMagnitude( - byte[] bytes, - int offset, - int length) - { - int end = offset + length; - - // strip leading zeros - int firstSignificant; - for (firstSignificant = offset; firstSignificant < end - && bytes[firstSignificant] == 0; firstSignificant++) - { - } - - if (firstSignificant >= end) - { - return ZeroMagnitude; - } - - int nInts = (end - firstSignificant + 3) / BytesPerInt; - int bCount = (end - firstSignificant) % BytesPerInt; - if (bCount == 0) - { - bCount = BytesPerInt; - } - - if (nInts < 1) - { - return ZeroMagnitude; - } - - int[] mag = new int[nInts]; - - int v = 0; - int magnitudeIndex = 0; - for (int i = firstSignificant; i < end; ++i) - { - v <<= 8; - v |= bytes[i] & 0xff; - bCount--; - if (bCount <= 0) - { - mag[magnitudeIndex] = v; - magnitudeIndex++; - bCount = BytesPerInt; - v = 0; - } - } - - if (magnitudeIndex < mag.Length) - { - mag[magnitudeIndex] = v; - } - - return mag; - } - - public BigInteger( - int sign, - byte[] bytes) - : this(sign, bytes, 0, bytes.Length) - { - } - - public BigInteger( - int sign, - byte[] bytes, - int offset, - int length) - { - if (sign < -1 || sign > 1) - throw new FormatException("Invalid sign value"); - - if (sign == 0) - { - this.sign = 0; - this.magnitude = ZeroMagnitude; - } - else - { - // copy bytes - this.magnitude = MakeMagnitude(bytes, offset, length); - this.sign = this.magnitude.Length < 1 ? 0 : sign; - } - } - - public BigInteger( - int sizeInBits, - Random random) - { - if (sizeInBits < 0) - throw new ArgumentException("sizeInBits must be non-negative"); - - this.nBits = -1; - this.nBitLength = -1; - - if (sizeInBits == 0) - { - this.sign = 0; - this.magnitude = ZeroMagnitude; - return; - } - - int nBytes = GetByteLength(sizeInBits); - byte[] b = new byte[nBytes]; -#pragma warning disable CA5394 // Do not use insecure randomness - random.NextBytes(b); -#pragma warning restore CA5394 // Do not use insecure randomness - - // strip off any excess bits in the MSB - int xBits = BitsPerByte * nBytes - sizeInBits; - b[0] &= (byte)(255U >> xBits); - - this.magnitude = MakeMagnitude(b, 0, b.Length); - this.sign = this.magnitude.Length < 1 ? 0 : 1; - } - -#pragma warning disable CA5394 // Do not use insecure randomness - public BigInteger( - int bitLength, - int certainty, - Random random) - { - if (bitLength < 2) - throw new ArithmeticException("bitLength < 2"); - - this.sign = 1; - this.nBitLength = bitLength; - - if (bitLength == 2) - { - this.magnitude = random.Next(2) == 0 - ? Two.magnitude - : Three.magnitude; - return; - } - - int nBytes = GetByteLength(bitLength); - byte[] b = new byte[nBytes]; - - int xBits = BitsPerByte * nBytes - bitLength; - byte mask = (byte)(255U >> xBits); - byte lead = (byte)(1 << (7 - xBits)); - - for (;;) - { - random.NextBytes(b); - - // strip off any excess bits in the MSB - b[0] &= mask; - - // ensure the leading bit is 1 (to meet the strength requirement) - b[0] |= lead; - - // ensure the trailing bit is 1 (i.e. must be odd) - b[nBytes - 1] |= 1; - - this.magnitude = MakeMagnitude(b, 0, b.Length); - this.nBits = -1; - this.mQuote = 0; - - if (certainty < 1) - break; - - if (CheckProbablePrime(certainty, random, true)) - break; - - for (int j = 1; j < (magnitude.Length - 1); ++j) - { - this.magnitude[j] ^= random.Next(); - - if (CheckProbablePrime(certainty, random, true)) - return; - } - } - } -#pragma warning restore CA5394 // Do not use insecure randomness - - public BigInteger Abs() - { - return sign >= 0 ? this : Negate(); - } - - /** - * return a = a + b - b preserved. - */ - private static int[] AddMagnitudes( - int[] a, - int[] b) - { - int tI = a.Length - 1; - int vI = b.Length - 1; - long m = 0; - - while (vI >= 0) - { - m += ((long)(uint)a[tI] + (long)(uint)b[vI--]); - a[tI--] = (int)m; - m = (long)((ulong)m >> 32); - } - - if (m != 0) - { - while (tI >= 0 && ++a[tI--] == 0) - { - } - } - - return a; - } - - public BigInteger Add( - BigInteger value) - { - if (this.sign == 0) - return value; - - if (this.sign != value.sign) - { - if (value.sign == 0) - return this; - - if (value.sign < 0) - return Subtract(value.Negate()); - - return value.Subtract(Negate()); - } - - return AddToMagnitude(value.magnitude); - } - - private BigInteger AddToMagnitude( - int[] magToAdd) - { - int[] big, small; - if (this.magnitude.Length < magToAdd.Length) - { - big = magToAdd; - small = this.magnitude; - } - else - { - big = this.magnitude; - small = magToAdd; - } - - // Conservatively avoid over-allocation when no overflow possible - uint limit = uint.MaxValue; - if (big.Length == small.Length) - limit -= (uint) small[0]; - - bool possibleOverflow = (uint) big[0] >= limit; - - int[] bigCopy; - if (possibleOverflow) - { - bigCopy = new int[big.Length + 1]; - big.CopyTo(bigCopy, 1); - } - else - { - bigCopy = (int[]) big.Clone(); - } - - bigCopy = AddMagnitudes(bigCopy, small); - - return new BigInteger(this.sign, bigCopy, possibleOverflow); - } - - public BigInteger And( - BigInteger value) - { - if (this.sign == 0 || value.sign == 0) - { - return Zero; - } - - int[] aMag = this.sign > 0 - ? this.magnitude - : Add(One).magnitude; - - int[] bMag = value.sign > 0 - ? value.magnitude - : value.Add(One).magnitude; - - bool resultNeg = sign < 0 && value.sign < 0; - int resultLength = System.Math.Max(aMag.Length, bMag.Length); - int[] resultMag = new int[resultLength]; - - int aStart = resultMag.Length - aMag.Length; - int bStart = resultMag.Length - bMag.Length; - - for (int i = 0; i < resultMag.Length; ++i) - { - int aWord = i >= aStart ? aMag[i - aStart] : 0; - int bWord = i >= bStart ? bMag[i - bStart] : 0; - - if (this.sign < 0) - { - aWord = ~aWord; - } - - if (value.sign < 0) - { - bWord = ~bWord; - } - - resultMag[i] = aWord & bWord; - - if (resultNeg) - { - resultMag[i] = ~resultMag[i]; - } - } - - BigInteger result = new BigInteger(1, resultMag, true); - - // TODO Optimise this case - if (resultNeg) - { - result = result.Not(); - } - - return result; - } - - public BigInteger AndNot( - BigInteger val) - { - return And(val.Not()); - } - - public int BitCount - { - get - { - if (nBits == -1) - { - if (sign < 0) - { - // TODO Optimise this case - nBits = Not().BitCount; - } - else - { - int sum = 0; - for (int i = 0; i < magnitude.Length; ++i) - { - sum += BitCnt(magnitude[i]); - } - nBits = sum; - } - } - - return nBits; - } - } - - public static int BitCnt(int i) - { - uint u = (uint)i; - u = u - ((u >> 1) & 0x55555555); - u = (u & 0x33333333) + ((u >> 2) & 0x33333333); - u = (u + (u >> 4)) & 0x0f0f0f0f; - u += (u >> 8); - u += (u >> 16); - u &= 0x3f; - return (int)u; - } - - private static int CalcBitLength(int sign, int indx, int[] mag) - { - for (;;) - { - if (indx >= mag.Length) - return 0; - - if (mag[indx] != 0) - break; - - ++indx; - } - - // bit length for everything after the first int - int bitLength = 32 * ((mag.Length - indx) - 1); - - // and determine bitlength of first int - int firstMag = mag[indx]; - bitLength += BitLen(firstMag); - - // Check for negative powers of two - if (sign < 0 && ((firstMag & -firstMag) == firstMag)) - { - do - { - if (++indx >= mag.Length) - { - --bitLength; - break; - } - } - while (mag[indx] == 0); - } - - return bitLength; - } - - public int BitLength - { - get - { - if (nBitLength == -1) - { - nBitLength = sign == 0 - ? 0 - : CalcBitLength(sign, 0, magnitude); - } - - return nBitLength; - } - } - - // - // BitLen(value) is the number of bits in value. - // - internal static int BitLen(int w) - { - uint v = (uint)w; - uint t = v >> 24; - if (t != 0) - return 24 + BitLengthTable[t]; - t = v >> 16; - if (t != 0) - return 16 + BitLengthTable[t]; - t = v >> 8; - if (t != 0) - return 8 + BitLengthTable[t]; - return BitLengthTable[v]; - } - - private bool QuickPow2Check() - { - return sign > 0 && nBits == 1; - } - - public int CompareTo( - object obj) - { - return CompareTo((BigInteger)obj); - } - - /** - * unsigned comparison on two arrays - note the arrays may - * start with leading zeros. - */ - private static int CompareTo( - int xIndx, - int[] x, - int yIndx, - int[] y) - { - while (xIndx != x.Length && x[xIndx] == 0) - { - xIndx++; - } - - while (yIndx != y.Length && y[yIndx] == 0) - { - yIndx++; - } - - return CompareNoLeadingZeroes(xIndx, x, yIndx, y); - } - - private static int CompareNoLeadingZeroes( - int xIndx, - int[] x, - int yIndx, - int[] y) - { - int diff = (x.Length - y.Length) - (xIndx - yIndx); - - if (diff != 0) - { - return diff < 0 ? -1 : 1; - } - - // lengths of magnitudes the same, test the magnitude values - - while (xIndx < x.Length) - { - uint v1 = (uint)x[xIndx++]; - uint v2 = (uint)y[yIndx++]; - - if (v1 != v2) - return v1 < v2 ? -1 : 1; - } - - return 0; - } - - public int CompareTo( - BigInteger value) - { - return sign < value.sign ? -1 - : sign > value.sign ? 1 - : sign == 0 ? 0 - : sign * CompareNoLeadingZeroes(0, magnitude, 0, value.magnitude); - } - - /** - * return z = x / y - done in place (z value preserved, x contains the - * remainder) - */ - private int[] Divide( - int[] x, - int[] y) - { - int xStart = 0; - while (xStart < x.Length && x[xStart] == 0) - { - ++xStart; - } - - int yStart = 0; - while (yStart < y.Length && y[yStart] == 0) - { - ++yStart; - } - - Debug.Assert(yStart < y.Length); - - int xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y); - int[] count; - - if (xyCmp > 0) - { - int yBitLength = CalcBitLength(1, yStart, y); - int xBitLength = CalcBitLength(1, xStart, x); - int shift = xBitLength - yBitLength; - - int[] iCount; - int iCountStart = 0; - - int[] c; - int cStart = 0; - int cBitLength = yBitLength; - if (shift > 0) - { -// iCount = ShiftLeft(One.magnitude, shift); - iCount = new int[(shift >> 5) + 1]; - iCount[0] = 1 << (shift % 32); - - c = ShiftLeft(y, shift); - cBitLength += shift; - } - else - { - iCount = new int[] { 1 }; - - int len = y.Length - yStart; - c = new int[len]; - Array.Copy(y, yStart, c, 0, len); - } - - count = new int[iCount.Length]; - - for (;;) - { - if (cBitLength < xBitLength - || CompareNoLeadingZeroes(xStart, x, cStart, c) >= 0) - { - Subtract(xStart, x, cStart, c); - AddMagnitudes(count, iCount); - - while (x[xStart] == 0) - { - if (++xStart == x.Length) - return count; - } - - //xBitLength = CalcBitLength(xStart, x); - xBitLength = 32 * (x.Length - xStart - 1) + BitLen(x[xStart]); - - if (xBitLength <= yBitLength) - { - if (xBitLength < yBitLength) - return count; - - xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y); - - if (xyCmp <= 0) - break; - } - } - - shift = cBitLength - xBitLength; - - // NB: The case where c[cStart] is 1-bit is harmless - if (shift == 1) - { - uint firstC = (uint) c[cStart] >> 1; - uint firstX = (uint) x[xStart]; - if (firstC > firstX) - ++shift; - } - - if (shift < 2) - { - ShiftRightOneInPlace(cStart, c); - --cBitLength; - ShiftRightOneInPlace(iCountStart, iCount); - } - else - { - ShiftRightInPlace(cStart, c, shift); - cBitLength -= shift; - ShiftRightInPlace(iCountStart, iCount, shift); - } - - //cStart = c.Length - ((cBitLength + 31) / 32); - while (c[cStart] == 0) - { - ++cStart; - } - - while (iCount[iCountStart] == 0) - { - ++iCountStart; - } - } - } - else - { - count = new int[1]; - } - - if (xyCmp == 0) - { - AddMagnitudes(count, One.magnitude); - Array.Clear(x, xStart, x.Length - xStart); - } - - return count; - } - - public BigInteger Divide( - BigInteger val) - { - if (val.sign == 0) - throw new ArithmeticException("Division by zero error"); - - if (sign == 0) - return Zero; - - if (val.QuickPow2Check()) // val is power of two - { - BigInteger result = this.Abs().ShiftRight(val.Abs().BitLength - 1); - return val.sign == this.sign ? result : result.Negate(); - } - - int[] mag = (int[]) this.magnitude.Clone(); - - return new BigInteger(this.sign * val.sign, Divide(mag, val.magnitude), true); - } - - public BigInteger[] DivideAndRemainder( - BigInteger val) - { - if (val.sign == 0) - throw new ArithmeticException("Division by zero error"); - - BigInteger[] biggies = new BigInteger[2]; - - if (sign == 0) - { - biggies[0] = Zero; - biggies[1] = Zero; - } - else if (val.QuickPow2Check()) // val is power of two - { - int e = val.Abs().BitLength - 1; - BigInteger quotient = this.Abs().ShiftRight(e); - int[] remainder = this.LastNBits(e); - - biggies[0] = val.sign == this.sign ? quotient : quotient.Negate(); - biggies[1] = new BigInteger(this.sign, remainder, true); - } - else - { - int[] remainder = (int[]) this.magnitude.Clone(); - int[] quotient = Divide(remainder, val.magnitude); - - biggies[0] = new BigInteger(this.sign * val.sign, quotient, true); - biggies[1] = new BigInteger(this.sign, remainder, true); - } - - return biggies; - } - - public override bool Equals( - object obj) - { - if (obj == this) - return true; - - BigInteger biggie = obj as BigInteger; - if (biggie == null) - return false; - - return sign == biggie.sign && IsEqualMagnitude(biggie); - } - - private bool IsEqualMagnitude(BigInteger x) - { - int[] xMag = x.magnitude; - if (magnitude.Length != x.magnitude.Length) - return false; - for (int i = 0; i < magnitude.Length; i++) - { - if (magnitude[i] != x.magnitude[i]) - return false; - } - return true; - } - - public BigInteger Gcd( - BigInteger value) - { - if (value.sign == 0) - return Abs(); - - if (sign == 0) - return value.Abs(); - - BigInteger r; - BigInteger u = this; - BigInteger v = value; - - while (v.sign != 0) - { - r = u.Mod(v); - u = v; - v = r; - } - - return u; - } - - public override int GetHashCode() - { - int hc = magnitude.Length; - if (magnitude.Length > 0) - { - hc ^= magnitude[0]; - - if (magnitude.Length > 1) - { - hc ^= magnitude[magnitude.Length - 1]; - } - } - - return sign < 0 ? ~hc : hc; - } - - // TODO Make public? - private BigInteger Inc() - { - if (this.sign == 0) - return One; - - if (this.sign < 0) - return new BigInteger(-1, doSubBigLil(this.magnitude, One.magnitude), true); - - return AddToMagnitude(One.magnitude); - } - - public int IntValue - { - get - { - if (sign == 0) - return 0; - - int n = magnitude.Length; - - int v = magnitude[n - 1]; - - return sign < 0 ? -v : v; - } - } - - /** - * return whether or not a BigInteger is probably prime with a - * probability of 1 - (1/2)**certainty. - * From Knuth Vol 2, pg 395. - */ - public bool IsProbablePrime(int certainty) - { - return IsProbablePrime(certainty, false); - } - - internal bool IsProbablePrime(int certainty, bool randomlySelected) - { - if (certainty <= 0) - return true; - - BigInteger n = Abs(); - - if (!n.TestBit(0)) - return n.Equals(Two); - - if (n.Equals(One)) - return false; - - return n.CheckProbablePrime(certainty, RandomSource, randomlySelected); - } - - private bool CheckProbablePrime(int certainty, Random random, bool randomlySelected) - { - Debug.Assert(certainty > 0); - Debug.Assert(CompareTo(Two) > 0); - Debug.Assert(TestBit(0)); - - - // Try to reduce the penalty for really small numbers - int numLists = System.Math.Min(BitLength - 1, primeLists.Length); - - for (int i = 0; i < numLists; ++i) - { - int test = Remainder(primeProducts[i]); - - int[] primeList = primeLists[i]; - for (int j = 0; j < primeList.Length; ++j) - { - int prime = primeList[j]; - int qRem = test % prime; - if (qRem == 0) - { - // We may find small numbers in the list - return BitLength < 16 && IntValue == prime; - } - } - } - - - // TODO Special case for < 10^16 (RabinMiller fixed list) -// if (BitLength < 30) -// { -// RabinMiller against 2, 3, 5, 7, 11, 13, 23 is sufficient -// } - - - // TODO Is it worth trying to create a hybrid of these two? - return RabinMillerTest(certainty, random, randomlySelected); -// return SolovayStrassenTest(certainty, random); - -// bool rbTest = RabinMillerTest(certainty, random); -// bool ssTest = SolovayStrassenTest(certainty, random); -// -// Debug.Assert(rbTest == ssTest); -// -// return rbTest; - } - - public bool RabinMillerTest(int certainty, Random random) - { - return RabinMillerTest(certainty, random, false); - } - - internal bool RabinMillerTest(int certainty, Random random, bool randomlySelected) - { - int bits = BitLength; - - Debug.Assert(certainty > 0); - Debug.Assert(bits > 2); - Debug.Assert(TestBit(0)); - - int iterations = ((certainty - 1) / 2) + 1; - if (randomlySelected) - { - int itersFor100Cert = bits >= 1024 ? 4 - : bits >= 512 ? 8 - : bits >= 256 ? 16 - : 50; - - if (certainty < 100) - { - iterations = System.Math.Min(itersFor100Cert, iterations); - } - else - { - iterations -= 50; - iterations += itersFor100Cert; - } - } - - // let n = 1 + d . 2^s - BigInteger n = this; - int s = n.GetLowestSetBitMaskFirst(-1 << 1); - Debug.Assert(s >= 1); - BigInteger r = n.ShiftRight(s); - - // NOTE: Avoid conversion to/from Montgomery form and check for R/-R as result instead - - BigInteger montRadix = One.ShiftLeft(32 * n.magnitude.Length).Remainder(n); - BigInteger minusMontRadix = n.Subtract(montRadix); - - do - { - BigInteger a; - do - { - a = new BigInteger(n.BitLength, random); - } - while (a.sign == 0 || a.CompareTo(n) >= 0 - || a.IsEqualMagnitude(montRadix) || a.IsEqualMagnitude(minusMontRadix)); - - BigInteger y = ModPowMonty(a, r, n, false); - - if (!y.Equals(montRadix)) - { - int j = 0; - while (!y.Equals(minusMontRadix)) - { - if (++j == s) - return false; - - y = ModPowMonty(y, Two, n, false); - - if (y.Equals(montRadix)) - return false; - } - } - } - while (--iterations > 0); - - return true; - } - -// private bool SolovayStrassenTest( -// int certainty, -// Random random) -// { -// Debug.Assert(certainty > 0); -// Debug.Assert(CompareTo(Two) > 0); -// Debug.Assert(TestBit(0)); -// -// BigInteger n = this; -// BigInteger nMinusOne = n.Subtract(One); -// BigInteger e = nMinusOne.ShiftRight(1); -// -// do -// { -// BigInteger a; -// do -// { -// a = new BigInteger(nBitLength, random); -// } -// // NB: Spec says 0 < x < n, but 1 is trivial -// while (a.CompareTo(One) <= 0 || a.CompareTo(n) >= 0); -// -// -// // TODO Check this is redundant given the way Jacobi() works? -//// if (!a.Gcd(n).Equals(One)) -//// return false; -// -// int x = Jacobi(a, n); -// -// if (x == 0) -// return false; -// -// BigInteger check = a.ModPow(e, n); -// -// if (x == 1 && !check.Equals(One)) -// return false; -// -// if (x == -1 && !check.Equals(nMinusOne)) -// return false; -// -// --certainty; -// } -// while (certainty > 0); -// -// return true; -// } -// -// private static int Jacobi( -// BigInteger a, -// BigInteger b) -// { -// Debug.Assert(a.sign >= 0); -// Debug.Assert(b.sign > 0); -// Debug.Assert(b.TestBit(0)); -// Debug.Assert(a.CompareTo(b) < 0); -// -// int totalS = 1; -// for (;;) -// { -// if (a.sign == 0) -// return 0; -// -// if (a.Equals(One)) -// break; -// -// int e = a.GetLowestSetBit(); -// -// int bLsw = b.magnitude[b.magnitude.Length - 1]; -// if ((e & 1) != 0 && ((bLsw & 7) == 3 || (bLsw & 7) == 5)) -// totalS = -totalS; -// -// // TODO Confirm this is faster than later a1.Equals(One) test -// if (a.BitLength == e + 1) -// break; -// BigInteger a1 = a.ShiftRight(e); -//// if (a1.Equals(One)) -//// break; -// -// int a1Lsw = a1.magnitude[a1.magnitude.Length - 1]; -// if ((bLsw & 3) == 3 && (a1Lsw & 3) == 3) -// totalS = -totalS; -// -//// a = b.Mod(a1); -// a = b.Remainder(a1); -// b = a1; -// } -// return totalS; -// } - - public long LongValue - { - get - { - if (sign == 0) - return 0; - - int n = magnitude.Length; - - long v = magnitude[n - 1] & IMASK; - if (n > 1) - { - v |= (magnitude[n - 2] & IMASK) << 32; - } - - return sign < 0 ? -v : v; - } - } - - public BigInteger Max( - BigInteger value) - { - return CompareTo(value) > 0 ? this : value; - } - - public BigInteger Min( - BigInteger value) - { - return CompareTo(value) < 0 ? this : value; - } - - public BigInteger Mod( - BigInteger m) - { - if (m.sign < 1) - throw new ArithmeticException("Modulus must be positive"); - - BigInteger biggie = Remainder(m); - - return (biggie.sign >= 0 ? biggie : biggie.Add(m)); - } - - public BigInteger ModInverse( - BigInteger m) - { - if (m.sign < 1) - throw new ArithmeticException("Modulus must be positive"); - - // TODO Too slow at the moment -// // "Fast Key Exchange with Elliptic Curve Systems" R.Schoeppel -// if (m.TestBit(0)) -// { -// //The Almost Inverse Algorithm -// int k = 0; -// BigInteger B = One, C = Zero, F = this, G = m, tmp; -// -// for (;;) -// { -// // While F is even, do F=F/u, C=C*u, k=k+1. -// int zeroes = F.GetLowestSetBit(); -// if (zeroes > 0) -// { -// F = F.ShiftRight(zeroes); -// C = C.ShiftLeft(zeroes); -// k += zeroes; -// } -// -// // If F = 1, then return B,k. -// if (F.Equals(One)) -// { -// BigInteger half = m.Add(One).ShiftRight(1); -// BigInteger halfK = half.ModPow(BigInteger.ValueOf(k), m); -// return B.Multiply(halfK).Mod(m); -// } -// -// if (F.CompareTo(G) < 0) -// { -// tmp = G; G = F; F = tmp; -// tmp = B; B = C; C = tmp; -// } -// -// F = F.Add(G); -// B = B.Add(C); -// } -// } - - if (m.QuickPow2Check()) - { - return ModInversePow2(m); - } - - BigInteger d = this.Remainder(m); - BigInteger x; - BigInteger gcd = ExtEuclid(d, m, out x); - - if (!gcd.Equals(One)) - throw new ArithmeticException("Numbers not relatively prime."); - - if (x.sign < 0) - { - x = x.Add(m); - } - - return x; - } - - private BigInteger ModInversePow2(BigInteger m) - { - Debug.Assert(m.SignValue > 0); - Debug.Assert(m.BitCount == 1); - - if (!TestBit(0)) - { - throw new ArithmeticException("Numbers not relatively prime."); - } - - int pow = m.BitLength - 1; - - long inv64 = ModInverse64(LongValue); - if (pow < 64) - { - inv64 &= ((1L << pow) - 1); - } - - BigInteger x = BigInteger.ValueOf(inv64); - - if (pow > 64) - { - BigInteger d = this.Remainder(m); - int bitsCorrect = 64; - - do - { - BigInteger t = x.Multiply(d).Remainder(m); - x = x.Multiply(Two.Subtract(t)).Remainder(m); - bitsCorrect <<= 1; - } - while (bitsCorrect < pow); - } - - if (x.sign < 0) - { - x = x.Add(m); - } - - return x; - } - - private static int ModInverse32(int d) - { - // Newton's method with initial estimate "correct to 4 bits" - Debug.Assert((d & 1) != 0); - int x = d + (((d + 1) & 4) << 1); // d.x == 1 mod 2**4 - Debug.Assert(((d * x) & 15) == 1); - x *= 2 - d * x; // d.x == 1 mod 2**8 - x *= 2 - d * x; // d.x == 1 mod 2**16 - x *= 2 - d * x; // d.x == 1 mod 2**32 - Debug.Assert(d * x == 1); - return x; - } - - private static long ModInverse64(long d) - { - // Newton's method with initial estimate "correct to 4 bits" - Debug.Assert((d & 1L) != 0); - long x = d + (((d + 1L) & 4L) << 1); // d.x == 1 mod 2**4 - Debug.Assert(((d * x) & 15L) == 1L); - x *= 2 - d * x; // d.x == 1 mod 2**8 - x *= 2 - d * x; // d.x == 1 mod 2**16 - x *= 2 - d * x; // d.x == 1 mod 2**32 - x *= 2 - d * x; // d.x == 1 mod 2**64 - Debug.Assert(d * x == 1L); - return x; - } - - /** - * Calculate the numbers u1, u2, and u3 such that: - * - * u1 * a + u2 * b = u3 - * - * where u3 is the greatest common divider of a and b. - * a and b using the extended Euclid algorithm (refer p. 323 - * of The Art of Computer Programming vol 2, 2nd ed). - * This also seems to have the side effect of calculating - * some form of multiplicative inverse. - * - * @param a First number to calculate gcd for - * @param b Second number to calculate gcd for - * @param u1Out the return object for the u1 value - * @return The greatest common divisor of a and b - */ - private static BigInteger ExtEuclid(BigInteger a, BigInteger b, out BigInteger u1Out) - { - BigInteger u1 = One, v1 = Zero; - BigInteger u3 = a, v3 = b; - - if (v3.sign > 0) - { - for (;;) - { - BigInteger[] q = u3.DivideAndRemainder(v3); - u3 = v3; - v3 = q[1]; - - BigInteger oldU1 = u1; - u1 = v1; - - if (v3.sign <= 0) - break; - - v1 = oldU1.Subtract(v1.Multiply(q[0])); - } - } - - u1Out = u1; - - return u3; - } - - private static void ZeroOut( - int[] x) - { - Array.Clear(x, 0, x.Length); - } - - public BigInteger ModPow(BigInteger e, BigInteger m) - { - if (m.sign < 1) - throw new ArithmeticException("Modulus must be positive"); - - if (m.Equals(One)) - return Zero; - - if (e.sign == 0) - return One; - - if (sign == 0) - return Zero; - - bool negExp = e.sign < 0; - if (negExp) - e = e.Negate(); - - BigInteger result = this.Mod(m); - if (!e.Equals(One)) - { - if ((m.magnitude[m.magnitude.Length - 1] & 1) == 0) - { - result = ModPowBarrett(result, e, m); - } - else - { - result = ModPowMonty(result, e, m, true); - } - } - - if (negExp) - result = result.ModInverse(m); - - return result; - } - - private static BigInteger ModPowBarrett(BigInteger b, BigInteger e, BigInteger m) - { - int k = m.magnitude.Length; - BigInteger mr = One.ShiftLeft((k + 1) << 5); - BigInteger yu = One.ShiftLeft(k << 6).Divide(m); - - // Sliding window from MSW to LSW - int extraBits = 0, expLength = e.BitLength; - while (expLength > ExpWindowThresholds[extraBits]) - { - ++extraBits; - } - - int numPowers = 1 << extraBits; - BigInteger[] oddPowers = new BigInteger[numPowers]; - oddPowers[0] = b; - - BigInteger b2 = ReduceBarrett(b.Square(), m, mr, yu); - - for (int i = 1; i < numPowers; ++i) - { - oddPowers[i] = ReduceBarrett(oddPowers[i - 1].Multiply(b2), m, mr, yu); - } - - int[] windowList = GetWindowList(e.magnitude, extraBits); - Debug.Assert(windowList.Length > 0); - - int window = windowList[0]; - int mult = window & 0xFF, lastZeroes = window >> 8; - - BigInteger y; - if (mult == 1) - { - y = b2; - --lastZeroes; - } - else - { - y = oddPowers[mult >> 1]; - } - - int windowPos = 1; - while ((window = windowList[windowPos++]) != -1) - { - mult = window & 0xFF; - - int bits = lastZeroes + BitLengthTable[mult]; - for (int j = 0; j < bits; ++j) - { - y = ReduceBarrett(y.Square(), m, mr, yu); - } - - y = ReduceBarrett(y.Multiply(oddPowers[mult >> 1]), m, mr, yu); - - lastZeroes = window >> 8; - } - - for (int i = 0; i < lastZeroes; ++i) - { - y = ReduceBarrett(y.Square(), m, mr, yu); - } - - return y; - } - - private static BigInteger ReduceBarrett(BigInteger x, BigInteger m, BigInteger mr, BigInteger yu) - { - int xLen = x.BitLength, mLen = m.BitLength; - if (xLen < mLen) - return x; - - if (xLen - mLen > 1) - { - int k = m.magnitude.Length; - - BigInteger q1 = x.DivideWords(k - 1); - BigInteger q2 = q1.Multiply(yu); // TODO Only need partial multiplication here - BigInteger q3 = q2.DivideWords(k + 1); - - BigInteger r1 = x.RemainderWords(k + 1); - BigInteger r2 = q3.Multiply(m); // TODO Only need partial multiplication here - BigInteger r3 = r2.RemainderWords(k + 1); - - x = r1.Subtract(r3); - if (x.sign < 0) - { - x = x.Add(mr); - } - } - - while (x.CompareTo(m) >= 0) - { - x = x.Subtract(m); - } - - return x; - } - - private static BigInteger ModPowMonty(BigInteger b, BigInteger e, BigInteger m, bool convert) - { - int n = m.magnitude.Length; - int powR = 32 * n; - bool smallMontyModulus = m.BitLength + 2 <= powR; - uint mDash = (uint)m.GetMQuote(); - - // tmp = this * R mod m - if (convert) - { - b = b.ShiftLeft(powR).Remainder(m); - } - - int[] yAccum = new int[n + 1]; - - int[] zVal = b.magnitude; - Debug.Assert(zVal.Length <= n); - if (zVal.Length < n) - { - int[] tmp = new int[n]; - zVal.CopyTo(tmp, n - zVal.Length); - zVal = tmp; - } - - // Sliding window from MSW to LSW - - int extraBits = 0; - - // Filter the common case of small RSA exponents with few bits set - if (e.magnitude.Length > 1 || e.BitCount > 2) - { - int expLength = e.BitLength; - while (expLength > ExpWindowThresholds[extraBits]) - { - ++extraBits; - } - } - - int numPowers = 1 << extraBits; - int[][] oddPowers = new int[numPowers][]; - oddPowers[0] = zVal; - - int[] zSquared = Arrays.Clone(zVal); - SquareMonty(yAccum, zSquared, m.magnitude, mDash, smallMontyModulus); - - for (int i = 1; i < numPowers; ++i) - { - oddPowers[i] = Arrays.Clone(oddPowers[i - 1]); - MultiplyMonty(yAccum, oddPowers[i], zSquared, m.magnitude, mDash, smallMontyModulus); - } - - int[] windowList = GetWindowList(e.magnitude, extraBits); - Debug.Assert(windowList.Length > 1); - - int window = windowList[0]; - int mult = window & 0xFF, lastZeroes = window >> 8; - - int[] yVal; - if (mult == 1) - { - yVal = zSquared; - --lastZeroes; - } - else - { - yVal = Arrays.Clone(oddPowers[mult >> 1]); - } - - int windowPos = 1; - while ((window = windowList[windowPos++]) != -1) - { - mult = window & 0xFF; - - int bits = lastZeroes + BitLengthTable[mult]; - for (int j = 0; j < bits; ++j) - { - SquareMonty(yAccum, yVal, m.magnitude, mDash, smallMontyModulus); - } - - MultiplyMonty(yAccum, yVal, oddPowers[mult >> 1], m.magnitude, mDash, smallMontyModulus); - - lastZeroes = window >> 8; - } - - for (int i = 0; i < lastZeroes; ++i) - { - SquareMonty(yAccum, yVal, m.magnitude, mDash, smallMontyModulus); - } - - if (convert) - { - // Return y * R^(-1) mod m - MontgomeryReduce(yVal, m.magnitude, mDash); - } - else if (smallMontyModulus && CompareTo(0, yVal, 0, m.magnitude) >= 0) - { - Subtract(0, yVal, 0, m.magnitude); - } - - return new BigInteger(1, yVal, true); - } - - private static int[] GetWindowList(int[] mag, int extraBits) - { - int v = mag[0]; - Debug.Assert(v != 0); - - int leadingBits = BitLen(v); - - int resultSize = (((mag.Length - 1) << 5) + leadingBits) / (1 + extraBits) + 2; - int[] result = new int[resultSize]; - int resultPos = 0; - - int bitPos = 33 - leadingBits; - v <<= bitPos; - - int mult = 1, multLimit = 1 << extraBits; - int zeroes = 0; - - int i = 0; - for (; ; ) - { - for (; bitPos < 32; ++bitPos) - { - if (mult < multLimit) - { - mult = (mult << 1) | (int)((uint)v >> 31); - } - else if (v < 0) - { - result[resultPos++] = CreateWindowEntry(mult, zeroes); - mult = 1; - zeroes = 0; - } - else - { - ++zeroes; - } - - v <<= 1; - } - - if (++i == mag.Length) - { - result[resultPos++] = CreateWindowEntry(mult, zeroes); - break; - } - - v = mag[i]; - bitPos = 0; - } - - result[resultPos] = -1; - return result; - } - - private static int CreateWindowEntry(int mult, int zeroes) - { - while ((mult & 1) == 0) - { - mult >>= 1; - ++zeroes; - } - - return mult | (zeroes << 8); - } - - /** - * return w with w = x * x - w is assumed to have enough space. - */ - private static int[] Square( - int[] w, - int[] x) - { - // Note: this method allows w to be only (2 * x.Length - 1) words if result will fit -// if (w.Length != 2 * x.Length) -// throw new ArgumentException("no I don't think so..."); - - ulong c; - - int wBase = w.Length - 1; - - for (int i = x.Length - 1; i > 0; --i) - { - ulong v = (uint)x[i]; - - c = v * v + (uint)w[wBase]; - w[wBase] = (int)c; - c >>= 32; - - for (int j = i - 1; j >= 0; --j) - { - ulong prod = v * (uint)x[j]; - - c += ((uint)w[--wBase] & UIMASK) + ((uint)prod << 1); - w[wBase] = (int)c; - c = (c >> 32) + (prod >> 31); - } - - c += (uint)w[--wBase]; - w[wBase] = (int)c; - - if (--wBase >= 0) - { - w[wBase] = (int)(c >> 32); - } - else - { - Debug.Assert((c >> 32) == 0); - } - - wBase += i; - } - - c = (uint)x[0]; - - c = c * c + (uint)w[wBase]; - w[wBase] = (int)c; - - if (--wBase >= 0) - { - w[wBase] += (int)(c >> 32); - } - else - { - Debug.Assert((c >> 32) == 0); - } - - return w; - } - - /** - * return x with x = y * z - x is assumed to have enough space. - */ - private static int[] Multiply(int[] x, int[] y, int[] z) - { - int i = z.Length; - - if (i < 1) - return x; - - int xBase = x.Length - y.Length; - - do - { - long a = z[--i] & IMASK; - long val = 0; - - if (a != 0) - { - for (int j = y.Length - 1; j >= 0; j--) - { - val += a * (y[j] & IMASK) + (x[xBase + j] & IMASK); - - x[xBase + j] = (int)val; - - val = (long)((ulong)val >> 32); - } - } - - --xBase; - - if (xBase >= 0) - { - x[xBase] = (int)val; - } - else - { - Debug.Assert(val == 0); - } - } - while (i > 0); - - return x; - } - - /** - * Calculate mQuote = -m^(-1) mod b with b = 2^32 (32 = word size) - */ - private int GetMQuote() - { - if (mQuote != 0) - { - return mQuote; // already calculated - } - - Debug.Assert(this.sign > 0); - - int d = -magnitude[magnitude.Length - 1]; - - Debug.Assert((d & 1) != 0); - - return mQuote = ModInverse32(d); - } - - private static void MontgomeryReduce(int[] x, int[] m, uint mDash) // mDash = -m^(-1) mod b - { - // NOTE: Not a general purpose reduction (which would allow x up to twice the bitlength of m) - Debug.Assert(x.Length == m.Length); - - int n = m.Length; - - for (int i = n - 1; i >= 0; --i) - { - uint x0 = (uint)x[n - 1]; - ulong t = x0 * mDash; - - ulong carry = t * (uint)m[n - 1] + x0; - Debug.Assert((uint)carry == 0); - carry >>= 32; - - for (int j = n - 2; j >= 0; --j) - { - carry += t * (uint)m[j] + (uint)x[j]; - x[j + 1] = (int)carry; - carry >>= 32; - } - - x[0] = (int)carry; - Debug.Assert(carry >> 32 == 0); - } - - if (CompareTo(0, x, 0, m) >= 0) - { - Subtract(0, x, 0, m); - } - } - - /** - * Montgomery multiplication: a = x * y * R^(-1) mod m - * - * Based algorithm 14.36 of Handbook of Applied Cryptography. - * - * m, x, y should have length n - * a should have length (n + 1) - * b = 2^32, R = b^n - * - * The result is put in x - * - * NOTE: the indices of x, y, m, a different in HAC and in Java - */ - private static void MultiplyMonty(int[] a, int[] x, int[] y, int[] m, uint mDash, bool smallMontyModulus) - // mDash = -m^(-1) mod b - { - int n = m.Length; - - if (n == 1) - { - x[0] = (int)MultiplyMontyNIsOne((uint)x[0], (uint)y[0], (uint)m[0], mDash); - return; - } - - uint y0 = (uint)y[n - 1]; - int aMax; - - { - ulong xi = (uint)x[n - 1]; - - ulong carry = xi * y0; - ulong t = (uint)carry * mDash; - - ulong prod2 = t * (uint)m[n - 1]; - carry += (uint)prod2; - Debug.Assert((uint)carry == 0); - carry = (carry >> 32) + (prod2 >> 32); - - for (int j = n - 2; j >= 0; --j) - { - ulong prod1 = xi * (uint)y[j]; - prod2 = t * (uint)m[j]; - - carry += (prod1 & UIMASK) + (uint)prod2; - a[j + 2] = (int)carry; - carry = (carry >> 32) + (prod1 >> 32) + (prod2 >> 32); - } - - a[1] = (int)carry; - aMax = (int)(carry >> 32); - } - - for (int i = n - 2; i >= 0; --i) - { - uint a0 = (uint)a[n]; - ulong xi = (uint)x[i]; - - ulong prod1 = xi * y0; - ulong carry = (prod1 & UIMASK) + a0; - ulong t = (uint)carry * mDash; - - ulong prod2 = t * (uint)m[n - 1]; - carry += (uint)prod2; - Debug.Assert((uint)carry == 0); - carry = (carry >> 32) + (prod1 >> 32) + (prod2 >> 32); - - for (int j = n - 2; j >= 0; --j) - { - prod1 = xi * (uint)y[j]; - prod2 = t * (uint)m[j]; - - carry += (prod1 & UIMASK) + (uint)prod2 + (uint)a[j + 1]; - a[j + 2] = (int)carry; - carry = (carry >> 32) + (prod1 >> 32) + (prod2 >> 32); - } - - carry += (uint)aMax; - a[1] = (int)carry; - aMax = (int)(carry >> 32); - } - - a[0] = aMax; - - if (!smallMontyModulus && CompareTo(0, a, 0, m) >= 0) - { - Subtract(0, a, 0, m); - } - - Array.Copy(a, 1, x, 0, n); - } - - private static void SquareMonty(int[] a, int[] x, int[] m, uint mDash, bool smallMontyModulus) - // mDash = -m^(-1) mod b - { - int n = m.Length; - - if (n == 1) - { - uint xVal = (uint)x[0]; - x[0] = (int)MultiplyMontyNIsOne(xVal, xVal, (uint)m[0], mDash); - return; - } - - ulong x0 = (uint)x[n - 1]; - int aMax; - - { - ulong carry = x0 * x0; - ulong t = (uint)carry * mDash; - - ulong prod2 = t * (uint)m[n - 1]; - carry += (uint)prod2; - Debug.Assert((uint)carry == 0); - carry = (carry >> 32) + (prod2 >> 32); - - for (int j = n - 2; j >= 0; --j) - { - ulong prod1 = x0 * (uint)x[j]; - prod2 = t * (uint)m[j]; - - carry += (prod2 & UIMASK) + ((uint)prod1 << 1); - a[j + 2] = (int)carry; - carry = (carry >> 32) + (prod1 >> 31) + (prod2 >> 32); - } - - a[1] = (int)carry; - aMax = (int)(carry >> 32); - } - - for (int i = n - 2; i >= 0; --i) - { - uint a0 = (uint)a[n]; - ulong t = a0 * mDash; - - ulong carry = t * (uint)m[n - 1] + a0; - Debug.Assert((uint)carry == 0); - carry >>= 32; - - for (int j = n - 2; j > i; --j) - { - carry += t * (uint)m[j] + (uint)a[j + 1]; - a[j + 2] = (int)carry; - carry >>= 32; - } - - ulong xi = (uint)x[i]; - - { - ulong prod1 = xi * xi; - ulong prod2 = t * (uint)m[i]; - - carry += (prod1 & UIMASK) + (uint)prod2 + (uint)a[i + 1]; - a[i + 2] = (int)carry; - carry = (carry >> 32) + (prod1 >> 32) + (prod2 >> 32); - } - - for (int j = i - 1; j >= 0; --j) - { - ulong prod1 = xi * (uint)x[j]; - ulong prod2 = t * (uint)m[j]; - - carry += (prod2 & UIMASK) + ((uint)prod1 << 1) + (uint)a[j + 1]; - a[j + 2] = (int)carry; - carry = (carry >> 32) + (prod1 >> 31) + (prod2 >> 32); - } - - carry += (uint)aMax; - a[1] = (int)carry; - aMax = (int)(carry >> 32); - } - - a[0] = aMax; - - if (!smallMontyModulus && CompareTo(0, a, 0, m) >= 0) - { - Subtract(0, a, 0, m); - } - - Array.Copy(a, 1, x, 0, n); - } - - private static uint MultiplyMontyNIsOne(uint x, uint y, uint m, uint mDash) - { - ulong carry = (ulong)x * y; - uint t = (uint)carry * mDash; - ulong um = m; - ulong prod2 = um * t; - carry += (uint)prod2; - Debug.Assert((uint)carry == 0); - carry = (carry >> 32) + (prod2 >> 32); - if (carry > um) - { - carry -= um; - } - Debug.Assert(carry < um); - return (uint)carry; - } - - public BigInteger Multiply( - BigInteger val) - { - if (val == this) - return Square(); - - if ((sign & val.sign) == 0) - return Zero; - - if (val.QuickPow2Check()) // val is power of two - { - BigInteger result = this.ShiftLeft(val.Abs().BitLength - 1); - return val.sign > 0 ? result : result.Negate(); - } - - if (this.QuickPow2Check()) // this is power of two - { - BigInteger result = val.ShiftLeft(this.Abs().BitLength - 1); - return this.sign > 0 ? result : result.Negate(); - } - - int resLength = magnitude.Length + val.magnitude.Length; - int[] res = new int[resLength]; - - Multiply(res, this.magnitude, val.magnitude); - - int resSign = sign ^ val.sign ^ 1; - return new BigInteger(resSign, res, true); - } - - public BigInteger Square() - { - if (sign == 0) - return Zero; - if (this.QuickPow2Check()) - return ShiftLeft(Abs().BitLength - 1); - int resLength = magnitude.Length << 1; - if ((uint)magnitude[0] >> 16 == 0) - --resLength; - int[] res = new int[resLength]; - Square(res, magnitude); - return new BigInteger(1, res, false); - } - - public BigInteger Negate() - { - if (sign == 0) - return this; - - return new BigInteger(-sign, magnitude, false); - } - - public BigInteger NextProbablePrime() - { - if (sign < 0) - throw new ArithmeticException("Cannot be called on value < 0"); - - if (CompareTo(Two) < 0) - return Two; - - BigInteger n = Inc().SetBit(0); - - while (!n.CheckProbablePrime(100, RandomSource, false)) - { - n = n.Add(Two); - } - - return n; - } - - public BigInteger Not() - { - return Inc().Negate(); - } - - public BigInteger Pow(int exp) - { - if (exp <= 0) - { - if (exp < 0) - throw new ArithmeticException("Negative exponent"); - - return One; - } - - if (sign == 0) - { - return this; - } - - if (QuickPow2Check()) - { - long powOf2 = (long)exp * (BitLength - 1); - if (powOf2 > Int32.MaxValue) - { - throw new ArithmeticException("Result too large"); - } - return One.ShiftLeft((int)powOf2); - } - - BigInteger y = One; - BigInteger z = this; - - for (;;) - { - if ((exp & 0x1) == 1) - { - y = y.Multiply(z); - } - exp >>= 1; - if (exp == 0) break; - z = z.Multiply(z); - } - - return y; - } - - public static BigInteger ProbablePrime( - int bitLength, - Random random) - { - return new BigInteger(bitLength, 100, random); - } - - private int Remainder( - int m) - { - Debug.Assert(m > 0); - - long acc = 0; - for (int pos = 0; pos < magnitude.Length; ++pos) - { - long posVal = (uint) magnitude[pos]; - acc = (acc << 32 | posVal) % m; - } - - return (int) acc; - } - - /** - * return x = x % y - done in place (y value preserved) - */ - private static int[] Remainder( - int[] x, - int[] y) - { - int xStart = 0; - while (xStart < x.Length && x[xStart] == 0) - { - ++xStart; - } - - int yStart = 0; - while (yStart < y.Length && y[yStart] == 0) - { - ++yStart; - } - - Debug.Assert(yStart < y.Length); - - int xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y); - - if (xyCmp > 0) - { - int yBitLength = CalcBitLength(1, yStart, y); - int xBitLength = CalcBitLength(1, xStart, x); - int shift = xBitLength - yBitLength; - - int[] c; - int cStart = 0; - int cBitLength = yBitLength; - if (shift > 0) - { - c = ShiftLeft(y, shift); - cBitLength += shift; - Debug.Assert(c[0] != 0); - } - else - { - int len = y.Length - yStart; - c = new int[len]; - Array.Copy(y, yStart, c, 0, len); - } - - for (;;) - { - if (cBitLength < xBitLength - || CompareNoLeadingZeroes(xStart, x, cStart, c) >= 0) - { - Subtract(xStart, x, cStart, c); - - while (x[xStart] == 0) - { - if (++xStart == x.Length) - return x; - } - - //xBitLength = CalcBitLength(xStart, x); - xBitLength = 32 * (x.Length - xStart - 1) + BitLen(x[xStart]); - - if (xBitLength <= yBitLength) - { - if (xBitLength < yBitLength) - return x; - - xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y); - - if (xyCmp <= 0) - break; - } - } - - shift = cBitLength - xBitLength; - - // NB: The case where c[cStart] is 1-bit is harmless - if (shift == 1) - { - uint firstC = (uint) c[cStart] >> 1; - uint firstX = (uint) x[xStart]; - if (firstC > firstX) - ++shift; - } - - if (shift < 2) - { - ShiftRightOneInPlace(cStart, c); - --cBitLength; - } - else - { - ShiftRightInPlace(cStart, c, shift); - cBitLength -= shift; - } - - //cStart = c.Length - ((cBitLength + 31) / 32); - while (c[cStart] == 0) - { - ++cStart; - } - } - } - - if (xyCmp == 0) - { - Array.Clear(x, xStart, x.Length - xStart); - } - - return x; - } - - public BigInteger Remainder( - BigInteger n) - { - if (n.sign == 0) - throw new ArithmeticException("Division by zero error"); - - if (this.sign == 0) - return Zero; - - // For small values, use fast remainder method - if (n.magnitude.Length == 1) - { - int val = n.magnitude[0]; - - if (val > 0) - { - if (val == 1) - return Zero; - - // TODO Make this func work on uint, and handle val == 1? - int rem = Remainder(val); - - return rem == 0 - ? Zero - : new BigInteger(sign, new int[]{ rem }, false); - } - } - - if (CompareNoLeadingZeroes(0, magnitude, 0, n.magnitude) < 0) - return this; - - int[] result; - if (n.QuickPow2Check()) // n is power of two - { - // TODO Move before small values branch above? - result = LastNBits(n.Abs().BitLength - 1); - } - else - { - result = (int[]) this.magnitude.Clone(); - result = Remainder(result, n.magnitude); - } - - return new BigInteger(sign, result, true); - } - - private int[] LastNBits( - int n) - { - if (n < 1) - return ZeroMagnitude; - - int numWords = (n + BitsPerInt - 1) / BitsPerInt; - numWords = System.Math.Min(numWords, this.magnitude.Length); - int[] result = new int[numWords]; - - Array.Copy(this.magnitude, this.magnitude.Length - numWords, result, 0, numWords); - - int excessBits = (numWords << 5) - n; - if (excessBits > 0) - { - result[0] &= (int)(UInt32.MaxValue >> excessBits); - } - - return result; - } - - private BigInteger DivideWords(int w) - { - Debug.Assert(w >= 0); - int n = magnitude.Length; - if (w >= n) - return Zero; - int[] mag = new int[n - w]; - Array.Copy(magnitude, 0, mag, 0, n - w); - return new BigInteger(sign, mag, false); - } - - private BigInteger RemainderWords(int w) - { - Debug.Assert(w >= 0); - int n = magnitude.Length; - if (w >= n) - return this; - int[] mag = new int[w]; - Array.Copy(magnitude, n - w, mag, 0, w); - return new BigInteger(sign, mag, false); - } - - /** - * do a left shift - this returns a new array. - */ - private static int[] ShiftLeft( - int[] mag, - int n) - { - int nInts = (int)((uint)n >> 5); - int nBits = n & 0x1f; - int magLen = mag.Length; - int[] newMag; - - if (nBits == 0) - { - newMag = new int[magLen + nInts]; - mag.CopyTo(newMag, 0); - } - else - { - int i = 0; - int nBits2 = 32 - nBits; - int highBits = (int)((uint)mag[0] >> nBits2); - - if (highBits != 0) - { - newMag = new int[magLen + nInts + 1]; - newMag[i++] = highBits; - } - else - { - newMag = new int[magLen + nInts]; - } - - int m = mag[0]; - for (int j = 0; j < magLen - 1; j++) - { - int next = mag[j + 1]; - - newMag[i++] = (m << nBits) | (int)((uint)next >> nBits2); - m = next; - } - - newMag[i] = mag[magLen - 1] << nBits; - } - - return newMag; - } - - private static int ShiftLeftOneInPlace(int[] x, int carry) - { - Debug.Assert(carry == 0 || carry == 1); - int pos = x.Length; - while (--pos >= 0) - { - uint val = (uint)x[pos]; - x[pos] = (int)(val << 1) | carry; - carry = (int)(val >> 31); - } - return carry; - } - - public BigInteger ShiftLeft( - int n) - { - if (sign == 0 || magnitude.Length == 0) - return Zero; - - if (n == 0) - return this; - - if (n < 0) - return ShiftRight(-n); - - BigInteger result = new BigInteger(sign, ShiftLeft(magnitude, n), true); - - if (this.nBits != -1) - { - result.nBits = sign > 0 - ? this.nBits - : this.nBits + n; - } - - if (this.nBitLength != -1) - { - result.nBitLength = this.nBitLength + n; - } - - return result; - } - - /** - * do a right shift - this does it in place. - */ - private static void ShiftRightInPlace( - int start, - int[] mag, - int n) - { - int nInts = (int)((uint)n >> 5) + start; - int nBits = n & 0x1f; - int magEnd = mag.Length - 1; - - if (nInts != start) - { - int delta = (nInts - start); - - for (int i = magEnd; i >= nInts; i--) - { - mag[i] = mag[i - delta]; - } - for (int i = nInts - 1; i >= start; i--) - { - mag[i] = 0; - } - } - - if (nBits != 0) - { - int nBits2 = 32 - nBits; - int m = mag[magEnd]; - - for (int i = magEnd; i > nInts; --i) - { - int next = mag[i - 1]; - - mag[i] = (int)((uint)m >> nBits) | (next << nBits2); - m = next; - } - - mag[nInts] = (int)((uint)mag[nInts] >> nBits); - } - } - - /** - * do a right shift by one - this does it in place. - */ - private static void ShiftRightOneInPlace( - int start, - int[] mag) - { - int i = mag.Length; - int m = mag[i - 1]; - - while (--i > start) - { - int next = mag[i - 1]; - mag[i] = ((int)((uint)m >> 1)) | (next << 31); - m = next; - } - - mag[start] = (int)((uint)mag[start] >> 1); - } - - public BigInteger ShiftRight( - int n) - { - if (n == 0) - return this; - - if (n < 0) - return ShiftLeft(-n); - - if (n >= BitLength) - return (this.sign < 0 ? One.Negate() : Zero); - -// int[] res = (int[]) this.magnitude.Clone(); -// -// ShiftRightInPlace(0, res, n); -// -// return new BigInteger(this.sign, res, true); - - int resultLength = (BitLength - n + 31) >> 5; - int[] res = new int[resultLength]; - - int numInts = n >> 5; - int numBits = n & 31; - - if (numBits == 0) - { - Array.Copy(this.magnitude, 0, res, 0, res.Length); - } - else - { - int numBits2 = 32 - numBits; - - int magPos = this.magnitude.Length - 1 - numInts; - for (int i = resultLength - 1; i >= 0; --i) - { - res[i] = (int)((uint) this.magnitude[magPos--] >> numBits); - - if (magPos >= 0) - { - res[i] |= this.magnitude[magPos] << numBits2; - } - } - } - - Debug.Assert(res[0] != 0); - - return new BigInteger(this.sign, res, false); - } - - public int SignValue - { - get { return sign; } - } - - /** - * returns x = x - y - we assume x is >= y - */ - private static int[] Subtract( - int xStart, - int[] x, - int yStart, - int[] y) - { - Debug.Assert(yStart < y.Length); - Debug.Assert(x.Length - xStart >= y.Length - yStart); - - int iT = x.Length; - int iV = y.Length; - long m; - int borrow = 0; - - do - { - m = (x[--iT] & IMASK) - (y[--iV] & IMASK) + borrow; - x[iT] = (int) m; - -// borrow = (m < 0) ? -1 : 0; - borrow = (int)(m >> 63); - } - while (iV > yStart); - - if (borrow != 0) - { - while (--x[--iT] == -1) - { - } - } - - return x; - } - - public BigInteger Subtract( - BigInteger n) - { - if (n.sign == 0) - return this; - - if (this.sign == 0) - return n.Negate(); - - if (this.sign != n.sign) - return Add(n.Negate()); - - int compare = CompareNoLeadingZeroes(0, magnitude, 0, n.magnitude); - if (compare == 0) - return Zero; - - BigInteger bigun, lilun; - if (compare < 0) - { - bigun = n; - lilun = this; - } - else - { - bigun = this; - lilun = n; - } - - return new BigInteger(this.sign * compare, doSubBigLil(bigun.magnitude, lilun.magnitude), true); - } - - private static int[] doSubBigLil( - int[] bigMag, - int[] lilMag) - { - int[] res = (int[]) bigMag.Clone(); - - return Subtract(0, res, 0, lilMag); - } - - public byte[] ToByteArray() - { - return ToByteArray(false); - } - - public byte[] ToByteArrayUnsigned() - { - return ToByteArray(true); - } - - private byte[] ToByteArray( - bool unsigned) - { - if (sign == 0) - return unsigned ? ZeroEncoding : new byte[1]; - - int nBits = (unsigned && sign > 0) - ? BitLength - : BitLength + 1; - - int nBytes = GetByteLength(nBits); - byte[] bytes = new byte[nBytes]; - - int magIndex = magnitude.Length; - int bytesIndex = bytes.Length; - - if (sign > 0) - { - while (magIndex > 1) - { - uint mag = (uint) magnitude[--magIndex]; - bytes[--bytesIndex] = (byte) mag; - bytes[--bytesIndex] = (byte)(mag >> 8); - bytes[--bytesIndex] = (byte)(mag >> 16); - bytes[--bytesIndex] = (byte)(mag >> 24); - } - - uint lastMag = (uint) magnitude[0]; - while (lastMag > byte.MaxValue) - { - bytes[--bytesIndex] = (byte) lastMag; - lastMag >>= 8; - } - - bytes[--bytesIndex] = (byte) lastMag; - } - else // sign < 0 - { - bool carry = true; - - while (magIndex > 1) - { - uint mag = ~((uint) magnitude[--magIndex]); - - if (carry) - { - carry = (++mag == uint.MinValue); - } - - bytes[--bytesIndex] = (byte) mag; - bytes[--bytesIndex] = (byte)(mag >> 8); - bytes[--bytesIndex] = (byte)(mag >> 16); - bytes[--bytesIndex] = (byte)(mag >> 24); - } - - uint lastMag = (uint) magnitude[0]; - - if (carry) - { - // Never wraps because magnitude[0] != 0 - --lastMag; - } - - while (lastMag > byte.MaxValue) - { - bytes[--bytesIndex] = (byte) ~lastMag; - lastMag >>= 8; - } - - bytes[--bytesIndex] = (byte) ~lastMag; - - if (bytesIndex > 0) - { - bytes[--bytesIndex] = byte.MaxValue; - } - } - - return bytes; - } - - public override string ToString() - { - return ToString(10); - } - - public string ToString(int radix) - { - // TODO Make this method work for other radices (ideally 2 <= radix <= 36 as in Java) - - switch (radix) - { - case 2: - case 8: - case 10: - case 16: - break; - default: - throw new FormatException("Only bases 2, 8, 10, 16 are allowed"); - } - - // NB: Can only happen to internally managed instances - if (magnitude == null) - return "null"; - - if (sign == 0) - return "0"; - - - // NOTE: This *should* be unnecessary, since the magnitude *should* never have leading zero digits - int firstNonZero = 0; - while (firstNonZero < magnitude.Length) - { - if (magnitude[firstNonZero] != 0) - { - break; - } - ++firstNonZero; - } - - if (firstNonZero == magnitude.Length) - { - return "0"; - } - - - StringBuilder sb = new StringBuilder(); - if (sign == -1) - { - sb.Append('-'); - } - - switch (radix) - { - case 2: - { - int pos = firstNonZero; - sb.Append(Convert.ToString(magnitude[pos], 2)); - while (++pos < magnitude.Length) - { - AppendZeroExtendedString(sb, Convert.ToString(magnitude[pos], 2), 32); - } - break; - } - case 8: - { - int mask = (1 << 30) - 1; - BigInteger u = this.Abs(); - int bits = u.BitLength; - IList S = new List(); - while (bits > 30) - { - S.Add(Convert.ToString(u.IntValue & mask, 8)); - u = u.ShiftRight(30); - bits -= 30; - } - sb.Append(Convert.ToString(u.IntValue, 8)); - for (int i = S.Count - 1; i >= 0; --i) - { - AppendZeroExtendedString(sb, (string)S[i], 10); - } - break; - } - case 16: - { - int pos = firstNonZero; - sb.Append(Convert.ToString(magnitude[pos], 16)); - while (++pos < magnitude.Length) - { - AppendZeroExtendedString(sb, Convert.ToString(magnitude[pos], 16), 8); - } - break; - } - // TODO This could work for other radices if there is an alternative to Convert.ToString method - //default: - case 10: - { - BigInteger q = this.Abs(); - if (q.BitLength < 64) - { - sb.Append(Convert.ToString(q.LongValue, radix)); - break; - } - - // TODO Could cache the moduli for each radix (soft reference?) - IList moduli = new List(); - BigInteger R = BigInteger.ValueOf(radix); - while (R.CompareTo(q) <= 0) - { - moduli.Add(R); - R = R.Square(); - } - - int scale = moduli.Count; - sb.EnsureCapacity(sb.Length + (1 << scale)); - - ToString(sb, radix, moduli, scale, q); - - break; - } - } - - return sb.ToString(); - } - - private static void ToString(StringBuilder sb, int radix, IList moduli, int scale, BigInteger pos) - { - if (pos.BitLength < 64) - { - string s = Convert.ToString(pos.LongValue, radix); - if (sb.Length > 1 || (sb.Length == 1 && sb[0] != '-')) - { - AppendZeroExtendedString(sb, s, 1 << scale); - } - else if (pos.SignValue != 0) - { - sb.Append(s); - } - return; - } - - BigInteger[] qr = pos.DivideAndRemainder((BigInteger)moduli[--scale]); - - ToString(sb, radix, moduli, scale, qr[0]); - ToString(sb, radix, moduli, scale, qr[1]); - } - - private static void AppendZeroExtendedString(StringBuilder sb, string s, int minLength) - { - for (int len = s.Length; len < minLength; ++len) - { - sb.Append('0'); - } - sb.Append(s); - } - - private static BigInteger CreateUValueOf( - ulong value) - { - int msw = (int)(value >> 32); - int lsw = (int)value; - - if (msw != 0) - return new BigInteger(1, new int[] { msw, lsw }, false); - - if (lsw != 0) - { - BigInteger n = new BigInteger(1, new int[] { lsw }, false); - // Check for a power of two - if ((lsw & -lsw) == lsw) - { - n.nBits = 1; - } - return n; - } - - return Zero; - } - - private static BigInteger CreateValueOf( - long value) - { - if (value < 0) - { - if (value == long.MinValue) - return CreateValueOf(~value).Not(); - - return CreateValueOf(-value).Negate(); - } - - return CreateUValueOf((ulong)value); - } - - public static BigInteger ValueOf( - long value) - { - if (value >= 0 && value < SMALL_CONSTANTS.Length) - { - return SMALL_CONSTANTS[value]; - } - - return CreateValueOf(value); - } - - public int GetLowestSetBit() - { - if (this.sign == 0) - return -1; - - return GetLowestSetBitMaskFirst(-1); - } - - private int GetLowestSetBitMaskFirst(int firstWordMask) - { - int w = magnitude.Length, offset = 0; - - uint word = (uint)(magnitude[--w] & firstWordMask); - Debug.Assert(magnitude[0] != 0); - - while (word == 0) - { - word = (uint)magnitude[--w]; - offset += 32; - } - - while ((word & 0xFF) == 0) - { - word >>= 8; - offset += 8; - } - - while ((word & 1) == 0) - { - word >>= 1; - ++offset; - } - - return offset; - } - - public bool TestBit( - int n) - { - if (n < 0) - throw new ArithmeticException("Bit position must not be negative"); - - if (sign < 0) - return !Not().TestBit(n); - - int wordNum = n / 32; - if (wordNum >= magnitude.Length) - return false; - - int word = magnitude[magnitude.Length - 1 - wordNum]; - return ((word >> (n % 32)) & 1) > 0; - } - - public BigInteger Or( - BigInteger value) - { - if (this.sign == 0) - return value; - - if (value.sign == 0) - return this; - - int[] aMag = this.sign > 0 - ? this.magnitude - : Add(One).magnitude; - - int[] bMag = value.sign > 0 - ? value.magnitude - : value.Add(One).magnitude; - - bool resultNeg = sign < 0 || value.sign < 0; - int resultLength = System.Math.Max(aMag.Length, bMag.Length); - int[] resultMag = new int[resultLength]; - - int aStart = resultMag.Length - aMag.Length; - int bStart = resultMag.Length - bMag.Length; - - for (int i = 0; i < resultMag.Length; ++i) - { - int aWord = i >= aStart ? aMag[i - aStart] : 0; - int bWord = i >= bStart ? bMag[i - bStart] : 0; - - if (this.sign < 0) - { - aWord = ~aWord; - } - - if (value.sign < 0) - { - bWord = ~bWord; - } - - resultMag[i] = aWord | bWord; - - if (resultNeg) - { - resultMag[i] = ~resultMag[i]; - } - } - - BigInteger result = new BigInteger(1, resultMag, true); - - // TODO Optimise this case - if (resultNeg) - { - result = result.Not(); - } - - return result; - } - - public BigInteger Xor( - BigInteger value) - { - if (this.sign == 0) - return value; - - if (value.sign == 0) - return this; - - int[] aMag = this.sign > 0 - ? this.magnitude - : Add(One).magnitude; - - int[] bMag = value.sign > 0 - ? value.magnitude - : value.Add(One).magnitude; - - // TODO Can just replace with sign != value.sign? - bool resultNeg = (sign < 0 && value.sign >= 0) || (sign >= 0 && value.sign < 0); - int resultLength = System.Math.Max(aMag.Length, bMag.Length); - int[] resultMag = new int[resultLength]; - - int aStart = resultMag.Length - aMag.Length; - int bStart = resultMag.Length - bMag.Length; - - for (int i = 0; i < resultMag.Length; ++i) - { - int aWord = i >= aStart ? aMag[i - aStart] : 0; - int bWord = i >= bStart ? bMag[i - bStart] : 0; - - if (this.sign < 0) - { - aWord = ~aWord; - } - - if (value.sign < 0) - { - bWord = ~bWord; - } - - resultMag[i] = aWord ^ bWord; - - if (resultNeg) - { - resultMag[i] = ~resultMag[i]; - } - } - - BigInteger result = new BigInteger(1, resultMag, true); - - // TODO Optimise this case - if (resultNeg) - { - result = result.Not(); - } - - return result; - } - - public BigInteger SetBit( - int n) - { - if (n < 0) - throw new ArithmeticException("Bit address less than zero"); - - if (TestBit(n)) - return this; - - // TODO Handle negative values and zero - if (sign > 0 && n < (BitLength - 1)) - return FlipExistingBit(n); - - return Or(One.ShiftLeft(n)); - } - - public BigInteger ClearBit( - int n) - { - if (n < 0) - throw new ArithmeticException("Bit address less than zero"); - - if (!TestBit(n)) - return this; - - // TODO Handle negative values - if (sign > 0 && n < (BitLength - 1)) - return FlipExistingBit(n); - - return AndNot(One.ShiftLeft(n)); - } - - public BigInteger FlipBit( - int n) - { - if (n < 0) - throw new ArithmeticException("Bit address less than zero"); - - // TODO Handle negative values and zero - if (sign > 0 && n < (BitLength - 1)) - return FlipExistingBit(n); - - return Xor(One.ShiftLeft(n)); - } - - private BigInteger FlipExistingBit( - int n) - { - Debug.Assert(sign > 0); - Debug.Assert(n >= 0); - Debug.Assert(n < BitLength - 1); - - int[] mag = (int[]) this.magnitude.Clone(); - mag[mag.Length - 1 - (n >> 5)] ^= (1 << (n & 31)); // Flip bit - //mag[mag.Length - 1 - (n / 32)] ^= (1 << (n % 32)); - return new BigInteger(this.sign, mag, false); - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/ec/ECAlgorithms.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/ECAlgorithms.cs deleted file mode 100644 index 1347a9af2..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/ECAlgorithms.cs +++ /dev/null @@ -1,496 +0,0 @@ -using System; - -using Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Endo; -using Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Multiplier; -using Renci.SshNet.Security.Org.BouncyCastle.Math.Field; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC -{ - internal class ECAlgorithms - { - public static bool IsF2mCurve(ECCurve c) - { - return IsF2mField(c.Field); - } - - public static bool IsF2mField(IFiniteField field) - { - return field.Dimension > 1 && field.Characteristic.Equals(BigInteger.Two) - && field is IPolynomialExtensionField; - } - - public static bool IsFpCurve(ECCurve c) - { - return IsFpField(c.Field); - } - - public static bool IsFpField(IFiniteField field) - { - return field.Dimension == 1; - } - - public static ECPoint SumOfMultiplies(ECPoint[] ps, BigInteger[] ks) - { - if (ps == null || ks == null || ps.Length != ks.Length || ps.Length < 1) - throw new ArgumentException("point and scalar arrays should be non-null, and of equal, non-zero, length"); - - int count = ps.Length; - switch (count) - { - case 1: - return ps[0].Multiply(ks[0]); - case 2: - return SumOfTwoMultiplies(ps[0], ks[0], ps[1], ks[1]); - default: - break; - } - - ECPoint p = ps[0]; - ECCurve c = p.Curve; - - ECPoint[] imported = new ECPoint[count]; - imported[0] = p; - for (int i = 1; i < count; ++i) - { - imported[i] = ImportPoint(c, ps[i]); - } - - GlvEndomorphism glvEndomorphism = c.GetEndomorphism() as GlvEndomorphism; - if (glvEndomorphism != null) - { - return ImplCheckResult(ImplSumOfMultipliesGlv(imported, ks, glvEndomorphism)); - } - - return ImplCheckResult(ImplSumOfMultiplies(imported, ks)); - } - - public static ECPoint SumOfTwoMultiplies(ECPoint P, BigInteger a, ECPoint Q, BigInteger b) - { - ECCurve cp = P.Curve; - Q = ImportPoint(cp, Q); - - // Point multiplication for Koblitz curves (using WTNAF) beats Shamir's trick - { - AbstractF2mCurve f2mCurve = cp as AbstractF2mCurve; - if (f2mCurve != null && f2mCurve.IsKoblitz) - { - return ImplCheckResult(P.Multiply(a).Add(Q.Multiply(b))); - } - } - - GlvEndomorphism glvEndomorphism = cp.GetEndomorphism() as GlvEndomorphism; - if (glvEndomorphism != null) - { - return ImplCheckResult( - ImplSumOfMultipliesGlv(new ECPoint[] { P, Q }, new BigInteger[] { a, b }, glvEndomorphism)); - } - - return ImplCheckResult(ImplShamirsTrickWNaf(P, a, Q, b)); - } - - /* - * "Shamir's Trick", originally due to E. G. Straus - * (Addition chains of vectors. American Mathematical Monthly, - * 71(7):806-808, Aug./Sept. 1964) - * - * Input: The points P, Q, scalar k = (km?, ... , k1, k0) - * and scalar l = (lm?, ... , l1, l0). - * Output: R = k * P + l * Q. - * 1: Z <- P + Q - * 2: R <- O - * 3: for i from m-1 down to 0 do - * 4: R <- R + R {point doubling} - * 5: if (ki = 1) and (li = 0) then R <- R + P end if - * 6: if (ki = 0) and (li = 1) then R <- R + Q end if - * 7: if (ki = 1) and (li = 1) then R <- R + Z end if - * 8: end for - * 9: return R - */ - public static ECPoint ShamirsTrick(ECPoint P, BigInteger k, ECPoint Q, BigInteger l) - { - ECCurve cp = P.Curve; - Q = ImportPoint(cp, Q); - - return ImplCheckResult(ImplShamirsTrickJsf(P, k, Q, l)); - } - - public static ECPoint ImportPoint(ECCurve c, ECPoint p) - { - ECCurve cp = p.Curve; - if (!c.Equals(cp)) - throw new ArgumentException("Point must be on the same curve"); - - return c.ImportPoint(p); - } - - public static void MontgomeryTrick(ECFieldElement[] zs, int off, int len) - { - MontgomeryTrick(zs, off, len, null); - } - - public static void MontgomeryTrick(ECFieldElement[] zs, int off, int len, ECFieldElement scale) - { - /* - * Uses the "Montgomery Trick" to invert many field elements, with only a single actual - * field inversion. See e.g. the paper: - * "Fast Multi-scalar Multiplication Methods on Elliptic Curves with Precomputation Strategy Using Montgomery Trick" - * by Katsuyuki Okeya, Kouichi Sakurai. - */ - - ECFieldElement[] c = new ECFieldElement[len]; - c[0] = zs[off]; - - int i = 0; - while (++i < len) - { - c[i] = c[i - 1].Multiply(zs[off + i]); - } - - --i; - - if (scale != null) - { - c[i] = c[i].Multiply(scale); - } - - ECFieldElement u = c[i].Invert(); - - while (i > 0) - { - int j = off + i--; - ECFieldElement tmp = zs[j]; - zs[j] = c[i].Multiply(u); - u = u.Multiply(tmp); - } - - zs[off] = u; - } - - /** - * Simple shift-and-add multiplication. Serves as reference implementation - * to verify (possibly faster) implementations, and for very small scalars. - * - * @param p - * The point to multiply. - * @param k - * The multiplier. - * @return The result of the point multiplication kP. - */ - public static ECPoint ReferenceMultiply(ECPoint p, BigInteger k) - { - BigInteger x = k.Abs(); - ECPoint q = p.Curve.Infinity; - int t = x.BitLength; - if (t > 0) - { - if (x.TestBit(0)) - { - q = p; - } - for (int i = 1; i < t; i++) - { - p = p.Twice(); - if (x.TestBit(i)) - { - q = q.Add(p); - } - } - } - return k.SignValue < 0 ? q.Negate() : q; - } - - public static ECPoint ValidatePoint(ECPoint p) - { - if (!p.IsValid()) - throw new InvalidOperationException("Invalid point"); - - return p; - } - - public static ECPoint CleanPoint(ECCurve c, ECPoint p) - { - ECCurve cp = p.Curve; - if (!c.Equals(cp)) - throw new ArgumentException("Point must be on the same curve", "p"); - - return c.DecodePoint(p.GetEncoded(false)); - } - - internal static ECPoint ImplCheckResult(ECPoint p) - { - if (!p.IsValidPartial()) - throw new InvalidOperationException("Invalid result"); - - return p; - } - - internal static ECPoint ImplShamirsTrickJsf(ECPoint P, BigInteger k, ECPoint Q, BigInteger l) - { - ECCurve curve = P.Curve; - ECPoint infinity = curve.Infinity; - - // TODO conjugate co-Z addition (ZADDC) can return both of these - ECPoint PaddQ = P.Add(Q); - ECPoint PsubQ = P.Subtract(Q); - - ECPoint[] points = new ECPoint[] { Q, PsubQ, P, PaddQ }; - curve.NormalizeAll(points); - - ECPoint[] table = new ECPoint[] { - points[3].Negate(), points[2].Negate(), points[1].Negate(), - points[0].Negate(), infinity, points[0], - points[1], points[2], points[3] }; - - byte[] jsf = WNafUtilities.GenerateJsf(k, l); - - ECPoint R = infinity; - - int i = jsf.Length; - while (--i >= 0) - { - int jsfi = jsf[i]; - - // NOTE: The shifting ensures the sign is extended correctly - int kDigit = ((jsfi << 24) >> 28), lDigit = ((jsfi << 28) >> 28); - - int index = 4 + (kDigit * 3) + lDigit; - R = R.TwicePlus(table[index]); - } - - return R; - } - - internal static ECPoint ImplShamirsTrickWNaf(ECPoint P, BigInteger k, - ECPoint Q, BigInteger l) - { - bool negK = k.SignValue < 0, negL = l.SignValue < 0; - - k = k.Abs(); - l = l.Abs(); - - 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, widthP, true); - WNafPreCompInfo infoQ = WNafUtilities.Precompute(Q, widthQ, true); - - 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); - - return ImplShamirsTrickWNaf(preCompP, preCompNegP, wnafP, preCompQ, preCompNegQ, wnafQ); - } - - internal static ECPoint ImplShamirsTrickWNaf(ECPoint P, BigInteger k, ECPointMap pointMapQ, 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)))); - - ECPoint Q = WNafUtilities.MapPointWithPrecomp(P, width, true, pointMapQ); - WNafPreCompInfo infoP = WNafUtilities.GetWNafPreCompInfo(P); - WNafPreCompInfo infoQ = WNafUtilities.GetWNafPreCompInfo(Q); - - 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); - - return ImplShamirsTrickWNaf(preCompP, preCompNegP, wnafP, preCompQ, preCompNegQ, wnafQ); - } - - private static ECPoint ImplShamirsTrickWNaf(ECPoint[] preCompP, ECPoint[] preCompNegP, byte[] wnafP, - ECPoint[] preCompQ, ECPoint[] preCompNegQ, byte[] wnafQ) - { - int len = System.Math.Max(wnafP.Length, wnafQ.Length); - - ECCurve curve = preCompP[0].Curve; - ECPoint infinity = curve.Infinity; - - ECPoint R = infinity; - int zeroes = 0; - - for (int i = len - 1; i >= 0; --i) - { - int wiP = i < wnafP.Length ? (int)(sbyte)wnafP[i] : 0; - int wiQ = i < wnafQ.Length ? (int)(sbyte)wnafQ[i] : 0; - - if ((wiP | wiQ) == 0) - { - ++zeroes; - continue; - } - - ECPoint r = infinity; - if (wiP != 0) - { - int nP = System.Math.Abs(wiP); - ECPoint[] tableP = wiP < 0 ? preCompNegP : preCompP; - r = r.Add(tableP[nP >> 1]); - } - if (wiQ != 0) - { - int nQ = System.Math.Abs(wiQ); - ECPoint[] tableQ = wiQ < 0 ? preCompNegQ : preCompQ; - r = r.Add(tableQ[nQ >> 1]); - } - - if (zeroes > 0) - { - R = R.TimesPow2(zeroes); - zeroes = 0; - } - - R = R.TwicePlus(r); - } - - if (zeroes > 0) - { - R = R.TimesPow2(zeroes); - } - - return R; - } - - internal static ECPoint ImplSumOfMultiplies(ECPoint[] ps, BigInteger[] ks) - { - int count = ps.Length; - bool[] negs = new bool[count]; - WNafPreCompInfo[] infos = new WNafPreCompInfo[count]; - byte[][] wnafs = new byte[count][]; - - for (int i = 0; i < count; ++i) - { - 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); - wnafs[i] = WNafUtilities.GenerateWindowNaf(width, ki); - } - - return ImplSumOfMultiplies(negs, infos, wnafs); - } - - internal static ECPoint ImplSumOfMultipliesGlv(ECPoint[] ps, BigInteger[] ks, GlvEndomorphism glvEndomorphism) - { - BigInteger n = ps[0].Curve.Order; - - int len = ps.Length; - - BigInteger[] abs = new BigInteger[len << 1]; - for (int i = 0, j = 0; i < len; ++i) - { - BigInteger[] ab = glvEndomorphism.DecomposeScalar(ks[i].Mod(n)); - abs[j++] = ab[0]; - abs[j++] = ab[1]; - } - - ECPointMap pointMap = glvEndomorphism.PointMap; - if (glvEndomorphism.HasEfficientPointMap) - { - return ECAlgorithms.ImplSumOfMultiplies(ps, pointMap, abs); - } - - ECPoint[] pqs = new ECPoint[len << 1]; - for (int i = 0, j = 0; i < len; ++i) - { - ECPoint p = ps[i], q = pointMap.Map(p); - pqs[j++] = p; - pqs[j++] = q; - } - - return ECAlgorithms.ImplSumOfMultiplies(pqs, abs); - } - - internal static ECPoint ImplSumOfMultiplies(ECPoint[] ps, ECPointMap pointMap, BigInteger[] ks) - { - int halfCount = ps.Length, fullCount = halfCount << 1; - - bool[] negs = new bool[fullCount]; - WNafPreCompInfo[] infos = new WNafPreCompInfo[fullCount]; - byte[][] wnafs = new byte[fullCount][]; - - for (int i = 0; i < halfCount; ++i) - { - int j0 = i << 1, j1 = j0 + 1; - - 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)))); - - 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); - } - - return ImplSumOfMultiplies(negs, infos, wnafs); - } - - private static ECPoint ImplSumOfMultiplies(bool[] negs, WNafPreCompInfo[] infos, byte[][] wnafs) - { - int len = 0, count = wnafs.Length; - for (int i = 0; i < count; ++i) - { - len = System.Math.Max(len, wnafs[i].Length); - } - - ECCurve curve = infos[0].PreComp[0].Curve; - ECPoint infinity = curve.Infinity; - - ECPoint R = infinity; - int zeroes = 0; - - for (int i = len - 1; i >= 0; --i) - { - ECPoint r = infinity; - - for (int j = 0; j < count; ++j) - { - byte[] wnaf = wnafs[j]; - int wi = i < wnaf.Length ? (int)(sbyte)wnaf[i] : 0; - if (wi != 0) - { - int n = System.Math.Abs(wi); - WNafPreCompInfo info = infos[j]; - ECPoint[] table = (wi < 0 == negs[j]) ? info.PreComp : info.PreCompNeg; - r = r.Add(table[n >> 1]); - } - } - - if (r == infinity) - { - ++zeroes; - continue; - } - - if (zeroes > 0) - { - R = R.TimesPow2(zeroes); - zeroes = 0; - } - - R = R.TwicePlus(r); - } - - if (zeroes > 0) - { - R = R.TimesPow2(zeroes); - } - - return R; - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/ec/ECCurve.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/ECCurve.cs deleted file mode 100644 index 46c69184d..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/ECCurve.cs +++ /dev/null @@ -1,1278 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Abc; -using Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Endo; -using Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Multiplier; -using Renci.SshNet.Security.Org.BouncyCastle.Math.Field; -using Renci.SshNet.Security.Org.BouncyCastle.Math.Raw; -using Renci.SshNet.Security.Org.BouncyCastle.Utilities; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC -{ - /// Base class for an elliptic curve. - internal abstract class ECCurve - { - public const int COORD_AFFINE = 0; - public const int COORD_HOMOGENEOUS = 1; - public const int COORD_JACOBIAN = 2; - public const int COORD_JACOBIAN_CHUDNOVSKY = 3; - public const int COORD_JACOBIAN_MODIFIED = 4; - public const int COORD_LAMBDA_AFFINE = 5; - public const int COORD_LAMBDA_PROJECTIVE = 6; - public const int COORD_SKEWED = 7; - - public static int[] GetAllCoordinateSystems() - { - return new int[]{ COORD_AFFINE, COORD_HOMOGENEOUS, COORD_JACOBIAN, COORD_JACOBIAN_CHUDNOVSKY, - COORD_JACOBIAN_MODIFIED, COORD_LAMBDA_AFFINE, COORD_LAMBDA_PROJECTIVE, COORD_SKEWED }; - } - - internal class Config - { - protected ECCurve outer; - protected int coord; - protected ECEndomorphism endomorphism; - protected ECMultiplier multiplier; - - internal Config(ECCurve outer, int coord, ECEndomorphism endomorphism, ECMultiplier multiplier) - { - this.outer = outer; - this.coord = coord; - this.endomorphism = endomorphism; - this.multiplier = multiplier; - } - - public Config SetCoordinateSystem(int coord) - { - this.coord = coord; - return this; - } - - public Config SetEndomorphism(ECEndomorphism endomorphism) - { - this.endomorphism = endomorphism; - return this; - } - - public Config SetMultiplier(ECMultiplier multiplier) - { - this.multiplier = multiplier; - return this; - } - - public ECCurve Create() - { - if (!outer.SupportsCoordinateSystem(coord)) - { - throw new InvalidOperationException("unsupported coordinate system"); - } - - ECCurve c = outer.CloneCurve(); - if (c == outer) - { - throw new InvalidOperationException("implementation returned current curve"); - } - - c.m_coord = coord; - c.m_endomorphism = endomorphism; - c.m_multiplier = multiplier; - - return c; - } - } - - protected readonly IFiniteField m_field; - protected ECFieldElement m_a, m_b; - protected BigInteger m_order, m_cofactor; - - protected int m_coord = COORD_AFFINE; - protected ECEndomorphism m_endomorphism = null; - protected ECMultiplier m_multiplier = null; - - protected ECCurve(IFiniteField field) - { - this.m_field = field; - } - - public abstract int FieldSize { get; } - public abstract ECFieldElement FromBigInteger(BigInteger x); - public abstract bool IsValidFieldElement(BigInteger x); - - public virtual Config Configure() - { - return new Config(this, this.m_coord, this.m_endomorphism, this.m_multiplier); - } - - public virtual ECPoint ValidatePoint(BigInteger x, BigInteger y) - { - ECPoint p = CreatePoint(x, y); - if (!p.IsValid()) - { - throw new ArgumentException("Invalid point coordinates"); - } - return p; - } - - public virtual ECPoint ValidatePoint(BigInteger x, BigInteger y, bool withCompression) - { - ECPoint p = CreatePoint(x, y, withCompression); - if (!p.IsValid()) - { - throw new ArgumentException("Invalid point coordinates"); - } - return p; - } - - public virtual ECPoint CreatePoint(BigInteger x, BigInteger y) - { - return CreatePoint(x, y, false); - } - - public virtual ECPoint CreatePoint(BigInteger x, BigInteger y, bool withCompression) - { - return CreateRawPoint(FromBigInteger(x), FromBigInteger(y), withCompression); - } - - protected abstract ECCurve CloneCurve(); - - protected internal abstract ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression); - - protected internal abstract ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression); - - protected virtual ECMultiplier CreateDefaultMultiplier() - { - GlvEndomorphism glvEndomorphism = m_endomorphism as GlvEndomorphism; - if (glvEndomorphism != null) - { - return new GlvMultiplier(this, glvEndomorphism); - } - - return new WNafL2RMultiplier(); - } - - public virtual bool SupportsCoordinateSystem(int coord) - { - return coord == COORD_AFFINE; - } - - public virtual PreCompInfo GetPreCompInfo(ECPoint point, string name) - { - CheckPoint(point); - - IDictionary table; - lock (point) - { - table = point.m_preCompTable; - } - - if (null == table) - return null; - - lock (table) - { - return (PreCompInfo)table[name]; - } - } - - /** - * Compute a PreCompInfo for a point on this curve, under a given name. Used by - * ECMultipliers to save the precomputation for this ECPoint for use - * by subsequent multiplication. - * - * @param point - * The ECPoint to store precomputations for. - * @param name - * A String used to index precomputations of different types. - * @param callback - * Called to calculate the PreCompInfo. - */ - public virtual PreCompInfo Precompute(ECPoint point, string name, IPreCompCallback callback) - { - CheckPoint(point); - - IDictionary table; - lock (point) - { - table = point.m_preCompTable; - if (null == table) - { - point.m_preCompTable = table = new Dictionary(4); - } - } - - lock (table) - { - PreCompInfo existing = (PreCompInfo)table[name]; - PreCompInfo result = callback.Precompute(existing); - - if (result != existing) - { - table[name] = result; - } - - return result; - } - } - - public virtual ECPoint ImportPoint(ECPoint p) - { - if (this == p.Curve) - { - return p; - } - if (p.IsInfinity) - { - return Infinity; - } - - // TODO Default behaviour could be improved if the two curves have the same coordinate system by copying any Z coordinates. - p = p.Normalize(); - - return CreatePoint(p.XCoord.ToBigInteger(), p.YCoord.ToBigInteger(), p.IsCompressed); - } - - /** - * Normalization ensures that any projective coordinate is 1, and therefore that the x, y - * coordinates reflect those of the equivalent point in an affine coordinate system. Where more - * than one point is to be normalized, this method will generally be more efficient than - * normalizing each point separately. - * - * @param points - * An array of points that will be updated in place with their normalized versions, - * where necessary - */ - public virtual void NormalizeAll(ECPoint[] points) - { - NormalizeAll(points, 0, points.Length, null); - } - - /** - * Normalization ensures that any projective coordinate is 1, and therefore that the x, y - * coordinates reflect those of the equivalent point in an affine coordinate system. Where more - * than one point is to be normalized, this method will generally be more efficient than - * normalizing each point separately. An (optional) z-scaling factor can be applied; effectively - * each z coordinate is scaled by this value prior to normalization (but only one - * actual multiplication is needed). - * - * @param points - * An array of points that will be updated in place with their normalized versions, - * where necessary - * @param off - * The start of the range of points to normalize - * @param len - * The length of the range of points to normalize - * @param iso - * The (optional) z-scaling factor - can be null - */ - public virtual void NormalizeAll(ECPoint[] points, int off, int len, ECFieldElement iso) - { - CheckPoints(points, off, len); - - switch (this.CoordinateSystem) - { - case ECCurve.COORD_AFFINE: - case ECCurve.COORD_LAMBDA_AFFINE: - { - if (iso != null) - throw new ArgumentException("not valid for affine coordinates", "iso"); - - return; - } - } - - /* - * Figure out which of the points actually need to be normalized - */ - ECFieldElement[] zs = new ECFieldElement[len]; - int[] indices = new int[len]; - int count = 0; - for (int i = 0; i < len; ++i) - { - ECPoint p = points[off + i]; - if (null != p && (iso != null || !p.IsNormalized())) - { - zs[count] = p.GetZCoord(0); - indices[count++] = off + i; - } - } - - if (count == 0) - { - return; - } - - ECAlgorithms.MontgomeryTrick(zs, 0, count, iso); - - for (int j = 0; j < count; ++j) - { - int index = indices[j]; - points[index] = points[index].Normalize(zs[j]); - } - } - - public abstract ECPoint Infinity { get; } - - public virtual IFiniteField Field - { - get { return m_field; } - } - - public virtual ECFieldElement A - { - get { return m_a; } - } - - public virtual ECFieldElement B - { - get { return m_b; } - } - - public virtual BigInteger Order - { - get { return m_order; } - } - - public virtual BigInteger Cofactor - { - get { return m_cofactor; } - } - - public virtual int CoordinateSystem - { - get { return m_coord; } - } - - /** - * Create a cache-safe lookup table for the specified sequence of points. All the points MUST - * belong to this ECCurve instance, and MUST already be normalized. - */ - public virtual ECLookupTable CreateCacheSafeLookupTable(ECPoint[] points, int off, int len) - { - int FE_BYTES = (FieldSize + 7) / 8; - byte[] table = new byte[len * FE_BYTES * 2]; - { - int pos = 0; - for (int i = 0; i < len; ++i) - { - ECPoint p = points[off + i]; - byte[] px = p.RawXCoord.ToBigInteger().ToByteArray(); - byte[] py = p.RawYCoord.ToBigInteger().ToByteArray(); - - int pxStart = px.Length > FE_BYTES ? 1 : 0, pxLen = px.Length - pxStart; - int pyStart = py.Length > FE_BYTES ? 1 : 0, pyLen = py.Length - pyStart; - - Array.Copy(px, pxStart, table, pos + FE_BYTES - pxLen, pxLen); pos += FE_BYTES; - Array.Copy(py, pyStart, table, pos + FE_BYTES - pyLen, pyLen); pos += FE_BYTES; - } - } - - return new DefaultLookupTable(this, table, len); - } - - protected virtual void CheckPoint(ECPoint point) - { - if (null == point || (this != point.Curve)) - throw new ArgumentException("must be non-null and on this curve", "point"); - } - - protected virtual void CheckPoints(ECPoint[] points) - { - CheckPoints(points, 0, points.Length); - } - - protected virtual void CheckPoints(ECPoint[] points, int off, int len) - { - if (points == null) - throw new ArgumentNullException("points"); - if (off < 0 || len < 0 || (off > (points.Length - len))) - throw new ArgumentException("invalid range specified", "points"); - - for (int i = 0; i < len; ++i) - { - ECPoint point = points[off + i]; - if (null != point && this != point.Curve) - throw new ArgumentException("entries must be null or on this curve", "points"); - } - } - - public virtual bool Equals(ECCurve other) - { - if (this == other) - return true; - if (null == other) - return false; - return Field.Equals(other.Field) - && A.ToBigInteger().Equals(other.A.ToBigInteger()) - && B.ToBigInteger().Equals(other.B.ToBigInteger()); - } - - public override bool Equals(object obj) - { - return Equals(obj as ECCurve); - } - - public override int GetHashCode() - { - return Field.GetHashCode() - ^ Integers.RotateLeft(A.ToBigInteger().GetHashCode(), 8) - ^ Integers.RotateLeft(B.ToBigInteger().GetHashCode(), 16); - } - - protected abstract ECPoint DecompressPoint(int yTilde, BigInteger X1); - - public virtual ECEndomorphism GetEndomorphism() - { - return m_endomorphism; - } - - /** - * Sets the default ECMultiplier, unless already set. - */ - public virtual ECMultiplier GetMultiplier() - { - lock (this) - { - if (this.m_multiplier == null) - { - this.m_multiplier = CreateDefaultMultiplier(); - } - return this.m_multiplier; - } - } - - /** - * Decode a point on this curve from its ASN.1 encoding. The different - * encodings are taken account of, including point compression for - * Fp (X9.62 s 4.2.1 pg 17). - * @return The decoded point. - */ - public virtual ECPoint DecodePoint(byte[] encoded) - { - ECPoint p = null; - int expectedLength = (FieldSize + 7) / 8; - - byte type = encoded[0]; - switch (type) - { - case 0x00: // infinity - { - if (encoded.Length != 1) - throw new ArgumentException("Incorrect length for infinity encoding", "encoded"); - - p = Infinity; - break; - } - - case 0x02: // compressed - case 0x03: // compressed - { - if (encoded.Length != (expectedLength + 1)) - throw new ArgumentException("Incorrect length for compressed encoding", "encoded"); - - int yTilde = type & 1; - BigInteger X = new BigInteger(1, encoded, 1, expectedLength); - - p = DecompressPoint(yTilde, X); - if (!p.ImplIsValid(true, true)) - throw new ArgumentException("Invalid point"); - - break; - } - - case 0x04: // uncompressed - { - if (encoded.Length != (2 * expectedLength + 1)) - throw new ArgumentException("Incorrect length for uncompressed encoding", "encoded"); - - BigInteger X = new BigInteger(1, encoded, 1, expectedLength); - BigInteger Y = new BigInteger(1, encoded, 1 + expectedLength, expectedLength); - - p = ValidatePoint(X, Y); - break; - } - - case 0x06: // hybrid - case 0x07: // hybrid - { - if (encoded.Length != (2 * expectedLength + 1)) - throw new ArgumentException("Incorrect length for hybrid encoding", "encoded"); - - BigInteger X = new BigInteger(1, encoded, 1, expectedLength); - BigInteger Y = new BigInteger(1, encoded, 1 + expectedLength, expectedLength); - - if (Y.TestBit(0) != (type == 0x07)) - throw new ArgumentException("Inconsistent Y coordinate in hybrid encoding", "encoded"); - - p = ValidatePoint(X, Y); - break; - } - - default: - throw new FormatException("Invalid point encoding " + type); - } - - if (type != 0x00 && p.IsInfinity) - throw new ArgumentException("Invalid infinity encoding", "encoded"); - - return p; - } - - private class DefaultLookupTable - : ECLookupTable - { - private readonly ECCurve m_outer; - private readonly byte[] m_table; - private readonly int m_size; - - internal DefaultLookupTable(ECCurve outer, byte[] table, int size) - { - this.m_outer = outer; - this.m_table = table; - this.m_size = size; - } - - public virtual int Size - { - get { return m_size; } - } - - public virtual ECPoint Lookup(int index) - { - int FE_BYTES = (m_outer.FieldSize + 7) / 8; - byte[] x = new byte[FE_BYTES], y = new byte[FE_BYTES]; - int pos = 0; - - for (int i = 0; i < m_size; ++i) - { - byte MASK = (byte)(((i ^ index) - 1) >> 31); - - for (int j = 0; j < FE_BYTES; ++j) - { - x[j] ^= (byte)(m_table[pos + j] & MASK); - y[j] ^= (byte)(m_table[pos + FE_BYTES + j] & MASK); - } - - pos += (FE_BYTES * 2); - } - - 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); - } - } - } - - internal abstract class AbstractFpCurve - : ECCurve - { - protected AbstractFpCurve(BigInteger q) - : base(FiniteFields.GetPrimeField(q)) - { - } - - public override bool IsValidFieldElement(BigInteger x) - { - return x != null && x.SignValue >= 0 && x.CompareTo(Field.Characteristic) < 0; - } - - protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) - { - ECFieldElement x = FromBigInteger(X1); - ECFieldElement rhs = x.Square().Add(A).Multiply(x).Add(B); - ECFieldElement y = rhs.Sqrt(); - - /* - * If y is not a square, then we haven't got a point on the curve - */ - if (y == null) - throw new ArgumentException("Invalid point compression"); - - if (y.TestBitZero() != (yTilde == 1)) - { - // Use the other root - y = y.Negate(); - } - - return CreateRawPoint(x, y, true); - } - } - - /** - * Elliptic curve over Fp - */ - internal class FpCurve - : AbstractFpCurve - { - private const int FP_DEFAULT_COORDS = COORD_JACOBIAN_MODIFIED; - - protected readonly BigInteger m_q, m_r; - protected readonly FpPoint m_infinity; - - public FpCurve(BigInteger q, BigInteger a, BigInteger b) - : this(q, a, b, null, null) - { - } - - public FpCurve(BigInteger q, BigInteger a, BigInteger b, BigInteger order, BigInteger cofactor) - : base(q) - { - this.m_q = q; - this.m_r = FpFieldElement.CalculateResidue(q); - this.m_infinity = new FpPoint(this, null, null, false); - - this.m_a = FromBigInteger(a); - this.m_b = FromBigInteger(b); - this.m_order = order; - this.m_cofactor = cofactor; - this.m_coord = FP_DEFAULT_COORDS; - } - - protected FpCurve(BigInteger q, BigInteger r, ECFieldElement a, ECFieldElement b) - : this(q, r, a, b, null, null) - { - } - - protected FpCurve(BigInteger q, BigInteger r, ECFieldElement a, ECFieldElement b, BigInteger order, BigInteger cofactor) - : base(q) - { - this.m_q = q; - this.m_r = r; - this.m_infinity = new FpPoint(this, null, null, false); - - this.m_a = a; - this.m_b = b; - this.m_order = order; - this.m_cofactor = cofactor; - this.m_coord = FP_DEFAULT_COORDS; - } - - protected override ECCurve CloneCurve() - { - return new FpCurve(m_q, m_r, m_a, m_b, m_order, m_cofactor); - } - - public override bool SupportsCoordinateSystem(int coord) - { - switch (coord) - { - case COORD_AFFINE: - case COORD_HOMOGENEOUS: - case COORD_JACOBIAN: - case COORD_JACOBIAN_MODIFIED: - return true; - default: - return false; - } - } - - public virtual BigInteger Q - { - get { return m_q; } - } - - public override ECPoint Infinity - { - get { return m_infinity; } - } - - public override int FieldSize - { - get { return m_q.BitLength; } - } - - public override ECFieldElement FromBigInteger(BigInteger x) - { - return new FpFieldElement(this.m_q, this.m_r, x); - } - - protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression) - { - return new FpPoint(this, x, y, withCompression); - } - - protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) - { - return new FpPoint(this, x, y, zs, withCompression); - } - - public override ECPoint ImportPoint(ECPoint p) - { - if (this != p.Curve && this.CoordinateSystem == COORD_JACOBIAN && !p.IsInfinity) - { - switch (p.Curve.CoordinateSystem) - { - case COORD_JACOBIAN: - case COORD_JACOBIAN_CHUDNOVSKY: - case COORD_JACOBIAN_MODIFIED: - return new FpPoint(this, - FromBigInteger(p.RawXCoord.ToBigInteger()), - FromBigInteger(p.RawYCoord.ToBigInteger()), - new ECFieldElement[] { FromBigInteger(p.GetZCoord(0).ToBigInteger()) }, - p.IsCompressed); - default: - break; - } - } - - return base.ImportPoint(p); - } - } - - internal abstract class AbstractF2mCurve - : ECCurve - { - public static BigInteger Inverse(int m, int[] ks, BigInteger x) - { - return new LongArray(x).ModInverse(m, ks).ToBigInteger(); - } - - /** - * The auxiliary values s0 and - * s1 used for partial modular reduction for - * Koblitz curves. - */ - private BigInteger[] si = null; - - private static IFiniteField BuildField(int m, int k1, int k2, int k3) - { - if (k1 == 0) - { - throw new ArgumentException("k1 must be > 0"); - } - - if (k2 == 0) - { - if (k3 != 0) - { - throw new ArgumentException("k3 must be 0 if k2 == 0"); - } - - return FiniteFields.GetBinaryExtensionField(new int[]{ 0, k1, m }); - } - - if (k2 <= k1) - { - throw new ArgumentException("k2 must be > k1"); - } - - if (k3 <= k2) - { - throw new ArgumentException("k3 must be > k2"); - } - - return FiniteFields.GetBinaryExtensionField(new int[]{ 0, k1, k2, k3, m }); - } - - protected AbstractF2mCurve(int m, int k1, int k2, int k3) - : base(BuildField(m, k1, k2, k3)) - { - } - - public override bool IsValidFieldElement(BigInteger x) - { - return x != null && x.SignValue >= 0 && x.BitLength <= FieldSize; - } - - public override ECPoint CreatePoint(BigInteger x, BigInteger y, bool withCompression) - { - ECFieldElement X = FromBigInteger(x), Y = FromBigInteger(y); - - switch (this.CoordinateSystem) - { - case COORD_LAMBDA_AFFINE: - case COORD_LAMBDA_PROJECTIVE: - { - if (X.IsZero) - { - if (!Y.Square().Equals(B)) - throw new ArgumentException(); - } - else - { - // Y becomes Lambda (X + Y/X) here - Y = Y.Divide(X).Add(X); - } - break; - } - default: - { - break; - } - } - - return CreateRawPoint(X, Y, withCompression); - } - - protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) - { - ECFieldElement xp = FromBigInteger(X1), yp = null; - if (xp.IsZero) - { - yp = B.Sqrt(); - } - else - { - ECFieldElement beta = xp.Square().Invert().Multiply(B).Add(A).Add(xp); - ECFieldElement z = SolveQuadraticEquation(beta); - - if (z != null) - { - if (z.TestBitZero() != (yTilde == 1)) - { - z = z.AddOne(); - } - - switch (this.CoordinateSystem) - { - case COORD_LAMBDA_AFFINE: - case COORD_LAMBDA_PROJECTIVE: - { - yp = z.Add(xp); - break; - } - default: - { - yp = z.Multiply(xp); - break; - } - } - } - } - - if (yp == null) - throw new ArgumentException("Invalid point compression"); - - return CreateRawPoint(xp, yp, true); - } - - /** - * Solves a quadratic equation z2 + z = beta(X9.62 - * D.1.6) The other solution is z + 1. - * - * @param beta - * The value to solve the quadratic equation for. - * @return the solution for z2 + z = beta or - * null if no solution exists. - */ - internal ECFieldElement SolveQuadraticEquation(ECFieldElement beta) - { - if (beta.IsZero) - return beta; - - ECFieldElement gamma, z, zeroElement = FromBigInteger(BigInteger.Zero); - - int m = FieldSize; - do - { - ECFieldElement t = FromBigInteger(BigInteger.Arbitrary(m)); - z = zeroElement; - ECFieldElement w = beta; - for (int i = 1; i < m; i++) - { - ECFieldElement w2 = w.Square(); - z = z.Square().Add(w2.Multiply(t)); - w = w2.Add(beta); - } - if (!w.IsZero) - { - return null; - } - gamma = z.Square().Add(z); - } - while (gamma.IsZero); - - return z; - } - - /** - * @return the auxiliary values s0 and - * s1 used for partial modular reduction for - * Koblitz curves. - */ - internal virtual BigInteger[] GetSi() - { - if (si == null) - { - lock (this) - { - if (si == null) - { - si = Tnaf.GetSi(this); - } - } - } - return si; - } - - /** - * Returns true if this is a Koblitz curve (ABC curve). - * @return true if this is a Koblitz curve (ABC curve), false otherwise - */ - public virtual bool IsKoblitz - { - get - { - return m_order != null && m_cofactor != null && m_b.IsOne && (m_a.IsZero || m_a.IsOne); - } - } - } - - /** - * Elliptic curves over F2m. The Weierstrass equation is given by - * y2 + xy = x3 + ax2 + b. - */ - internal class F2mCurve - : AbstractF2mCurve - { - private const int F2M_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE; - - /** - * The exponent m of F2m. - */ - private readonly int m; - - /** - * TPB: The integer k where xm + - * xk + 1 represents the reduction polynomial - * f(z). - * PPB: The integer k1 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z). - */ - private readonly int k1; - - /** - * TPB: Always set to 0 - * PPB: The integer k2 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z). - */ - private readonly int k2; - - /** - * TPB: Always set to 0 - * PPB: The integer k3 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z). - */ - private readonly int k3; - - /** - * The point at infinity on this curve. - */ - protected readonly F2mPoint m_infinity; - - /** - * Constructor for Trinomial Polynomial Basis (TPB). - * @param m The exponent m of - * F2m. - * @param k The integer k where xm + - * xk + 1 represents the reduction - * polynomial f(z). - * @param a The coefficient a in the Weierstrass equation - * for non-supersingular elliptic curves over - * F2m. - * @param b The coefficient b in the Weierstrass equation - * for non-supersingular elliptic curves over - * F2m. - */ - [Obsolete("Use constructor taking order/cofactor")] - public F2mCurve( - int m, - int k, - BigInteger a, - BigInteger b) - : this(m, k, 0, 0, a, b, null, null) - { - } - - /** - * Constructor for Trinomial Polynomial Basis (TPB). - * @param m The exponent m of - * F2m. - * @param k The integer k where xm + - * xk + 1 represents the reduction - * polynomial f(z). - * @param a The coefficient a in the Weierstrass equation - * for non-supersingular elliptic curves over - * F2m. - * @param b The coefficient b in the Weierstrass equation - * for non-supersingular elliptic curves over - * F2m. - * @param order The order of the main subgroup of the elliptic curve. - * @param cofactor The cofactor of the elliptic curve, i.e. - * #Ea(F2m) = h * n. - */ - public F2mCurve( - int m, - int k, - BigInteger a, - BigInteger b, - BigInteger order, - BigInteger cofactor) - : this(m, k, 0, 0, a, b, order, cofactor) - { - } - - /** - * Constructor for Pentanomial Polynomial Basis (PPB). - * @param m The exponent m of - * F2m. - * @param k1 The integer k1 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z). - * @param k2 The integer k2 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z). - * @param k3 The integer k3 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z). - * @param a The coefficient a in the Weierstrass equation - * for non-supersingular elliptic curves over - * F2m. - * @param b The coefficient b in the Weierstrass equation - * for non-supersingular elliptic curves over - * F2m. - */ - [Obsolete("Use constructor taking order/cofactor")] - public F2mCurve( - int m, - int k1, - int k2, - int k3, - BigInteger a, - BigInteger b) - : this(m, k1, k2, k3, a, b, null, null) - { - } - - /** - * Constructor for Pentanomial Polynomial Basis (PPB). - * @param m The exponent m of - * F2m. - * @param k1 The integer k1 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z). - * @param k2 The integer k2 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z). - * @param k3 The integer k3 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z). - * @param a The coefficient a in the Weierstrass equation - * for non-supersingular elliptic curves over - * F2m. - * @param b The coefficient b in the Weierstrass equation - * for non-supersingular elliptic curves over - * F2m. - * @param order The order of the main subgroup of the elliptic curve. - * @param cofactor The cofactor of the elliptic curve, i.e. - * #Ea(F2m) = h * n. - */ - public F2mCurve( - int m, - int k1, - int k2, - int k3, - BigInteger a, - BigInteger b, - BigInteger order, - BigInteger cofactor) - : base(m, k1, k2, k3) - { - this.m = m; - this.k1 = k1; - this.k2 = k2; - this.k3 = k3; - this.m_order = order; - this.m_cofactor = cofactor; - this.m_infinity = new F2mPoint(this, null, null, false); - - if (k1 == 0) - throw new ArgumentException("k1 must be > 0"); - - if (k2 == 0) - { - if (k3 != 0) - throw new ArgumentException("k3 must be 0 if k2 == 0"); - } - else - { - if (k2 <= k1) - throw new ArgumentException("k2 must be > k1"); - - if (k3 <= k2) - throw new ArgumentException("k3 must be > k2"); - } - - this.m_a = FromBigInteger(a); - this.m_b = FromBigInteger(b); - this.m_coord = F2M_DEFAULT_COORDS; - } - - protected F2mCurve(int m, int k1, int k2, int k3, ECFieldElement a, ECFieldElement b, BigInteger order, BigInteger cofactor) - : base(m, k1, k2, k3) - { - this.m = m; - this.k1 = k1; - this.k2 = k2; - this.k3 = k3; - this.m_order = order; - this.m_cofactor = cofactor; - - this.m_infinity = new F2mPoint(this, null, null, false); - this.m_a = a; - this.m_b = b; - this.m_coord = F2M_DEFAULT_COORDS; - } - - protected override ECCurve CloneCurve() - { - return new F2mCurve(m, k1, k2, k3, m_a, m_b, m_order, m_cofactor); - } - - public override bool SupportsCoordinateSystem(int coord) - { - switch (coord) - { - case COORD_AFFINE: - case COORD_HOMOGENEOUS: - case COORD_LAMBDA_PROJECTIVE: - return true; - default: - return false; - } - } - - protected override ECMultiplier CreateDefaultMultiplier() - { - if (IsKoblitz) - { - return new WTauNafMultiplier(); - } - - return base.CreateDefaultMultiplier(); - } - - public override int FieldSize - { - get { return m; } - } - - public override ECFieldElement FromBigInteger(BigInteger x) - { - return new F2mFieldElement(this.m, this.k1, this.k2, this.k3, x); - } - - protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression) - { - return new F2mPoint(this, x, y, withCompression); - } - - protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) - { - return new F2mPoint(this, x, y, zs, withCompression); - } - - public override ECPoint Infinity - { - get { return m_infinity; } - } - - public int M - { - get { return m; } - } - - /** - * Return true if curve uses a Trinomial basis. - * - * @return true if curve Trinomial, false otherwise. - */ - public bool IsTrinomial() - { - return k2 == 0 && k3 == 0; - } - - public int K1 - { - get { return k1; } - } - - public int K2 - { - get { return k2; } - } - - public int K3 - { - get { return k3; } - } - - public override ECLookupTable CreateCacheSafeLookupTable(ECPoint[] points, int off, int len) - { - int FE_LONGS = (m + 63) / 64; - - long[] table = new long[len * FE_LONGS * 2]; - { - int pos = 0; - for (int i = 0; i < len; ++i) - { - ECPoint p = points[off + i]; - ((F2mFieldElement)p.RawXCoord).x.CopyTo(table, pos); pos += FE_LONGS; - ((F2mFieldElement)p.RawYCoord).x.CopyTo(table, pos); pos += FE_LONGS; - } - } - - return new DefaultF2mLookupTable(this, table, len); - } - - private class DefaultF2mLookupTable - : ECLookupTable - { - private readonly F2mCurve m_outer; - private readonly long[] m_table; - private readonly int m_size; - - internal DefaultF2mLookupTable(F2mCurve outer, long[] table, int size) - { - this.m_outer = outer; - this.m_table = table; - this.m_size = size; - } - - public virtual int Size - { - get { return m_size; } - } - - public virtual 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; - - for (int i = 0; i < m_size; ++i) - { - long MASK =((i ^ index) - 1) >> 31; - - for (int j = 0; j < FE_LONGS; ++j) - { - x[j] ^= m_table[pos + j] & MASK; - y[j] ^= m_table[pos + FE_LONGS + j] & MASK; - } - - pos += (FE_LONGS * 2); - } - - 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/src/Renci.SshNet/Security/BouncyCastle/math/ec/ECFieldElement.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/ECFieldElement.cs deleted file mode 100644 index 3ebb3332c..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/ECFieldElement.cs +++ /dev/null @@ -1,972 +0,0 @@ -using System; -using System.Diagnostics; - -using Renci.SshNet.Security.Org.BouncyCastle.Math.Raw; -using Renci.SshNet.Security.Org.BouncyCastle.Utilities; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC -{ - internal abstract class ECFieldElement - { - public abstract BigInteger ToBigInteger(); - public abstract string FieldName { get; } - public abstract int FieldSize { get; } - public abstract ECFieldElement Add(ECFieldElement b); - public abstract ECFieldElement AddOne(); - public abstract ECFieldElement Subtract(ECFieldElement b); - public abstract ECFieldElement Multiply(ECFieldElement b); - public abstract ECFieldElement Divide(ECFieldElement b); - public abstract ECFieldElement Negate(); - public abstract ECFieldElement Square(); - public abstract ECFieldElement Invert(); - public abstract ECFieldElement Sqrt(); - - public virtual int BitLength - { - get { return ToBigInteger().BitLength; } - } - - public virtual bool IsOne - { - get { return BitLength == 1; } - } - - public virtual bool IsZero - { - get { return 0 == ToBigInteger().SignValue; } - } - - public virtual ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) - { - return Multiply(b).Subtract(x.Multiply(y)); - } - - public virtual ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) - { - return Multiply(b).Add(x.Multiply(y)); - } - - public virtual ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y) - { - return Square().Subtract(x.Multiply(y)); - } - - public virtual ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y) - { - return Square().Add(x.Multiply(y)); - } - - public virtual ECFieldElement SquarePow(int pow) - { - ECFieldElement r = this; - for (int i = 0; i < pow; ++i) - { - r = r.Square(); - } - return r; - } - - public virtual bool TestBitZero() - { - return ToBigInteger().TestBit(0); - } - - public override bool Equals(object obj) - { - return Equals(obj as ECFieldElement); - } - - public virtual bool Equals(ECFieldElement other) - { - if (this == other) - return true; - if (null == other) - return false; - return ToBigInteger().Equals(other.ToBigInteger()); - } - - public override int GetHashCode() - { - return ToBigInteger().GetHashCode(); - } - - public override string ToString() - { - return this.ToBigInteger().ToString(16); - } - - public virtual byte[] GetEncoded() - { - return BigIntegers.AsUnsignedByteArray((FieldSize + 7) / 8, ToBigInteger()); - } - } - - internal abstract class AbstractFpFieldElement - : ECFieldElement - { - } - - internal class FpFieldElement - : AbstractFpFieldElement - { - private readonly BigInteger q, r, x; - - internal static BigInteger CalculateResidue(BigInteger p) - { - int bitLength = p.BitLength; - if (bitLength >= 96) - { - BigInteger firstWord = p.ShiftRight(bitLength - 64); - if (firstWord.LongValue == -1L) - { - return BigInteger.One.ShiftLeft(bitLength).Subtract(p); - } - if ((bitLength & 7) == 0) - { - return BigInteger.One.ShiftLeft(bitLength << 1).Divide(p).Negate(); - } - } - return null; - } - - [Obsolete("Use ECCurve.FromBigInteger to construct field elements")] - public FpFieldElement(BigInteger q, BigInteger x) - : this(q, CalculateResidue(q), x) - { - } - - internal FpFieldElement(BigInteger q, BigInteger r, BigInteger x) - { - if (x == null || x.SignValue < 0 || x.CompareTo(q) >= 0) - throw new ArgumentException("value invalid in Fp field element", "x"); - - this.q = q; - this.r = r; - this.x = x; - } - - public override BigInteger ToBigInteger() - { - return x; - } - - /** - * return the field name for this field. - * - * @return the string "Fp". - */ - public override string FieldName - { - get { return "Fp"; } - } - - public override int FieldSize - { - get { return q.BitLength; } - } - - public BigInteger Q - { - get { return q; } - } - - public override ECFieldElement Add( - ECFieldElement b) - { - return new FpFieldElement(q, r, ModAdd(x, b.ToBigInteger())); - } - - public override ECFieldElement AddOne() - { - BigInteger x2 = x.Add(BigInteger.One); - if (x2.CompareTo(q) == 0) - { - x2 = BigInteger.Zero; - } - return new FpFieldElement(q, r, x2); - } - - public override ECFieldElement Subtract( - ECFieldElement b) - { - return new FpFieldElement(q, r, ModSubtract(x, b.ToBigInteger())); - } - - public override ECFieldElement Multiply( - ECFieldElement b) - { - return new FpFieldElement(q, r, ModMult(x, b.ToBigInteger())); - } - - public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) - { - BigInteger ax = this.x, bx = b.ToBigInteger(), xx = x.ToBigInteger(), yx = y.ToBigInteger(); - BigInteger ab = ax.Multiply(bx); - BigInteger xy = xx.Multiply(yx); - return new FpFieldElement(q, r, ModReduce(ab.Subtract(xy))); - } - - public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) - { - BigInteger ax = this.x, bx = b.ToBigInteger(), xx = x.ToBigInteger(), yx = y.ToBigInteger(); - BigInteger ab = ax.Multiply(bx); - BigInteger xy = xx.Multiply(yx); - BigInteger sum = ab.Add(xy); - if (r != null && r.SignValue < 0 && sum.BitLength > (q.BitLength << 1)) - { - sum = sum.Subtract(q.ShiftLeft(q.BitLength)); - } - return new FpFieldElement(q, r, ModReduce(sum)); - } - - public override ECFieldElement Divide( - ECFieldElement b) - { - return new FpFieldElement(q, r, ModMult(x, ModInverse(b.ToBigInteger()))); - } - - public override ECFieldElement Negate() - { - return x.SignValue == 0 ? this : new FpFieldElement(q, r, q.Subtract(x)); - } - - public override ECFieldElement Square() - { - return new FpFieldElement(q, r, ModMult(x, x)); - } - - public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y) - { - BigInteger ax = this.x, xx = x.ToBigInteger(), yx = y.ToBigInteger(); - BigInteger aa = ax.Multiply(ax); - BigInteger xy = xx.Multiply(yx); - return new FpFieldElement(q, r, ModReduce(aa.Subtract(xy))); - } - - public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y) - { - BigInteger ax = this.x, xx = x.ToBigInteger(), yx = y.ToBigInteger(); - BigInteger aa = ax.Multiply(ax); - BigInteger xy = xx.Multiply(yx); - BigInteger sum = aa.Add(xy); - if (r != null && r.SignValue < 0 && sum.BitLength > (q.BitLength << 1)) - { - sum = sum.Subtract(q.ShiftLeft(q.BitLength)); - } - return new FpFieldElement(q, r, ModReduce(sum)); - } - - public override ECFieldElement Invert() - { - // TODO Modular inversion can be faster for a (Generalized) Mersenne Prime. - return new FpFieldElement(q, r, ModInverse(x)); - } - - /** - * return a sqrt root - the routine verifies that the calculation - * returns the right value - if none exists it returns null. - */ - public override ECFieldElement Sqrt() - { - if (IsZero || IsOne) - return this; - - if (!q.TestBit(0)) - throw new NotImplementedException("even value of q"); - - if (q.TestBit(1)) // q == 4m + 3 - { - BigInteger e = q.ShiftRight(2).Add(BigInteger.One); - return CheckSqrt(new FpFieldElement(q, r, x.ModPow(e, q))); - } - - if (q.TestBit(2)) // q == 8m + 5 - { - BigInteger t1 = x.ModPow(q.ShiftRight(3), q); - BigInteger t2 = ModMult(t1, x); - BigInteger t3 = ModMult(t2, t1); - - if (t3.Equals(BigInteger.One)) - { - return CheckSqrt(new FpFieldElement(q, r, t2)); - } - - // TODO This is constant and could be precomputed - BigInteger t4 = BigInteger.Two.ModPow(q.ShiftRight(2), q); - - BigInteger y = ModMult(t2, t4); - - return CheckSqrt(new FpFieldElement(q, r, y)); - } - - // q == 8m + 1 - - BigInteger legendreExponent = q.ShiftRight(1); - if (!(x.ModPow(legendreExponent, q).Equals(BigInteger.One))) - return null; - - BigInteger X = this.x; - BigInteger fourX = ModDouble(ModDouble(X)); ; - - BigInteger k = legendreExponent.Add(BigInteger.One), qMinusOne = q.Subtract(BigInteger.One); - - BigInteger U, V; - do - { - BigInteger P; - do - { - P = BigInteger.Arbitrary(q.BitLength); - } - while (P.CompareTo(q) >= 0 - || !ModReduce(P.Multiply(P).Subtract(fourX)).ModPow(legendreExponent, q).Equals(qMinusOne)); - - BigInteger[] result = LucasSequence(P, X, k); - U = result[0]; - V = result[1]; - - if (ModMult(V, V).Equals(fourX)) - { - return new FpFieldElement(q, r, ModHalfAbs(V)); - } - } - while (U.Equals(BigInteger.One) || U.Equals(qMinusOne)); - - return null; - } - - private ECFieldElement CheckSqrt(ECFieldElement z) - { - return z.Square().Equals(this) ? z : null; - } - - private BigInteger[] LucasSequence( - BigInteger P, - BigInteger Q, - BigInteger k) - { - // TODO Research and apply "common-multiplicand multiplication here" - - int n = k.BitLength; - int s = k.GetLowestSetBit(); - - Debug.Assert(k.TestBit(s)); - - BigInteger Uh = BigInteger.One; - BigInteger Vl = BigInteger.Two; - BigInteger Vh = P; - BigInteger Ql = BigInteger.One; - BigInteger Qh = BigInteger.One; - - for (int j = n - 1; j >= s + 1; --j) - { - Ql = ModMult(Ql, Qh); - - if (k.TestBit(j)) - { - Qh = ModMult(Ql, Q); - Uh = ModMult(Uh, Vh); - Vl = ModReduce(Vh.Multiply(Vl).Subtract(P.Multiply(Ql))); - Vh = ModReduce(Vh.Multiply(Vh).Subtract(Qh.ShiftLeft(1))); - } - else - { - Qh = Ql; - Uh = ModReduce(Uh.Multiply(Vl).Subtract(Ql)); - Vh = ModReduce(Vh.Multiply(Vl).Subtract(P.Multiply(Ql))); - Vl = ModReduce(Vl.Multiply(Vl).Subtract(Ql.ShiftLeft(1))); - } - } - - Ql = ModMult(Ql, Qh); - Qh = ModMult(Ql, Q); - Uh = ModReduce(Uh.Multiply(Vl).Subtract(Ql)); - Vl = ModReduce(Vh.Multiply(Vl).Subtract(P.Multiply(Ql))); - Ql = ModMult(Ql, Qh); - - for (int j = 1; j <= s; ++j) - { - Uh = ModMult(Uh, Vl); - Vl = ModReduce(Vl.Multiply(Vl).Subtract(Ql.ShiftLeft(1))); - Ql = ModMult(Ql, Ql); - } - - return new BigInteger[] { Uh, Vl }; - } - - protected virtual BigInteger ModAdd(BigInteger x1, BigInteger x2) - { - BigInteger x3 = x1.Add(x2); - if (x3.CompareTo(q) >= 0) - { - x3 = x3.Subtract(q); - } - return x3; - } - - protected virtual BigInteger ModDouble(BigInteger x) - { - BigInteger _2x = x.ShiftLeft(1); - if (_2x.CompareTo(q) >= 0) - { - _2x = _2x.Subtract(q); - } - return _2x; - } - - protected virtual BigInteger ModHalf(BigInteger x) - { - if (x.TestBit(0)) - { - x = q.Add(x); - } - return x.ShiftRight(1); - } - - protected virtual BigInteger ModHalfAbs(BigInteger x) - { - if (x.TestBit(0)) - { - x = q.Subtract(x); - } - return x.ShiftRight(1); - } - - protected virtual BigInteger ModInverse(BigInteger x) - { - int bits = FieldSize; - int len = (bits + 31) >> 5; - uint[] p = Nat.FromBigInteger(bits, q); - uint[] n = Nat.FromBigInteger(bits, x); - uint[] z = Nat.Create(len); - Mod.Invert(p, n, z); - return Nat.ToBigInteger(len, z); - } - - protected virtual BigInteger ModMult(BigInteger x1, BigInteger x2) - { - return ModReduce(x1.Multiply(x2)); - } - - protected virtual BigInteger ModReduce(BigInteger x) - { - if (r == null) - { - x = x.Mod(q); - } - else - { - bool negative = x.SignValue < 0; - if (negative) - { - x = x.Abs(); - } - int qLen = q.BitLength; - if (r.SignValue > 0) - { - BigInteger qMod = BigInteger.One.ShiftLeft(qLen); - bool rIsOne = r.Equals(BigInteger.One); - while (x.BitLength > (qLen + 1)) - { - BigInteger u = x.ShiftRight(qLen); - BigInteger v = x.Remainder(qMod); - if (!rIsOne) - { - u = u.Multiply(r); - } - x = u.Add(v); - } - } - else - { - int d = ((qLen - 1) & 31) + 1; - BigInteger mu = r.Negate(); - BigInteger u = mu.Multiply(x.ShiftRight(qLen - d)); - BigInteger quot = u.ShiftRight(qLen + d); - BigInteger v = quot.Multiply(q); - BigInteger bk1 = BigInteger.One.ShiftLeft(qLen + d); - v = v.Remainder(bk1); - x = x.Remainder(bk1); - x = x.Subtract(v); - if (x.SignValue < 0) - { - x = x.Add(bk1); - } - } - while (x.CompareTo(q) >= 0) - { - x = x.Subtract(q); - } - if (negative && x.SignValue != 0) - { - x = q.Subtract(x); - } - } - return x; - } - - protected virtual BigInteger ModSubtract(BigInteger x1, BigInteger x2) - { - BigInteger x3 = x1.Subtract(x2); - if (x3.SignValue < 0) - { - x3 = x3.Add(q); - } - return x3; - } - - public override bool Equals( - object obj) - { - if (obj == this) - return true; - - FpFieldElement other = obj as FpFieldElement; - - if (other == null) - return false; - - return Equals(other); - } - - public virtual bool Equals( - FpFieldElement other) - { - return q.Equals(other.q) && base.Equals(other); - } - - public override int GetHashCode() - { - return q.GetHashCode() ^ base.GetHashCode(); - } - } - - internal abstract class AbstractF2mFieldElement - : ECFieldElement - { - public virtual ECFieldElement HalfTrace() - { - int m = FieldSize; - 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) - { - fe = fe.SquarePow(2); - ht = ht.Add(fe); - } - - return ht; - } - - public virtual int Trace() - { - int m = FieldSize; - ECFieldElement fe = this; - ECFieldElement tr = fe; - for (int i = 1; i < m; ++i) - { - fe = fe.Square(); - tr = tr.Add(fe); - } - if (tr.IsZero) - return 0; - if (tr.IsOne) - return 1; - - throw new InvalidOperationException("Internal error in trace calculation"); - } - } - - /** - * Class representing the Elements of the finite field - * F2m in polynomial basis (PB) - * representation. Both trinomial (Tpb) and pentanomial (Ppb) polynomial - * basis representations are supported. Gaussian normal basis (GNB) - * representation is not supported. - */ - internal class F2mFieldElement - : AbstractF2mFieldElement - { - /** - * Indicates gaussian normal basis representation (GNB). Number chosen - * according to X9.62. GNB is not implemented at present. - */ - public const int Gnb = 1; - - /** - * Indicates trinomial basis representation (Tpb). Number chosen - * according to X9.62. - */ - public const int Tpb = 2; - - /** - * Indicates pentanomial basis representation (Ppb). Number chosen - * according to X9.62. - */ - public const int Ppb = 3; - - /** - * Tpb or Ppb. - */ - private int representation; - - /** - * The exponent m of F2m. - */ - private int m; - - private int[] ks; - - /** - * The LongArray holding the bits. - */ - internal LongArray x; - - /** - * Constructor for Ppb. - * @param m The exponent m of - * F2m. - * @param k1 The integer k1 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z). - * @param k2 The integer k2 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z). - * @param k3 The integer k3 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z). - * @param x The BigInteger representing the value of the field element. - */ - public F2mFieldElement( - int m, - int k1, - int k2, - int k3, - BigInteger x) - { - if (x == null || x.SignValue < 0 || x.BitLength > m) - throw new ArgumentException("value invalid in F2m field element", "x"); - - if ((k2 == 0) && (k3 == 0)) - { - this.representation = Tpb; - this.ks = new int[] { k1 }; - } - else - { - if (k2 >= k3) - throw new ArgumentException("k2 must be smaller than k3"); - if (k2 <= 0) - throw new ArgumentException("k2 must be larger than 0"); - - this.representation = Ppb; - this.ks = new int[] { k1, k2, k3 }; - } - - this.m = m; - this.x = new LongArray(x); - } - - /** - * Constructor for Tpb. - * @param m The exponent m of - * F2m. - * @param k The integer k where xm + - * xk + 1 represents the reduction - * polynomial f(z). - * @param x The BigInteger representing the value of the field element. - */ - public F2mFieldElement( - int m, - int k, - BigInteger x) - : this(m, k, 0, 0, x) - { - // Set k1 to k, and set k2 and k3 to 0 - } - - internal F2mFieldElement(int m, int[] ks, LongArray x) - { - this.m = m; - this.representation = (ks.Length == 1) ? Tpb : Ppb; - this.ks = ks; - this.x = x; - } - - public override int BitLength - { - get { return x.Degree(); } - } - - public override bool IsOne - { - get { return x.IsOne(); } - } - - public override bool IsZero - { - get { return x.IsZero(); } - } - - public override bool TestBitZero() - { - return x.TestBitZero(); - } - - public override BigInteger ToBigInteger() - { - return x.ToBigInteger(); - } - - public override string FieldName - { - get { return "F2m"; } - } - - public override int FieldSize - { - get { return m; } - } - - /** - * Checks, if the ECFieldElements a and b - * are elements of the same field F2m - * (having the same representation). - * @param a field element. - * @param b field element to be compared. - * @throws ArgumentException if a and b - * are not elements of the same field - * F2m (having the same - * representation). - */ - public static void CheckFieldElements( - ECFieldElement a, - ECFieldElement b) - { - if (!(a is F2mFieldElement) || !(b is F2mFieldElement)) - { - throw new ArgumentException("Field elements are not " - + "both instances of F2mFieldElement"); - } - - F2mFieldElement aF2m = (F2mFieldElement)a; - F2mFieldElement bF2m = (F2mFieldElement)b; - - if (aF2m.representation != bF2m.representation) - { - // Should never occur - throw new ArgumentException("One of the F2m field elements has incorrect representation"); - } - - if ((aF2m.m != bF2m.m) || !Arrays.AreEqual(aF2m.ks, bF2m.ks)) - { - throw new ArgumentException("Field elements are not elements of the same field F2m"); - } - } - - public override ECFieldElement Add( - ECFieldElement b) - { - // No check performed here for performance reasons. Instead the - // elements involved are checked in ECPoint.F2m - // checkFieldElements(this, b); - LongArray iarrClone = this.x.Copy(); - F2mFieldElement bF2m = (F2mFieldElement)b; - iarrClone.AddShiftedByWords(bF2m.x, 0); - return new F2mFieldElement(m, ks, iarrClone); - } - - public override ECFieldElement AddOne() - { - return new F2mFieldElement(m, ks, x.AddOne()); - } - - public override ECFieldElement Subtract( - ECFieldElement b) - { - // Addition and subtraction are the same in F2m - return Add(b); - } - - public override ECFieldElement Multiply( - ECFieldElement b) - { - // Right-to-left comb multiplication in the LongArray - // Input: Binary polynomials a(z) and b(z) of degree at most m-1 - // Output: c(z) = a(z) * b(z) mod f(z) - - // No check performed here for performance reasons. Instead the - // elements involved are checked in ECPoint.F2m - // checkFieldElements(this, b); - return new F2mFieldElement(m, ks, x.ModMultiply(((F2mFieldElement)b).x, m, ks)); - } - - public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) - { - return MultiplyPlusProduct(b, x, y); - } - - public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) - { - LongArray ax = this.x, bx = ((F2mFieldElement)b).x, xx = ((F2mFieldElement)x).x, yx = ((F2mFieldElement)y).x; - - LongArray ab = ax.Multiply(bx, m, ks); - LongArray xy = xx.Multiply(yx, m, ks); - - if (ab == ax || ab == bx) - { - ab = (LongArray)ab.Copy(); - } - - ab.AddShiftedByWords(xy, 0); - ab.Reduce(m, ks); - - return new F2mFieldElement(m, ks, ab); - } - - public override ECFieldElement Divide( - ECFieldElement b) - { - // There may be more efficient implementations - ECFieldElement bInv = b.Invert(); - return Multiply(bInv); - } - - public override ECFieldElement Negate() - { - // -x == x holds for all x in F2m - return this; - } - - public override ECFieldElement Square() - { - return new F2mFieldElement(m, ks, x.ModSquare(m, ks)); - } - - public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y) - { - return SquarePlusProduct(x, y); - } - - public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y) - { - LongArray ax = this.x, xx = ((F2mFieldElement)x).x, yx = ((F2mFieldElement)y).x; - - LongArray aa = ax.Square(m, ks); - LongArray xy = xx.Multiply(yx, m, ks); - - if (aa == ax) - { - aa = (LongArray)aa.Copy(); - } - - aa.AddShiftedByWords(xy, 0); - aa.Reduce(m, ks); - - return new F2mFieldElement(m, ks, aa); - } - - public override ECFieldElement SquarePow(int pow) - { - return pow < 1 ? this : new F2mFieldElement(m, ks, x.ModSquareN(pow, m, ks)); - } - - public override ECFieldElement Invert() - { - return new F2mFieldElement(this.m, this.ks, this.x.ModInverse(m, ks)); - } - - public override ECFieldElement Sqrt() - { - return (x.IsZero() || x.IsOne()) ? this : SquarePow(m - 1); - } - - /** - * @return the representation of the field - * F2m, either of - * {@link F2mFieldElement.Tpb} (trinomial - * basis representation) or - * {@link F2mFieldElement.Ppb} (pentanomial - * basis representation). - */ - public int Representation - { - get { return this.representation; } - } - - /** - * @return the degree m of the reduction polynomial - * f(z). - */ - public int M - { - get { return this.m; } - } - - /** - * @return Tpb: The integer k where xm + - * xk + 1 represents the reduction polynomial - * f(z). - * Ppb: The integer k1 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z). - */ - public int K1 - { - get { return this.ks[0]; } - } - - /** - * @return Tpb: Always returns 0 - * Ppb: The integer k2 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z). - */ - public int K2 - { - get { return this.ks.Length >= 2 ? this.ks[1] : 0; } - } - - /** - * @return Tpb: Always set to 0 - * Ppb: The integer k3 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z). - */ - public int K3 - { - get { return this.ks.Length >= 3 ? this.ks[2] : 0; } - } - - public override bool Equals( - object obj) - { - if (obj == this) - return true; - - F2mFieldElement other = obj as F2mFieldElement; - - if (other == null) - return false; - - return Equals(other); - } - - public virtual bool Equals( - F2mFieldElement other) - { - return ((this.m == other.m) - && (this.representation == other.representation) - && Arrays.AreEqual(this.ks, other.ks) - && (this.x.Equals(other.x))); - } - - public override int GetHashCode() - { - return x.GetHashCode() ^ m ^ Arrays.GetHashCode(ks); - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/ec/ECLookupTable.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/ECLookupTable.cs deleted file mode 100644 index 0b9a3999f..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/ECLookupTable.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC -{ - internal interface ECLookupTable - { - int Size { get; } - ECPoint Lookup(int index); - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/ec/ECPoint.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/ECPoint.cs deleted file mode 100644 index 3a93c3e76..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/ECPoint.cs +++ /dev/null @@ -1,2122 +0,0 @@ -using System; -using System.Collections; -using System.Diagnostics; -using System.Text; - -using Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Multiplier; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC -{ - /** - * base class for points on elliptic curves. - */ - internal abstract class ECPoint - { - protected static ECFieldElement[] EMPTY_ZS = new ECFieldElement[0]; - - protected static ECFieldElement[] GetInitialZCoords(ECCurve curve) - { - // Cope with null curve, most commonly used by implicitlyCa - int coord = null == curve ? ECCurve.COORD_AFFINE : curve.CoordinateSystem; - - switch (coord) - { - case ECCurve.COORD_AFFINE: - case ECCurve.COORD_LAMBDA_AFFINE: - return EMPTY_ZS; - default: - break; - } - - ECFieldElement one = curve.FromBigInteger(BigInteger.One); - - switch (coord) - { - case ECCurve.COORD_HOMOGENEOUS: - case ECCurve.COORD_JACOBIAN: - case ECCurve.COORD_LAMBDA_PROJECTIVE: - return new ECFieldElement[] { one }; - case ECCurve.COORD_JACOBIAN_CHUDNOVSKY: - return new ECFieldElement[] { one, one, one }; - case ECCurve.COORD_JACOBIAN_MODIFIED: - return new ECFieldElement[] { one, curve.A }; - default: - throw new ArgumentException("unknown coordinate system"); - } - } - - protected internal readonly ECCurve m_curve; - protected internal readonly ECFieldElement m_x, m_y; - protected internal readonly ECFieldElement[] m_zs; - protected internal readonly bool m_withCompression; - - // Dictionary is (string -> PreCompInfo) - protected internal IDictionary m_preCompTable = null; - - protected ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) - : this(curve, x, y, GetInitialZCoords(curve), withCompression) - { - } - - internal ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) - { - this.m_curve = curve; - this.m_x = x; - this.m_y = y; - this.m_zs = zs; - this.m_withCompression = withCompression; - } - - protected abstract bool SatisfiesCurveEquation(); - - protected virtual bool SatisfiesOrder() - { - if (BigInteger.One.Equals(Curve.Cofactor)) - return true; - - BigInteger n = Curve.Order; - - // TODO Require order to be available for all curves - - return n == null || ECAlgorithms.ReferenceMultiply(this, n).IsInfinity; - } - - public ECPoint GetDetachedPoint() - { - return Normalize().Detach(); - } - - public virtual ECCurve Curve - { - get { return m_curve; } - } - - protected abstract ECPoint Detach(); - - protected virtual int CurveCoordinateSystem - { - get - { - // Cope with null curve, most commonly used by implicitlyCa - return null == m_curve ? ECCurve.COORD_AFFINE : m_curve.CoordinateSystem; - } - } - - /** - * Returns the affine x-coordinate after checking that this point is normalized. - * - * @return The affine x-coordinate of this point - * @throws IllegalStateException if the point is not normalized - */ - public virtual ECFieldElement AffineXCoord - { - get - { - CheckNormalized(); - return XCoord; - } - } - - /** - * Returns the affine y-coordinate after checking that this point is normalized - * - * @return The affine y-coordinate of this point - * @throws IllegalStateException if the point is not normalized - */ - public virtual ECFieldElement AffineYCoord - { - get - { - CheckNormalized(); - return YCoord; - } - } - - /** - * Returns the x-coordinate. - * - * Caution: depending on the curve's coordinate system, this may not be the same value as in an - * affine coordinate system; use Normalize() to get a point where the coordinates have their - * affine values, or use AffineXCoord if you expect the point to already have been normalized. - * - * @return the x-coordinate of this point - */ - public virtual ECFieldElement XCoord - { - get { return m_x; } - } - - /** - * Returns the y-coordinate. - * - * Caution: depending on the curve's coordinate system, this may not be the same value as in an - * affine coordinate system; use Normalize() to get a point where the coordinates have their - * affine values, or use AffineYCoord if you expect the point to already have been normalized. - * - * @return the y-coordinate of this point - */ - public virtual ECFieldElement YCoord - { - get { return m_y; } - } - - public virtual ECFieldElement GetZCoord(int index) - { - return (index < 0 || index >= m_zs.Length) ? null : m_zs[index]; - } - - public virtual ECFieldElement[] GetZCoords() - { - int zsLen = m_zs.Length; - if (zsLen == 0) - { - return m_zs; - } - ECFieldElement[] copy = new ECFieldElement[zsLen]; - Array.Copy(m_zs, 0, copy, 0, zsLen); - return copy; - } - - protected internal ECFieldElement RawXCoord - { - get { return m_x; } - } - - protected internal ECFieldElement RawYCoord - { - get { return m_y; } - } - - protected internal ECFieldElement[] RawZCoords - { - get { return m_zs; } - } - - protected virtual void CheckNormalized() - { - if (!IsNormalized()) - throw new InvalidOperationException("point not in normal form"); - } - - public virtual bool IsNormalized() - { - int coord = this.CurveCoordinateSystem; - - return coord == ECCurve.COORD_AFFINE - || coord == ECCurve.COORD_LAMBDA_AFFINE - || IsInfinity - || RawZCoords[0].IsOne; - } - - /** - * Normalization ensures that any projective coordinate is 1, and therefore that the x, y - * coordinates reflect those of the equivalent point in an affine coordinate system. - * - * @return a new ECPoint instance representing the same point, but with normalized coordinates - */ - public virtual ECPoint Normalize() - { - if (this.IsInfinity) - { - return this; - } - - switch (this.CurveCoordinateSystem) - { - case ECCurve.COORD_AFFINE: - case ECCurve.COORD_LAMBDA_AFFINE: - { - return this; - } - default: - { - ECFieldElement Z1 = RawZCoords[0]; - if (Z1.IsOne) - { - return this; - } - - return Normalize(Z1.Invert()); - } - } - } - - internal virtual ECPoint Normalize(ECFieldElement zInv) - { - switch (this.CurveCoordinateSystem) - { - case ECCurve.COORD_HOMOGENEOUS: - case ECCurve.COORD_LAMBDA_PROJECTIVE: - { - return CreateScaledPoint(zInv, zInv); - } - case ECCurve.COORD_JACOBIAN: - case ECCurve.COORD_JACOBIAN_CHUDNOVSKY: - case ECCurve.COORD_JACOBIAN_MODIFIED: - { - ECFieldElement zInv2 = zInv.Square(), zInv3 = zInv2.Multiply(zInv); - return CreateScaledPoint(zInv2, zInv3); - } - default: - { - throw new InvalidOperationException("not a projective coordinate system"); - } - } - } - - protected virtual ECPoint CreateScaledPoint(ECFieldElement sx, ECFieldElement sy) - { - return Curve.CreateRawPoint(RawXCoord.Multiply(sx), RawYCoord.Multiply(sy), IsCompressed); - } - - public bool IsInfinity - { - get { return m_x == null && m_y == null; } - } - - public bool IsCompressed - { - get { return m_withCompression; } - } - - public bool IsValid() - { - return ImplIsValid(false, true); - } - - internal bool IsValidPartial() - { - return ImplIsValid(false, false); - } - - internal bool ImplIsValid(bool decompressed, bool checkOrder) - { - if (IsInfinity) - return true; - - ValidityCallback callback = new ValidityCallback(this, decompressed, checkOrder); - ValidityPreCompInfo validity = (ValidityPreCompInfo)Curve.Precompute(this, ValidityPreCompInfo.PRECOMP_NAME, callback); - return !validity.HasFailed(); - } - - public virtual ECPoint ScaleX(ECFieldElement scale) - { - return IsInfinity - ? this - : Curve.CreateRawPoint(RawXCoord.Multiply(scale), RawYCoord, RawZCoords, IsCompressed); - } - - public virtual ECPoint ScaleY(ECFieldElement scale) - { - return IsInfinity - ? this - : Curve.CreateRawPoint(RawXCoord, RawYCoord.Multiply(scale), RawZCoords, IsCompressed); - } - - public override bool Equals(object obj) - { - return Equals(obj as ECPoint); - } - - public virtual bool Equals(ECPoint other) - { - if (this == other) - return true; - if (null == other) - return false; - - ECCurve c1 = this.Curve, c2 = other.Curve; - bool n1 = (null == c1), n2 = (null == c2); - bool i1 = IsInfinity, i2 = other.IsInfinity; - - if (i1 || i2) - { - return (i1 && i2) && (n1 || n2 || c1.Equals(c2)); - } - - ECPoint p1 = this, p2 = other; - if (n1 && n2) - { - // Points with null curve are in affine form, so already normalized - } - else if (n1) - { - p2 = p2.Normalize(); - } - else if (n2) - { - p1 = p1.Normalize(); - } - else if (!c1.Equals(c2)) - { - return false; - } - else - { - // TODO Consider just requiring already normalized, to avoid silent performance degradation - - ECPoint[] points = new ECPoint[] { this, c1.ImportPoint(p2) }; - - // TODO This is a little strong, really only requires coZNormalizeAll to get Zs equal - c1.NormalizeAll(points); - - p1 = points[0]; - p2 = points[1]; - } - - return p1.XCoord.Equals(p2.XCoord) && p1.YCoord.Equals(p2.YCoord); - } - - public override int GetHashCode() - { - ECCurve c = this.Curve; - int hc = (null == c) ? 0 : ~c.GetHashCode(); - - if (!this.IsInfinity) - { - // TODO Consider just requiring already normalized, to avoid silent performance degradation - - ECPoint p = Normalize(); - - hc ^= p.XCoord.GetHashCode() * 17; - hc ^= p.YCoord.GetHashCode() * 257; - } - - return hc; - } - - public override string ToString() - { - if (this.IsInfinity) - { - return "INF"; - } - - StringBuilder sb = new StringBuilder(); - sb.Append('('); - sb.Append(RawXCoord); - sb.Append(','); - sb.Append(RawYCoord); - for (int i = 0; i < m_zs.Length; ++i) - { - sb.Append(','); - sb.Append(m_zs[i]); - } - sb.Append(')'); - return sb.ToString(); - } - - public virtual byte[] GetEncoded() - { - return GetEncoded(m_withCompression); - } - - public abstract byte[] GetEncoded(bool compressed); - - protected internal abstract bool CompressionYTilde { get; } - - public abstract ECPoint Add(ECPoint b); - public abstract ECPoint Subtract(ECPoint b); - public abstract ECPoint Negate(); - - public virtual ECPoint TimesPow2(int e) - { - if (e < 0) - throw new ArgumentException("cannot be negative", "e"); - - ECPoint p = this; - while (--e >= 0) - { - p = p.Twice(); - } - return p; - } - - public abstract ECPoint Twice(); - public abstract ECPoint Multiply(BigInteger b); - - public virtual ECPoint TwicePlus(ECPoint b) - { - return Twice().Add(b); - } - - public virtual ECPoint ThreeTimes() - { - return TwicePlus(this); - } - - private class ValidityCallback - : IPreCompCallback - { - private readonly ECPoint m_outer; - private readonly bool m_decompressed, m_checkOrder; - - internal ValidityCallback(ECPoint outer, bool decompressed, bool checkOrder) - { - this.m_outer = outer; - this.m_decompressed = decompressed; - this.m_checkOrder = checkOrder; - } - - public PreCompInfo Precompute(PreCompInfo existing) - { - ValidityPreCompInfo info = existing as ValidityPreCompInfo; - if (info == null) - { - info = new ValidityPreCompInfo(); - } - - if (info.HasFailed()) - return info; - - if (!info.HasCurveEquationPassed()) - { - if (!m_decompressed && !m_outer.SatisfiesCurveEquation()) - { - info.ReportFailed(); - return info; - } - info.ReportCurveEquationPassed(); - } - if (m_checkOrder && !info.HasOrderPassed()) - { - if (!m_outer.SatisfiesOrder()) - { - info.ReportFailed(); - return info; - } - info.ReportOrderPassed(); - } - return info; - } - } - } - - internal abstract class ECPointBase - : ECPoint - { - protected internal ECPointBase( - ECCurve curve, - ECFieldElement x, - ECFieldElement y, - bool withCompression) - : base(curve, x, y, withCompression) - { - } - - protected internal ECPointBase(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) - : base(curve, x, y, zs, withCompression) - { - } - - /** - * return the field element encoded with point compression. (S 4.3.6) - */ - public override byte[] GetEncoded(bool compressed) - { - if (this.IsInfinity) - { - return new byte[1]; - } - - ECPoint normed = Normalize(); - - byte[] X = normed.XCoord.GetEncoded(); - - if (compressed) - { - byte[] PO = new byte[X.Length + 1]; - PO[0] = (byte)(normed.CompressionYTilde ? 0x03 : 0x02); - Array.Copy(X, 0, PO, 1, X.Length); - return PO; - } - - byte[] Y = normed.YCoord.GetEncoded(); - - { - byte[] PO = new byte[X.Length + Y.Length + 1]; - PO[0] = 0x04; - Array.Copy(X, 0, PO, 1, X.Length); - Array.Copy(Y, 0, PO, X.Length + 1, Y.Length); - return PO; - } - } - - /** - * Multiplies this ECPoint by the given number. - * @param k The multiplicator. - * @return k * this. - */ - public override ECPoint Multiply(BigInteger k) - { - return this.Curve.GetMultiplier().Multiply(this, k); - } - } - - internal abstract class AbstractFpPoint - : ECPointBase - { - protected AbstractFpPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) - : base(curve, x, y, withCompression) - { - } - - protected AbstractFpPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) - : base(curve, x, y, zs, withCompression) - { - } - - protected internal override bool CompressionYTilde - { - get { return this.AffineYCoord.TestBitZero(); } - } - - protected override bool SatisfiesCurveEquation() - { - ECFieldElement X = this.RawXCoord, Y = this.RawYCoord, A = Curve.A, B = Curve.B; - ECFieldElement lhs = Y.Square(); - - switch (CurveCoordinateSystem) - { - case ECCurve.COORD_AFFINE: - break; - case ECCurve.COORD_HOMOGENEOUS: - { - ECFieldElement Z = this.RawZCoords[0]; - if (!Z.IsOne) - { - ECFieldElement Z2 = Z.Square(), Z3 = Z.Multiply(Z2); - lhs = lhs.Multiply(Z); - A = A.Multiply(Z2); - B = B.Multiply(Z3); - } - break; - } - case ECCurve.COORD_JACOBIAN: - case ECCurve.COORD_JACOBIAN_CHUDNOVSKY: - case ECCurve.COORD_JACOBIAN_MODIFIED: - { - ECFieldElement Z = this.RawZCoords[0]; - if (!Z.IsOne) - { - ECFieldElement Z2 = Z.Square(), Z4 = Z2.Square(), Z6 = Z2.Multiply(Z4); - A = A.Multiply(Z4); - B = B.Multiply(Z6); - } - break; - } - default: - throw new InvalidOperationException("unsupported coordinate system"); - } - - ECFieldElement rhs = X.Square().Add(A).Multiply(X).Add(B); - return lhs.Equals(rhs); - } - - public override ECPoint Subtract(ECPoint b) - { - if (b.IsInfinity) - return this; - - // Add -b - return Add(b.Negate()); - } - } - - /** - * Elliptic curve points over Fp - */ - internal class FpPoint - : AbstractFpPoint - { - /** - * Create a point which encodes without point compression. - * - * @param curve the curve to use - * @param x affine x co-ordinate - * @param y affine y co-ordinate - */ - public FpPoint(ECCurve curve, ECFieldElement x, ECFieldElement y) - : this(curve, x, y, false) - { - } - - /** - * Create a point that encodes with or without point compression. - * - * @param curve the curve to use - * @param x affine x co-ordinate - * @param y affine y co-ordinate - * @param withCompression if true encode with point compression - */ - public FpPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) - : base(curve, x, y, withCompression) - { - if ((x == null) != (y == null)) - throw new ArgumentException("Exactly one of the field elements is null"); - } - - internal FpPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) - : base(curve, x, y, zs, withCompression) - { - } - - protected override ECPoint Detach() - { - return new FpPoint(null, AffineXCoord, AffineYCoord, false); - } - - public override ECFieldElement GetZCoord(int index) - { - if (index == 1 && ECCurve.COORD_JACOBIAN_MODIFIED == this.CurveCoordinateSystem) - { - return GetJacobianModifiedW(); - } - - return base.GetZCoord(index); - } - - // B.3 pg 62 - public override ECPoint Add(ECPoint b) - { - if (this.IsInfinity) - return b; - if (b.IsInfinity) - return this; - if (this == b) - return Twice(); - - ECCurve curve = this.Curve; - int coord = curve.CoordinateSystem; - - ECFieldElement X1 = this.RawXCoord, Y1 = this.RawYCoord; - ECFieldElement X2 = b.RawXCoord, Y2 = b.RawYCoord; - - switch (coord) - { - case ECCurve.COORD_AFFINE: - { - ECFieldElement dx = X2.Subtract(X1), dy = Y2.Subtract(Y1); - - if (dx.IsZero) - { - if (dy.IsZero) - { - // this == b, i.e. this must be doubled - return Twice(); - } - - // this == -b, i.e. the result is the point at infinity - return Curve.Infinity; - } - - ECFieldElement gamma = dy.Divide(dx); - ECFieldElement X3 = gamma.Square().Subtract(X1).Subtract(X2); - ECFieldElement Y3 = gamma.Multiply(X1.Subtract(X3)).Subtract(Y1); - - return new FpPoint(Curve, X3, Y3, IsCompressed); - } - - case ECCurve.COORD_HOMOGENEOUS: - { - ECFieldElement Z1 = this.RawZCoords[0]; - ECFieldElement Z2 = b.RawZCoords[0]; - - bool Z1IsOne = Z1.IsOne; - bool Z2IsOne = Z2.IsOne; - - ECFieldElement u1 = Z1IsOne ? Y2 : Y2.Multiply(Z1); - ECFieldElement u2 = Z2IsOne ? Y1 : Y1.Multiply(Z2); - ECFieldElement u = u1.Subtract(u2); - ECFieldElement v1 = Z1IsOne ? X2 : X2.Multiply(Z1); - ECFieldElement v2 = Z2IsOne ? X1 : X1.Multiply(Z2); - ECFieldElement v = v1.Subtract(v2); - - // Check if b == this or b == -this - if (v.IsZero) - { - if (u.IsZero) - { - // this == b, i.e. this must be doubled - return this.Twice(); - } - - // this == -b, i.e. the result is the point at infinity - return curve.Infinity; - } - - // TODO Optimize for when w == 1 - ECFieldElement w = Z1IsOne ? Z2 : Z2IsOne ? Z1 : Z1.Multiply(Z2); - ECFieldElement vSquared = v.Square(); - ECFieldElement vCubed = vSquared.Multiply(v); - ECFieldElement vSquaredV2 = vSquared.Multiply(v2); - ECFieldElement A = u.Square().Multiply(w).Subtract(vCubed).Subtract(Two(vSquaredV2)); - - ECFieldElement X3 = v.Multiply(A); - ECFieldElement Y3 = vSquaredV2.Subtract(A).MultiplyMinusProduct(u, u2, vCubed); - ECFieldElement Z3 = vCubed.Multiply(w); - - return new FpPoint(curve, X3, Y3, new ECFieldElement[] { Z3 }, IsCompressed); - } - - case ECCurve.COORD_JACOBIAN: - case ECCurve.COORD_JACOBIAN_MODIFIED: - { - ECFieldElement Z1 = this.RawZCoords[0]; - ECFieldElement Z2 = b.RawZCoords[0]; - - bool Z1IsOne = Z1.IsOne; - - ECFieldElement X3, Y3, Z3, Z3Squared = null; - - if (!Z1IsOne && Z1.Equals(Z2)) - { - // TODO Make this available as public method coZAdd? - - ECFieldElement dx = X1.Subtract(X2), dy = Y1.Subtract(Y2); - if (dx.IsZero) - { - if (dy.IsZero) - { - return Twice(); - } - return curve.Infinity; - } - - ECFieldElement C = dx.Square(); - ECFieldElement W1 = X1.Multiply(C), W2 = X2.Multiply(C); - ECFieldElement A1 = W1.Subtract(W2).Multiply(Y1); - - X3 = dy.Square().Subtract(W1).Subtract(W2); - Y3 = W1.Subtract(X3).Multiply(dy).Subtract(A1); - Z3 = dx; - - if (Z1IsOne) - { - Z3Squared = C; - } - else - { - Z3 = Z3.Multiply(Z1); - } - } - else - { - ECFieldElement Z1Squared, U2, S2; - if (Z1IsOne) - { - Z1Squared = Z1; U2 = X2; S2 = Y2; - } - else - { - Z1Squared = Z1.Square(); - U2 = Z1Squared.Multiply(X2); - ECFieldElement Z1Cubed = Z1Squared.Multiply(Z1); - S2 = Z1Cubed.Multiply(Y2); - } - - bool Z2IsOne = Z2.IsOne; - ECFieldElement Z2Squared, U1, S1; - if (Z2IsOne) - { - Z2Squared = Z2; U1 = X1; S1 = Y1; - } - else - { - Z2Squared = Z2.Square(); - U1 = Z2Squared.Multiply(X1); - ECFieldElement Z2Cubed = Z2Squared.Multiply(Z2); - S1 = Z2Cubed.Multiply(Y1); - } - - ECFieldElement H = U1.Subtract(U2); - ECFieldElement R = S1.Subtract(S2); - - // Check if b == this or b == -this - if (H.IsZero) - { - if (R.IsZero) - { - // this == b, i.e. this must be doubled - return this.Twice(); - } - - // this == -b, i.e. the result is the point at infinity - return curve.Infinity; - } - - ECFieldElement HSquared = H.Square(); - ECFieldElement G = HSquared.Multiply(H); - ECFieldElement V = HSquared.Multiply(U1); - - X3 = R.Square().Add(G).Subtract(Two(V)); - Y3 = V.Subtract(X3).MultiplyMinusProduct(R, G, S1); - - Z3 = H; - if (!Z1IsOne) - { - Z3 = Z3.Multiply(Z1); - } - if (!Z2IsOne) - { - Z3 = Z3.Multiply(Z2); - } - - // Alternative calculation of Z3 using fast square - //X3 = four(X3); - //Y3 = eight(Y3); - //Z3 = doubleProductFromSquares(Z1, Z2, Z1Squared, Z2Squared).Multiply(H); - - if (Z3 == H) - { - Z3Squared = HSquared; - } - } - - ECFieldElement[] zs; - if (coord == ECCurve.COORD_JACOBIAN_MODIFIED) - { - // TODO If the result will only be used in a subsequent addition, we don't need W3 - ECFieldElement W3 = CalculateJacobianModifiedW(Z3, Z3Squared); - - zs = new ECFieldElement[] { Z3, W3 }; - } - else - { - zs = new ECFieldElement[] { Z3 }; - } - - return new FpPoint(curve, X3, Y3, zs, IsCompressed); - } - - default: - { - throw new InvalidOperationException("unsupported coordinate system"); - } - } - } - - // B.3 pg 62 - public override ECPoint Twice() - { - if (this.IsInfinity) - return this; - - ECCurve curve = this.Curve; - - ECFieldElement Y1 = this.RawYCoord; - if (Y1.IsZero) - return curve.Infinity; - - int coord = curve.CoordinateSystem; - - ECFieldElement X1 = this.RawXCoord; - - switch (coord) - { - case ECCurve.COORD_AFFINE: - { - ECFieldElement X1Squared = X1.Square(); - ECFieldElement gamma = Three(X1Squared).Add(this.Curve.A).Divide(Two(Y1)); - ECFieldElement X3 = gamma.Square().Subtract(Two(X1)); - ECFieldElement Y3 = gamma.Multiply(X1.Subtract(X3)).Subtract(Y1); - - return new FpPoint(Curve, X3, Y3, IsCompressed); - } - - case ECCurve.COORD_HOMOGENEOUS: - { - ECFieldElement Z1 = this.RawZCoords[0]; - - bool Z1IsOne = Z1.IsOne; - - // TODO Optimize for small negative a4 and -3 - ECFieldElement w = curve.A; - if (!w.IsZero && !Z1IsOne) - { - w = w.Multiply(Z1.Square()); - } - w = w.Add(Three(X1.Square())); - - ECFieldElement s = Z1IsOne ? Y1 : Y1.Multiply(Z1); - ECFieldElement t = Z1IsOne ? Y1.Square() : s.Multiply(Y1); - ECFieldElement B = X1.Multiply(t); - ECFieldElement _4B = Four(B); - ECFieldElement h = w.Square().Subtract(Two(_4B)); - - ECFieldElement _2s = Two(s); - ECFieldElement X3 = h.Multiply(_2s); - ECFieldElement _2t = Two(t); - ECFieldElement Y3 = _4B.Subtract(h).Multiply(w).Subtract(Two(_2t.Square())); - ECFieldElement _4sSquared = Z1IsOne ? Two(_2t) : _2s.Square(); - ECFieldElement Z3 = Two(_4sSquared).Multiply(s); - - return new FpPoint(curve, X3, Y3, new ECFieldElement[] { Z3 }, IsCompressed); - } - - case ECCurve.COORD_JACOBIAN: - { - ECFieldElement Z1 = this.RawZCoords[0]; - - bool Z1IsOne = Z1.IsOne; - - ECFieldElement Y1Squared = Y1.Square(); - ECFieldElement T = Y1Squared.Square(); - - ECFieldElement a4 = curve.A; - ECFieldElement a4Neg = a4.Negate(); - - ECFieldElement M, S; - if (a4Neg.ToBigInteger().Equals(BigInteger.ValueOf(3))) - { - ECFieldElement Z1Squared = Z1IsOne ? Z1 : Z1.Square(); - M = Three(X1.Add(Z1Squared).Multiply(X1.Subtract(Z1Squared))); - S = Four(Y1Squared.Multiply(X1)); - } - else - { - ECFieldElement X1Squared = X1.Square(); - M = Three(X1Squared); - if (Z1IsOne) - { - M = M.Add(a4); - } - else if (!a4.IsZero) - { - ECFieldElement Z1Squared = Z1IsOne ? Z1 : Z1.Square(); - ECFieldElement Z1Pow4 = Z1Squared.Square(); - if (a4Neg.BitLength < a4.BitLength) - { - M = M.Subtract(Z1Pow4.Multiply(a4Neg)); - } - else - { - M = M.Add(Z1Pow4.Multiply(a4)); - } - } - //S = two(doubleProductFromSquares(X1, Y1Squared, X1Squared, T)); - S = Four(X1.Multiply(Y1Squared)); - } - - ECFieldElement X3 = M.Square().Subtract(Two(S)); - ECFieldElement Y3 = S.Subtract(X3).Multiply(M).Subtract(Eight(T)); - - ECFieldElement Z3 = Two(Y1); - if (!Z1IsOne) - { - Z3 = Z3.Multiply(Z1); - } - - // Alternative calculation of Z3 using fast square - //ECFieldElement Z3 = doubleProductFromSquares(Y1, Z1, Y1Squared, Z1Squared); - - return new FpPoint(curve, X3, Y3, new ECFieldElement[] { Z3 }, IsCompressed); - } - - case ECCurve.COORD_JACOBIAN_MODIFIED: - { - return TwiceJacobianModified(true); - } - - default: - { - throw new InvalidOperationException("unsupported coordinate system"); - } - } - } - - public override ECPoint TwicePlus(ECPoint b) - { - if (this == b) - return ThreeTimes(); - if (this.IsInfinity) - return b; - if (b.IsInfinity) - return Twice(); - - ECFieldElement Y1 = this.RawYCoord; - if (Y1.IsZero) - return b; - - ECCurve curve = this.Curve; - int coord = curve.CoordinateSystem; - - switch (coord) - { - case ECCurve.COORD_AFFINE: - { - ECFieldElement X1 = this.RawXCoord; - ECFieldElement X2 = b.RawXCoord, Y2 = b.RawYCoord; - - ECFieldElement dx = X2.Subtract(X1), dy = Y2.Subtract(Y1); - - if (dx.IsZero) - { - if (dy.IsZero) - { - // this == b i.e. the result is 3P - return ThreeTimes(); - } - - // this == -b, i.e. the result is P - return this; - } - - /* - * Optimized calculation of 2P + Q, as described in "Trading Inversions for - * Multiplications in Elliptic Curve Cryptography", by Ciet, Joye, Lauter, Montgomery. - */ - - ECFieldElement X = dx.Square(), Y = dy.Square(); - ECFieldElement d = X.Multiply(Two(X1).Add(X2)).Subtract(Y); - if (d.IsZero) - { - return Curve.Infinity; - } - - ECFieldElement D = d.Multiply(dx); - ECFieldElement I = D.Invert(); - ECFieldElement L1 = d.Multiply(I).Multiply(dy); - ECFieldElement L2 = Two(Y1).Multiply(X).Multiply(dx).Multiply(I).Subtract(L1); - ECFieldElement X4 = (L2.Subtract(L1)).Multiply(L1.Add(L2)).Add(X2); - ECFieldElement Y4 = (X1.Subtract(X4)).Multiply(L2).Subtract(Y1); - - return new FpPoint(Curve, X4, Y4, IsCompressed); - } - case ECCurve.COORD_JACOBIAN_MODIFIED: - { - return TwiceJacobianModified(false).Add(b); - } - default: - { - return Twice().Add(b); - } - } - } - - public override ECPoint ThreeTimes() - { - if (this.IsInfinity) - return this; - - ECFieldElement Y1 = this.RawYCoord; - if (Y1.IsZero) - return this; - - ECCurve curve = this.Curve; - int coord = curve.CoordinateSystem; - - switch (coord) - { - case ECCurve.COORD_AFFINE: - { - ECFieldElement X1 = this.RawXCoord; - - ECFieldElement _2Y1 = Two(Y1); - ECFieldElement X = _2Y1.Square(); - ECFieldElement Z = Three(X1.Square()).Add(Curve.A); - ECFieldElement Y = Z.Square(); - - ECFieldElement d = Three(X1).Multiply(X).Subtract(Y); - if (d.IsZero) - { - return Curve.Infinity; - } - - ECFieldElement D = d.Multiply(_2Y1); - ECFieldElement I = D.Invert(); - ECFieldElement L1 = d.Multiply(I).Multiply(Z); - ECFieldElement L2 = X.Square().Multiply(I).Subtract(L1); - - ECFieldElement X4 = (L2.Subtract(L1)).Multiply(L1.Add(L2)).Add(X1); - ECFieldElement Y4 = (X1.Subtract(X4)).Multiply(L2).Subtract(Y1); - return new FpPoint(Curve, X4, Y4, IsCompressed); - } - case ECCurve.COORD_JACOBIAN_MODIFIED: - { - return TwiceJacobianModified(false).Add(this); - } - default: - { - // NOTE: Be careful about recursions between TwicePlus and ThreeTimes - return Twice().Add(this); - } - } - } - - public override ECPoint TimesPow2(int e) - { - if (e < 0) - throw new ArgumentException("cannot be negative", "e"); - if (e == 0 || this.IsInfinity) - return this; - if (e == 1) - return Twice(); - - ECCurve curve = this.Curve; - - ECFieldElement Y1 = this.RawYCoord; - if (Y1.IsZero) - return curve.Infinity; - - int coord = curve.CoordinateSystem; - - ECFieldElement W1 = curve.A; - ECFieldElement X1 = this.RawXCoord; - ECFieldElement Z1 = this.RawZCoords.Length < 1 ? curve.FromBigInteger(BigInteger.One) : this.RawZCoords[0]; - - if (!Z1.IsOne) - { - switch (coord) - { - case ECCurve.COORD_HOMOGENEOUS: - ECFieldElement Z1Sq = Z1.Square(); - X1 = X1.Multiply(Z1); - Y1 = Y1.Multiply(Z1Sq); - W1 = CalculateJacobianModifiedW(Z1, Z1Sq); - break; - case ECCurve.COORD_JACOBIAN: - W1 = CalculateJacobianModifiedW(Z1, null); - break; - case ECCurve.COORD_JACOBIAN_MODIFIED: - W1 = GetJacobianModifiedW(); - break; - } - } - - for (int i = 0; i < e; ++i) - { - if (Y1.IsZero) - return curve.Infinity; - - ECFieldElement X1Squared = X1.Square(); - ECFieldElement M = Three(X1Squared); - ECFieldElement _2Y1 = Two(Y1); - ECFieldElement _2Y1Squared = _2Y1.Multiply(Y1); - ECFieldElement S = Two(X1.Multiply(_2Y1Squared)); - ECFieldElement _4T = _2Y1Squared.Square(); - ECFieldElement _8T = Two(_4T); - - if (!W1.IsZero) - { - M = M.Add(W1); - W1 = Two(_8T.Multiply(W1)); - } - - X1 = M.Square().Subtract(Two(S)); - Y1 = M.Multiply(S.Subtract(X1)).Subtract(_8T); - Z1 = Z1.IsOne ? _2Y1 : _2Y1.Multiply(Z1); - } - - switch (coord) - { - case ECCurve.COORD_AFFINE: - ECFieldElement zInv = Z1.Invert(), zInv2 = zInv.Square(), zInv3 = zInv2.Multiply(zInv); - return new FpPoint(curve, X1.Multiply(zInv2), Y1.Multiply(zInv3), IsCompressed); - case ECCurve.COORD_HOMOGENEOUS: - X1 = X1.Multiply(Z1); - Z1 = Z1.Multiply(Z1.Square()); - return new FpPoint(curve, X1, Y1, new ECFieldElement[] { Z1 }, IsCompressed); - case ECCurve.COORD_JACOBIAN: - return new FpPoint(curve, X1, Y1, new ECFieldElement[] { Z1 }, IsCompressed); - case ECCurve.COORD_JACOBIAN_MODIFIED: - return new FpPoint(curve, X1, Y1, new ECFieldElement[] { Z1, W1 }, IsCompressed); - default: - throw new InvalidOperationException("unsupported coordinate system"); - } - } - - protected virtual ECFieldElement Two(ECFieldElement x) - { - return x.Add(x); - } - - protected virtual ECFieldElement Three(ECFieldElement x) - { - return Two(x).Add(x); - } - - protected virtual ECFieldElement Four(ECFieldElement x) - { - return Two(Two(x)); - } - - protected virtual ECFieldElement Eight(ECFieldElement x) - { - return Four(Two(x)); - } - - protected virtual ECFieldElement DoubleProductFromSquares(ECFieldElement a, ECFieldElement b, - ECFieldElement aSquared, ECFieldElement bSquared) - { - /* - * NOTE: If squaring in the field is faster than multiplication, then this is a quicker - * way to calculate 2.A.B, if A^2 and B^2 are already known. - */ - return a.Add(b).Square().Subtract(aSquared).Subtract(bSquared); - } - - public override ECPoint Negate() - { - if (IsInfinity) - return this; - - ECCurve curve = Curve; - int coord = curve.CoordinateSystem; - - if (ECCurve.COORD_AFFINE != coord) - { - return new FpPoint(curve, RawXCoord, RawYCoord.Negate(), RawZCoords, IsCompressed); - } - - return new FpPoint(curve, RawXCoord, RawYCoord.Negate(), IsCompressed); - } - - protected virtual ECFieldElement CalculateJacobianModifiedW(ECFieldElement Z, ECFieldElement ZSquared) - { - ECFieldElement a4 = this.Curve.A; - if (a4.IsZero || Z.IsOne) - return a4; - - if (ZSquared == null) - { - ZSquared = Z.Square(); - } - - ECFieldElement W = ZSquared.Square(); - ECFieldElement a4Neg = a4.Negate(); - if (a4Neg.BitLength < a4.BitLength) - { - W = W.Multiply(a4Neg).Negate(); - } - else - { - W = W.Multiply(a4); - } - return W; - } - - protected virtual ECFieldElement GetJacobianModifiedW() - { - ECFieldElement[] ZZ = this.RawZCoords; - ECFieldElement W = ZZ[1]; - if (W == null) - { - // NOTE: Rarely, TwicePlus will result in the need for a lazy W1 calculation here - ZZ[1] = W = CalculateJacobianModifiedW(ZZ[0], null); - } - return W; - } - - protected virtual FpPoint TwiceJacobianModified(bool calculateW) - { - ECFieldElement X1 = this.RawXCoord, Y1 = this.RawYCoord, Z1 = this.RawZCoords[0], W1 = GetJacobianModifiedW(); - - ECFieldElement X1Squared = X1.Square(); - ECFieldElement M = Three(X1Squared).Add(W1); - ECFieldElement _2Y1 = Two(Y1); - ECFieldElement _2Y1Squared = _2Y1.Multiply(Y1); - ECFieldElement S = Two(X1.Multiply(_2Y1Squared)); - ECFieldElement X3 = M.Square().Subtract(Two(S)); - ECFieldElement _4T = _2Y1Squared.Square(); - ECFieldElement _8T = Two(_4T); - ECFieldElement Y3 = M.Multiply(S.Subtract(X3)).Subtract(_8T); - ECFieldElement W3 = calculateW ? Two(_8T.Multiply(W1)) : null; - ECFieldElement Z3 = Z1.IsOne ? _2Y1 : _2Y1.Multiply(Z1); - - return new FpPoint(this.Curve, X3, Y3, new ECFieldElement[] { Z3, W3 }, IsCompressed); - } - } - - internal abstract class AbstractF2mPoint - : ECPointBase - { - protected AbstractF2mPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) - : base(curve, x, y, withCompression) - { - } - - protected AbstractF2mPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) - : base(curve, x, y, zs, withCompression) - { - } - - protected override bool SatisfiesCurveEquation() - { - ECCurve curve = Curve; - ECFieldElement X = this.RawXCoord, Y = this.RawYCoord, A = curve.A, B = curve.B; - ECFieldElement lhs, rhs; - - int coord = curve.CoordinateSystem; - if (coord == ECCurve.COORD_LAMBDA_PROJECTIVE) - { - ECFieldElement Z = this.RawZCoords[0]; - bool ZIsOne = Z.IsOne; - - if (X.IsZero) - { - // NOTE: For x == 0, we expect the affine-y instead of the lambda-y - lhs = Y.Square(); - rhs = B; - if (!ZIsOne) - { - ECFieldElement Z2 = Z.Square(); - rhs = rhs.Multiply(Z2); - } - } - else - { - ECFieldElement L = Y, X2 = X.Square(); - if (ZIsOne) - { - lhs = L.Square().Add(L).Add(A); - rhs = X2.Square().Add(B); - } - else - { - ECFieldElement Z2 = Z.Square(), Z4 = Z2.Square(); - lhs = L.Add(Z).MultiplyPlusProduct(L, A, Z2); - // TODO If sqrt(b) is precomputed this can be simplified to a single square - rhs = X2.SquarePlusProduct(B, Z4); - } - lhs = lhs.Multiply(X2); - } - } - else - { - lhs = Y.Add(X).Multiply(Y); - - switch (coord) - { - case ECCurve.COORD_AFFINE: - break; - case ECCurve.COORD_HOMOGENEOUS: - { - ECFieldElement Z = this.RawZCoords[0]; - if (!Z.IsOne) - { - ECFieldElement Z2 = Z.Square(), Z3 = Z.Multiply(Z2); - lhs = lhs.Multiply(Z); - A = A.Multiply(Z); - B = B.Multiply(Z3); - } - break; - } - default: - throw new InvalidOperationException("unsupported coordinate system"); - } - - rhs = X.Add(A).Multiply(X.Square()).Add(B); - } - - return lhs.Equals(rhs); - } - - protected override bool SatisfiesOrder() - { - ECCurve curve = Curve; - BigInteger cofactor = curve.Cofactor; - 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. - */ - ECPoint N = this.Normalize(); - ECFieldElement X = N.AffineXCoord; - ECFieldElement rhs = X.Add(curve.A); - return ((AbstractF2mFieldElement)rhs).Trace() == 0; - } - 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). - */ - ECPoint N = this.Normalize(); - ECFieldElement X = N.AffineXCoord; - ECFieldElement lambda = ((AbstractF2mCurve)curve).SolveQuadraticEquation(X.Add(curve.A)); - if (lambda == null) - 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; - } - - return base.SatisfiesOrder(); - } - - public override ECPoint ScaleX(ECFieldElement scale) - { - if (this.IsInfinity) - return this; - - switch (CurveCoordinateSystem) - { - case ECCurve.COORD_LAMBDA_AFFINE: - { - // Y is actually Lambda (X + Y/X) here - ECFieldElement X = RawXCoord, L = RawYCoord; - - ECFieldElement X2 = X.Multiply(scale); - ECFieldElement L2 = L.Add(X).Divide(scale).Add(X2); - - return Curve.CreateRawPoint(X, L2, RawZCoords, IsCompressed); - } - case ECCurve.COORD_LAMBDA_PROJECTIVE: - { - // Y is actually Lambda (X + Y/X) here - ECFieldElement X = RawXCoord, L = RawYCoord, Z = RawZCoords[0]; - - // We scale the Z coordinate also, to avoid an inversion - ECFieldElement X2 = X.Multiply(scale.Square()); - ECFieldElement L2 = L.Add(X).Add(X2); - ECFieldElement Z2 = Z.Multiply(scale); - - return Curve.CreateRawPoint(X, L2, new ECFieldElement[] { Z2 }, IsCompressed); - } - default: - { - return base.ScaleX(scale); - } - } - } - - public override ECPoint ScaleY(ECFieldElement scale) - { - if (this.IsInfinity) - return this; - - switch (CurveCoordinateSystem) - { - case ECCurve.COORD_LAMBDA_AFFINE: - case ECCurve.COORD_LAMBDA_PROJECTIVE: - { - ECFieldElement X = RawXCoord, L = RawYCoord; - - // Y is actually Lambda (X + Y/X) here - ECFieldElement L2 = L.Add(X).Multiply(scale).Add(X); - - return Curve.CreateRawPoint(X, L2, RawZCoords, IsCompressed); - } - default: - { - return base.ScaleY(scale); - } - } - } - - public override ECPoint Subtract(ECPoint b) - { - if (b.IsInfinity) - return this; - - // Add -b - return Add(b.Negate()); - } - - public virtual AbstractF2mPoint Tau() - { - if (this.IsInfinity) - return this; - - ECCurve curve = this.Curve; - int coord = curve.CoordinateSystem; - - ECFieldElement X1 = this.RawXCoord; - - switch (coord) - { - case ECCurve.COORD_AFFINE: - case ECCurve.COORD_LAMBDA_AFFINE: - { - ECFieldElement Y1 = this.RawYCoord; - return (AbstractF2mPoint)curve.CreateRawPoint(X1.Square(), Y1.Square(), IsCompressed); - } - case ECCurve.COORD_HOMOGENEOUS: - case ECCurve.COORD_LAMBDA_PROJECTIVE: - { - ECFieldElement Y1 = this.RawYCoord, Z1 = this.RawZCoords[0]; - return (AbstractF2mPoint)curve.CreateRawPoint(X1.Square(), Y1.Square(), - new ECFieldElement[] { Z1.Square() }, IsCompressed); - } - default: - { - throw new InvalidOperationException("unsupported coordinate system"); - } - } - } - - public virtual AbstractF2mPoint TauPow(int pow) - { - if (this.IsInfinity) - return this; - - ECCurve curve = this.Curve; - int coord = curve.CoordinateSystem; - - ECFieldElement X1 = this.RawXCoord; - - switch (coord) - { - case ECCurve.COORD_AFFINE: - case ECCurve.COORD_LAMBDA_AFFINE: - { - ECFieldElement Y1 = this.RawYCoord; - return (AbstractF2mPoint)curve.CreateRawPoint(X1.SquarePow(pow), Y1.SquarePow(pow), IsCompressed); - } - case ECCurve.COORD_HOMOGENEOUS: - case ECCurve.COORD_LAMBDA_PROJECTIVE: - { - ECFieldElement Y1 = this.RawYCoord, Z1 = this.RawZCoords[0]; - return (AbstractF2mPoint)curve.CreateRawPoint(X1.SquarePow(pow), Y1.SquarePow(pow), - new ECFieldElement[] { Z1.SquarePow(pow) }, IsCompressed); - } - default: - { - throw new InvalidOperationException("unsupported coordinate system"); - } - } - } - } - - /** - * Elliptic curve points over F2m - */ - internal class F2mPoint - : AbstractF2mPoint - { - /** - * @param curve base curve - * @param x x point - * @param y y point - */ - public F2mPoint( - ECCurve curve, - ECFieldElement x, - ECFieldElement y) - : this(curve, x, y, false) - { - } - - /** - * @param curve base curve - * @param x x point - * @param y y point - * @param withCompression true if encode with point compression. - */ - public F2mPoint( - ECCurve curve, - ECFieldElement x, - ECFieldElement y, - bool withCompression) - : base(curve, x, y, withCompression) - { - if ((x == null) != (y == null)) - { - throw new ArgumentException("Exactly one of the field elements is null"); - } - - if (x != null) - { - // Check if x and y are elements of the same field - F2mFieldElement.CheckFieldElements(x, y); - - // Check if x and a are elements of the same field - if (curve != null) - { - F2mFieldElement.CheckFieldElements(x, curve.A); - } - } - } - - internal F2mPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) - : base(curve, x, y, zs, withCompression) - { - } - - protected override ECPoint Detach() - { - return new F2mPoint(null, AffineXCoord, AffineYCoord, false); - } - - public override ECFieldElement YCoord - { - get - { - int coord = this.CurveCoordinateSystem; - - switch (coord) - { - case ECCurve.COORD_LAMBDA_AFFINE: - case ECCurve.COORD_LAMBDA_PROJECTIVE: - { - ECFieldElement X = RawXCoord, L = RawYCoord; - - if (this.IsInfinity || X.IsZero) - return L; - - // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly - ECFieldElement Y = L.Add(X).Multiply(X); - if (ECCurve.COORD_LAMBDA_PROJECTIVE == coord) - { - ECFieldElement Z = RawZCoords[0]; - if (!Z.IsOne) - { - Y = Y.Divide(Z); - } - } - return Y; - } - default: - { - return RawYCoord; - } - } - } - } - - protected internal override bool CompressionYTilde - { - get - { - ECFieldElement X = this.RawXCoord; - if (X.IsZero) - { - return false; - } - - ECFieldElement Y = this.RawYCoord; - - switch (this.CurveCoordinateSystem) - { - case ECCurve.COORD_LAMBDA_AFFINE: - case ECCurve.COORD_LAMBDA_PROJECTIVE: - { - // Y is actually Lambda (X + Y/X) here - return Y.TestBitZero() != X.TestBitZero(); - } - default: - { - return Y.Divide(X).TestBitZero(); - } - } - } - } - - public override ECPoint Add(ECPoint b) - { - if (this.IsInfinity) - return b; - if (b.IsInfinity) - return this; - - ECCurve curve = this.Curve; - int coord = curve.CoordinateSystem; - - ECFieldElement X1 = this.RawXCoord; - ECFieldElement X2 = b.RawXCoord; - - switch (coord) - { - case ECCurve.COORD_AFFINE: - { - ECFieldElement Y1 = this.RawYCoord; - ECFieldElement Y2 = b.RawYCoord; - - ECFieldElement dx = X1.Add(X2), dy = Y1.Add(Y2); - if (dx.IsZero) - { - if (dy.IsZero) - { - return Twice(); - } - - return curve.Infinity; - } - - ECFieldElement L = dy.Divide(dx); - - ECFieldElement X3 = L.Square().Add(L).Add(dx).Add(curve.A); - ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1); - - return new F2mPoint(curve, X3, Y3, IsCompressed); - } - case ECCurve.COORD_HOMOGENEOUS: - { - ECFieldElement Y1 = this.RawYCoord, Z1 = this.RawZCoords[0]; - ECFieldElement Y2 = b.RawYCoord, Z2 = b.RawZCoords[0]; - - bool Z1IsOne = Z1.IsOne; - ECFieldElement U1 = Y2, V1 = X2; - if (!Z1IsOne) - { - U1 = U1.Multiply(Z1); - V1 = V1.Multiply(Z1); - } - - bool Z2IsOne = Z2.IsOne; - ECFieldElement U2 = Y1, V2 = X1; - if (!Z2IsOne) - { - U2 = U2.Multiply(Z2); - V2 = V2.Multiply(Z2); - } - - ECFieldElement U = U1.Add(U2); - ECFieldElement V = V1.Add(V2); - - if (V.IsZero) - { - if (U.IsZero) - { - return Twice(); - } - - return curve.Infinity; - } - - ECFieldElement VSq = V.Square(); - ECFieldElement VCu = VSq.Multiply(V); - ECFieldElement W = Z1IsOne ? Z2 : Z2IsOne ? Z1 : Z1.Multiply(Z2); - ECFieldElement uv = U.Add(V); - ECFieldElement A = uv.MultiplyPlusProduct(U, VSq, curve.A).Multiply(W).Add(VCu); - - ECFieldElement X3 = V.Multiply(A); - ECFieldElement VSqZ2 = Z2IsOne ? VSq : VSq.Multiply(Z2); - ECFieldElement Y3 = U.MultiplyPlusProduct(X1, V, Y1).MultiplyPlusProduct(VSqZ2, uv, A); - ECFieldElement Z3 = VCu.Multiply(W); - - return new F2mPoint(curve, X3, Y3, new ECFieldElement[] { Z3 }, IsCompressed); - } - case ECCurve.COORD_LAMBDA_PROJECTIVE: - { - if (X1.IsZero) - { - if (X2.IsZero) - return curve.Infinity; - - return b.Add(this); - } - - ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; - ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0]; - - bool Z1IsOne = Z1.IsOne; - ECFieldElement U2 = X2, S2 = L2; - if (!Z1IsOne) - { - U2 = U2.Multiply(Z1); - S2 = S2.Multiply(Z1); - } - - bool Z2IsOne = Z2.IsOne; - ECFieldElement U1 = X1, S1 = L1; - if (!Z2IsOne) - { - U1 = U1.Multiply(Z2); - S1 = S1.Multiply(Z2); - } - - ECFieldElement A = S1.Add(S2); - ECFieldElement B = U1.Add(U2); - - if (B.IsZero) - { - if (A.IsZero) - { - return Twice(); - } - - return curve.Infinity; - } - - ECFieldElement X3, L3, Z3; - if (X2.IsZero) - { - // TODO This can probably be optimized quite a bit - ECPoint p = this.Normalize(); - X1 = p.RawXCoord; - ECFieldElement Y1 = p.YCoord; - - ECFieldElement Y2 = L2; - ECFieldElement L = Y1.Add(Y2).Divide(X1); - - X3 = L.Square().Add(L).Add(X1).Add(curve.A); - if (X3.IsZero) - { - return new F2mPoint(curve, X3, curve.B.Sqrt(), IsCompressed); - } - - ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1); - L3 = Y3.Divide(X3).Add(X3); - Z3 = curve.FromBigInteger(BigInteger.One); - } - else - { - B = B.Square(); - - ECFieldElement AU1 = A.Multiply(U1); - ECFieldElement AU2 = A.Multiply(U2); - - X3 = AU1.Multiply(AU2); - if (X3.IsZero) - { - return new F2mPoint(curve, X3, curve.B.Sqrt(), IsCompressed); - } - - ECFieldElement ABZ2 = A.Multiply(B); - if (!Z2IsOne) - { - ABZ2 = ABZ2.Multiply(Z2); - } - - L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1)); - - Z3 = ABZ2; - if (!Z1IsOne) - { - Z3 = Z3.Multiply(Z1); - } - } - - return new F2mPoint(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); - } - default: - { - throw new InvalidOperationException("unsupported coordinate system"); - } - } - } - - /* (non-Javadoc) - * @see Org.BouncyCastle.Math.EC.ECPoint#twice() - */ - public override ECPoint Twice() - { - if (this.IsInfinity) - return this; - - ECCurve curve = this.Curve; - - ECFieldElement X1 = this.RawXCoord; - if (X1.IsZero) - { - // A point with X == 0 is it's own additive inverse - return curve.Infinity; - } - - int coord = curve.CoordinateSystem; - - switch (coord) - { - case ECCurve.COORD_AFFINE: - { - ECFieldElement Y1 = this.RawYCoord; - - ECFieldElement L1 = Y1.Divide(X1).Add(X1); - - ECFieldElement X3 = L1.Square().Add(L1).Add(curve.A); - ECFieldElement Y3 = X1.SquarePlusProduct(X3, L1.AddOne()); - - return new F2mPoint(curve, X3, Y3, IsCompressed); - } - case ECCurve.COORD_HOMOGENEOUS: - { - ECFieldElement Y1 = this.RawYCoord, Z1 = this.RawZCoords[0]; - - bool Z1IsOne = Z1.IsOne; - ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1); - ECFieldElement Y1Z1 = Z1IsOne ? Y1 : Y1.Multiply(Z1); - - ECFieldElement X1Sq = X1.Square(); - ECFieldElement S = X1Sq.Add(Y1Z1); - ECFieldElement V = X1Z1; - ECFieldElement vSquared = V.Square(); - ECFieldElement sv = S.Add(V); - ECFieldElement h = sv.MultiplyPlusProduct(S, vSquared, curve.A); - - ECFieldElement X3 = V.Multiply(h); - ECFieldElement Y3 = X1Sq.Square().MultiplyPlusProduct(V, h, sv); - ECFieldElement Z3 = V.Multiply(vSquared); - - return new F2mPoint(curve, X3, Y3, new ECFieldElement[] { Z3 }, IsCompressed); - } - case ECCurve.COORD_LAMBDA_PROJECTIVE: - { - ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; - - bool Z1IsOne = Z1.IsOne; - ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1); - ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square(); - ECFieldElement a = curve.A; - ECFieldElement aZ1Sq = Z1IsOne ? a : a.Multiply(Z1Sq); - ECFieldElement T = L1.Square().Add(L1Z1).Add(aZ1Sq); - if (T.IsZero) - { - return new F2mPoint(curve, T, curve.B.Sqrt(), IsCompressed); - } - - ECFieldElement X3 = T.Square(); - ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq); - - ECFieldElement b = curve.B; - ECFieldElement L3; - if (b.BitLength < (curve.FieldSize >> 1)) - { - ECFieldElement t1 = L1.Add(X1).Square(); - ECFieldElement t2; - if (b.IsOne) - { - t2 = aZ1Sq.Add(Z1Sq).Square(); - } - else - { - // TODO Can be calculated with one square if we pre-compute sqrt(b) - t2 = aZ1Sq.SquarePlusProduct(b, Z1Sq.Square()); - } - L3 = t1.Add(T).Add(Z1Sq).Multiply(t1).Add(t2).Add(X3); - if (a.IsZero) - { - L3 = L3.Add(Z3); - } - else if (!a.IsOne) - { - L3 = L3.Add(a.AddOne().Multiply(Z3)); - } - } - else - { - ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1); - L3 = X1Z1.SquarePlusProduct(T, L1Z1).Add(X3).Add(Z3); - } - - return new F2mPoint(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); - } - default: - { - throw new InvalidOperationException("unsupported coordinate system"); - } - } - } - - public override ECPoint TwicePlus(ECPoint b) - { - if (this.IsInfinity) - return b; - if (b.IsInfinity) - return Twice(); - - ECCurve curve = this.Curve; - - ECFieldElement X1 = this.RawXCoord; - if (X1.IsZero) - { - // A point with X == 0 is it's own additive inverse - return b; - } - - int coord = curve.CoordinateSystem; - - switch (coord) - { - case ECCurve.COORD_LAMBDA_PROJECTIVE: - { - // NOTE: twicePlus() only optimized for lambda-affine argument - ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0]; - if (X2.IsZero || !Z2.IsOne) - { - return Twice().Add(b); - } - - ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; - ECFieldElement L2 = b.RawYCoord; - - ECFieldElement X1Sq = X1.Square(); - ECFieldElement L1Sq = L1.Square(); - ECFieldElement Z1Sq = Z1.Square(); - ECFieldElement L1Z1 = L1.Multiply(Z1); - - ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1); - ECFieldElement L2plus1 = L2.AddOne(); - ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); - ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq); - ECFieldElement B = X2Z1Sq.Add(T).Square(); - - if (B.IsZero) - { - if (A.IsZero) - { - return b.Twice(); - } - - return curve.Infinity; - } - - if (A.IsZero) - { - return new F2mPoint(curve, A, curve.B.Sqrt(), IsCompressed); - } - - ECFieldElement X3 = A.Square().Multiply(X2Z1Sq); - ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq); - ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3); - - return new F2mPoint(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); - } - default: - { - return Twice().Add(b); - } - } - } - - public override ECPoint Negate() - { - if (this.IsInfinity) - return this; - - ECFieldElement X = this.RawXCoord; - if (X.IsZero) - return this; - - ECCurve curve = this.Curve; - int coord = curve.CoordinateSystem; - - switch (coord) - { - case ECCurve.COORD_AFFINE: - { - ECFieldElement Y = this.RawYCoord; - return new F2mPoint(curve, X, Y.Add(X), IsCompressed); - } - case ECCurve.COORD_HOMOGENEOUS: - { - ECFieldElement Y = this.RawYCoord, Z = this.RawZCoords[0]; - return new F2mPoint(curve, X, Y.Add(X), new ECFieldElement[] { Z }, IsCompressed); - } - case ECCurve.COORD_LAMBDA_AFFINE: - { - ECFieldElement L = this.RawYCoord; - return new F2mPoint(curve, X, L.AddOne(), IsCompressed); - } - case ECCurve.COORD_LAMBDA_PROJECTIVE: - { - // L is actually Lambda (X + Y/X) here - ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0]; - return new F2mPoint(curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed); - } - default: - { - throw new InvalidOperationException("unsupported coordinate system"); - } - } - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/ec/ECPointMap.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/ECPointMap.cs deleted file mode 100644 index 9f2819951..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/ECPointMap.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC -{ - internal interface ECPointMap - { - ECPoint Map(ECPoint p); - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/ec/LongArray.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/LongArray.cs deleted file mode 100644 index 6b51b5ff6..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/LongArray.cs +++ /dev/null @@ -1,2206 +0,0 @@ -using System; -using System.Text; - -using Renci.SshNet.Security.Org.BouncyCastle.Utilities; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC -{ - internal class LongArray - { - //private static long DEInterleave_MASK = 0x5555555555555555L; - - /* - * This expands 8 bit indices into 16 bit contents (high bit 14), by inserting 0s between bits. - * In a binary field, this operation is the same as squaring an 8 bit number. - */ - private static readonly ushort[] INTERLEAVE2_TABLE = new ushort[] - { - 0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015, - 0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055, - 0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115, - 0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155, - 0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415, - 0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455, - 0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515, - 0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555, - 0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015, - 0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055, - 0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115, - 0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155, - 0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415, - 0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455, - 0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515, - 0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555, - 0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015, - 0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055, - 0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115, - 0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155, - 0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415, - 0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455, - 0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515, - 0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555, - 0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015, - 0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055, - 0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115, - 0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155, - 0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415, - 0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455, - 0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515, - 0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555 - }; - - /* - * This expands 7 bit indices into 21 bit contents (high bit 18), by inserting 0s between bits. - */ - private static readonly int[] INTERLEAVE3_TABLE = new int[] - { - 0x00000, 0x00001, 0x00008, 0x00009, 0x00040, 0x00041, 0x00048, 0x00049, - 0x00200, 0x00201, 0x00208, 0x00209, 0x00240, 0x00241, 0x00248, 0x00249, - 0x01000, 0x01001, 0x01008, 0x01009, 0x01040, 0x01041, 0x01048, 0x01049, - 0x01200, 0x01201, 0x01208, 0x01209, 0x01240, 0x01241, 0x01248, 0x01249, - 0x08000, 0x08001, 0x08008, 0x08009, 0x08040, 0x08041, 0x08048, 0x08049, - 0x08200, 0x08201, 0x08208, 0x08209, 0x08240, 0x08241, 0x08248, 0x08249, - 0x09000, 0x09001, 0x09008, 0x09009, 0x09040, 0x09041, 0x09048, 0x09049, - 0x09200, 0x09201, 0x09208, 0x09209, 0x09240, 0x09241, 0x09248, 0x09249, - 0x40000, 0x40001, 0x40008, 0x40009, 0x40040, 0x40041, 0x40048, 0x40049, - 0x40200, 0x40201, 0x40208, 0x40209, 0x40240, 0x40241, 0x40248, 0x40249, - 0x41000, 0x41001, 0x41008, 0x41009, 0x41040, 0x41041, 0x41048, 0x41049, - 0x41200, 0x41201, 0x41208, 0x41209, 0x41240, 0x41241, 0x41248, 0x41249, - 0x48000, 0x48001, 0x48008, 0x48009, 0x48040, 0x48041, 0x48048, 0x48049, - 0x48200, 0x48201, 0x48208, 0x48209, 0x48240, 0x48241, 0x48248, 0x48249, - 0x49000, 0x49001, 0x49008, 0x49009, 0x49040, 0x49041, 0x49048, 0x49049, - 0x49200, 0x49201, 0x49208, 0x49209, 0x49240, 0x49241, 0x49248, 0x49249 - }; - - /* - * This expands 8 bit indices into 32 bit contents (high bit 28), by inserting 0s between bits. - */ - private static readonly int[] INTERLEAVE4_TABLE = new int[] - { - 0x00000000, 0x00000001, 0x00000010, 0x00000011, 0x00000100, 0x00000101, 0x00000110, 0x00000111, - 0x00001000, 0x00001001, 0x00001010, 0x00001011, 0x00001100, 0x00001101, 0x00001110, 0x00001111, - 0x00010000, 0x00010001, 0x00010010, 0x00010011, 0x00010100, 0x00010101, 0x00010110, 0x00010111, - 0x00011000, 0x00011001, 0x00011010, 0x00011011, 0x00011100, 0x00011101, 0x00011110, 0x00011111, - 0x00100000, 0x00100001, 0x00100010, 0x00100011, 0x00100100, 0x00100101, 0x00100110, 0x00100111, - 0x00101000, 0x00101001, 0x00101010, 0x00101011, 0x00101100, 0x00101101, 0x00101110, 0x00101111, - 0x00110000, 0x00110001, 0x00110010, 0x00110011, 0x00110100, 0x00110101, 0x00110110, 0x00110111, - 0x00111000, 0x00111001, 0x00111010, 0x00111011, 0x00111100, 0x00111101, 0x00111110, 0x00111111, - 0x01000000, 0x01000001, 0x01000010, 0x01000011, 0x01000100, 0x01000101, 0x01000110, 0x01000111, - 0x01001000, 0x01001001, 0x01001010, 0x01001011, 0x01001100, 0x01001101, 0x01001110, 0x01001111, - 0x01010000, 0x01010001, 0x01010010, 0x01010011, 0x01010100, 0x01010101, 0x01010110, 0x01010111, - 0x01011000, 0x01011001, 0x01011010, 0x01011011, 0x01011100, 0x01011101, 0x01011110, 0x01011111, - 0x01100000, 0x01100001, 0x01100010, 0x01100011, 0x01100100, 0x01100101, 0x01100110, 0x01100111, - 0x01101000, 0x01101001, 0x01101010, 0x01101011, 0x01101100, 0x01101101, 0x01101110, 0x01101111, - 0x01110000, 0x01110001, 0x01110010, 0x01110011, 0x01110100, 0x01110101, 0x01110110, 0x01110111, - 0x01111000, 0x01111001, 0x01111010, 0x01111011, 0x01111100, 0x01111101, 0x01111110, 0x01111111, - 0x10000000, 0x10000001, 0x10000010, 0x10000011, 0x10000100, 0x10000101, 0x10000110, 0x10000111, - 0x10001000, 0x10001001, 0x10001010, 0x10001011, 0x10001100, 0x10001101, 0x10001110, 0x10001111, - 0x10010000, 0x10010001, 0x10010010, 0x10010011, 0x10010100, 0x10010101, 0x10010110, 0x10010111, - 0x10011000, 0x10011001, 0x10011010, 0x10011011, 0x10011100, 0x10011101, 0x10011110, 0x10011111, - 0x10100000, 0x10100001, 0x10100010, 0x10100011, 0x10100100, 0x10100101, 0x10100110, 0x10100111, - 0x10101000, 0x10101001, 0x10101010, 0x10101011, 0x10101100, 0x10101101, 0x10101110, 0x10101111, - 0x10110000, 0x10110001, 0x10110010, 0x10110011, 0x10110100, 0x10110101, 0x10110110, 0x10110111, - 0x10111000, 0x10111001, 0x10111010, 0x10111011, 0x10111100, 0x10111101, 0x10111110, 0x10111111, - 0x11000000, 0x11000001, 0x11000010, 0x11000011, 0x11000100, 0x11000101, 0x11000110, 0x11000111, - 0x11001000, 0x11001001, 0x11001010, 0x11001011, 0x11001100, 0x11001101, 0x11001110, 0x11001111, - 0x11010000, 0x11010001, 0x11010010, 0x11010011, 0x11010100, 0x11010101, 0x11010110, 0x11010111, - 0x11011000, 0x11011001, 0x11011010, 0x11011011, 0x11011100, 0x11011101, 0x11011110, 0x11011111, - 0x11100000, 0x11100001, 0x11100010, 0x11100011, 0x11100100, 0x11100101, 0x11100110, 0x11100111, - 0x11101000, 0x11101001, 0x11101010, 0x11101011, 0x11101100, 0x11101101, 0x11101110, 0x11101111, - 0x11110000, 0x11110001, 0x11110010, 0x11110011, 0x11110100, 0x11110101, 0x11110110, 0x11110111, - 0x11111000, 0x11111001, 0x11111010, 0x11111011, 0x11111100, 0x11111101, 0x11111110, 0x11111111 - }; - - /* - * This expands 7 bit indices into 35 bit contents (high bit 30), by inserting 0s between bits. - */ - private static readonly int[] INTERLEAVE5_TABLE = new int[] { - 0x00000000, 0x00000001, 0x00000020, 0x00000021, 0x00000400, 0x00000401, 0x00000420, 0x00000421, - 0x00008000, 0x00008001, 0x00008020, 0x00008021, 0x00008400, 0x00008401, 0x00008420, 0x00008421, - 0x00100000, 0x00100001, 0x00100020, 0x00100021, 0x00100400, 0x00100401, 0x00100420, 0x00100421, - 0x00108000, 0x00108001, 0x00108020, 0x00108021, 0x00108400, 0x00108401, 0x00108420, 0x00108421, - 0x02000000, 0x02000001, 0x02000020, 0x02000021, 0x02000400, 0x02000401, 0x02000420, 0x02000421, - 0x02008000, 0x02008001, 0x02008020, 0x02008021, 0x02008400, 0x02008401, 0x02008420, 0x02008421, - 0x02100000, 0x02100001, 0x02100020, 0x02100021, 0x02100400, 0x02100401, 0x02100420, 0x02100421, - 0x02108000, 0x02108001, 0x02108020, 0x02108021, 0x02108400, 0x02108401, 0x02108420, 0x02108421, - 0x40000000, 0x40000001, 0x40000020, 0x40000021, 0x40000400, 0x40000401, 0x40000420, 0x40000421, - 0x40008000, 0x40008001, 0x40008020, 0x40008021, 0x40008400, 0x40008401, 0x40008420, 0x40008421, - 0x40100000, 0x40100001, 0x40100020, 0x40100021, 0x40100400, 0x40100401, 0x40100420, 0x40100421, - 0x40108000, 0x40108001, 0x40108020, 0x40108021, 0x40108400, 0x40108401, 0x40108420, 0x40108421, - 0x42000000, 0x42000001, 0x42000020, 0x42000021, 0x42000400, 0x42000401, 0x42000420, 0x42000421, - 0x42008000, 0x42008001, 0x42008020, 0x42008021, 0x42008400, 0x42008401, 0x42008420, 0x42008421, - 0x42100000, 0x42100001, 0x42100020, 0x42100021, 0x42100400, 0x42100401, 0x42100420, 0x42100421, - 0x42108000, 0x42108001, 0x42108020, 0x42108021, 0x42108400, 0x42108401, 0x42108420, 0x42108421 - }; - - /* - * This expands 9 bit indices into 63 bit (long) contents (high bit 56), by inserting 0s between bits. - */ - private static readonly long[] INTERLEAVE7_TABLE = new long[] - { - 0x0000000000000000L, 0x0000000000000001L, 0x0000000000000080L, 0x0000000000000081L, - 0x0000000000004000L, 0x0000000000004001L, 0x0000000000004080L, 0x0000000000004081L, - 0x0000000000200000L, 0x0000000000200001L, 0x0000000000200080L, 0x0000000000200081L, - 0x0000000000204000L, 0x0000000000204001L, 0x0000000000204080L, 0x0000000000204081L, - 0x0000000010000000L, 0x0000000010000001L, 0x0000000010000080L, 0x0000000010000081L, - 0x0000000010004000L, 0x0000000010004001L, 0x0000000010004080L, 0x0000000010004081L, - 0x0000000010200000L, 0x0000000010200001L, 0x0000000010200080L, 0x0000000010200081L, - 0x0000000010204000L, 0x0000000010204001L, 0x0000000010204080L, 0x0000000010204081L, - 0x0000000800000000L, 0x0000000800000001L, 0x0000000800000080L, 0x0000000800000081L, - 0x0000000800004000L, 0x0000000800004001L, 0x0000000800004080L, 0x0000000800004081L, - 0x0000000800200000L, 0x0000000800200001L, 0x0000000800200080L, 0x0000000800200081L, - 0x0000000800204000L, 0x0000000800204001L, 0x0000000800204080L, 0x0000000800204081L, - 0x0000000810000000L, 0x0000000810000001L, 0x0000000810000080L, 0x0000000810000081L, - 0x0000000810004000L, 0x0000000810004001L, 0x0000000810004080L, 0x0000000810004081L, - 0x0000000810200000L, 0x0000000810200001L, 0x0000000810200080L, 0x0000000810200081L, - 0x0000000810204000L, 0x0000000810204001L, 0x0000000810204080L, 0x0000000810204081L, - 0x0000040000000000L, 0x0000040000000001L, 0x0000040000000080L, 0x0000040000000081L, - 0x0000040000004000L, 0x0000040000004001L, 0x0000040000004080L, 0x0000040000004081L, - 0x0000040000200000L, 0x0000040000200001L, 0x0000040000200080L, 0x0000040000200081L, - 0x0000040000204000L, 0x0000040000204001L, 0x0000040000204080L, 0x0000040000204081L, - 0x0000040010000000L, 0x0000040010000001L, 0x0000040010000080L, 0x0000040010000081L, - 0x0000040010004000L, 0x0000040010004001L, 0x0000040010004080L, 0x0000040010004081L, - 0x0000040010200000L, 0x0000040010200001L, 0x0000040010200080L, 0x0000040010200081L, - 0x0000040010204000L, 0x0000040010204001L, 0x0000040010204080L, 0x0000040010204081L, - 0x0000040800000000L, 0x0000040800000001L, 0x0000040800000080L, 0x0000040800000081L, - 0x0000040800004000L, 0x0000040800004001L, 0x0000040800004080L, 0x0000040800004081L, - 0x0000040800200000L, 0x0000040800200001L, 0x0000040800200080L, 0x0000040800200081L, - 0x0000040800204000L, 0x0000040800204001L, 0x0000040800204080L, 0x0000040800204081L, - 0x0000040810000000L, 0x0000040810000001L, 0x0000040810000080L, 0x0000040810000081L, - 0x0000040810004000L, 0x0000040810004001L, 0x0000040810004080L, 0x0000040810004081L, - 0x0000040810200000L, 0x0000040810200001L, 0x0000040810200080L, 0x0000040810200081L, - 0x0000040810204000L, 0x0000040810204001L, 0x0000040810204080L, 0x0000040810204081L, - 0x0002000000000000L, 0x0002000000000001L, 0x0002000000000080L, 0x0002000000000081L, - 0x0002000000004000L, 0x0002000000004001L, 0x0002000000004080L, 0x0002000000004081L, - 0x0002000000200000L, 0x0002000000200001L, 0x0002000000200080L, 0x0002000000200081L, - 0x0002000000204000L, 0x0002000000204001L, 0x0002000000204080L, 0x0002000000204081L, - 0x0002000010000000L, 0x0002000010000001L, 0x0002000010000080L, 0x0002000010000081L, - 0x0002000010004000L, 0x0002000010004001L, 0x0002000010004080L, 0x0002000010004081L, - 0x0002000010200000L, 0x0002000010200001L, 0x0002000010200080L, 0x0002000010200081L, - 0x0002000010204000L, 0x0002000010204001L, 0x0002000010204080L, 0x0002000010204081L, - 0x0002000800000000L, 0x0002000800000001L, 0x0002000800000080L, 0x0002000800000081L, - 0x0002000800004000L, 0x0002000800004001L, 0x0002000800004080L, 0x0002000800004081L, - 0x0002000800200000L, 0x0002000800200001L, 0x0002000800200080L, 0x0002000800200081L, - 0x0002000800204000L, 0x0002000800204001L, 0x0002000800204080L, 0x0002000800204081L, - 0x0002000810000000L, 0x0002000810000001L, 0x0002000810000080L, 0x0002000810000081L, - 0x0002000810004000L, 0x0002000810004001L, 0x0002000810004080L, 0x0002000810004081L, - 0x0002000810200000L, 0x0002000810200001L, 0x0002000810200080L, 0x0002000810200081L, - 0x0002000810204000L, 0x0002000810204001L, 0x0002000810204080L, 0x0002000810204081L, - 0x0002040000000000L, 0x0002040000000001L, 0x0002040000000080L, 0x0002040000000081L, - 0x0002040000004000L, 0x0002040000004001L, 0x0002040000004080L, 0x0002040000004081L, - 0x0002040000200000L, 0x0002040000200001L, 0x0002040000200080L, 0x0002040000200081L, - 0x0002040000204000L, 0x0002040000204001L, 0x0002040000204080L, 0x0002040000204081L, - 0x0002040010000000L, 0x0002040010000001L, 0x0002040010000080L, 0x0002040010000081L, - 0x0002040010004000L, 0x0002040010004001L, 0x0002040010004080L, 0x0002040010004081L, - 0x0002040010200000L, 0x0002040010200001L, 0x0002040010200080L, 0x0002040010200081L, - 0x0002040010204000L, 0x0002040010204001L, 0x0002040010204080L, 0x0002040010204081L, - 0x0002040800000000L, 0x0002040800000001L, 0x0002040800000080L, 0x0002040800000081L, - 0x0002040800004000L, 0x0002040800004001L, 0x0002040800004080L, 0x0002040800004081L, - 0x0002040800200000L, 0x0002040800200001L, 0x0002040800200080L, 0x0002040800200081L, - 0x0002040800204000L, 0x0002040800204001L, 0x0002040800204080L, 0x0002040800204081L, - 0x0002040810000000L, 0x0002040810000001L, 0x0002040810000080L, 0x0002040810000081L, - 0x0002040810004000L, 0x0002040810004001L, 0x0002040810004080L, 0x0002040810004081L, - 0x0002040810200000L, 0x0002040810200001L, 0x0002040810200080L, 0x0002040810200081L, - 0x0002040810204000L, 0x0002040810204001L, 0x0002040810204080L, 0x0002040810204081L, - 0x0100000000000000L, 0x0100000000000001L, 0x0100000000000080L, 0x0100000000000081L, - 0x0100000000004000L, 0x0100000000004001L, 0x0100000000004080L, 0x0100000000004081L, - 0x0100000000200000L, 0x0100000000200001L, 0x0100000000200080L, 0x0100000000200081L, - 0x0100000000204000L, 0x0100000000204001L, 0x0100000000204080L, 0x0100000000204081L, - 0x0100000010000000L, 0x0100000010000001L, 0x0100000010000080L, 0x0100000010000081L, - 0x0100000010004000L, 0x0100000010004001L, 0x0100000010004080L, 0x0100000010004081L, - 0x0100000010200000L, 0x0100000010200001L, 0x0100000010200080L, 0x0100000010200081L, - 0x0100000010204000L, 0x0100000010204001L, 0x0100000010204080L, 0x0100000010204081L, - 0x0100000800000000L, 0x0100000800000001L, 0x0100000800000080L, 0x0100000800000081L, - 0x0100000800004000L, 0x0100000800004001L, 0x0100000800004080L, 0x0100000800004081L, - 0x0100000800200000L, 0x0100000800200001L, 0x0100000800200080L, 0x0100000800200081L, - 0x0100000800204000L, 0x0100000800204001L, 0x0100000800204080L, 0x0100000800204081L, - 0x0100000810000000L, 0x0100000810000001L, 0x0100000810000080L, 0x0100000810000081L, - 0x0100000810004000L, 0x0100000810004001L, 0x0100000810004080L, 0x0100000810004081L, - 0x0100000810200000L, 0x0100000810200001L, 0x0100000810200080L, 0x0100000810200081L, - 0x0100000810204000L, 0x0100000810204001L, 0x0100000810204080L, 0x0100000810204081L, - 0x0100040000000000L, 0x0100040000000001L, 0x0100040000000080L, 0x0100040000000081L, - 0x0100040000004000L, 0x0100040000004001L, 0x0100040000004080L, 0x0100040000004081L, - 0x0100040000200000L, 0x0100040000200001L, 0x0100040000200080L, 0x0100040000200081L, - 0x0100040000204000L, 0x0100040000204001L, 0x0100040000204080L, 0x0100040000204081L, - 0x0100040010000000L, 0x0100040010000001L, 0x0100040010000080L, 0x0100040010000081L, - 0x0100040010004000L, 0x0100040010004001L, 0x0100040010004080L, 0x0100040010004081L, - 0x0100040010200000L, 0x0100040010200001L, 0x0100040010200080L, 0x0100040010200081L, - 0x0100040010204000L, 0x0100040010204001L, 0x0100040010204080L, 0x0100040010204081L, - 0x0100040800000000L, 0x0100040800000001L, 0x0100040800000080L, 0x0100040800000081L, - 0x0100040800004000L, 0x0100040800004001L, 0x0100040800004080L, 0x0100040800004081L, - 0x0100040800200000L, 0x0100040800200001L, 0x0100040800200080L, 0x0100040800200081L, - 0x0100040800204000L, 0x0100040800204001L, 0x0100040800204080L, 0x0100040800204081L, - 0x0100040810000000L, 0x0100040810000001L, 0x0100040810000080L, 0x0100040810000081L, - 0x0100040810004000L, 0x0100040810004001L, 0x0100040810004080L, 0x0100040810004081L, - 0x0100040810200000L, 0x0100040810200001L, 0x0100040810200080L, 0x0100040810200081L, - 0x0100040810204000L, 0x0100040810204001L, 0x0100040810204080L, 0x0100040810204081L, - 0x0102000000000000L, 0x0102000000000001L, 0x0102000000000080L, 0x0102000000000081L, - 0x0102000000004000L, 0x0102000000004001L, 0x0102000000004080L, 0x0102000000004081L, - 0x0102000000200000L, 0x0102000000200001L, 0x0102000000200080L, 0x0102000000200081L, - 0x0102000000204000L, 0x0102000000204001L, 0x0102000000204080L, 0x0102000000204081L, - 0x0102000010000000L, 0x0102000010000001L, 0x0102000010000080L, 0x0102000010000081L, - 0x0102000010004000L, 0x0102000010004001L, 0x0102000010004080L, 0x0102000010004081L, - 0x0102000010200000L, 0x0102000010200001L, 0x0102000010200080L, 0x0102000010200081L, - 0x0102000010204000L, 0x0102000010204001L, 0x0102000010204080L, 0x0102000010204081L, - 0x0102000800000000L, 0x0102000800000001L, 0x0102000800000080L, 0x0102000800000081L, - 0x0102000800004000L, 0x0102000800004001L, 0x0102000800004080L, 0x0102000800004081L, - 0x0102000800200000L, 0x0102000800200001L, 0x0102000800200080L, 0x0102000800200081L, - 0x0102000800204000L, 0x0102000800204001L, 0x0102000800204080L, 0x0102000800204081L, - 0x0102000810000000L, 0x0102000810000001L, 0x0102000810000080L, 0x0102000810000081L, - 0x0102000810004000L, 0x0102000810004001L, 0x0102000810004080L, 0x0102000810004081L, - 0x0102000810200000L, 0x0102000810200001L, 0x0102000810200080L, 0x0102000810200081L, - 0x0102000810204000L, 0x0102000810204001L, 0x0102000810204080L, 0x0102000810204081L, - 0x0102040000000000L, 0x0102040000000001L, 0x0102040000000080L, 0x0102040000000081L, - 0x0102040000004000L, 0x0102040000004001L, 0x0102040000004080L, 0x0102040000004081L, - 0x0102040000200000L, 0x0102040000200001L, 0x0102040000200080L, 0x0102040000200081L, - 0x0102040000204000L, 0x0102040000204001L, 0x0102040000204080L, 0x0102040000204081L, - 0x0102040010000000L, 0x0102040010000001L, 0x0102040010000080L, 0x0102040010000081L, - 0x0102040010004000L, 0x0102040010004001L, 0x0102040010004080L, 0x0102040010004081L, - 0x0102040010200000L, 0x0102040010200001L, 0x0102040010200080L, 0x0102040010200081L, - 0x0102040010204000L, 0x0102040010204001L, 0x0102040010204080L, 0x0102040010204081L, - 0x0102040800000000L, 0x0102040800000001L, 0x0102040800000080L, 0x0102040800000081L, - 0x0102040800004000L, 0x0102040800004001L, 0x0102040800004080L, 0x0102040800004081L, - 0x0102040800200000L, 0x0102040800200001L, 0x0102040800200080L, 0x0102040800200081L, - 0x0102040800204000L, 0x0102040800204001L, 0x0102040800204080L, 0x0102040800204081L, - 0x0102040810000000L, 0x0102040810000001L, 0x0102040810000080L, 0x0102040810000081L, - 0x0102040810004000L, 0x0102040810004001L, 0x0102040810004080L, 0x0102040810004081L, - 0x0102040810200000L, 0x0102040810200001L, 0x0102040810200080L, 0x0102040810200081L, - 0x0102040810204000L, 0x0102040810204001L, 0x0102040810204080L, 0x0102040810204081L - }; - - // For toString(); must have length 64 - private const string ZEROES = "0000000000000000000000000000000000000000000000000000000000000000"; - - internal static readonly byte[] BitLengths = - { - 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 - }; - - // TODO make m fixed for the LongArray, and hence compute T once and for all - - private long[] m_ints; - - public LongArray(int intLen) - { - m_ints = new long[intLen]; - } - - public LongArray(long[] ints) - { - m_ints = ints; - } - - public LongArray(long[] ints, int off, int len) - { - if (off == 0 && len == ints.Length) - { - m_ints = ints; - } - else - { - m_ints = new long[len]; - Array.Copy(ints, off, m_ints, 0, len); - } - } - - public LongArray(BigInteger bigInt) - { - if (bigInt == null || bigInt.SignValue < 0) - { - throw new ArgumentException("invalid F2m field value", "bigInt"); - } - - if (bigInt.SignValue == 0) - { - m_ints = new long[] { 0L }; - return; - } - - byte[] barr = bigInt.ToByteArray(); - int barrLen = barr.Length; - int barrStart = 0; - if (barr[0] == 0) - { - // First byte is 0 to enforce highest (=sign) bit is zero. - // In this case ignore barr[0]. - barrLen--; - barrStart = 1; - } - int intLen = (barrLen + 7) / 8; - m_ints = new long[intLen]; - - int iarrJ = intLen - 1; - int rem = barrLen % 8 + barrStart; - long temp = 0; - int barrI = barrStart; - if (barrStart < rem) - { - for (; barrI < rem; barrI++) - { - temp <<= 8; - uint barrBarrI = barr[barrI]; - temp |= barrBarrI; - } - m_ints[iarrJ--] = temp; - } - - for (; iarrJ >= 0; iarrJ--) - { - temp = 0; - for (int i = 0; i < 8; i++) - { - temp <<= 8; - uint barrBarrI = barr[barrI++]; - temp |= barrBarrI; - } - m_ints[iarrJ] = temp; - } - } - - internal void CopyTo(long[] z, int zOff) - { - Array.Copy(m_ints, 0, z, zOff, m_ints.Length); - } - - public bool IsOne() - { - long[] a = m_ints; - if (a[0] != 1L) - { - return false; - } - for (int i = 1; i < a.Length; ++i) - { - if (a[i] != 0L) - { - return false; - } - } - return true; - } - - public bool IsZero() - { - long[] a = m_ints; - for (int i = 0; i < a.Length; ++i) - { - if (a[i] != 0L) - { - return false; - } - } - return true; - } - - public int GetUsedLength() - { - return GetUsedLengthFrom(m_ints.Length); - } - - public int GetUsedLengthFrom(int from) - { - long[] a = m_ints; - from = System.Math.Min(from, a.Length); - - if (from < 1) - { - return 0; - } - - // Check if first element will act as sentinel - if (a[0] != 0) - { - while (a[--from] == 0) - { - } - return from + 1; - } - - do - { - if (a[--from] != 0) - { - return from + 1; - } - } - while (from > 0); - - return 0; - } - - public int Degree() - { - int i = m_ints.Length; - long w; - do - { - if (i == 0) - { - return 0; - } - w = m_ints[--i]; - } - while (w == 0); - - return (i << 6) + BitLength(w); - } - - private int DegreeFrom(int limit) - { - int i = (int)(((uint)limit + 62) >> 6); - long w; - do - { - if (i == 0) - { - return 0; - } - w = m_ints[--i]; - } - while (w == 0); - - return (i << 6) + BitLength(w); - } - - // private int lowestCoefficient() - // { - // for (int i = 0; i < m_ints.Length; ++i) - // { - // long mi = m_ints[i]; - // if (mi != 0) - // { - // int j = 0; - // while ((mi & 0xFFL) == 0) - // { - // j += 8; - // mi >>>= 8; - // } - // while ((mi & 1L) == 0) - // { - // ++j; - // mi >>>= 1; - // } - // return (i << 6) + j; - // } - // } - // return -1; - // } - - private static int BitLength(long w) - { - int u = (int)((ulong)w >> 32), b; - if (u == 0) - { - u = (int)w; - b = 0; - } - else - { - b = 32; - } - - int t = (int)((uint)u >> 16), k; - if (t == 0) - { - t = (int)((uint)u >> 8); - k = (t == 0) ? BitLengths[u] : 8 + BitLengths[t]; - } - else - { - int v = (int)((uint)t >> 8); - k = (v == 0) ? 16 + BitLengths[t] : 24 + BitLengths[v]; - } - - return b + k; - } - - private long[] ResizedInts(int newLen) - { - long[] newInts = new long[newLen]; - Array.Copy(m_ints, 0, newInts, 0, System.Math.Min(m_ints.Length, newLen)); - return newInts; - } - - public BigInteger ToBigInteger() - { - int usedLen = GetUsedLength(); - if (usedLen == 0) - { - return BigInteger.Zero; - } - - long highestInt = m_ints[usedLen - 1]; - byte[] temp = new byte[8]; - int barrI = 0; - bool trailingZeroBytesDone = false; - for (int j = 7; j >= 0; j--) - { - byte thisByte = (byte)((ulong)highestInt >> (8 * j)); - if (trailingZeroBytesDone || (thisByte != 0)) - { - trailingZeroBytesDone = true; - temp[barrI++] = thisByte; - } - } - - int barrLen = 8 * (usedLen - 1) + barrI; - byte[] barr = new byte[barrLen]; - for (int j = 0; j < barrI; j++) - { - barr[j] = temp[j]; - } - // Highest value int is done now - - for (int iarrJ = usedLen - 2; iarrJ >= 0; iarrJ--) - { - long mi = m_ints[iarrJ]; - for (int j = 7; j >= 0; j--) - { - barr[barrI++] = (byte)((ulong)mi >> (8 * j)); - } - } - return new BigInteger(1, barr); - } - - // private static long shiftUp(long[] x, int xOff, int count) - // { - // long prev = 0; - // for (int i = 0; i < count; ++i) - // { - // long next = x[xOff + i]; - // x[xOff + i] = (next << 1) | prev; - // prev = next >>> 63; - // } - // return prev; - // } - - private static long ShiftUp(long[] x, int xOff, int count, int shift) - { - int shiftInv = 64 - shift; - long prev = 0; - for (int i = 0; i < count; ++i) - { - long next = x[xOff + i]; - x[xOff + i] = (next << shift) | prev; - prev = (long)((ulong)next >> shiftInv); - } - return prev; - } - - private static long ShiftUp(long[] x, int xOff, long[] z, int zOff, int count, int shift) - { - int shiftInv = 64 - shift; - long prev = 0; - for (int i = 0; i < count; ++i) - { - long next = x[xOff + i]; - z[zOff + i] = (next << shift) | prev; - prev = (long)((ulong)next >> shiftInv); - } - return prev; - } - - public LongArray AddOne() - { - if (m_ints.Length == 0) - { - return new LongArray(new long[]{ 1L }); - } - - int resultLen = System.Math.Max(1, GetUsedLength()); - long[] ints = ResizedInts(resultLen); - ints[0] ^= 1L; - return new LongArray(ints); - } - - // private void addShiftedByBits(LongArray other, int bits) - // { - // int words = bits >>> 6; - // int shift = bits & 0x3F; - // - // if (shift == 0) - // { - // addShiftedByWords(other, words); - // return; - // } - // - // int otherUsedLen = other.GetUsedLength(); - // if (otherUsedLen == 0) - // { - // return; - // } - // - // int minLen = otherUsedLen + words + 1; - // if (minLen > m_ints.Length) - // { - // m_ints = resizedInts(minLen); - // } - // - // long carry = addShiftedByBits(m_ints, words, other.m_ints, 0, otherUsedLen, shift); - // m_ints[otherUsedLen + words] ^= carry; - // } - - private void AddShiftedByBitsSafe(LongArray other, int otherDegree, int bits) - { - int otherLen = (int)((uint)(otherDegree + 63) >> 6); - - int words = (int)((uint)bits >> 6); - int shift = bits & 0x3F; - - if (shift == 0) - { - Add(m_ints, words, other.m_ints, 0, otherLen); - return; - } - - long carry = AddShiftedUp(m_ints, words, other.m_ints, 0, otherLen, shift); - if (carry != 0L) - { - m_ints[otherLen + words] ^= carry; - } - } - - private static long AddShiftedUp(long[] x, int xOff, long[] y, int yOff, int count, int shift) - { - int shiftInv = 64 - shift; - long prev = 0; - for (int i = 0; i < count; ++i) - { - long next = y[yOff + i]; - x[xOff + i] ^= (next << shift) | prev; - prev = (long)((ulong)next >> shiftInv); - } - return prev; - } - - private static long AddShiftedDown(long[] x, int xOff, long[] y, int yOff, int count, int shift) - { - int shiftInv = 64 - shift; - long prev = 0; - int i = count; - while (--i >= 0) - { - long next = y[yOff + i]; - x[xOff + i] ^= (long)((ulong)next >> shift) | prev; - prev = next << shiftInv; - } - return prev; - } - - public void AddShiftedByWords(LongArray other, int words) - { - int otherUsedLen = other.GetUsedLength(); - if (otherUsedLen == 0) - { - return; - } - - int minLen = otherUsedLen + words; - if (minLen > m_ints.Length) - { - m_ints = ResizedInts(minLen); - } - - Add(m_ints, words, other.m_ints, 0, otherUsedLen); - } - - private static void Add(long[] x, int xOff, long[] y, int yOff, int count) - { - for (int i = 0; i < count; ++i) - { - x[xOff + i] ^= y[yOff + i]; - } - } - - private static void Add(long[] x, int xOff, long[] y, int yOff, long[] z, int zOff, int count) - { - for (int i = 0; i < count; ++i) - { - z[zOff + i] = x[xOff + i] ^ y[yOff + i]; - } - } - - private static void AddBoth(long[] x, int xOff, long[] y1, int y1Off, long[] y2, int y2Off, int count) - { - for (int i = 0; i < count; ++i) - { - x[xOff + i] ^= y1[y1Off + i] ^ y2[y2Off + i]; - } - } - - private static void Distribute(long[] x, int src, int dst1, int dst2, int count) - { - for (int i = 0; i < count; ++i) - { - long v = x[src + i]; - x[dst1 + i] ^= v; - x[dst2 + i] ^= v; - } - } - - public int Length - { - get { return m_ints.Length; } - } - - private static void FlipWord(long[] buf, int off, int bit, long word) - { - int n = off + (int)((uint)bit >> 6); - int shift = bit & 0x3F; - if (shift == 0) - { - buf[n] ^= word; - } - else - { - buf[n] ^= word << shift; - word = (long)((ulong)word >> (64 - shift)); - if (word != 0) - { - buf[++n] ^= word; - } - } - } - - // private static long getWord(long[] buf, int off, int len, int bit) - // { - // int n = off + (bit >>> 6); - // int shift = bit & 0x3F; - // if (shift == 0) - // { - // return buf[n]; - // } - // long result = buf[n] >>> shift; - // if (++n < len) - // { - // result |= buf[n] << (64 - shift); - // } - // return result; - // } - - public bool TestBitZero() - { - return m_ints.Length > 0 && (m_ints[0] & 1L) != 0; - } - - private static bool TestBit(long[] buf, int off, int n) - { - // theInt = n / 64 - int theInt = (int)((uint)n >> 6); - // theBit = n % 64 - int theBit = n & 0x3F; - long tester = 1L << theBit; - return (buf[off + theInt] & tester) != 0; - } - - private static void FlipBit(long[] buf, int off, int n) - { - // theInt = n / 64 - int theInt = (int)((uint)n >> 6); - // theBit = n % 64 - int theBit = n & 0x3F; - long flipper = 1L << theBit; - buf[off + theInt] ^= flipper; - } - - // private static void SetBit(long[] buf, int off, int n) - // { - // // theInt = n / 64 - // int theInt = n >>> 6; - // // theBit = n % 64 - // int theBit = n & 0x3F; - // long setter = 1L << theBit; - // buf[off + theInt] |= setter; - // } - // - // private static void ClearBit(long[] buf, int off, int n) - // { - // // theInt = n / 64 - // int theInt = n >>> 6; - // // theBit = n % 64 - // int theBit = n & 0x3F; - // long setter = 1L << theBit; - // buf[off + theInt] &= ~setter; - // } - - private static void MultiplyWord(long a, long[] b, int bLen, long[] c, int cOff) - { - if ((a & 1L) != 0L) - { - Add(c, cOff, b, 0, bLen); - } - int k = 1; - while ((a = (long)((ulong)a >> 1)) != 0L) - { - if ((a & 1L) != 0L) - { - long carry = AddShiftedUp(c, cOff, b, 0, bLen, k); - if (carry != 0L) - { - c[cOff + bLen] ^= carry; - } - } - ++k; - } - } - - public LongArray ModMultiplyLD(LongArray other, int m, int[] ks) - { - /* - * Find out the degree of each argument and handle the zero cases - */ - int aDeg = Degree(); - if (aDeg == 0) - { - return this; - } - int bDeg = other.Degree(); - if (bDeg == 0) - { - return other; - } - - /* - * Swap if necessary so that A is the smaller argument - */ - LongArray A = this, B = other; - if (aDeg > bDeg) - { - A = other; B = this; - int tmp = aDeg; aDeg = bDeg; bDeg = tmp; - } - - /* - * Establish the word lengths of the arguments and result - */ - int aLen = (int)((uint)(aDeg + 63) >> 6); - int bLen = (int)((uint)(bDeg + 63) >> 6); - int cLen = (int)((uint)(aDeg + bDeg + 62) >> 6); - - if (aLen == 1) - { - long a0 = A.m_ints[0]; - if (a0 == 1L) - { - return B; - } - - /* - * Fast path for small A, with performance dependent only on the number of set bits - */ - long[] c0 = new long[cLen]; - MultiplyWord(a0, B.m_ints, bLen, c0, 0); - - /* - * Reduce the raw answer against the reduction coefficients - */ - return ReduceResult(c0, 0, cLen, m, ks); - } - - /* - * Determine if B will get bigger during shifting - */ - int bMax = (int)((uint)(bDeg + 7 + 63) >> 6); - - /* - * Lookup table for the offset of each B in the tables - */ - int[] ti = new int[16]; - - /* - * Precompute table of all 4-bit products of B - */ - long[] T0 = new long[bMax << 4]; - int tOff = bMax; - ti[1] = tOff; - Array.Copy(B.m_ints, 0, T0, tOff, bLen); - for (int i = 2; i < 16; ++i) - { - ti[i] = (tOff += bMax); - if ((i & 1) == 0) - { - ShiftUp(T0, (int)((uint)tOff >> 1), T0, tOff, bMax, 1); - } - else - { - Add(T0, bMax, T0, tOff - bMax, T0, tOff, bMax); - } - } - - /* - * Second table with all 4-bit products of B shifted 4 bits - */ - long[] T1 = new long[T0.Length]; - ShiftUp(T0, 0, T1, 0, T0.Length, 4); - // shiftUp(T0, bMax, T1, bMax, tOff, 4); - - long[] a = A.m_ints; - long[] c = new long[cLen]; - - int MASK = 0xF; - - /* - * Lopez-Dahab algorithm - */ - - for (int k = 56; k >= 0; k -= 8) - { - for (int j = 1; j < aLen; j += 2) - { - int aVal = (int)((ulong)a[j] >> k); - int u = aVal & MASK; - int v = (int)((uint)aVal >> 4) & MASK; - AddBoth(c, j - 1, T0, ti[u], T1, ti[v], bMax); - } - ShiftUp(c, 0, cLen, 8); - } - - for (int k = 56; k >= 0; k -= 8) - { - for (int j = 0; j < aLen; j += 2) - { - int aVal = (int)((ulong)a[j] >> k); - int u = aVal & MASK; - int v = (int)((uint)aVal >> 4) & MASK; - AddBoth(c, j, T0, ti[u], T1, ti[v], bMax); - } - if (k > 0) - { - ShiftUp(c, 0, cLen, 8); - } - } - - /* - * Finally the raw answer is collected, reduce it against the reduction coefficients - */ - return ReduceResult(c, 0, cLen, m, ks); - } - - public LongArray ModMultiply(LongArray other, int m, int[] ks) - { - /* - * Find out the degree of each argument and handle the zero cases - */ - int aDeg = Degree(); - if (aDeg == 0) - { - return this; - } - int bDeg = other.Degree(); - if (bDeg == 0) - { - return other; - } - - /* - * Swap if necessary so that A is the smaller argument - */ - LongArray A = this, B = other; - if (aDeg > bDeg) - { - A = other; B = this; - int tmp = aDeg; aDeg = bDeg; bDeg = tmp; - } - - /* - * Establish the word lengths of the arguments and result - */ - int aLen = (int)((uint)(aDeg + 63) >> 6); - int bLen = (int)((uint)(bDeg + 63) >> 6); - int cLen = (int)((uint)(aDeg + bDeg + 62) >> 6); - - if (aLen == 1) - { - long a0 = A.m_ints[0]; - if (a0 == 1L) - { - return B; - } - - /* - * Fast path for small A, with performance dependent only on the number of set bits - */ - long[] c0 = new long[cLen]; - MultiplyWord(a0, B.m_ints, bLen, c0, 0); - - /* - * Reduce the raw answer against the reduction coefficients - */ - return ReduceResult(c0, 0, cLen, m, ks); - } - - /* - * Determine if B will get bigger during shifting - */ - int bMax = (int)((uint)(bDeg + 7 + 63) >> 6); - - /* - * Lookup table for the offset of each B in the tables - */ - int[] ti = new int[16]; - - /* - * Precompute table of all 4-bit products of B - */ - long[] T0 = new long[bMax << 4]; - int tOff = bMax; - ti[1] = tOff; - Array.Copy(B.m_ints, 0, T0, tOff, bLen); - for (int i = 2; i < 16; ++i) - { - ti[i] = (tOff += bMax); - if ((i & 1) == 0) - { - ShiftUp(T0, (int)((uint)tOff >> 1), T0, tOff, bMax, 1); - } - else - { - Add(T0, bMax, T0, tOff - bMax, T0, tOff, bMax); - } - } - - /* - * Second table with all 4-bit products of B shifted 4 bits - */ - long[] T1 = new long[T0.Length]; - ShiftUp(T0, 0, T1, 0, T0.Length, 4); - // ShiftUp(T0, bMax, T1, bMax, tOff, 4); - - long[] a = A.m_ints; - long[] c = new long[cLen << 3]; - - int MASK = 0xF; - - /* - * Lopez-Dahab (Modified) algorithm - */ - - for (int aPos = 0; aPos < aLen; ++aPos) - { - long aVal = a[aPos]; - int cOff = aPos; - for (;;) - { - int u = (int)aVal & MASK; - aVal = (long)((ulong)aVal >> 4); - int v = (int)aVal & MASK; - AddBoth(c, cOff, T0, ti[u], T1, ti[v], bMax); - aVal = (long)((ulong)aVal >> 4); - if (aVal == 0L) - { - break; - } - cOff += cLen; - } - } - - { - int cOff = c.Length; - while ((cOff -= cLen) != 0) - { - AddShiftedUp(c, cOff - cLen, c, cOff, cLen, 8); - } - } - - /* - * Finally the raw answer is collected, reduce it against the reduction coefficients - */ - return ReduceResult(c, 0, cLen, m, ks); - } - - public LongArray ModMultiplyAlt(LongArray other, int m, int[] ks) - { - /* - * Find out the degree of each argument and handle the zero cases - */ - int aDeg = Degree(); - if (aDeg == 0) - { - return this; - } - int bDeg = other.Degree(); - if (bDeg == 0) - { - return other; - } - - /* - * Swap if necessary so that A is the smaller argument - */ - LongArray A = this, B = other; - if (aDeg > bDeg) - { - A = other; B = this; - int tmp = aDeg; aDeg = bDeg; bDeg = tmp; - } - - /* - * Establish the word lengths of the arguments and result - */ - int aLen = (int)((uint)(aDeg + 63) >> 6); - int bLen = (int)((uint)(bDeg + 63) >> 6); - int cLen = (int)((uint)(aDeg + bDeg + 62) >> 6); - - if (aLen == 1) - { - long a0 = A.m_ints[0]; - if (a0 == 1L) - { - return B; - } - - /* - * Fast path for small A, with performance dependent only on the number of set bits - */ - long[] c0 = new long[cLen]; - MultiplyWord(a0, B.m_ints, bLen, c0, 0); - - /* - * Reduce the raw answer against the reduction coefficients - */ - return ReduceResult(c0, 0, cLen, m, ks); - } - - // NOTE: This works, but is slower than width 4 processing - // if (aLen == 2) - // { - // /* - // * Use common-multiplicand optimization to save ~1/4 of the adds - // */ - // long a1 = A.m_ints[0], a2 = A.m_ints[1]; - // long aa = a1 & a2; a1 ^= aa; a2 ^= aa; - // - // long[] b = B.m_ints; - // long[] c = new long[cLen]; - // multiplyWord(aa, b, bLen, c, 1); - // add(c, 0, c, 1, cLen - 1); - // multiplyWord(a1, b, bLen, c, 0); - // multiplyWord(a2, b, bLen, c, 1); - // - // /* - // * Reduce the raw answer against the reduction coefficients - // */ - // return ReduceResult(c, 0, cLen, m, ks); - // } - - /* - * Determine the parameters of the Interleaved window algorithm: the 'width' in bits to - * process together, the number of evaluation 'positions' implied by that width, and the - * 'top' position at which the regular window algorithm stops. - */ - int width, positions, top, banks; - - // NOTE: width 4 is the fastest over the entire range of sizes used in current crypto - // width = 1; positions = 64; top = 64; banks = 4; - // width = 2; positions = 32; top = 64; banks = 4; - // width = 3; positions = 21; top = 63; banks = 3; - width = 4; positions = 16; top = 64; banks = 8; - // width = 5; positions = 13; top = 65; banks = 7; - // width = 7; positions = 9; top = 63; banks = 9; - // width = 8; positions = 8; top = 64; banks = 8; - - /* - * Determine if B will get bigger during shifting - */ - int shifts = top < 64 ? positions : positions - 1; - int bMax = (int)((uint)(bDeg + shifts + 63) >> 6); - - int bTotal = bMax * banks, stride = width * banks; - - /* - * Create a single temporary buffer, with an offset table to find the positions of things in it - */ - int[] ci = new int[1 << width]; - int cTotal = aLen; - { - ci[0] = cTotal; - cTotal += bTotal; - ci[1] = cTotal; - for (int i = 2; i < ci.Length; ++i) - { - cTotal += cLen; - ci[i] = cTotal; - } - cTotal += cLen; - } - // NOTE: Provide a safe dump for "high zeroes" since we are adding 'bMax' and not 'bLen' - ++cTotal; - - long[] c = new long[cTotal]; - - // Prepare A in Interleaved form, according to the chosen width - Interleave(A.m_ints, 0, c, 0, aLen, width); - - // Make a working copy of B, since we will be shifting it - { - int bOff = aLen; - Array.Copy(B.m_ints, 0, c, bOff, bLen); - for (int bank = 1; bank < banks; ++bank) - { - ShiftUp(c, aLen, c, bOff += bMax, bMax, bank); - } - } - - /* - * The main loop analyzes the Interleaved windows in A, and for each non-zero window - * a single word-array XOR is performed to a carefully selected slice of 'c'. The loop is - * breadth-first, checking the lowest window in each word, then looping again for the - * next higher window position. - */ - int MASK = (1 << width) - 1; - - int k = 0; - for (;;) - { - int aPos = 0; - do - { - long aVal = (long)((ulong)c[aPos] >> k); - int bank = 0, bOff = aLen; - for (;;) - { - int index = (int)(aVal) & MASK; - if (index != 0) - { - /* - * Add to a 'c' buffer based on the bit-pattern of 'index'. Since A is in - * Interleaved form, the bits represent the current B shifted by 0, 'positions', - * 'positions' * 2, ..., 'positions' * ('width' - 1) - */ - Add(c, aPos + ci[index], c, bOff, bMax); - } - if (++bank == banks) - { - break; - } - bOff += bMax; - aVal = (long)((ulong)aVal >> width); - } - } - while (++aPos < aLen); - - if ((k += stride) >= top) - { - if (k >= 64) - { - break; - } - - /* - * Adjustment for window setups with top == 63, the final bit (if any) is processed - * as the top-bit of a window - */ - k = 64 - width; - MASK &= MASK << (top - k); - } - - /* - * After each position has been checked for all words of A, B is shifted up 1 place - */ - ShiftUp(c, aLen, bTotal, banks); - } - - int ciPos = ci.Length; - while (--ciPos > 1) - { - if ((ciPos & 1L) == 0L) - { - /* - * For even numbers, shift contents and add to the half-position - */ - AddShiftedUp(c, ci[(uint)ciPos >> 1], c, ci[ciPos], cLen, positions); - } - else - { - /* - * For odd numbers, 'distribute' contents to the result and the next-lowest position - */ - Distribute(c, ci[ciPos], ci[ciPos - 1], ci[1], cLen); - } - } - - /* - * Finally the raw answer is collected, reduce it against the reduction coefficients - */ - return ReduceResult(c, ci[1], cLen, m, ks); - } - - public LongArray ModReduce(int m, int[] ks) - { - long[] buf = Arrays.Clone(m_ints); - int rLen = ReduceInPlace(buf, 0, buf.Length, m, ks); - return new LongArray(buf, 0, rLen); - } - - public LongArray Multiply(LongArray other, int m, int[] ks) - { - /* - * Find out the degree of each argument and handle the zero cases - */ - int aDeg = Degree(); - if (aDeg == 0) - { - return this; - } - int bDeg = other.Degree(); - if (bDeg == 0) - { - return other; - } - - /* - * Swap if necessary so that A is the smaller argument - */ - LongArray A = this, B = other; - if (aDeg > bDeg) - { - A = other; B = this; - int tmp = aDeg; aDeg = bDeg; bDeg = tmp; - } - - /* - * Establish the word lengths of the arguments and result - */ - int aLen = (int)((uint)(aDeg + 63) >> 6); - int bLen = (int)((uint)(bDeg + 63) >> 6); - int cLen = (int)((uint)(aDeg + bDeg + 62) >> 6); - - if (aLen == 1) - { - long a0 = A.m_ints[0]; - if (a0 == 1L) - { - return B; - } - - /* - * Fast path for small A, with performance dependent only on the number of set bits - */ - long[] c0 = new long[cLen]; - MultiplyWord(a0, B.m_ints, bLen, c0, 0); - - /* - * Reduce the raw answer against the reduction coefficients - */ - //return ReduceResult(c0, 0, cLen, m, ks); - return new LongArray(c0, 0, cLen); - } - - /* - * Determine if B will get bigger during shifting - */ - int bMax = (int)((uint)(bDeg + 7 + 63) >> 6); - - /* - * Lookup table for the offset of each B in the tables - */ - int[] ti = new int[16]; - - /* - * Precompute table of all 4-bit products of B - */ - long[] T0 = new long[bMax << 4]; - int tOff = bMax; - ti[1] = tOff; - Array.Copy(B.m_ints, 0, T0, tOff, bLen); - for (int i = 2; i < 16; ++i) - { - ti[i] = (tOff += bMax); - if ((i & 1) == 0) - { - ShiftUp(T0, (int)((uint)tOff >> 1), T0, tOff, bMax, 1); - } - else - { - Add(T0, bMax, T0, tOff - bMax, T0, tOff, bMax); - } - } - - /* - * Second table with all 4-bit products of B shifted 4 bits - */ - long[] T1 = new long[T0.Length]; - ShiftUp(T0, 0, T1, 0, T0.Length, 4); - // ShiftUp(T0, bMax, T1, bMax, tOff, 4); - - long[] a = A.m_ints; - long[] c = new long[cLen << 3]; - - int MASK = 0xF; - - /* - * Lopez-Dahab (Modified) algorithm - */ - - for (int aPos = 0; aPos < aLen; ++aPos) - { - long aVal = a[aPos]; - int cOff = aPos; - for (; ; ) - { - int u = (int)aVal & MASK; - aVal = (long)((ulong)aVal >> 4); - int v = (int)aVal & MASK; - AddBoth(c, cOff, T0, ti[u], T1, ti[v], bMax); - aVal = (long)((ulong)aVal >> 4); - if (aVal == 0L) - { - break; - } - cOff += cLen; - } - } - - { - int cOff = c.Length; - while ((cOff -= cLen) != 0) - { - AddShiftedUp(c, cOff - cLen, c, cOff, cLen, 8); - } - } - - /* - * Finally the raw answer is collected, reduce it against the reduction coefficients - */ - //return ReduceResult(c, 0, cLen, m, ks); - return new LongArray(c, 0, cLen); - } - - public void Reduce(int m, int[] ks) - { - long[] buf = m_ints; - int rLen = ReduceInPlace(buf, 0, buf.Length, m, ks); - if (rLen < buf.Length) - { - m_ints = new long[rLen]; - Array.Copy(buf, 0, m_ints, 0, rLen); - } - } - - private static LongArray ReduceResult(long[] buf, int off, int len, int m, int[] ks) - { - int rLen = ReduceInPlace(buf, off, len, m, ks); - return new LongArray(buf, off, rLen); - } - - // private static void deInterleave(long[] x, int xOff, long[] z, int zOff, int count, int rounds) - // { - // for (int i = 0; i < count; ++i) - // { - // z[zOff + i] = deInterleave(x[zOff + i], rounds); - // } - // } - // - // private static long deInterleave(long x, int rounds) - // { - // while (--rounds >= 0) - // { - // x = deInterleave32(x & DEInterleave_MASK) | (deInterleave32((x >>> 1) & DEInterleave_MASK) << 32); - // } - // return x; - // } - // - // private static long deInterleave32(long x) - // { - // x = (x | (x >>> 1)) & 0x3333333333333333L; - // x = (x | (x >>> 2)) & 0x0F0F0F0F0F0F0F0FL; - // x = (x | (x >>> 4)) & 0x00FF00FF00FF00FFL; - // x = (x | (x >>> 8)) & 0x0000FFFF0000FFFFL; - // x = (x | (x >>> 16)) & 0x00000000FFFFFFFFL; - // return x; - // } - - private static int ReduceInPlace(long[] buf, int off, int len, int m, int[] ks) - { - int mLen = (m + 63) >> 6; - if (len < mLen) - { - return len; - } - - int numBits = System.Math.Min(len << 6, (m << 1) - 1); // TODO use actual degree? - int excessBits = (len << 6) - numBits; - while (excessBits >= 64) - { - --len; - excessBits -= 64; - } - - int kLen = ks.Length, kMax = ks[kLen - 1], kNext = kLen > 1 ? ks[kLen - 2] : 0; - int wordWiseLimit = System.Math.Max(m, kMax + 64); - int vectorableWords = (excessBits + System.Math.Min(numBits - wordWiseLimit, m - kNext)) >> 6; - if (vectorableWords > 1) - { - int vectorWiseWords = len - vectorableWords; - ReduceVectorWise(buf, off, len, vectorWiseWords, m, ks); - while (len > vectorWiseWords) - { - buf[off + --len] = 0L; - } - numBits = vectorWiseWords << 6; - } - - if (numBits > wordWiseLimit) - { - ReduceWordWise(buf, off, len, wordWiseLimit, m, ks); - numBits = wordWiseLimit; - } - - if (numBits > m) - { - ReduceBitWise(buf, off, numBits, m, ks); - } - - return mLen; - } - - private static void ReduceBitWise(long[] buf, int off, int BitLength, int m, int[] ks) - { - while (--BitLength >= m) - { - if (TestBit(buf, off, BitLength)) - { - ReduceBit(buf, off, BitLength, m, ks); - } - } - } - - private static void ReduceBit(long[] buf, int off, int bit, int m, int[] ks) - { - FlipBit(buf, off, bit); - int n = bit - m; - int j = ks.Length; - while (--j >= 0) - { - FlipBit(buf, off, ks[j] + n); - } - FlipBit(buf, off, n); - } - - private static void ReduceWordWise(long[] buf, int off, int len, int toBit, int m, int[] ks) - { - int toPos = (int)((uint)toBit >> 6); - - while (--len > toPos) - { - long word = buf[off + len]; - if (word != 0) - { - buf[off + len] = 0; - ReduceWord(buf, off, (len << 6), word, m, ks); - } - } - - { - int partial = toBit & 0x3F; - long word = (long)((ulong)buf[off + toPos] >> partial); - if (word != 0) - { - buf[off + toPos] ^= word << partial; - ReduceWord(buf, off, toBit, word, m, ks); - } - } - } - - private static void ReduceWord(long[] buf, int off, int bit, long word, int m, int[] ks) - { - int offset = bit - m; - int j = ks.Length; - while (--j >= 0) - { - FlipWord(buf, off, offset + ks[j], word); - } - FlipWord(buf, off, offset, word); - } - - private static void ReduceVectorWise(long[] buf, int off, int len, int words, int m, int[] ks) - { - /* - * NOTE: It's important we go from highest coefficient to lowest, because for the highest - * one (only) we allow the ranges to partially overlap, and therefore any changes must take - * effect for the subsequent lower coefficients. - */ - int baseBit = (words << 6) - m; - int j = ks.Length; - while (--j >= 0) - { - FlipVector(buf, off, buf, off + words, len - words, baseBit + ks[j]); - } - FlipVector(buf, off, buf, off + words, len - words, baseBit); - } - - private static void FlipVector(long[] x, int xOff, long[] y, int yOff, int yLen, int bits) - { - xOff += (int)((uint)bits >> 6); - bits &= 0x3F; - - if (bits == 0) - { - Add(x, xOff, y, yOff, yLen); - } - else - { - long carry = AddShiftedDown(x, xOff + 1, y, yOff, yLen, 64 - bits); - x[xOff] ^= carry; - } - } - - public LongArray ModSquare(int m, int[] ks) - { - int len = GetUsedLength(); - if (len == 0) - { - return this; - } - - int _2len = len << 1; - long[] r = new long[_2len]; - - int pos = 0; - while (pos < _2len) - { - long mi = m_ints[(uint)pos >> 1]; - r[pos++] = Interleave2_32to64((int)mi); - r[pos++] = Interleave2_32to64((int)((ulong)mi >> 32)); - } - - return new LongArray(r, 0, ReduceInPlace(r, 0, r.Length, m, ks)); - } - - public LongArray ModSquareN(int n, int m, int[] ks) - { - int len = GetUsedLength(); - if (len == 0) - { - return this; - } - - int mLen = (m + 63) >> 6; - long[] r = new long[mLen << 1]; - Array.Copy(m_ints, 0, r, 0, len); - - while (--n >= 0) - { - SquareInPlace(r, len, m, ks); - len = ReduceInPlace(r, 0, r.Length, m, ks); - } - - return new LongArray(r, 0, len); - } - - public LongArray Square(int m, int[] ks) - { - int len = GetUsedLength(); - if (len == 0) - { - return this; - } - - int _2len = len << 1; - long[] r = new long[_2len]; - - int pos = 0; - while (pos < _2len) - { - long mi = m_ints[(uint)pos >> 1]; - r[pos++] = Interleave2_32to64((int)mi); - r[pos++] = Interleave2_32to64((int)((ulong)mi >> 32)); - } - - return new LongArray(r, 0, r.Length); - } - - private static void SquareInPlace(long[] x, int xLen, int m, int[] ks) - { - int pos = xLen << 1; - while (--xLen >= 0) - { - long xVal = x[xLen]; - x[--pos] = Interleave2_32to64((int)((ulong)xVal >> 32)); - x[--pos] = Interleave2_32to64((int)xVal); - } - } - - private static void Interleave(long[] x, int xOff, long[] z, int zOff, int count, int width) - { - switch (width) - { - case 3: - Interleave3(x, xOff, z, zOff, count); - break; - case 5: - Interleave5(x, xOff, z, zOff, count); - break; - case 7: - Interleave7(x, xOff, z, zOff, count); - break; - default: - Interleave2_n(x, xOff, z, zOff, count, BitLengths[width] - 1); - break; - } - } - - private static void Interleave3(long[] x, int xOff, long[] z, int zOff, int count) - { - for (int i = 0; i < count; ++i) - { - z[zOff + i] = Interleave3(x[xOff + i]); - } - } - - private static long Interleave3(long x) - { - long z = x & (1L << 63); - return z - | Interleave3_21to63((int)x & 0x1FFFFF) - | Interleave3_21to63((int)((ulong)x >> 21) & 0x1FFFFF) << 1 - | Interleave3_21to63((int)((ulong)x >> 42) & 0x1FFFFF) << 2; - - // int zPos = 0, wPos = 0, xPos = 0; - // for (;;) - // { - // z |= ((x >>> xPos) & 1L) << zPos; - // if (++zPos == 63) - // { - // String sz2 = Long.toBinaryString(z); - // return z; - // } - // if ((xPos += 21) >= 63) - // { - // xPos = ++wPos; - // } - // } - } - - private static long Interleave3_21to63(int x) - { - int r00 = INTERLEAVE3_TABLE[x & 0x7F]; - int r21 = INTERLEAVE3_TABLE[((uint)x >> 7) & 0x7F]; - int r42 = INTERLEAVE3_TABLE[(uint)x >> 14]; - return (r42 & 0xFFFFFFFFL) << 42 | (r21 & 0xFFFFFFFFL) << 21 | (r00 & 0xFFFFFFFFL); - } - - private static void Interleave5(long[] x, int xOff, long[] z, int zOff, int count) - { - for (int i = 0; i < count; ++i) - { - z[zOff + i] = Interleave5(x[xOff + i]); - } - } - - private static long Interleave5(long x) - { - return Interleave3_13to65((int)x & 0x1FFF) - | Interleave3_13to65((int)((ulong)x >> 13) & 0x1FFF) << 1 - | Interleave3_13to65((int)((ulong)x >> 26) & 0x1FFF) << 2 - | Interleave3_13to65((int)((ulong)x >> 39) & 0x1FFF) << 3 - | Interleave3_13to65((int)((ulong)x >> 52) & 0x1FFF) << 4; - - // long z = 0; - // int zPos = 0, wPos = 0, xPos = 0; - // for (;;) - // { - // z |= ((x >>> xPos) & 1L) << zPos; - // if (++zPos == 64) - // { - // return z; - // } - // if ((xPos += 13) >= 64) - // { - // xPos = ++wPos; - // } - // } - } - - private static long Interleave3_13to65(int x) - { - int r00 = INTERLEAVE5_TABLE[x & 0x7F]; - int r35 = INTERLEAVE5_TABLE[(uint)x >> 7]; - return (r35 & 0xFFFFFFFFL) << 35 | (r00 & 0xFFFFFFFFL); - } - - private static void Interleave7(long[] x, int xOff, long[] z, int zOff, int count) - { - for (int i = 0; i < count; ++i) - { - z[zOff + i] = Interleave7(x[xOff + i]); - } - } - - private static long Interleave7(long x) - { - long z = x & (1L << 63); - return z - | INTERLEAVE7_TABLE[(int)x & 0x1FF] - | INTERLEAVE7_TABLE[(int)((ulong)x >> 9) & 0x1FF] << 1 - | INTERLEAVE7_TABLE[(int)((ulong)x >> 18) & 0x1FF] << 2 - | INTERLEAVE7_TABLE[(int)((ulong)x >> 27) & 0x1FF] << 3 - | INTERLEAVE7_TABLE[(int)((ulong)x >> 36) & 0x1FF] << 4 - | INTERLEAVE7_TABLE[(int)((ulong)x >> 45) & 0x1FF] << 5 - | INTERLEAVE7_TABLE[(int)((ulong)x >> 54) & 0x1FF] << 6; - - // int zPos = 0, wPos = 0, xPos = 0; - // for (;;) - // { - // z |= ((x >>> xPos) & 1L) << zPos; - // if (++zPos == 63) - // { - // return z; - // } - // if ((xPos += 9) >= 63) - // { - // xPos = ++wPos; - // } - // } - } - - private static void Interleave2_n(long[] x, int xOff, long[] z, int zOff, int count, int rounds) - { - for (int i = 0; i < count; ++i) - { - z[zOff + i] = Interleave2_n(x[xOff + i], rounds); - } - } - - private static long Interleave2_n(long x, int rounds) - { - while (rounds > 1) - { - rounds -= 2; - x = Interleave4_16to64((int)x & 0xFFFF) - | Interleave4_16to64((int)((ulong)x >> 16) & 0xFFFF) << 1 - | Interleave4_16to64((int)((ulong)x >> 32) & 0xFFFF) << 2 - | Interleave4_16to64((int)((ulong)x >> 48) & 0xFFFF) << 3; - } - if (rounds > 0) - { - x = Interleave2_32to64((int)x) | Interleave2_32to64((int)((ulong)x >> 32)) << 1; - } - return x; - } - - private static long Interleave4_16to64(int x) - { - int r00 = INTERLEAVE4_TABLE[x & 0xFF]; - int r32 = INTERLEAVE4_TABLE[(uint)x >> 8]; - return (r32 & 0xFFFFFFFFL) << 32 | (r00 & 0xFFFFFFFFL); - } - - private static long Interleave2_32to64(int x) - { - int r00 = INTERLEAVE2_TABLE[x & 0xFF] | INTERLEAVE2_TABLE[((uint)x >> 8) & 0xFF] << 16; - int r32 = INTERLEAVE2_TABLE[((uint)x >> 16) & 0xFF] | INTERLEAVE2_TABLE[(uint)x >> 24] << 16; - return (r32 & 0xFFFFFFFFL) << 32 | (r00 & 0xFFFFFFFFL); - } - - // private static LongArray ExpItohTsujii2(LongArray B, int n, int m, int[] ks) - // { - // LongArray t1 = B, t3 = new LongArray(new long[]{ 1L }); - // int scale = 1; - // - // int numTerms = n; - // while (numTerms > 1) - // { - // if ((numTerms & 1) != 0) - // { - // t3 = t3.ModMultiply(t1, m, ks); - // t1 = t1.modSquareN(scale, m, ks); - // } - // - // LongArray t2 = t1.modSquareN(scale, m, ks); - // t1 = t1.ModMultiply(t2, m, ks); - // numTerms >>>= 1; scale <<= 1; - // } - // - // return t3.ModMultiply(t1, m, ks); - // } - // - // private static LongArray ExpItohTsujii23(LongArray B, int n, int m, int[] ks) - // { - // LongArray t1 = B, t3 = new LongArray(new long[]{ 1L }); - // int scale = 1; - // - // int numTerms = n; - // while (numTerms > 1) - // { - // bool m03 = numTerms % 3 == 0; - // bool m14 = !m03 && (numTerms & 1) != 0; - // - // if (m14) - // { - // t3 = t3.ModMultiply(t1, m, ks); - // t1 = t1.modSquareN(scale, m, ks); - // } - // - // LongArray t2 = t1.modSquareN(scale, m, ks); - // t1 = t1.ModMultiply(t2, m, ks); - // - // if (m03) - // { - // t2 = t2.modSquareN(scale, m, ks); - // t1 = t1.ModMultiply(t2, m, ks); - // numTerms /= 3; scale *= 3; - // } - // else - // { - // numTerms >>>= 1; scale <<= 1; - // } - // } - // - // return t3.ModMultiply(t1, m, ks); - // } - // - // private static LongArray ExpItohTsujii235(LongArray B, int n, int m, int[] ks) - // { - // LongArray t1 = B, t4 = new LongArray(new long[]{ 1L }); - // int scale = 1; - // - // int numTerms = n; - // while (numTerms > 1) - // { - // if (numTerms % 5 == 0) - // { - //// t1 = ExpItohTsujii23(t1, 5, m, ks); - // - // LongArray t3 = t1; - // t1 = t1.modSquareN(scale, m, ks); - // - // LongArray t2 = t1.modSquareN(scale, m, ks); - // t1 = t1.ModMultiply(t2, m, ks); - // t2 = t1.modSquareN(scale << 1, m, ks); - // t1 = t1.ModMultiply(t2, m, ks); - // - // t1 = t1.ModMultiply(t3, m, ks); - // - // numTerms /= 5; scale *= 5; - // continue; - // } - // - // bool m03 = numTerms % 3 == 0; - // bool m14 = !m03 && (numTerms & 1) != 0; - // - // if (m14) - // { - // t4 = t4.ModMultiply(t1, m, ks); - // t1 = t1.modSquareN(scale, m, ks); - // } - // - // LongArray t2 = t1.modSquareN(scale, m, ks); - // t1 = t1.ModMultiply(t2, m, ks); - // - // if (m03) - // { - // t2 = t2.modSquareN(scale, m, ks); - // t1 = t1.ModMultiply(t2, m, ks); - // numTerms /= 3; scale *= 3; - // } - // else - // { - // numTerms >>>= 1; scale <<= 1; - // } - // } - // - // return t4.ModMultiply(t1, m, ks); - // } - - public LongArray ModInverse(int m, int[] ks) - { - /* - * Fermat's Little Theorem - */ - // LongArray A = this; - // LongArray B = A.modSquare(m, ks); - // LongArray R0 = B, R1 = B; - // for (int i = 2; i < m; ++i) - // { - // R1 = R1.modSquare(m, ks); - // R0 = R0.ModMultiply(R1, m, ks); - // } - // - // return R0; - - /* - * Itoh-Tsujii - */ - // LongArray B = modSquare(m, ks); - // switch (m) - // { - // case 409: - // return ExpItohTsujii23(B, m - 1, m, ks); - // case 571: - // return ExpItohTsujii235(B, m - 1, m, ks); - // case 163: - // case 233: - // case 283: - // default: - // return ExpItohTsujii2(B, m - 1, m, ks); - // } - - /* - * Inversion in F2m using the extended Euclidean algorithm - * - * Input: A nonzero polynomial a(z) of degree at most m-1 - * Output: a(z)^(-1) mod f(z) - */ - int uzDegree = Degree(); - if (uzDegree == 0) - { - throw new InvalidOperationException(); - } - if (uzDegree == 1) - { - return this; - } - - // u(z) := a(z) - LongArray uz = (LongArray)Copy(); - - int t = (m + 63) >> 6; - - // v(z) := f(z) - LongArray vz = new LongArray(t); - ReduceBit(vz.m_ints, 0, m, m, ks); - - // g1(z) := 1, g2(z) := 0 - LongArray g1z = new LongArray(t); - g1z.m_ints[0] = 1L; - LongArray g2z = new LongArray(t); - - int[] uvDeg = new int[]{ uzDegree, m + 1 }; - LongArray[] uv = new LongArray[]{ uz, vz }; - - int[] ggDeg = new int[]{ 1, 0 }; - LongArray[] gg = new LongArray[]{ g1z, g2z }; - - int b = 1; - int duv1 = uvDeg[b]; - int dgg1 = ggDeg[b]; - int j = duv1 - uvDeg[1 - b]; - - for (;;) - { - if (j < 0) - { - j = -j; - uvDeg[b] = duv1; - ggDeg[b] = dgg1; - b = 1 - b; - duv1 = uvDeg[b]; - dgg1 = ggDeg[b]; - } - - uv[b].AddShiftedByBitsSafe(uv[1 - b], uvDeg[1 - b], j); - - int duv2 = uv[b].DegreeFrom(duv1); - if (duv2 == 0) - { - return gg[1 - b]; - } - - { - int dgg2 = ggDeg[1 - b]; - gg[b].AddShiftedByBitsSafe(gg[1 - b], dgg2, j); - dgg2 += j; - - if (dgg2 > dgg1) - { - dgg1 = dgg2; - } - else if (dgg2 == dgg1) - { - dgg1 = gg[b].DegreeFrom(dgg1); - } - } - - j += (duv2 - duv1); - duv1 = duv2; - } - } - - public override bool Equals(object obj) - { - return Equals(obj as LongArray); - } - - public virtual bool Equals(LongArray other) - { - if (this == other) - return true; - if (null == other) - return false; - int usedLen = GetUsedLength(); - if (other.GetUsedLength() != usedLen) - { - return false; - } - for (int i = 0; i < usedLen; i++) - { - if (m_ints[i] != other.m_ints[i]) - { - return false; - } - } - return true; - } - - public override int GetHashCode() - { - int usedLen = GetUsedLength(); - int hash = 1; - for (int i = 0; i < usedLen; i++) - { - long mi = m_ints[i]; - hash *= 31; - hash ^= (int)mi; - hash *= 31; - hash ^= (int)((ulong)mi >> 32); - } - return hash; - } - - public LongArray Copy() - { - return new LongArray(Arrays.Clone(m_ints)); - } - - public override string ToString() - { - int i = GetUsedLength(); - if (i == 0) - { - return "0"; - } - - StringBuilder sb = new StringBuilder(Convert.ToString(m_ints[--i], 2)); - while (--i >= 0) - { - string s = Convert.ToString(m_ints[i], 2); - - // Add leading zeroes, except for highest significant word - int len = s.Length; - if (len < 64) - { - sb.Append(ZEROES.Substring(len)); - } - - sb.Append(s); - } - return sb.ToString(); - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/ec/abc/SimpleBigDecimal.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/abc/SimpleBigDecimal.cs deleted file mode 100644 index 23604d1ba..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/abc/SimpleBigDecimal.cs +++ /dev/null @@ -1,241 +0,0 @@ -using System; -using System.Text; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Abc -{ - /** - * Class representing a simple version of a big decimal. A - * SimpleBigDecimal is basically a - * {@link java.math.BigInteger BigInteger} with a few digits on the right of - * the decimal point. The number of (binary) digits on the right of the decimal - * point is called the scale of the SimpleBigDecimal. - * Unlike in {@link java.math.BigDecimal BigDecimal}, the scale is not adjusted - * automatically, but must be set manually. All SimpleBigDecimals - * taking part in the same arithmetic operation must have equal scale. The - * result of a multiplication of two SimpleBigDecimals returns a - * SimpleBigDecimal with double scale. - */ - internal class SimpleBigDecimal - // : Number - { - // private static final long serialVersionUID = 1L; - - private readonly BigInteger bigInt; - private readonly int scale; - - /** - * Returns a SimpleBigDecimal representing the same numerical - * value as value. - * @param value The value of the SimpleBigDecimal to be - * created. - * @param scale The scale of the SimpleBigDecimal to be - * created. - * @return The such created SimpleBigDecimal. - */ - public static SimpleBigDecimal GetInstance(BigInteger val, int scale) - { - return new SimpleBigDecimal(val.ShiftLeft(scale), scale); - } - - /** - * Constructor for SimpleBigDecimal. The value of the - * constructed SimpleBigDecimal Equals bigInt / - * 2scale. - * @param bigInt The bigInt value parameter. - * @param scale The scale of the constructed SimpleBigDecimal. - */ - public SimpleBigDecimal(BigInteger bigInt, int scale) - { - if (scale < 0) - throw new ArgumentException("scale may not be negative"); - - this.bigInt = bigInt; - this.scale = scale; - } - - private SimpleBigDecimal(SimpleBigDecimal limBigDec) - { - bigInt = limBigDec.bigInt; - scale = limBigDec.scale; - } - - private void CheckScale(SimpleBigDecimal b) - { - if (scale != b.scale) - throw new ArgumentException("Only SimpleBigDecimal of same scale allowed in arithmetic operations"); - } - - public SimpleBigDecimal AdjustScale(int newScale) - { - if (newScale < 0) - throw new ArgumentException("scale may not be negative"); - - if (newScale == scale) - return this; - - return new SimpleBigDecimal(bigInt.ShiftLeft(newScale - scale), newScale); - } - - public SimpleBigDecimal Add(SimpleBigDecimal b) - { - CheckScale(b); - return new SimpleBigDecimal(bigInt.Add(b.bigInt), scale); - } - - public SimpleBigDecimal Add(BigInteger b) - { - return new SimpleBigDecimal(bigInt.Add(b.ShiftLeft(scale)), scale); - } - - public SimpleBigDecimal Negate() - { - return new SimpleBigDecimal(bigInt.Negate(), scale); - } - - public SimpleBigDecimal Subtract(SimpleBigDecimal b) - { - return Add(b.Negate()); - } - - public SimpleBigDecimal Subtract(BigInteger b) - { - return new SimpleBigDecimal(bigInt.Subtract(b.ShiftLeft(scale)), scale); - } - - public SimpleBigDecimal Multiply(SimpleBigDecimal b) - { - CheckScale(b); - return new SimpleBigDecimal(bigInt.Multiply(b.bigInt), scale + scale); - } - - public SimpleBigDecimal Multiply(BigInteger b) - { - return new SimpleBigDecimal(bigInt.Multiply(b), scale); - } - - public SimpleBigDecimal Divide(SimpleBigDecimal b) - { - CheckScale(b); - BigInteger dividend = bigInt.ShiftLeft(scale); - return new SimpleBigDecimal(dividend.Divide(b.bigInt), scale); - } - - public SimpleBigDecimal Divide(BigInteger b) - { - return new SimpleBigDecimal(bigInt.Divide(b), scale); - } - - public SimpleBigDecimal ShiftLeft(int n) - { - return new SimpleBigDecimal(bigInt.ShiftLeft(n), scale); - } - - public int CompareTo(SimpleBigDecimal val) - { - CheckScale(val); - return bigInt.CompareTo(val.bigInt); - } - - public int CompareTo(BigInteger val) - { - return bigInt.CompareTo(val.ShiftLeft(scale)); - } - - public BigInteger Floor() - { - return bigInt.ShiftRight(scale); - } - - public BigInteger Round() - { - SimpleBigDecimal oneHalf = new SimpleBigDecimal(BigInteger.One, 1); - return Add(oneHalf.AdjustScale(scale)).Floor(); - } - - public int IntValue - { - get { return Floor().IntValue; } - } - - public long LongValue - { - get { return Floor().LongValue; } - } - -// public double doubleValue() -// { -// return new Double(ToString()).doubleValue(); -// } -// -// public float floatValue() -// { -// return new Float(ToString()).floatValue(); -// } - - public int Scale - { - get { return scale; } - } - - public override string ToString() - { - if (scale == 0) - return bigInt.ToString(); - - BigInteger floorBigInt = Floor(); - - BigInteger fract = bigInt.Subtract(floorBigInt.ShiftLeft(scale)); - if (bigInt.SignValue < 0) - { - fract = BigInteger.One.ShiftLeft(scale).Subtract(fract); - } - - if ((floorBigInt.SignValue == -1) && (!(fract.Equals(BigInteger.Zero)))) - { - floorBigInt = floorBigInt.Add(BigInteger.One); - } - string leftOfPoint = floorBigInt.ToString(); - - char[] fractCharArr = new char[scale]; - string fractStr = fract.ToString(2); - int fractLen = fractStr.Length; - int zeroes = scale - fractLen; - for (int i = 0; i < zeroes; i++) - { - fractCharArr[i] = '0'; - } - for (int j = 0; j < fractLen; j++) - { - fractCharArr[zeroes + j] = fractStr[j]; - } - string rightOfPoint = new string(fractCharArr); - - StringBuilder sb = new StringBuilder(leftOfPoint); - sb.Append("."); - sb.Append(rightOfPoint); - - return sb.ToString(); - } - - public override bool Equals( - object obj) - { - if (this == obj) - return true; - - SimpleBigDecimal other = obj as SimpleBigDecimal; - - if (other == null) - return false; - - return bigInt.Equals(other.bigInt) - && scale == other.scale; - } - - public override int GetHashCode() - { - return bigInt.GetHashCode() ^ scale; - } - - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/ec/abc/Tnaf.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/abc/Tnaf.cs deleted file mode 100644 index 86e582f2a..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/abc/Tnaf.cs +++ /dev/null @@ -1,845 +0,0 @@ -using System; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Abc -{ - /** - * Class holding methods for point multiplication based on the window - * τ-adic nonadjacent form (WTNAF). The algorithms are based on the - * paper "Improved Algorithms for Arithmetic on Anomalous Binary Curves" - * by Jerome A. Solinas. The paper first appeared in the Proceedings of - * Crypto 1997. - */ - internal class Tnaf - { - private static readonly BigInteger MinusOne = BigInteger.One.Negate(); - private static readonly BigInteger MinusTwo = BigInteger.Two.Negate(); - private static readonly BigInteger MinusThree = BigInteger.Three.Negate(); - private static readonly BigInteger Four = BigInteger.ValueOf(4); - - /** - * The window width of WTNAF. The standard value of 4 is slightly less - * than optimal for running time, but keeps space requirements for - * precomputation low. For typical curves, a value of 5 or 6 results in - * a better running time. When changing this value, the - * αu's must be computed differently, see - * e.g. "Guide to Elliptic Curve Cryptography", Darrel Hankerson, - * Alfred Menezes, Scott Vanstone, Springer-Verlag New York Inc., 2004, - * p. 121-122 - */ - public const sbyte Width = 4; - - /** - * 24 - */ - public const sbyte Pow2Width = 16; - - /** - * The αu's for a=0 as an array - * of ZTauElements. - */ - public static readonly ZTauElement[] Alpha0 = - { - null, - new ZTauElement(BigInteger.One, BigInteger.Zero), null, - new ZTauElement(MinusThree, MinusOne), null, - new ZTauElement(MinusOne, MinusOne), null, - new ZTauElement(BigInteger.One, MinusOne), null - }; - - /** - * The αu's for a=0 as an array - * of TNAFs. - */ - public static readonly sbyte[][] Alpha0Tnaf = - { - null, new sbyte[]{1}, null, new sbyte[]{-1, 0, 1}, null, new sbyte[]{1, 0, 1}, null, new sbyte[]{-1, 0, 0, 1} - }; - - /** - * The αu's for a=1 as an array - * of ZTauElements. - */ - public static readonly ZTauElement[] Alpha1 = - { - null, - new ZTauElement(BigInteger.One, BigInteger.Zero), null, - new ZTauElement(MinusThree, BigInteger.One), null, - new ZTauElement(MinusOne, BigInteger.One), null, - new ZTauElement(BigInteger.One, BigInteger.One), null - }; - - /** - * The αu's for a=1 as an array - * of TNAFs. - */ - public static readonly sbyte[][] Alpha1Tnaf = - { - null, new sbyte[]{1}, null, new sbyte[]{-1, 0, 1}, null, new sbyte[]{1, 0, 1}, null, new sbyte[]{-1, 0, 0, -1} - }; - - /** - * Computes the norm of an element λ of - * Z[τ]. - * @param mu The parameter μ of the elliptic curve. - * @param lambda The element λ of - * Z[τ]. - * @return The norm of λ. - */ - public static BigInteger Norm(sbyte mu, ZTauElement lambda) - { - BigInteger norm; - - // s1 = u^2 - BigInteger s1 = lambda.u.Multiply(lambda.u); - - // s2 = u * v - BigInteger s2 = lambda.u.Multiply(lambda.v); - - // s3 = 2 * v^2 - BigInteger s3 = lambda.v.Multiply(lambda.v).ShiftLeft(1); - - if (mu == 1) - { - norm = s1.Add(s2).Add(s3); - } - else if (mu == -1) - { - norm = s1.Subtract(s2).Add(s3); - } - else - { - throw new ArgumentException("mu must be 1 or -1"); - } - - return norm; - } - - /** - * Computes the norm of an element λ of - * R[τ], where λ = u + vτ - * and u and u are real numbers (elements of - * R). - * @param mu The parameter μ of the elliptic curve. - * @param u The real part of the element λ of - * R[τ]. - * @param v The τ-adic part of the element - * λ of R[τ]. - * @return The norm of λ. - */ - public static SimpleBigDecimal Norm(sbyte mu, SimpleBigDecimal u, SimpleBigDecimal v) - { - SimpleBigDecimal norm; - - // s1 = u^2 - SimpleBigDecimal s1 = u.Multiply(u); - - // s2 = u * v - SimpleBigDecimal s2 = u.Multiply(v); - - // s3 = 2 * v^2 - SimpleBigDecimal s3 = v.Multiply(v).ShiftLeft(1); - - if (mu == 1) - { - norm = s1.Add(s2).Add(s3); - } - else if (mu == -1) - { - norm = s1.Subtract(s2).Add(s3); - } - else - { - throw new ArgumentException("mu must be 1 or -1"); - } - - return norm; - } - - /** - * Rounds an element λ of R[τ] - * to an element of Z[τ], such that their difference - * has minimal norm. λ is given as - * λ = λ0 + λ1τ. - * @param lambda0 The component λ0. - * @param lambda1 The component λ1. - * @param mu The parameter μ of the elliptic curve. Must - * equal 1 or -1. - * @return The rounded element of Z[τ]. - * @throws ArgumentException if lambda0 and - * lambda1 do not have same scale. - */ - public static ZTauElement Round(SimpleBigDecimal lambda0, - SimpleBigDecimal lambda1, sbyte mu) - { - int scale = lambda0.Scale; - if (lambda1.Scale != scale) - throw new ArgumentException("lambda0 and lambda1 do not have same scale"); - - if (!((mu == 1) || (mu == -1))) - throw new ArgumentException("mu must be 1 or -1"); - - BigInteger f0 = lambda0.Round(); - BigInteger f1 = lambda1.Round(); - - SimpleBigDecimal eta0 = lambda0.Subtract(f0); - SimpleBigDecimal eta1 = lambda1.Subtract(f1); - - // eta = 2*eta0 + mu*eta1 - SimpleBigDecimal eta = eta0.Add(eta0); - if (mu == 1) - { - eta = eta.Add(eta1); - } - else - { - // mu == -1 - eta = eta.Subtract(eta1); - } - - // check1 = eta0 - 3*mu*eta1 - // check2 = eta0 + 4*mu*eta1 - SimpleBigDecimal threeEta1 = eta1.Add(eta1).Add(eta1); - SimpleBigDecimal fourEta1 = threeEta1.Add(eta1); - SimpleBigDecimal check1; - SimpleBigDecimal check2; - if (mu == 1) - { - check1 = eta0.Subtract(threeEta1); - check2 = eta0.Add(fourEta1); - } - else - { - // mu == -1 - check1 = eta0.Add(threeEta1); - check2 = eta0.Subtract(fourEta1); - } - - sbyte h0 = 0; - sbyte h1 = 0; - - // if eta >= 1 - if (eta.CompareTo(BigInteger.One) >= 0) - { - if (check1.CompareTo(MinusOne) < 0) - { - h1 = mu; - } - else - { - h0 = 1; - } - } - else - { - // eta < 1 - if (check2.CompareTo(BigInteger.Two) >= 0) - { - h1 = mu; - } - } - - // if eta < -1 - if (eta.CompareTo(MinusOne) < 0) - { - if (check1.CompareTo(BigInteger.One) >= 0) - { - h1 = (sbyte)-mu; - } - else - { - h0 = -1; - } - } - else - { - // eta >= -1 - if (check2.CompareTo(MinusTwo) < 0) - { - h1 = (sbyte)-mu; - } - } - - BigInteger q0 = f0.Add(BigInteger.ValueOf(h0)); - BigInteger q1 = f1.Add(BigInteger.ValueOf(h1)); - return new ZTauElement(q0, q1); - } - - /** - * Approximate division by n. For an integer - * k, the value λ = s k / n is - * computed to c bits of accuracy. - * @param k The parameter k. - * @param s The curve parameter s0 or - * s1. - * @param vm The Lucas Sequence element Vm. - * @param a The parameter a of the elliptic curve. - * @param m The bit length of the finite field - * Fm. - * @param c The number of bits of accuracy, i.e. the scale of the returned - * SimpleBigDecimal. - * @return The value λ = s k / n computed to - * c bits of accuracy. - */ - public static SimpleBigDecimal ApproximateDivisionByN(BigInteger k, - BigInteger s, BigInteger vm, sbyte a, int m, int c) - { - int _k = (m + 5)/2 + c; - BigInteger ns = k.ShiftRight(m - _k - 2 + a); - - BigInteger gs = s.Multiply(ns); - - BigInteger hs = gs.ShiftRight(m); - - BigInteger js = vm.Multiply(hs); - - BigInteger gsPlusJs = gs.Add(js); - BigInteger ls = gsPlusJs.ShiftRight(_k-c); - if (gsPlusJs.TestBit(_k-c-1)) - { - // round up - ls = ls.Add(BigInteger.One); - } - - return new SimpleBigDecimal(ls, c); - } - - /** - * Computes the τ-adic NAF (non-adjacent form) of an - * element λ of Z[τ]. - * @param mu The parameter μ of the elliptic curve. - * @param lambda The element λ of - * Z[τ]. - * @return The τ-adic NAF of λ. - */ - public static sbyte[] TauAdicNaf(sbyte mu, ZTauElement lambda) - { - if (!((mu == 1) || (mu == -1))) - throw new ArgumentException("mu must be 1 or -1"); - - BigInteger norm = Norm(mu, lambda); - - // Ceiling of log2 of the norm - int log2Norm = norm.BitLength; - - // If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52 - int maxLength = log2Norm > 30 ? log2Norm + 4 : 34; - - // The array holding the TNAF - sbyte[] u = new sbyte[maxLength]; - int i = 0; - - // The actual length of the TNAF - int length = 0; - - BigInteger r0 = lambda.u; - BigInteger r1 = lambda.v; - - while(!((r0.Equals(BigInteger.Zero)) && (r1.Equals(BigInteger.Zero)))) - { - // If r0 is odd - if (r0.TestBit(0)) - { - u[i] = (sbyte) BigInteger.Two.Subtract((r0.Subtract(r1.ShiftLeft(1))).Mod(Four)).IntValue; - - // r0 = r0 - u[i] - if (u[i] == 1) - { - r0 = r0.ClearBit(0); - } - else - { - // u[i] == -1 - r0 = r0.Add(BigInteger.One); - } - length = i; - } - else - { - u[i] = 0; - } - - BigInteger t = r0; - BigInteger s = r0.ShiftRight(1); - if (mu == 1) - { - r0 = r1.Add(s); - } - else - { - // mu == -1 - r0 = r1.Subtract(s); - } - - r1 = t.ShiftRight(1).Negate(); - i++; - } - - length++; - - // Reduce the TNAF array to its actual length - sbyte[] tnaf = new sbyte[length]; - Array.Copy(u, 0, tnaf, 0, length); - return tnaf; - } - - /** - * Applies the operation τ() to an - * AbstractF2mPoint. - * @param p The AbstractF2mPoint to which τ() is applied. - * @return τ(p) - */ - public static AbstractF2mPoint Tau(AbstractF2mPoint p) - { - return p.Tau(); - } - - /** - * Returns the parameter μ of the elliptic curve. - * @param curve The elliptic curve from which to obtain μ. - * The curve must be a Koblitz curve, i.e. a Equals - * 0 or 1 and b Equals - * 1. - * @return μ of the elliptic curve. - * @throws ArgumentException if the given ECCurve is not a Koblitz - * curve. - */ - public static sbyte GetMu(AbstractF2mCurve curve) - { - BigInteger a = curve.A.ToBigInteger(); - - sbyte mu; - if (a.SignValue == 0) - { - mu = -1; - } - else if (a.Equals(BigInteger.One)) - { - mu = 1; - } - else - { - throw new ArgumentException("No Koblitz curve (ABC), TNAF multiplication not possible"); - } - return mu; - } - - public static sbyte GetMu(ECFieldElement curveA) - { - return (sbyte)(curveA.IsZero ? -1 : 1); - } - - public static sbyte GetMu(int curveA) - { - return (sbyte)(curveA == 0 ? -1 : 1); - } - - /** - * Calculates the Lucas Sequence elements Uk-1 and - * Uk or Vk-1 and - * Vk. - * @param mu The parameter μ of the elliptic curve. - * @param k The index of the second element of the Lucas Sequence to be - * returned. - * @param doV If set to true, computes Vk-1 and - * Vk, otherwise Uk-1 and - * Uk. - * @return An array with 2 elements, containing Uk-1 - * and Uk or Vk-1 - * and Vk. - */ - public static BigInteger[] GetLucas(sbyte mu, int k, bool doV) - { - if (!(mu == 1 || mu == -1)) - throw new ArgumentException("mu must be 1 or -1"); - - BigInteger u0; - BigInteger u1; - BigInteger u2; - - if (doV) - { - u0 = BigInteger.Two; - u1 = BigInteger.ValueOf(mu); - } - else - { - u0 = BigInteger.Zero; - u1 = BigInteger.One; - } - - for (int i = 1; i < k; i++) - { - // u2 = mu*u1 - 2*u0; - BigInteger s = null; - if (mu == 1) - { - s = u1; - } - else - { - // mu == -1 - s = u1.Negate(); - } - - u2 = s.Subtract(u0.ShiftLeft(1)); - u0 = u1; - u1 = u2; - // System.out.println(i + ": " + u2); - // System.out.println(); - } - - BigInteger[] retVal = {u0, u1}; - return retVal; - } - - /** - * Computes the auxiliary value tw. If the width is - * 4, then for mu = 1, tw = 6 and for - * mu = -1, tw = 10 - * @param mu The parameter μ of the elliptic curve. - * @param w The window width of the WTNAF. - * @return the auxiliary value tw - */ - public static BigInteger GetTw(sbyte mu, int w) - { - if (w == 4) - { - if (mu == 1) - { - return BigInteger.ValueOf(6); - } - else - { - // mu == -1 - return BigInteger.ValueOf(10); - } - } - else - { - // For w <> 4, the values must be computed - BigInteger[] us = GetLucas(mu, w, false); - BigInteger twoToW = BigInteger.Zero.SetBit(w); - BigInteger u1invert = us[1].ModInverse(twoToW); - BigInteger tw; - tw = BigInteger.Two.Multiply(us[0]).Multiply(u1invert).Mod(twoToW); - //System.out.println("mu = " + mu); - //System.out.println("tw = " + tw); - return tw; - } - } - - /** - * Computes the auxiliary values s0 and - * s1 used for partial modular reduction. - * @param curve The elliptic curve for which to compute - * s0 and s1. - * @throws ArgumentException if curve is not a - * Koblitz curve (Anomalous Binary Curve, ABC). - */ - public static BigInteger[] GetSi(AbstractF2mCurve curve) - { - if (!curve.IsKoblitz) - throw new ArgumentException("si is defined for Koblitz curves only"); - - int m = curve.FieldSize; - int a = curve.A.ToBigInteger().IntValue; - sbyte mu = GetMu(a); - int shifts = GetShiftsForCofactor(curve.Cofactor); - int index = m + 3 - a; - BigInteger[] ui = GetLucas(mu, index, false); - - if (mu == 1) - { - ui[0] = ui[0].Negate(); - ui[1] = ui[1].Negate(); - } - - BigInteger dividend0 = BigInteger.One.Add(ui[1]).ShiftRight(shifts); - BigInteger dividend1 = BigInteger.One.Add(ui[0]).ShiftRight(shifts).Negate(); - - return new BigInteger[] { dividend0, dividend1 }; - } - - public static BigInteger[] GetSi(int fieldSize, int curveA, BigInteger cofactor) - { - sbyte mu = GetMu(curveA); - int shifts = GetShiftsForCofactor(cofactor); - int index = fieldSize + 3 - curveA; - BigInteger[] ui = GetLucas(mu, index, false); - if (mu == 1) - { - ui[0] = ui[0].Negate(); - ui[1] = ui[1].Negate(); - } - - BigInteger dividend0 = BigInteger.One.Add(ui[1]).ShiftRight(shifts); - BigInteger dividend1 = BigInteger.One.Add(ui[0]).ShiftRight(shifts).Negate(); - - return new BigInteger[] { dividend0, dividend1 }; - } - - protected static int GetShiftsForCofactor(BigInteger h) - { - if (h != null && h.BitLength < 4) - { - int hi = h.IntValue; - if (hi == 2) - return 1; - if (hi == 4) - return 2; - } - - throw new ArgumentException("h (Cofactor) must be 2 or 4"); - } - - /** - * Partial modular reduction modulo - * (τm - 1)/(τ - 1). - * @param k The integer to be reduced. - * @param m The bitlength of the underlying finite field. - * @param a The parameter a of the elliptic curve. - * @param s The auxiliary values s0 and - * s1. - * @param mu The parameter μ of the elliptic curve. - * @param c The precision (number of bits of accuracy) of the partial - * modular reduction. - * @return ρ := k partmod (τm - 1)/(τ - 1) - */ - public static ZTauElement PartModReduction(BigInteger k, int m, sbyte a, - BigInteger[] s, sbyte mu, sbyte c) - { - // d0 = s[0] + mu*s[1]; mu is either 1 or -1 - BigInteger d0; - if (mu == 1) - { - d0 = s[0].Add(s[1]); - } - else - { - d0 = s[0].Subtract(s[1]); - } - - BigInteger[] v = GetLucas(mu, m, true); - BigInteger vm = v[1]; - - SimpleBigDecimal lambda0 = ApproximateDivisionByN( - k, s[0], vm, a, m, c); - - SimpleBigDecimal lambda1 = ApproximateDivisionByN( - k, s[1], vm, a, m, c); - - ZTauElement q = Round(lambda0, lambda1, mu); - - // r0 = n - d0*q0 - 2*s1*q1 - BigInteger r0 = k.Subtract(d0.Multiply(q.u)).Subtract( - BigInteger.ValueOf(2).Multiply(s[1]).Multiply(q.v)); - - // r1 = s1*q0 - s0*q1 - BigInteger r1 = s[1].Multiply(q.u).Subtract(s[0].Multiply(q.v)); - - return new ZTauElement(r0, r1); - } - - /** - * Multiplies a {@link org.bouncycastle.math.ec.AbstractF2mPoint AbstractF2mPoint} - * by a BigInteger using the reduced τ-adic - * NAF (RTNAF) method. - * @param p The AbstractF2mPoint to Multiply. - * @param k The BigInteger by which to Multiply p. - * @return k * p - */ - public static AbstractF2mPoint MultiplyRTnaf(AbstractF2mPoint p, BigInteger k) - { - AbstractF2mCurve curve = (AbstractF2mCurve)p.Curve; - int m = curve.FieldSize; - int a = curve.A.ToBigInteger().IntValue; - sbyte mu = GetMu(a); - BigInteger[] s = curve.GetSi(); - ZTauElement rho = PartModReduction(k, m, (sbyte)a, s, mu, (sbyte)10); - - return MultiplyTnaf(p, rho); - } - - /** - * Multiplies a {@link org.bouncycastle.math.ec.AbstractF2mPoint AbstractF2mPoint} - * by an element λ of Z[τ] - * using the τ-adic NAF (TNAF) method. - * @param p The AbstractF2mPoint to Multiply. - * @param lambda The element λ of - * Z[τ]. - * @return λ * p - */ - public static AbstractF2mPoint MultiplyTnaf(AbstractF2mPoint p, ZTauElement lambda) - { - AbstractF2mCurve curve = (AbstractF2mCurve)p.Curve; - sbyte mu = GetMu(curve.A); - sbyte[] u = TauAdicNaf(mu, lambda); - - AbstractF2mPoint q = MultiplyFromTnaf(p, u); - - return q; - } - - /** - * Multiplies a {@link org.bouncycastle.math.ec.AbstractF2mPoint AbstractF2mPoint} - * by an element λ of Z[τ] - * using the τ-adic NAF (TNAF) method, given the TNAF - * of λ. - * @param p The AbstractF2mPoint to Multiply. - * @param u The the TNAF of λ.. - * @return λ * p - */ - public static AbstractF2mPoint MultiplyFromTnaf(AbstractF2mPoint p, sbyte[] u) - { - ECCurve curve = p.Curve; - AbstractF2mPoint q = (AbstractF2mPoint)curve.Infinity; - AbstractF2mPoint pNeg = (AbstractF2mPoint)p.Negate(); - int tauCount = 0; - for (int i = u.Length - 1; i >= 0; i--) - { - ++tauCount; - sbyte ui = u[i]; - if (ui != 0) - { - q = q.TauPow(tauCount); - tauCount = 0; - - ECPoint x = ui > 0 ? p : pNeg; - q = (AbstractF2mPoint)q.Add(x); - } - } - if (tauCount > 0) - { - q = q.TauPow(tauCount); - } - return q; - } - - /** - * Computes the [τ]-adic window NAF of an element - * λ of Z[τ]. - * @param mu The parameter μ of the elliptic curve. - * @param lambda The element λ of - * Z[τ] of which to compute the - * [τ]-adic NAF. - * @param width The window width of the resulting WNAF. - * @param pow2w 2width. - * @param tw The auxiliary value tw. - * @param alpha The αu's for the window width. - * @return The [τ]-adic window NAF of - * λ. - */ - public static sbyte[] TauAdicWNaf(sbyte mu, ZTauElement lambda, - sbyte width, BigInteger pow2w, BigInteger tw, ZTauElement[] alpha) - { - if (!((mu == 1) || (mu == -1))) - throw new ArgumentException("mu must be 1 or -1"); - - BigInteger norm = Norm(mu, lambda); - - // Ceiling of log2 of the norm - int log2Norm = norm.BitLength; - - // If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52 - int maxLength = log2Norm > 30 ? log2Norm + 4 + width : 34 + width; - - // The array holding the TNAF - sbyte[] u = new sbyte[maxLength]; - - // 2^(width - 1) - BigInteger pow2wMin1 = pow2w.ShiftRight(1); - - // Split lambda into two BigIntegers to simplify calculations - BigInteger r0 = lambda.u; - BigInteger r1 = lambda.v; - int i = 0; - - // while lambda <> (0, 0) - while (!((r0.Equals(BigInteger.Zero))&&(r1.Equals(BigInteger.Zero)))) - { - // if r0 is odd - if (r0.TestBit(0)) - { - // uUnMod = r0 + r1*tw Mod 2^width - BigInteger uUnMod - = r0.Add(r1.Multiply(tw)).Mod(pow2w); - - sbyte uLocal; - // if uUnMod >= 2^(width - 1) - if (uUnMod.CompareTo(pow2wMin1) >= 0) - { - uLocal = (sbyte) uUnMod.Subtract(pow2w).IntValue; - } - else - { - uLocal = (sbyte) uUnMod.IntValue; - } - // uLocal is now in [-2^(width-1), 2^(width-1)-1] - - u[i] = uLocal; - bool s = true; - if (uLocal < 0) - { - s = false; - uLocal = (sbyte)-uLocal; - } - // uLocal is now >= 0 - - if (s) - { - r0 = r0.Subtract(alpha[uLocal].u); - r1 = r1.Subtract(alpha[uLocal].v); - } - else - { - r0 = r0.Add(alpha[uLocal].u); - r1 = r1.Add(alpha[uLocal].v); - } - } - else - { - u[i] = 0; - } - - BigInteger t = r0; - - if (mu == 1) - { - r0 = r1.Add(r0.ShiftRight(1)); - } - else - { - // mu == -1 - r0 = r1.Subtract(r0.ShiftRight(1)); - } - r1 = t.ShiftRight(1).Negate(); - i++; - } - return u; - } - - /** - * Does the precomputation for WTNAF multiplication. - * @param p The ECPoint for which to do the precomputation. - * @param a The parameter a of the elliptic curve. - * @return The precomputation array for p. - */ - public static AbstractF2mPoint[] GetPreComp(AbstractF2mPoint p, sbyte a) - { - sbyte[][] alphaTnaf = (a == 0) ? Tnaf.Alpha0Tnaf : Tnaf.Alpha1Tnaf; - - AbstractF2mPoint[] pu = new AbstractF2mPoint[(uint)(alphaTnaf.Length + 1) >> 1]; - pu[0] = p; - - uint precompLen = (uint)alphaTnaf.Length; - for (uint i = 3; i < precompLen; i += 2) - { - pu[i >> 1] = Tnaf.MultiplyFromTnaf(p, alphaTnaf[i]); - } - - p.Curve.NormalizeAll(pu); - - return pu; - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/ec/abc/ZTauElement.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/abc/ZTauElement.cs deleted file mode 100644 index 0b74e48d9..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/abc/ZTauElement.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Abc -{ - /** - * Class representing an element of Z[τ]. Let - * λ be an element of Z[τ]. Then - * λ is given as λ = u + vτ. The - * components u and v may be used directly, there - * are no accessor methods. - * Immutable class. - */ - internal class ZTauElement - { - /** - * The "real" part of λ. - */ - public readonly BigInteger u; - - /** - * The "τ-adic" part of λ. - */ - public readonly BigInteger v; - - /** - * Constructor for an element λ of - * Z[τ]. - * @param u The "real" part of λ. - * @param v The "τ-adic" part of - * λ. - */ - public ZTauElement(BigInteger u, BigInteger v) - { - this.u = u; - this.v = v; - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/ec/endo/ECEndomorphism.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/endo/ECEndomorphism.cs deleted file mode 100644 index 8dbbace40..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/endo/ECEndomorphism.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Endo -{ - internal interface ECEndomorphism - { - ECPointMap PointMap { get; } - - bool HasEfficientPointMap { get; } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/ec/endo/GlvEndomorphism.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/endo/GlvEndomorphism.cs deleted file mode 100644 index acfae5264..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/endo/GlvEndomorphism.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Endo -{ - internal interface GlvEndomorphism - : ECEndomorphism - { - BigInteger[] DecomposeScalar(BigInteger k); - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/AbstractECMultiplier.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/AbstractECMultiplier.cs deleted file mode 100644 index 9c9b4cb27..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/AbstractECMultiplier.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Multiplier -{ - internal abstract class AbstractECMultiplier - : ECMultiplier - { - public virtual ECPoint Multiply(ECPoint p, BigInteger k) - { - int sign = k.SignValue; - if (sign == 0 || p.IsInfinity) - return p.Curve.Infinity; - - ECPoint positive = MultiplyPositive(p, k.Abs()); - ECPoint result = sign > 0 ? positive : positive.Negate(); - - /* - * Although the various multipliers ought not to produce invalid output under normal - * circumstances, a final check here is advised to guard against fault attacks. - */ - return CheckResult(result); - } - - protected abstract ECPoint MultiplyPositive(ECPoint p, BigInteger k); - - protected virtual ECPoint CheckResult(ECPoint p) - { - return ECAlgorithms.ImplCheckResult(p); - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/ECMultiplier.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/ECMultiplier.cs deleted file mode 100644 index 97fe1d131..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/ECMultiplier.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Multiplier -{ - /** - * Interface for classes encapsulating a point multiplication algorithm - * for ECPoints. - */ - internal interface ECMultiplier - { - /** - * Multiplies the ECPoint p by k, i.e. - * p is added k times to itself. - * @param p The ECPoint to be multiplied. - * @param k The factor by which p is multiplied. - * @return p multiplied by k. - */ - ECPoint Multiply(ECPoint p, BigInteger k); - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/FixedPointCombMultiplier.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/FixedPointCombMultiplier.cs deleted file mode 100644 index a63e18e25..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/FixedPointCombMultiplier.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; - -using Renci.SshNet.Security.Org.BouncyCastle.Math.Raw; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Multiplier -{ - internal class FixedPointCombMultiplier - : AbstractECMultiplier - { - protected override ECPoint MultiplyPositive(ECPoint p, BigInteger k) - { - ECCurve c = p.Curve; - int size = FixedPointUtilities.GetCombSize(c); - - if (k.BitLength > size) - { - /* - * 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 info = FixedPointUtilities.Precompute(p); - ECLookupTable lookupTable = info.LookupTable; - int width = info.Width; - - int d = (size + width - 1) / width; - - ECPoint R = c.Infinity; - - int fullComb = d * width; - uint[] K = Nat.FromBigInteger(fullComb, k); - - int top = fullComb - 1; - for (int i = 0; i < d; ++i) - { - uint secretIndex = 0; - - for (int j = top - i; j >= 0; j -= d) - { - uint secretBit = K[j >> 5] >> (j & 0x1F); - secretIndex ^= secretBit >> 1; - secretIndex <<= 1; - secretIndex ^= secretBit; - } - - ECPoint add = lookupTable.Lookup((int)secretIndex); - - R = R.TwicePlus(add); - } - - return R.Add(info.Offset); - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/FixedPointPreCompInfo.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/FixedPointPreCompInfo.cs deleted file mode 100644 index d54116575..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/FixedPointPreCompInfo.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Multiplier -{ - /** - * Class holding precomputation data for fixed-point multiplications. - */ - internal class FixedPointPreCompInfo - : PreCompInfo - { - protected ECPoint m_offset = null; - - /** - * Lookup table for the precomputed ECPoints used for a fixed point multiplication. - */ - protected ECLookupTable m_lookupTable = null; - - /** - * The width used for the precomputation. If a larger width precomputation - * is already available this may be larger than was requested, so calling - * code should refer to the actual width. - */ - protected int m_width = -1; - - public virtual ECLookupTable LookupTable - { - get { return m_lookupTable; } - set { this.m_lookupTable = value; } - } - - public virtual ECPoint Offset - { - get { return m_offset; } - set { this.m_offset = value; } - } - - public virtual int Width - { - get { return m_width; } - set { this.m_width = value; } - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/FixedPointUtilities.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/FixedPointUtilities.cs deleted file mode 100644 index 14dea10a7..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/FixedPointUtilities.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Multiplier -{ - internal class FixedPointUtilities - { - public static readonly string PRECOMP_NAME = "bc_fixed_point"; - - public static int GetCombSize(ECCurve c) - { - BigInteger order = c.Order; - return order == null ? c.FieldSize + 1 : order.BitLength; - } - - public static FixedPointPreCompInfo GetFixedPointPreCompInfo(PreCompInfo preCompInfo) - { - return preCompInfo as FixedPointPreCompInfo; - } - - public static FixedPointPreCompInfo Precompute(ECPoint p) - { - return (FixedPointPreCompInfo)p.Curve.Precompute(p, PRECOMP_NAME, new FixedPointCallback(p)); - } - - private class FixedPointCallback - : IPreCompCallback - { - private readonly ECPoint m_p; - - internal FixedPointCallback(ECPoint p) - { - this.m_p = p; - } - - public PreCompInfo Precompute(PreCompInfo existing) - { - FixedPointPreCompInfo existingFP = (existing is FixedPointPreCompInfo) ? (FixedPointPreCompInfo)existing : null; - - ECCurve c = m_p.Curve; - int bits = FixedPointUtilities.GetCombSize(c); - int minWidth = bits > 250 ? 6 : 5; - int n = 1 << minWidth; - - if (CheckExisting(existingFP, n)) - return existingFP; - - int d = (bits + minWidth - 1) / minWidth; - - ECPoint[] pow2Table = new ECPoint[minWidth + 1]; - pow2Table[0] = m_p; - for (int i = 1; i < minWidth; ++i) - { - pow2Table[i] = pow2Table[i - 1].TimesPow2(d); - } - - // This will be the 'offset' value - pow2Table[minWidth] = pow2Table[0].Subtract(pow2Table[1]); - - c.NormalizeAll(pow2Table); - - ECPoint[] lookupTable = new ECPoint[n]; - lookupTable[0] = pow2Table[0]; - - for (int bit = minWidth - 1; bit >= 0; --bit) - { - ECPoint pow2 = pow2Table[bit]; - - int step = 1 << bit; - for (int i = step; i < n; i += (step << 1)) - { - lookupTable[i] = lookupTable[i - step].Add(pow2); - } - } - - c.NormalizeAll(lookupTable); - - FixedPointPreCompInfo result = new FixedPointPreCompInfo(); - result.LookupTable = c.CreateCacheSafeLookupTable(lookupTable, 0, lookupTable.Length); - result.Offset = pow2Table[minWidth]; - result.Width = minWidth; - return result; - } - - private bool CheckExisting(FixedPointPreCompInfo existingFP, int n) - { - return existingFP != null && CheckTable(existingFP.LookupTable, n); - } - - private bool CheckTable(ECLookupTable table, int n) - { - return table != null && table.Size >= n; - } - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/GlvMultiplier.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/GlvMultiplier.cs deleted file mode 100644 index e255b3ee8..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/GlvMultiplier.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; - -using Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Endo; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Multiplier -{ - internal class GlvMultiplier - : AbstractECMultiplier - { - protected readonly ECCurve curve; - protected readonly GlvEndomorphism glvEndomorphism; - - public GlvMultiplier(ECCurve curve, GlvEndomorphism glvEndomorphism) - { - if (curve == null || curve.Order == null) - throw new ArgumentException("Need curve with known group order", "curve"); - - this.curve = curve; - this.glvEndomorphism = glvEndomorphism; - } - - protected override ECPoint MultiplyPositive(ECPoint p, BigInteger k) - { - if (!curve.Equals(p.Curve)) - throw new InvalidOperationException(); - - BigInteger n = p.Curve.Order; - 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(p, a, pointMap.Map(p), b); - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/IPreCompCallback.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/IPreCompCallback.cs deleted file mode 100644 index 871998899..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/IPreCompCallback.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Multiplier -{ - internal interface IPreCompCallback - { - PreCompInfo Precompute(PreCompInfo existing); - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/PreCompInfo.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/PreCompInfo.cs deleted file mode 100644 index 32c40216c..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/PreCompInfo.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Multiplier -{ - /** - * Interface for classes storing precomputation data for multiplication - * algorithms. Used as a Memento (see GOF patterns) for - * WNafMultiplier. - */ - internal interface PreCompInfo - { - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/ValidityPreCompInfo.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/ValidityPreCompInfo.cs deleted file mode 100644 index 78dabc26d..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/ValidityPreCompInfo.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Multiplier -{ - internal class ValidityPreCompInfo - : PreCompInfo - { - internal static readonly string PRECOMP_NAME = "bc_validity"; - - private bool failed = false; - private bool curveEquationPassed = false; - private bool orderPassed = false; - - internal bool HasFailed() - { - return failed; - } - - internal void ReportFailed() - { - failed = true; - } - - internal bool HasCurveEquationPassed() - { - return curveEquationPassed; - } - - internal void ReportCurveEquationPassed() - { - curveEquationPassed = true; - } - - internal bool HasOrderPassed() - { - return orderPassed; - } - - internal void ReportOrderPassed() - { - orderPassed = true; - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/WNafL2RMultiplier.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/WNafL2RMultiplier.cs deleted file mode 100644 index 043415661..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/WNafL2RMultiplier.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Multiplier -{ - /** - * Class implementing the WNAF (Window Non-Adjacent Form) multiplication - * algorithm. - */ - internal class WNafL2RMultiplier - : AbstractECMultiplier - { - /** - * Multiplies this by an integer k using the - * Window NAF method. - * @param k The integer by which this is multiplied. - * @return A new ECPoint which equals this - * multiplied by k. - */ - 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))); - - WNafPreCompInfo wnafPreCompInfo = WNafUtilities.Precompute(p, width, true); - ECPoint[] preComp = wnafPreCompInfo.PreComp; - ECPoint[] preCompNeg = wnafPreCompInfo.PreCompNeg; - - int[] wnaf = WNafUtilities.GenerateCompactWindowNaf(width, k); - - ECPoint R = p.Curve.Infinity; - - int i = wnaf.Length; - - /* - * NOTE: We try to optimize the first window using the precomputed points to substitute an - * addition for 2 or more doublings. - */ - if (i > 1) - { - int wi = wnaf[--i]; - int digit = wi >> 16, zeroes = wi & 0xFFFF; - - int n = System.Math.Abs(digit); - ECPoint[] table = digit < 0 ? preCompNeg : preComp; - - // Optimization can only be used for values in the lower half of the table - if ((n << 2) < (1 << width)) - { - int highest = LongArray.BitLengths[n]; - - // TODO Get addition/doubling cost ratio from curve and compare to 'scale' to see if worth substituting? - int scale = width - highest; - int lowBits = n ^ (1 << (highest - 1)); - - int i1 = ((1 << (width - 1)) - 1); - int i2 = (lowBits << scale) + 1; - R = table[i1 >> 1].Add(table[i2 >> 1]); - - zeroes -= scale; - - //Console.WriteLine("Optimized: 2^" + scale + " * " + n + " = " + i1 + " + " + i2); - } - else - { - R = table[n >> 1]; - } - - R = R.TimesPow2(zeroes); - } - - while (i > 0) - { - int wi = wnaf[--i]; - int digit = wi >> 16, zeroes = wi & 0xFFFF; - - int n = System.Math.Abs(digit); - ECPoint[] table = digit < 0 ? preCompNeg : preComp; - ECPoint r = table[n >> 1]; - - R = R.TwicePlus(r); - R = R.TimesPow2(zeroes); - } - - 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/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/WNafPreCompInfo.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/WNafPreCompInfo.cs deleted file mode 100644 index 91d56512f..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/WNafPreCompInfo.cs +++ /dev/null @@ -1,46 +0,0 @@ -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Multiplier -{ - /** - * Class holding precomputation data for the WNAF (Window Non-Adjacent Form) - * algorithm. - */ - internal class WNafPreCompInfo - : PreCompInfo - { - /** - * Array holding the precomputed ECPoints used for a Window - * NAF multiplication. - */ - protected ECPoint[] m_preComp = null; - - /** - * Array holding the negations of the precomputed ECPoints used - * for a Window NAF multiplication. - */ - protected ECPoint[] m_preCompNeg = null; - - /** - * Holds an ECPoint representing Twice(this). Used for the - * Window NAF multiplication to create or extend the precomputed values. - */ - protected ECPoint m_twice = null; - - public virtual ECPoint[] PreComp - { - get { return m_preComp; } - set { this.m_preComp = value; } - } - - public virtual ECPoint[] PreCompNeg - { - get { return m_preCompNeg; } - set { this.m_preCompNeg = value; } - } - - public virtual ECPoint Twice - { - get { return m_twice; } - set { this.m_twice = value; } - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/WNafUtilities.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/WNafUtilities.cs deleted file mode 100644 index 8dbe7ef73..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/WNafUtilities.cs +++ /dev/null @@ -1,579 +0,0 @@ -using System; - -using Renci.SshNet.Security.Org.BouncyCastle.Utilities; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Multiplier -{ - internal abstract class WNafUtilities - { - 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 ECPoint[] EMPTY_POINTS = new ECPoint[0]; - - public static int[] GenerateCompactNaf(BigInteger k) - { - if ((k.BitLength >> 16) != 0) - throw new ArgumentException("must have bitlength < 2^16", "k"); - if (k.SignValue == 0) - return Arrays.EmptyInts; - - BigInteger _3k = k.ShiftLeft(1).Add(k); - - int bits = _3k.BitLength; - int[] naf = new int[bits >> 1]; - - BigInteger diff = _3k.Xor(k); - - int highBit = bits - 1, length = 0, zeroes = 0; - for (int i = 1; i < highBit; ++i) - { - if (!diff.TestBit(i)) - { - ++zeroes; - continue; - } - - int digit = k.TestBit(i) ? -1 : 1; - naf[length++] = (digit << 16) | zeroes; - zeroes = 1; - ++i; - } - - naf[length++] = (1 << 16) | zeroes; - - if (naf.Length > length) - { - naf = Trim(naf, length); - } - - return naf; - } - - public static int[] GenerateCompactWindowNaf(int width, BigInteger k) - { - if (width == 2) - { - return GenerateCompactNaf(k); - } - - if (width < 2 || width > 16) - throw new ArgumentException("must be in the range [2, 16]", "width"); - if ((k.BitLength >> 16) != 0) - throw new ArgumentException("must have bitlength < 2^16", "k"); - if (k.SignValue == 0) - return Arrays.EmptyInts; - - int[] wnaf = new int[k.BitLength / width + 1]; - - // 2^width and a mask and sign bit set accordingly - int pow2 = 1 << width; - int mask = pow2 - 1; - int sign = pow2 >> 1; - - bool carry = false; - int length = 0, pos = 0; - - while (pos <= k.BitLength) - { - if (k.TestBit(pos) == carry) - { - ++pos; - continue; - } - - k = k.ShiftRight(pos); - - int digit = k.IntValue & mask; - if (carry) - { - ++digit; - } - - carry = (digit & sign) != 0; - if (carry) - { - digit -= pow2; - } - - int zeroes = length > 0 ? pos - 1 : pos; - wnaf[length++] = (digit << 16) | zeroes; - pos = width; - } - - // Reduce the WNAF array to its actual length - if (wnaf.Length > length) - { - wnaf = Trim(wnaf, length); - } - - return wnaf; - } - - public static byte[] GenerateJsf(BigInteger g, BigInteger h) - { - int digits = System.Math.Max(g.BitLength, h.BitLength) + 1; - byte[] jsf = new byte[digits]; - - BigInteger k0 = g, k1 = h; - int j = 0, d0 = 0, d1 = 0; - - int offset = 0; - while ((d0 | d1) != 0 || k0.BitLength > offset || k1.BitLength > offset) - { - int n0 = ((int)((uint)k0.IntValue >> offset) + d0) & 7; - int n1 = ((int)((uint)k1.IntValue >> offset) + d1) & 7; - - int u0 = n0 & 1; - if (u0 != 0) - { - u0 -= (n0 & 2); - if ((n0 + u0) == 4 && (n1 & 3) == 2) - { - u0 = -u0; - } - } - - int u1 = n1 & 1; - if (u1 != 0) - { - u1 -= (n1 & 2); - if ((n1 + u1) == 4 && (n0 & 3) == 2) - { - u1 = -u1; - } - } - - if ((d0 << 1) == 1 + u0) - { - d0 ^= 1; - } - if ((d1 << 1) == 1 + u1) - { - d1 ^= 1; - } - - if (++offset == 30) - { - offset = 0; - k0 = k0.ShiftRight(30); - k1 = k1.ShiftRight(30); - } - - jsf[j++] = (byte)((u0 << 4) | (u1 & 0xF)); - } - - // Reduce the JSF array to its actual length - if (jsf.Length > j) - { - jsf = Trim(jsf, j); - } - - return jsf; - } - - public static byte[] GenerateNaf(BigInteger k) - { - if (k.SignValue == 0) - return Arrays.EmptyBytes; - - BigInteger _3k = k.ShiftLeft(1).Add(k); - - int digits = _3k.BitLength - 1; - byte[] naf = new byte[digits]; - - BigInteger diff = _3k.Xor(k); - - for (int i = 1; i < digits; ++i) - { - if (diff.TestBit(i)) - { - naf[i - 1] = (byte)(k.TestBit(i) ? -1 : 1); - ++i; - } - } - - naf[digits - 1] = 1; - - return naf; - } - - /** - * Computes the Window NAF (non-adjacent Form) of an integer. - * @param width The width w of the Window NAF. The width is - * defined as the minimal number w, such that for any - * w consecutive digits in the resulting representation, at - * most one is non-zero. - * @param k The integer of which the Window NAF is computed. - * @return The Window NAF of the given width, such that the following holds: - * k = ∑i=0l-1 ki2i - * , where the ki denote the elements of the - * returned byte[]. - */ - public static byte[] GenerateWindowNaf(int width, BigInteger k) - { - if (width == 2) - { - return GenerateNaf(k); - } - - if (width < 2 || width > 8) - throw new ArgumentException("must be in the range [2, 8]", "width"); - if (k.SignValue == 0) - return Arrays.EmptyBytes; - - byte[] wnaf = new byte[k.BitLength + 1]; - - // 2^width and a mask and sign bit set accordingly - int pow2 = 1 << width; - int mask = pow2 - 1; - int sign = pow2 >> 1; - - bool carry = false; - int length = 0, pos = 0; - - while (pos <= k.BitLength) - { - if (k.TestBit(pos) == carry) - { - ++pos; - continue; - } - - k = k.ShiftRight(pos); - - int digit = k.IntValue & mask; - if (carry) - { - ++digit; - } - - carry = (digit & sign) != 0; - if (carry) - { - digit -= pow2; - } - - length += (length > 0) ? pos - 1 : pos; - wnaf[length++] = (byte)digit; - pos = width; - } - - // Reduce the WNAF array to its actual length - if (wnaf.Length > length) - { - wnaf = Trim(wnaf, length); - } - - return wnaf; - } - - public static int GetNafWeight(BigInteger k) - { - if (k.SignValue == 0) - return 0; - - BigInteger _3k = k.ShiftLeft(1).Add(k); - BigInteger diff = _3k.Xor(k); - - return diff.BitCount; - } - - public static WNafPreCompInfo GetWNafPreCompInfo(ECPoint p) - { - return GetWNafPreCompInfo(p.Curve.GetPreCompInfo(p, PRECOMP_NAME)); - } - - public static WNafPreCompInfo GetWNafPreCompInfo(PreCompInfo preCompInfo) - { - return preCompInfo as WNafPreCompInfo; - } - - /** - * 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 - */ - public static int GetWindowSize(int bits) - { - return GetWindowSize(bits, DEFAULT_WINDOW_SIZE_CUTOFFS); - } - - /** - * 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 - * @return the window size to use - */ - public static int GetWindowSize(int bits, int[] windowSizeCutoffs) - { - int w = 0; - for (; w < windowSizeCutoffs.Length; ++w) - { - if (bits < windowSizeCutoffs[w]) - { - break; - } - } - return w + 2; - } - - public static ECPoint MapPointWithPrecomp(ECPoint p, int width, bool includeNegated, - ECPointMap pointMap) - { - ECCurve c = p.Curve; - WNafPreCompInfo wnafPreCompP = Precompute(p, width, includeNegated); - - ECPoint q = pointMap.Map(p); - c.Precompute(q, PRECOMP_NAME, new MapPointCallback(wnafPreCompP, includeNegated, pointMap)); - return q; - } - - public static WNafPreCompInfo Precompute(ECPoint p, int width, bool includeNegated) - { - return (WNafPreCompInfo)p.Curve.Precompute(p, PRECOMP_NAME, new WNafCallback(p, width, includeNegated)); - } - - private static byte[] Trim(byte[] a, int length) - { - byte[] result = new byte[length]; - Array.Copy(a, 0, result, 0, result.Length); - return result; - } - - private static int[] Trim(int[] a, int length) - { - int[] result = new int[length]; - Array.Copy(a, 0, result, 0, result.Length); - return result; - } - - private static ECPoint[] ResizeTable(ECPoint[] a, int length) - { - ECPoint[] result = new ECPoint[length]; - Array.Copy(a, 0, result, 0, a.Length); - return result; - } - - private class MapPointCallback - : IPreCompCallback - { - private readonly WNafPreCompInfo m_wnafPreCompP; - private readonly bool m_includeNegated; - private readonly ECPointMap m_pointMap; - - internal MapPointCallback(WNafPreCompInfo wnafPreCompP, bool includeNegated, ECPointMap pointMap) - { - this.m_wnafPreCompP = wnafPreCompP; - this.m_includeNegated = includeNegated; - this.m_pointMap = pointMap; - } - - public PreCompInfo Precompute(PreCompInfo existing) - { - WNafPreCompInfo result = new WNafPreCompInfo(); - - ECPoint twiceP = m_wnafPreCompP.Twice; - if (twiceP != null) - { - ECPoint twiceQ = m_pointMap.Map(twiceP); - result.Twice = twiceQ; - } - - ECPoint[] preCompP = m_wnafPreCompP.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; - - if (m_includeNegated) - { - ECPoint[] preCompNegQ = new ECPoint[preCompQ.Length]; - for (int i = 0; i < preCompNegQ.Length; ++i) - { - preCompNegQ[i] = preCompQ[i].Negate(); - } - result.PreCompNeg = preCompNegQ; - } - - return result; - } - } - - private class WNafCallback - : IPreCompCallback - { - private readonly ECPoint m_p; - private readonly int m_width; - private readonly bool m_includeNegated; - - internal WNafCallback(ECPoint p, int width, bool includeNegated) - { - this.m_p = p; - this.m_width = width; - this.m_includeNegated = includeNegated; - } - - public PreCompInfo Precompute(PreCompInfo existing) - { - WNafPreCompInfo existingWNaf = existing as WNafPreCompInfo; - - int reqPreCompLen = 1 << System.Math.Max(0, m_width - 2); - - if (CheckExisting(existingWNaf, reqPreCompLen, m_includeNegated)) - return existingWNaf; - - ECCurve c = m_p.Curve; - ECPoint[] preComp = null, preCompNeg = null; - ECPoint twiceP = null; - - if (existingWNaf != null) - { - preComp = existingWNaf.PreComp; - preCompNeg = existingWNaf.PreCompNeg; - twiceP = existingWNaf.Twice; - } - - int iniPreCompLen = 0; - if (preComp == null) - { - preComp = EMPTY_POINTS; - } - else - { - iniPreCompLen = preComp.Length; - } - - if (iniPreCompLen < reqPreCompLen) - { - preComp = WNafUtilities.ResizeTable(preComp, reqPreCompLen); - - if (reqPreCompLen == 1) - { - preComp[0] = m_p.Normalize(); - } - else - { - int curPreCompLen = iniPreCompLen; - if (curPreCompLen == 0) - { - preComp[0] = m_p; - curPreCompLen = 1; - } - - ECFieldElement iso = null; - - if (reqPreCompLen == 2) - { - preComp[1] = m_p.ThreeTimes(); - } - else - { - ECPoint isoTwiceP = twiceP, last = preComp[curPreCompLen - 1]; - if (isoTwiceP == null) - { - isoTwiceP = preComp[0].Twice(); - twiceP = isoTwiceP; - - /* - * For Fp curves with Jacobian projective coordinates, use a (quasi-)isomorphism - * where 'twiceP' is "affine", so that the subsequent additions are cheaper. This - * also requires scaling the initial point's X, Y coordinates, and reversing the - * isomorphism as part of the subsequent normalization. - * - * NOTE: The correctness of this optimization depends on: - * 1) additions do not use the curve's A, B coefficients. - * 2) no special cases (i.e. Q +/- Q) when calculating 1P, 3P, 5P, ... - */ - if (!twiceP.IsInfinity && ECAlgorithms.IsFpCurve(c) && c.FieldSize >= 64) - { - switch (c.CoordinateSystem) - { - case ECCurve.COORD_JACOBIAN: - case ECCurve.COORD_JACOBIAN_CHUDNOVSKY: - case ECCurve.COORD_JACOBIAN_MODIFIED: - { - iso = twiceP.GetZCoord(0); - isoTwiceP = c.CreatePoint(twiceP.XCoord.ToBigInteger(), - twiceP.YCoord.ToBigInteger()); - - ECFieldElement iso2 = iso.Square(), iso3 = iso2.Multiply(iso); - last = last.ScaleX(iso2).ScaleY(iso3); - - if (iniPreCompLen == 0) - { - preComp[0] = last; - } - break; - } - } - } - } - - while (curPreCompLen < reqPreCompLen) - { - /* - * Compute the new ECPoints for the precomputation array. The values 1, 3, - * 5, ..., 2^(width-1)-1 times p are computed - */ - preComp[curPreCompLen++] = last = last.Add(isoTwiceP); - } - } - - /* - * Having oft-used operands in affine form makes operations faster. - */ - c.NormalizeAll(preComp, iniPreCompLen, reqPreCompLen - iniPreCompLen, iso); - } - } - - if (m_includeNegated) - { - int pos; - if (preCompNeg == null) - { - pos = 0; - preCompNeg = new ECPoint[reqPreCompLen]; - } - else - { - pos = preCompNeg.Length; - if (pos < reqPreCompLen) - { - preCompNeg = WNafUtilities.ResizeTable(preCompNeg, reqPreCompLen); - } - } - - while (pos < reqPreCompLen) - { - preCompNeg[pos] = preComp[pos].Negate(); - ++pos; - } - } - - WNafPreCompInfo result = new WNafPreCompInfo(); - result.PreComp = preComp; - result.PreCompNeg = preCompNeg; - result.Twice = twiceP; - return result; - } - - private bool CheckExisting(WNafPreCompInfo existingWNaf, int reqPreCompLen, bool includeNegated) - { - return existingWNaf != null - && CheckTable(existingWNaf.PreComp, reqPreCompLen) - && (!includeNegated || CheckTable(existingWNaf.PreCompNeg, reqPreCompLen)); - } - - private bool CheckTable(ECPoint[] table, int reqLen) - { - return table != null && table.Length >= reqLen; - } - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/WTauNafMultiplier.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/WTauNafMultiplier.cs deleted file mode 100644 index 1d19bdb6e..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/WTauNafMultiplier.cs +++ /dev/null @@ -1,138 +0,0 @@ -using System; - -using Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Abc; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Multiplier -{ - /** - * Class implementing the WTNAF (Window - * τ-adic Non-Adjacent Form) algorithm. - */ - internal class WTauNafMultiplier - : AbstractECMultiplier - { - // TODO Create WTauNafUtilities class and move various functionality into it - internal static readonly string PRECOMP_NAME = "bc_wtnaf"; - - /** - * Multiplies a {@link org.bouncycastle.math.ec.AbstractF2mPoint AbstractF2mPoint} - * by k using the reduced τ-adic NAF (RTNAF) - * method. - * @param p The AbstractF2mPoint to multiply. - * @param k The integer by which to multiply k. - * @return p multiplied by k. - */ - protected override ECPoint MultiplyPositive(ECPoint point, BigInteger k) - { - if (!(point is AbstractF2mPoint)) - throw new ArgumentException("Only AbstractF2mPoint can be used in WTauNafMultiplier"); - - AbstractF2mPoint p = (AbstractF2mPoint)point; - AbstractF2mCurve curve = (AbstractF2mCurve)p.Curve; - int m = curve.FieldSize; - sbyte a = (sbyte)curve.A.ToBigInteger().IntValue; - sbyte mu = Tnaf.GetMu(a); - BigInteger[] s = curve.GetSi(); - - ZTauElement rho = Tnaf.PartModReduction(k, m, a, s, mu, (sbyte)10); - - return MultiplyWTnaf(p, rho, a, mu); - } - - /** - * Multiplies a {@link org.bouncycastle.math.ec.AbstractF2mPoint AbstractF2mPoint} - * by an element λ of Z[τ] using - * the τ-adic NAF (TNAF) method. - * @param p The AbstractF2mPoint to multiply. - * @param lambda The element λ of - * Z[τ] of which to compute the - * [τ]-adic NAF. - * @return p multiplied by λ. - */ - private AbstractF2mPoint MultiplyWTnaf(AbstractF2mPoint p, ZTauElement lambda, - sbyte a, sbyte mu) - { - ZTauElement[] alpha = (a == 0) ? Tnaf.Alpha0 : Tnaf.Alpha1; - - BigInteger tw = Tnaf.GetTw(mu, Tnaf.Width); - - sbyte[]u = Tnaf.TauAdicWNaf(mu, lambda, Tnaf.Width, - BigInteger.ValueOf(Tnaf.Pow2Width), tw, alpha); - - return MultiplyFromWTnaf(p, u); - } - - /** - * Multiplies a {@link org.bouncycastle.math.ec.AbstractF2mPoint AbstractF2mPoint} - * by an element λ of Z[τ] - * using the window τ-adic NAF (TNAF) method, given the - * WTNAF of λ. - * @param p The AbstractF2mPoint to multiply. - * @param u The the WTNAF of λ.. - * @return λ * p - */ - private static AbstractF2mPoint MultiplyFromWTnaf(AbstractF2mPoint p, sbyte[] u) - { - AbstractF2mCurve curve = (AbstractF2mCurve)p.Curve; - sbyte a = (sbyte)curve.A.ToBigInteger().IntValue; - - WTauNafCallback callback = new WTauNafCallback(p, a); - WTauNafPreCompInfo preCompInfo = (WTauNafPreCompInfo)curve.Precompute(p, PRECOMP_NAME, callback); - AbstractF2mPoint[] pu = preCompInfo.PreComp; - - // TODO Include negations in precomp (optionally) and use from here - AbstractF2mPoint[] puNeg = new AbstractF2mPoint[pu.Length]; - for (int i = 0; i < pu.Length; ++i) - { - puNeg[i] = (AbstractF2mPoint)pu[i].Negate(); - } - - - // q = infinity - AbstractF2mPoint q = (AbstractF2mPoint) p.Curve.Infinity; - - int tauCount = 0; - for (int i = u.Length - 1; i >= 0; i--) - { - ++tauCount; - int ui = u[i]; - if (ui != 0) - { - q = q.TauPow(tauCount); - tauCount = 0; - - ECPoint x = ui > 0 ? pu[ui >> 1] : puNeg[(-ui) >> 1]; - q = (AbstractF2mPoint)q.Add(x); - } - } - if (tauCount > 0) - { - q = q.TauPow(tauCount); - } - return q; - } - - private class WTauNafCallback - : IPreCompCallback - { - private readonly AbstractF2mPoint m_p; - private readonly sbyte m_a; - - internal WTauNafCallback(AbstractF2mPoint p, sbyte a) - { - this.m_p = p; - this.m_a = a; - } - - public PreCompInfo Precompute(PreCompInfo existing) - { - if (existing is WTauNafPreCompInfo) - return existing; - - WTauNafPreCompInfo result = new WTauNafPreCompInfo(); - result.PreComp = Tnaf.GetPreComp(m_p, m_a); - return result; - } - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/WTauNafPreCompInfo.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/WTauNafPreCompInfo.cs deleted file mode 100644 index f0a6f489d..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/multiplier/WTauNafPreCompInfo.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Multiplier -{ - /** - * Class holding precomputation data for the WTNAF (Window - * τ-adic Non-Adjacent Form) algorithm. - */ - internal class WTauNafPreCompInfo - : PreCompInfo - { - /** - * Array holding the precomputed AbstractF2mPoints used for the - * WTNAF multiplication in - * {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply() - * WTauNafMultiplier.multiply()}. - */ - protected AbstractF2mPoint[] m_preComp; - - public virtual AbstractF2mPoint[] PreComp - { - get { return m_preComp; } - set { this.m_preComp = value; } - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/field/FiniteFields.cs b/src/Renci.SshNet/Security/BouncyCastle/math/field/FiniteFields.cs deleted file mode 100644 index 77533c761..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/field/FiniteFields.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.Field -{ - internal abstract class FiniteFields - { - internal static readonly IFiniteField GF_2 = new PrimeField(BigInteger.ValueOf(2)); - internal static readonly IFiniteField GF_3 = new PrimeField(BigInteger.ValueOf(3)); - - public static IPolynomialExtensionField GetBinaryExtensionField(int[] exponents) - { - if (exponents[0] != 0) - { - throw new ArgumentException("Irreducible polynomials in GF(2) must have constant term", "exponents"); - } - for (int i = 1; i < exponents.Length; ++i) - { - if (exponents[i] <= exponents[i - 1]) - { - throw new ArgumentException("Polynomial exponents must be montonically increasing", "exponents"); - } - } - - return new GenericPolynomialExtensionField(GF_2, new GF2Polynomial(exponents)); - } - - // public static IPolynomialExtensionField GetTernaryExtensionField(Term[] terms) - // { - // return new GenericPolynomialExtensionField(GF_3, new GF3Polynomial(terms)); - // } - - public static IFiniteField GetPrimeField(BigInteger characteristic) - { - int bitLength = characteristic.BitLength; - if (characteristic.SignValue <= 0 || bitLength < 2) - { - throw new ArgumentException("Must be >= 2", "characteristic"); - } - - if (bitLength < 3) - { - switch (characteristic.IntValue) - { - case 2: - return GF_2; - case 3: - return GF_3; - } - } - - return new PrimeField(characteristic); - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/field/GF2Polynomial.cs b/src/Renci.SshNet/Security/BouncyCastle/math/field/GF2Polynomial.cs deleted file mode 100644 index a7c916db6..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/field/GF2Polynomial.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; - -using Renci.SshNet.Security.Org.BouncyCastle.Utilities; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.Field -{ - internal class GF2Polynomial - : IPolynomial - { - protected readonly int[] exponents; - - internal GF2Polynomial(int[] exponents) - { - this.exponents = Arrays.Clone(exponents); - } - - public virtual int Degree - { - get { return exponents[exponents.Length - 1]; } - } - - public virtual int[] GetExponentsPresent() - { - return Arrays.Clone(exponents); - } - - public override bool Equals(object obj) - { - if (this == obj) - { - return true; - } - GF2Polynomial other = obj as GF2Polynomial; - if (null == other) - { - return false; - } - return Arrays.AreEqual(exponents, other.exponents); - } - - public override int GetHashCode() - { - return Arrays.GetHashCode(exponents); - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/field/GenericPolynomialExtensionField.cs b/src/Renci.SshNet/Security/BouncyCastle/math/field/GenericPolynomialExtensionField.cs deleted file mode 100644 index 29b4f57d8..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/field/GenericPolynomialExtensionField.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; - -using Renci.SshNet.Security.Org.BouncyCastle.Utilities; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.Field -{ - internal class GenericPolynomialExtensionField - : IPolynomialExtensionField - { - protected readonly IFiniteField subfield; - protected readonly IPolynomial minimalPolynomial; - - internal GenericPolynomialExtensionField(IFiniteField subfield, IPolynomial polynomial) - { - this.subfield = subfield; - this.minimalPolynomial = polynomial; - } - - public virtual BigInteger Characteristic - { - get { return subfield.Characteristic; } - } - - public virtual int Dimension - { - get { return subfield.Dimension * minimalPolynomial.Degree; } - } - - public virtual IFiniteField Subfield - { - get { return subfield; } - } - - public virtual int Degree - { - get { return minimalPolynomial.Degree; } - } - - public virtual IPolynomial MinimalPolynomial - { - get { return minimalPolynomial; } - } - - public override bool Equals(object obj) - { - if (this == obj) - { - return true; - } - GenericPolynomialExtensionField other = obj as GenericPolynomialExtensionField; - if (null == other) - { - return false; - } - return subfield.Equals(other.subfield) && minimalPolynomial.Equals(other.minimalPolynomial); - } - - public override int GetHashCode() - { - return subfield.GetHashCode() ^ Integers.RotateLeft(minimalPolynomial.GetHashCode(), 16); - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/field/IExtensionField.cs b/src/Renci.SshNet/Security/BouncyCastle/math/field/IExtensionField.cs deleted file mode 100644 index 242bcd00c..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/field/IExtensionField.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.Field -{ - internal interface IExtensionField - : IFiniteField - { - IFiniteField Subfield { get; } - - int Degree { get; } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/field/IFiniteField.cs b/src/Renci.SshNet/Security/BouncyCastle/math/field/IFiniteField.cs deleted file mode 100644 index fa6b6fca1..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/field/IFiniteField.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.Field -{ - internal interface IFiniteField - { - BigInteger Characteristic { get; } - - int Dimension { get; } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/field/IPolynomial.cs b/src/Renci.SshNet/Security/BouncyCastle/math/field/IPolynomial.cs deleted file mode 100644 index 06a61663c..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/field/IPolynomial.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.Field -{ - internal interface IPolynomial - { - int Degree { get; } - - //BigInteger[] GetCoefficients(); - - int[] GetExponentsPresent(); - - //Term[] GetNonZeroTerms(); - } -} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/field/IPolynomialExtensionField.cs b/src/Renci.SshNet/Security/BouncyCastle/math/field/IPolynomialExtensionField.cs deleted file mode 100644 index a419bec83..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/field/IPolynomialExtensionField.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.Field -{ - internal interface IPolynomialExtensionField - : IExtensionField - { - IPolynomial MinimalPolynomial { get; } - } -} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/field/PrimeField.cs b/src/Renci.SshNet/Security/BouncyCastle/math/field/PrimeField.cs deleted file mode 100644 index c0651e147..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/field/PrimeField.cs +++ /dev/null @@ -1,42 +0,0 @@ -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.Field -{ - internal class PrimeField - : IFiniteField - { - protected readonly BigInteger characteristic; - - internal PrimeField(BigInteger characteristic) - { - this.characteristic = characteristic; - } - - public virtual BigInteger Characteristic - { - get { return characteristic; } - } - - public virtual int Dimension - { - get { return 1; } - } - - public override bool Equals(object obj) - { - if (this == obj) - { - return true; - } - PrimeField other = obj as PrimeField; - if (null == other) - { - return false; - } - return characteristic.Equals(other.characteristic); - } - - public override int GetHashCode() - { - return characteristic.GetHashCode(); - } - } -} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/raw/Mod.cs b/src/Renci.SshNet/Security/BouncyCastle/math/raw/Mod.cs deleted file mode 100644 index 1fa6b6da1..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/raw/Mod.cs +++ /dev/null @@ -1,185 +0,0 @@ -using System; -using System.Diagnostics; - -using Renci.SshNet.Security.Org.BouncyCastle.Crypto.Utilities; -using Renci.SshNet.Security.Org.BouncyCastle.Security; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.Raw -{ - internal abstract class Mod - { - private static readonly SecureRandom RandomSource = new SecureRandom(); - - public static void Invert(uint[] p, uint[] x, uint[] z) - { - int len = p.Length; - if (Nat.IsZero(len, x)) - throw new ArgumentException("cannot be 0", "x"); - if (Nat.IsOne(len, x)) - { - Array.Copy(x, 0, z, 0, len); - return; - } - - uint[] u = Nat.Copy(len, x); - uint[] a = Nat.Create(len); - a[0] = 1; - int ac = 0; - - if ((u[0] & 1) == 0) - { - InversionStep(p, u, len, a, ref ac); - } - if (Nat.IsOne(len, u)) - { - InversionResult(p, ac, a, z); - return; - } - - uint[] v = Nat.Copy(len, p); - uint[] b = Nat.Create(len); - int bc = 0; - - int uvLen = len; - - for (;;) - { - while (u[uvLen - 1] == 0 && v[uvLen - 1] == 0) - { - --uvLen; - } - - if (Nat.Gte(len, u, v)) - { - Nat.SubFrom(len, v, u); - Debug.Assert((u[0] & 1) == 0); - ac += Nat.SubFrom(len, b, a) - bc; - InversionStep(p, u, uvLen, a, ref ac); - if (Nat.IsOne(len, u)) - { - InversionResult(p, ac, a, z); - return; - } - } - else - { - Nat.SubFrom(len, u, v); - Debug.Assert((v[0] & 1) == 0); - bc += Nat.SubFrom(len, a, b) - ac; - InversionStep(p, v, uvLen, b, ref bc); - if (Nat.IsOne(len, v)) - { - InversionResult(p, bc, b, z); - return; - } - } - } - } - - public static uint[] Random(uint[] p) - { - int len = p.Length; - uint[] s = Nat.Create(len); - - uint m = p[len - 1]; - m |= m >> 1; - m |= m >> 2; - m |= m >> 4; - m |= m >> 8; - m |= m >> 16; - - do - { - byte[] bytes = new byte[len << 2]; - RandomSource.NextBytes(bytes); - Pack.BE_To_UInt32(bytes, 0, s); - s[len - 1] &= m; - } - while (Nat.Gte(len, s, p)); - - return s; - } - - public static void Add(uint[] p, uint[] x, uint[] y, uint[] z) - { - int len = p.Length; - uint c = Nat.Add(len, x, y, z); - if (c != 0) - { - Nat.SubFrom(len, p, z); - } - } - - public static void Subtract(uint[] p, uint[] x, uint[] y, uint[] z) - { - int len = p.Length; - int c = Nat.Sub(len, x, y, z); - if (c != 0) - { - Nat.AddTo(len, p, z); - } - } - - private static void InversionResult(uint[] p, int ac, uint[] a, uint[] z) - { - if (ac < 0) - { - Nat.Add(p.Length, a, p, z); - } - else - { - Array.Copy(a, 0, z, 0, p.Length); - } - } - - private static void InversionStep(uint[] p, uint[] u, int uLen, uint[] x, ref int xc) - { - int len = p.Length; - int count = 0; - while (u[0] == 0) - { - Nat.ShiftDownWord(uLen, u, 0); - count += 32; - } - - { - int zeroes = GetTrailingZeroes(u[0]); - if (zeroes > 0) - { - Nat.ShiftDownBits(uLen, u, zeroes, 0); - count += zeroes; - } - } - - for (int i = 0; i < count; ++i) - { - if ((x[0] & 1) != 0) - { - if (xc < 0) - { - xc += (int)Nat.AddTo(len, p, x); - } - else - { - xc += Nat.SubFrom(len, p, x); - } - } - - Debug.Assert(xc == 0 || xc == -1); - Nat.ShiftDownBit(len, x, (uint)xc); - } - } - - private static int GetTrailingZeroes(uint x) - { - Debug.Assert(x != 0); - int count = 0; - while ((x & 1) == 0) - { - x >>= 1; - ++count; - } - return count; - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/raw/Nat.cs b/src/Renci.SshNet/Security/BouncyCastle/math/raw/Nat.cs deleted file mode 100644 index 710c2497a..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/math/raw/Nat.cs +++ /dev/null @@ -1,1153 +0,0 @@ -using System; -using System.Diagnostics; - -using Renci.SshNet.Security.Org.BouncyCastle.Crypto.Utilities; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Math.Raw -{ - internal abstract class Nat - { - private const ulong M = 0xFFFFFFFFUL; - - public static uint Add(int len, uint[] x, uint[] y, uint[] z) - { - ulong c = 0; - for (int i = 0; i < len; ++i) - { - c += (ulong)x[i] + y[i]; - z[i] = (uint)c; - c >>= 32; - } - return (uint)c; - } - - public static uint Add33At(int len, uint x, uint[] z, int zPos) - { - Debug.Assert(zPos <= (len - 2)); - ulong c = (ulong)z[zPos + 0] + x; - z[zPos + 0] = (uint)c; - c >>= 32; - c += (ulong)z[zPos + 1] + 1; - z[zPos + 1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, zPos + 2); - } - - public static uint Add33At(int len, uint x, uint[] z, int zOff, int zPos) - { - Debug.Assert(zPos <= (len - 2)); - ulong c = (ulong)z[zOff + zPos] + x; - z[zOff + zPos] = (uint)c; - c >>= 32; - c += (ulong)z[zOff + zPos + 1] + 1; - z[zOff + zPos + 1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, zOff, zPos + 2); - } - - public static uint Add33To(int len, uint x, uint[] z) - { - ulong c = (ulong)z[0] + x; - z[0] = (uint)c; - c >>= 32; - c += (ulong)z[1] + 1; - z[1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, 2); - } - - public static uint Add33To(int len, uint x, uint[] z, int zOff) - { - ulong c = (ulong)z[zOff + 0] + x; - z[zOff + 0] = (uint)c; - c >>= 32; - c += (ulong)z[zOff + 1] + 1; - z[zOff + 1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, zOff, 2); - } - - public static uint AddBothTo(int len, uint[] x, uint[] y, uint[] z) - { - ulong c = 0; - for (int i = 0; i < len; ++i) - { - c += (ulong)x[i] + y[i] + z[i]; - z[i] = (uint)c; - c >>= 32; - } - return (uint)c; - } - - public static uint AddBothTo(int len, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) - { - ulong c = 0; - for (int i = 0; i < len; ++i) - { - c += (ulong)x[xOff + i] + y[yOff + i] + z[zOff + i]; - z[zOff + i] = (uint)c; - c >>= 32; - } - return (uint)c; - } - - public static uint AddDWordAt(int len, ulong x, uint[] z, int zPos) - { - Debug.Assert(zPos <= (len - 2)); - ulong c = (ulong)z[zPos + 0] + (x & M); - z[zPos + 0] = (uint)c; - c >>= 32; - c += (ulong)z[zPos + 1] + (x >> 32); - z[zPos + 1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, zPos + 2); - } - - public static uint AddDWordAt(int len, ulong x, uint[] z, int zOff, int zPos) - { - Debug.Assert(zPos <= (len - 2)); - ulong c = (ulong)z[zOff + zPos] + (x & M); - z[zOff + zPos] = (uint)c; - c >>= 32; - c += (ulong)z[zOff + zPos + 1] + (x >> 32); - z[zOff + zPos + 1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, zOff, zPos + 2); - } - - public static uint AddDWordTo(int len, ulong x, uint[] z) - { - ulong c = (ulong)z[0] + (x & M); - z[0] = (uint)c; - c >>= 32; - c += (ulong)z[1] + (x >> 32); - z[1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, 2); - } - - public static uint AddDWordTo(int len, ulong x, uint[] z, int zOff) - { - ulong c = (ulong)z[zOff + 0] + (x & M); - z[zOff + 0] = (uint)c; - c >>= 32; - c += (ulong)z[zOff + 1] + (x >> 32); - z[zOff + 1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, zOff, 2); - } - - public static uint AddTo(int len, uint[] x, uint[] z) - { - ulong c = 0; - for (int i = 0; i < len; ++i) - { - c += (ulong)x[i] + z[i]; - z[i] = (uint)c; - c >>= 32; - } - return (uint)c; - } - - public static uint AddTo(int len, uint[] x, int xOff, uint[] z, int zOff) - { - ulong c = 0; - 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 AddWordAt(int len, uint x, uint[] z, int zPos) - { - Debug.Assert(zPos <= (len - 1)); - ulong c = (ulong)x + z[zPos]; - z[zPos] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, zPos + 1); - } - - public static uint AddWordAt(int len, uint x, uint[] z, int zOff, int zPos) - { - Debug.Assert(zPos <= (len - 1)); - ulong c = (ulong)x + z[zOff + zPos]; - z[zOff + zPos] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, zOff, zPos + 1); - } - - public static uint AddWordTo(int len, uint x, uint[] z) - { - ulong c = (ulong)x + z[0]; - z[0] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, 1); - } - - public static uint AddWordTo(int len, uint x, uint[] z, int zOff) - { - ulong c = (ulong)x + z[zOff]; - z[zOff] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, zOff, 1); - } - - public static uint CAdd(int len, int mask, uint[] x, uint[] y, uint[] z) - { - uint MASK = (uint)-(mask & 1); - - ulong c = 0; - for (int i = 0; i < len; ++i) - { - c += (ulong)x[i] + (y[i] & MASK); - z[i] = (uint)c; - c >>= 32; - } - return (uint)c; - } - - public static void CMov(int len, int mask, uint[] x, int xOff, uint[] z, int zOff) - { - uint MASK = (uint)-(mask & 1); - - for (int i = 0; i < len; ++i) - { - uint z_i = z[zOff + i], diff = z_i ^ x[xOff + i]; - z_i ^= (diff & MASK); - z[zOff + i] = z_i; - } - - //uint half = 0x55555555U, rest = half << (-(int)MASK); - - //for (int i = 0; i < len; ++i) - //{ - // uint z_i = z[zOff + i], diff = z_i ^ x[xOff + i]; - // z_i ^= (diff & half); - // z_i ^= (diff & rest); - // z[zOff + i] = z_i; - //} - } - - public static void CMov(int len, int mask, int[] x, int xOff, int[] z, int zOff) - { - mask = -(mask & 1); - - for (int i = 0; i < len; ++i) - { - int z_i = z[zOff + i], diff = z_i ^ x[xOff + i]; - z_i ^= (diff & mask); - z[zOff + i] = z_i; - } - - //int half = 0x55555555, rest = half << (-mask); - - //for (int i = 0; i < len; ++i) - //{ - // int z_i = z[zOff + i], diff = z_i ^ x[xOff + i]; - // z_i ^= (diff & half); - // z_i ^= (diff & rest); - // z[zOff + i] = z_i; - //} - } - - public static void Copy(int len, uint[] x, uint[] z) - { - Array.Copy(x, 0, z, 0, len); - } - - public static uint[] Copy(int len, uint[] x) - { - uint[] z = new uint[len]; - Array.Copy(x, 0, z, 0, len); - return z; - } - - public static void Copy(int len, uint[] x, int xOff, uint[] z, int zOff) - { - Array.Copy(x, xOff, z, zOff, len); - } - - public static uint[] Create(int len) - { - return new uint[len]; - } - - public static ulong[] Create64(int len) - { - return new ulong[len]; - } - - public static int Dec(int len, uint[] z) - { - for (int i = 0; i < len; ++i) - { - if (--z[i] != uint.MaxValue) - { - return 0; - } - } - return -1; - } - - public static int Dec(int len, uint[] x, uint[] z) - { - int i = 0; - while (i < len) - { - uint c = x[i] - 1; - z[i] = c; - ++i; - if (c != uint.MaxValue) - { - while (i < len) - { - z[i] = x[i]; - ++i; - } - return 0; - } - } - return -1; - } - - public static int DecAt(int len, uint[] z, int zPos) - { - Debug.Assert(zPos <= len); - for (int i = zPos; i < len; ++i) - { - if (--z[i] != uint.MaxValue) - { - return 0; - } - } - return -1; - } - - public static int DecAt(int len, uint[] z, int zOff, int zPos) - { - Debug.Assert(zPos <= len); - for (int i = zPos; i < len; ++i) - { - if (--z[zOff + i] != uint.MaxValue) - { - return 0; - } - } - return -1; - } - - public static bool Eq(int len, uint[] x, uint[] y) - { - for (int i = len - 1; i >= 0; --i) - { - if (x[i] != y[i]) - { - return false; - } - } - return true; - } - - public static uint[] FromBigInteger(int bits, BigInteger x) - { - if (x.SignValue < 0 || x.BitLength > bits) - throw new ArgumentException(); - - int len = (bits + 31) >> 5; - uint[] z = Create(len); - int i = 0; - while (x.SignValue != 0) - { - z[i++] = (uint)x.IntValue; - x = x.ShiftRight(32); - } - return z; - } - - public static uint GetBit(uint[] x, int bit) - { - if (bit == 0) - { - return x[0] & 1; - } - int w = bit >> 5; - if (w < 0 || w >= x.Length) - { - return 0; - } - int b = bit & 31; - return (x[w] >> b) & 1; - } - - public static bool Gte(int len, uint[] x, uint[] y) - { - for (int i = len - 1; i >= 0; --i) - { - uint x_i = x[i], y_i = y[i]; - if (x_i < y_i) - return false; - if (x_i > y_i) - return true; - } - return true; - } - - public static uint Inc(int len, uint[] z) - { - for (int i = 0; i < len; ++i) - { - if (++z[i] != uint.MinValue) - { - return 0; - } - } - return 1; - } - - public static uint Inc(int len, uint[] x, uint[] z) - { - int i = 0; - while (i < len) - { - uint c = x[i] + 1; - z[i] = c; - ++i; - if (c != 0) - { - while (i < len) - { - z[i] = x[i]; - ++i; - } - return 0; - } - } - return 1; - } - - public static uint IncAt(int len, uint[] z, int zPos) - { - Debug.Assert(zPos <= len); - for (int i = zPos; i < len; ++i) - { - if (++z[i] != uint.MinValue) - { - return 0; - } - } - return 1; - } - - public static uint IncAt(int len, uint[] z, int zOff, int zPos) - { - Debug.Assert(zPos <= len); - for (int i = zPos; i < len; ++i) - { - if (++z[zOff + i] != uint.MinValue) - { - return 0; - } - } - return 1; - } - - public static bool IsOne(int len, uint[] x) - { - if (x[0] != 1) - { - return false; - } - for (int i = 1; i < len; ++i) - { - if (x[i] != 0) - { - return false; - } - } - return true; - } - - public static bool IsZero(int len, uint[] x) - { - if (x[0] != 0) - { - return false; - } - for (int i = 1; i < len; ++i) - { - if (x[i] != 0) - { - return false; - } - } - return true; - } - - public static void Mul(int len, uint[] x, uint[] y, uint[] zz) - { - zz[len] = MulWord(len, x[0], y, zz); - - for (int i = 1; i < len; ++i) - { - zz[i + len] = MulWordAddTo(len, x[i], y, 0, zz, i); - } - } - - public static void Mul(int len, uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff) - { - zz[zzOff + len] = MulWord(len, x[xOff], y, yOff, zz, zzOff); - - for (int i = 1; i < len; ++i) - { - zz[zzOff + i + len] = MulWordAddTo(len, x[xOff + i], y, yOff, zz, zzOff + i); - } - } - - public static void Mul(uint[] x, int xOff, int xLen, uint[] y, int yOff, int yLen, uint[] zz, int zzOff) - { - zz[zzOff + yLen] = MulWord(yLen, x[xOff], y, yOff, zz, zzOff); - - for (int i = 1; i < xLen; ++i) - { - zz[zzOff + i + yLen] = MulWordAddTo(yLen, x[xOff + i], y, yOff, zz, zzOff + i); - } - } - - public static uint MulAddTo(int len, uint[] x, uint[] y, uint[] zz) - { - 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; - } - return (uint)zc; - } - - public static uint MulAddTo(int len, uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff) - { - 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; - ++zzOff; - } - return (uint)zc; - } - - public static uint Mul31BothAdd(int len, uint a, uint[] x, uint b, uint[] y, uint[] z, int zOff) - { - ulong c = 0, aVal = (ulong)a, bVal = (ulong)b; - int i = 0; - do - { - c += aVal * x[i] + bVal * y[i] + z[zOff + i]; - z[zOff + i] = (uint)c; - c >>= 32; - } - while (++i < len); - return (uint)c; - } - - public static uint MulWord(int len, uint x, uint[] y, uint[] z) - { - ulong c = 0, xVal = (ulong)x; - int i = 0; - do - { - c += xVal * y[i]; - z[i] = (uint)c; - c >>= 32; - } - while (++i < len); - return (uint)c; - } - - public static uint MulWord(int len, uint x, uint[] y, int yOff, uint[] z, int zOff) - { - ulong c = 0, xVal = (ulong)x; - int i = 0; - do - { - c += xVal * y[yOff + i]; - z[zOff + i] = (uint)c; - c >>= 32; - } - while (++i < len); - return (uint)c; - } - - public static uint MulWordAddTo(int len, uint x, uint[] y, int yOff, uint[] z, int zOff) - { - ulong c = 0, xVal = (ulong)x; - int i = 0; - do - { - c += xVal * y[yOff + i] + z[zOff + i]; - z[zOff + i] = (uint)c; - c >>= 32; - } - while (++i < len); - return (uint)c; - } - - public static uint MulWordDwordAddAt(int len, uint x, ulong y, uint[] z, int zPos) - { - Debug.Assert(zPos <= (len - 3)); - ulong c = 0, xVal = (ulong)x; - c += xVal * (uint)y + z[zPos + 0]; - z[zPos + 0] = (uint)c; - c >>= 32; - c += xVal * (y >> 32) + z[zPos + 1]; - z[zPos + 1] = (uint)c; - c >>= 32; - c += (ulong)z[zPos + 2]; - z[zPos + 2] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, zPos + 3); - } - - public static uint ShiftDownBit(int len, uint[] z, uint c) - { - int i = len; - while (--i >= 0) - { - uint next = z[i]; - z[i] = (next >> 1) | (c << 31); - c = next; - } - return c << 31; - } - - public static uint ShiftDownBit(int len, uint[] z, int zOff, uint c) - { - int i = len; - while (--i >= 0) - { - uint next = z[zOff + i]; - z[zOff + i] = (next >> 1) | (c << 31); - c = next; - } - return c << 31; - } - - public static uint ShiftDownBit(int len, uint[] x, uint c, uint[] z) - { - int i = len; - while (--i >= 0) - { - uint next = x[i]; - z[i] = (next >> 1) | (c << 31); - c = next; - } - return c << 31; - } - - public static uint ShiftDownBit(int len, uint[] x, int xOff, uint c, uint[] z, int zOff) - { - int i = len; - while (--i >= 0) - { - uint next = x[xOff + i]; - z[zOff + i] = (next >> 1) | (c << 31); - c = next; - } - return c << 31; - } - - public static uint ShiftDownBits(int len, uint[] z, int bits, uint c) - { - Debug.Assert(bits > 0 && bits < 32); - int i = len; - while (--i >= 0) - { - uint next = z[i]; - z[i] = (next >> bits) | (c << -bits); - c = next; - } - return c << -bits; - } - - public static uint ShiftDownBits(int len, uint[] z, int zOff, int bits, uint c) - { - Debug.Assert(bits > 0 && bits < 32); - int i = len; - while (--i >= 0) - { - uint next = z[zOff + i]; - z[zOff + i] = (next >> bits) | (c << -bits); - c = next; - } - return c << -bits; - } - - public static uint ShiftDownBits(int len, uint[] x, int bits, uint c, uint[] z) - { - Debug.Assert(bits > 0 && bits < 32); - int i = len; - while (--i >= 0) - { - uint next = x[i]; - z[i] = (next >> bits) | (c << -bits); - c = next; - } - return c << -bits; - } - - public static uint ShiftDownBits(int len, uint[] x, int xOff, int bits, uint c, uint[] z, int zOff) - { - Debug.Assert(bits > 0 && bits < 32); - int i = len; - while (--i >= 0) - { - uint next = x[xOff + i]; - z[zOff + i] = (next >> bits) | (c << -bits); - c = next; - } - return c << -bits; - } - - public static uint ShiftDownWord(int len, uint[] z, uint c) - { - int i = len; - while (--i >= 0) - { - uint next = z[i]; - z[i] = c; - c = next; - } - return c; - } - - public static uint ShiftUpBit(int len, uint[] z, uint c) - { - for (int i = 0; i < len; ++i) - { - uint next = z[i]; - z[i] = (next << 1) | (c >> 31); - c = next; - } - return c >> 31; - } - - public static uint ShiftUpBit(int len, uint[] z, int zOff, uint c) - { - for (int i = 0; i < len; ++i) - { - uint next = z[zOff + i]; - z[zOff + i] = (next << 1) | (c >> 31); - c = next; - } - return c >> 31; - } - - public static uint ShiftUpBit(int len, uint[] x, uint c, uint[] z) - { - for (int i = 0; i < len; ++i) - { - uint next = x[i]; - z[i] = (next << 1) | (c >> 31); - c = next; - } - return c >> 31; - } - - public static uint ShiftUpBit(int len, uint[] x, int xOff, uint c, uint[] z, int zOff) - { - for (int i = 0; i < len; ++i) - { - uint next = x[xOff + i]; - z[zOff + i] = (next << 1) | (c >> 31); - c = next; - } - return c >> 31; - } - - public static ulong ShiftUpBit64(int len, ulong[] x, int xOff, ulong c, ulong[] z, int zOff) - { - for (int i = 0; i < len; ++i) - { - ulong next = x[xOff + i]; - z[zOff + i] = (next << 1) | (c >> 63); - c = next; - } - return c >> 63; - } - - public static uint ShiftUpBits(int len, uint[] z, int bits, uint c) - { - Debug.Assert(bits > 0 && bits < 32); - for (int i = 0; i < len; ++i) - { - uint next = z[i]; - z[i] = (next << bits) | (c >> -bits); - c = next; - } - return c >> -bits; - } - - public static uint ShiftUpBits(int len, uint[] z, int zOff, int bits, uint c) - { - Debug.Assert(bits > 0 && bits < 32); - for (int i = 0; i < len; ++i) - { - uint next = z[zOff + i]; - z[zOff + i] = (next << bits) | (c >> -bits); - c = next; - } - return c >> -bits; - } - - public static ulong ShiftUpBits64(int len, ulong[] z, int zOff, int bits, ulong c) - { - Debug.Assert(bits > 0 && bits < 64); - for (int i = 0; i < len; ++i) - { - ulong next = z[zOff + i]; - z[zOff + i] = (next << bits) | (c >> -bits); - c = next; - } - return c >> -bits; - } - - public static uint ShiftUpBits(int len, uint[] x, int bits, uint c, uint[] z) - { - Debug.Assert(bits > 0 && bits < 32); - for (int i = 0; i < len; ++i) - { - uint next = x[i]; - z[i] = (next << bits) | (c >> -bits); - c = next; - } - return c >> -bits; - } - - public static uint ShiftUpBits(int len, uint[] x, int xOff, int bits, uint c, uint[] z, int zOff) - { - Debug.Assert(bits > 0 && bits < 32); - for (int i = 0; i < len; ++i) - { - uint next = x[xOff + i]; - z[zOff + i] = (next << bits) | (c >> -bits); - c = next; - } - return c >> -bits; - } - - public static ulong ShiftUpBits64(int len, ulong[] x, int xOff, int bits, ulong c, ulong[] z, int zOff) - { - Debug.Assert(bits > 0 && bits < 64); - for (int i = 0; i < len; ++i) - { - ulong next = x[xOff + i]; - z[zOff + i] = (next << bits) | (c >> -bits); - c = next; - } - return c >> -bits; - } - - public static void Square(int len, uint[] x, uint[] zz) - { - int extLen = len << 1; - uint c = 0; - int j = len, k = extLen; - do - { - ulong xVal = (ulong)x[--j]; - ulong p = xVal * xVal; - zz[--k] = (c << 31) | (uint)(p >> 33); - zz[--k] = (uint)(p >> 1); - c = (uint)p; - } - while (j > 0); - - for (int i = 1; i < len; ++i) - { - c = SquareWordAdd(x, i, zz); - AddWordAt(extLen, c, zz, i << 1); - } - - ShiftUpBit(extLen, zz, x[0] << 31); - } - - public static void Square(int len, uint[] x, int xOff, uint[] zz, int zzOff) - { - int extLen = len << 1; - uint c = 0; - int j = len, k = extLen; - do - { - ulong xVal = (ulong)x[xOff + --j]; - ulong p = xVal * xVal; - zz[zzOff + --k] = (c << 31) | (uint)(p >> 33); - zz[zzOff + --k] = (uint)(p >> 1); - c = (uint)p; - } - while (j > 0); - - for (int i = 1; i < len; ++i) - { - c = SquareWordAdd(x, xOff, i, zz, zzOff); - AddWordAt(extLen, c, zz, zzOff, i << 1); - } - - ShiftUpBit(extLen, zz, zzOff, x[xOff] << 31); - } - - public static uint SquareWordAdd(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 SquareWordAdd(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; - for (int i = 0; i < len; ++i) - { - c += (long)x[i] - y[i]; - z[i] = (uint)c; - c >>= 32; - } - return (int)c; - } - - public static int Sub(int len, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) - { - long c = 0; - for (int i = 0; i < len; ++i) - { - c += (long)x[xOff + i] - y[yOff + i]; - z[zOff + i] = (uint)c; - c >>= 32; - } - return (int)c; - } - public static int Sub33At(int len, uint x, uint[] z, int zPos) - { - Debug.Assert(zPos <= (len - 2)); - long c = (long)z[zPos + 0] - x; - z[zPos + 0] = (uint)c; - c >>= 32; - c += (long)z[zPos + 1] - 1; - z[zPos + 1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : DecAt(len, z, zPos + 2); - } - - public static int Sub33At(int len, uint x, uint[] z, int zOff, int zPos) - { - Debug.Assert(zPos <= (len - 2)); - long c = (long)z[zOff + zPos] - x; - z[zOff + zPos] = (uint)c; - c >>= 32; - c += (long)z[zOff + zPos + 1] - 1; - z[zOff + zPos + 1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : DecAt(len, z, zOff, zPos + 2); - } - - public static int Sub33From(int len, uint x, uint[] z) - { - long c = (long)z[0] - x; - z[0] = (uint)c; - c >>= 32; - c += (long)z[1] - 1; - z[1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : DecAt(len, z, 2); - } - - public static int Sub33From(int len, uint x, uint[] z, int zOff) - { - long c = (long)z[zOff + 0] - x; - z[zOff + 0] = (uint)c; - c >>= 32; - c += (long)z[zOff + 1] - 1; - z[zOff + 1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : DecAt(len, z, zOff, 2); - } - - public static int SubBothFrom(int len, uint[] x, uint[] y, uint[] z) - { - long c = 0; - for (int i = 0; i < len; ++i) - { - c += (long)z[i] - x[i] - y[i]; - z[i] = (uint)c; - c >>= 32; - } - return (int)c; - } - - public static int SubBothFrom(int len, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) - { - long c = 0; - for (int i = 0; i < len; ++i) - { - c += (long)z[zOff + i] - x[xOff + i] - y[yOff + i]; - z[zOff + i] = (uint)c; - c >>= 32; - } - return (int)c; - } - - public static int SubDWordAt(int len, ulong x, uint[] z, int zPos) - { - Debug.Assert(zPos <= (len - 2)); - long c = (long)z[zPos + 0] - (long)(x & M); - z[zPos + 0] = (uint)c; - c >>= 32; - c += (long)z[zPos + 1] - (long)(x >> 32); - z[zPos + 1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : DecAt(len, z, zPos + 2); - } - - public static int SubDWordAt(int len, ulong x, uint[] z, int zOff, int zPos) - { - Debug.Assert(zPos <= (len - 2)); - long c = (long)z[zOff + zPos] - (long)(x & M); - z[zOff + zPos] = (uint)c; - c >>= 32; - c += (long)z[zOff + zPos + 1] - (long)(x >> 32); - z[zOff + zPos + 1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : DecAt(len, z, zOff, zPos + 2); - } - - public static int SubDWordFrom(int len, ulong x, uint[] z) - { - long c = (long)z[0] - (long)(x & M); - z[0] = (uint)c; - c >>= 32; - c += (long)z[1] - (long)(x >> 32); - z[1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : DecAt(len, z, 2); - } - - public static int SubDWordFrom(int len, ulong x, uint[] z, int zOff) - { - long c = (long)z[zOff + 0] - (long)(x & M); - z[zOff + 0] = (uint)c; - c >>= 32; - c += (long)z[zOff + 1] - (long)(x >> 32); - z[zOff + 1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : DecAt(len, z, zOff, 2); - } - - public static int SubFrom(int len, uint[] x, uint[] z) - { - long c = 0; - for (int i = 0; i < len; ++i) - { - c += (long)z[i] - x[i]; - z[i] = (uint)c; - c >>= 32; - } - return (int)c; - } - - public static int SubFrom(int len, uint[] x, int xOff, uint[] z, int zOff) - { - long c = 0; - for (int i = 0; i < len; ++i) - { - c += (long)z[zOff + i] - x[xOff + i]; - z[zOff + i] = (uint)c; - c >>= 32; - } - return (int)c; - } - - public static int SubWordAt(int len, uint x, uint[] z, int zPos) - { - Debug.Assert(zPos <= (len - 1)); - long c = (long)z[zPos] - x; - z[zPos] = (uint)c; - c >>= 32; - return c == 0 ? 0 : DecAt(len, z, zPos + 1); - } - - public static int SubWordAt(int len, uint x, uint[] z, int zOff, int zPos) - { - Debug.Assert(zPos <= (len - 1)); - long c = (long)z[zOff + zPos] - x; - z[zOff + zPos] = (uint)c; - c >>= 32; - return c == 0 ? 0 : DecAt(len, z, zOff, zPos + 1); - } - - public static int SubWordFrom(int len, uint x, uint[] z) - { - long c = (long)z[0] - x; - z[0] = (uint)c; - c >>= 32; - return c == 0 ? 0 : DecAt(len, z, 1); - } - - public static int SubWordFrom(int len, uint x, uint[] z, int zOff) - { - long c = (long)z[zOff + 0] - x; - z[zOff + 0] = (uint)c; - c >>= 32; - return c == 0 ? 0 : DecAt(len, z, zOff, 1); - } - - public static BigInteger ToBigInteger(int len, uint[] x) - { - byte[] bs = new byte[len << 2]; - for (int i = 0; i < len; ++i) - { - uint x_i = x[i]; - if (x_i != 0) - { - Pack.UInt32_To_BE(x_i, bs, (len - 1 - i) << 2); - } - } - return new BigInteger(1, bs); - } - - public static void Zero(int len, uint[] z) - { - for (int i = 0; i < len; ++i) - { - z[i] = 0; - } - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/security/DigestUtilities.cs b/src/Renci.SshNet/Security/BouncyCastle/security/DigestUtilities.cs deleted file mode 100644 index 06fbd9a62..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/security/DigestUtilities.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Renci.SshNet.Security.Org.BouncyCastle.Crypto; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Security -{ - /// - /// Utility class for creating IDigest objects from their names/Oids - /// - internal sealed class DigestUtilities - { - private enum DigestAlgorithm { - SHA_256 - }; - - private DigestUtilities() - { - } - - public static byte[] DoFinal( - IDigest digest) - { - byte[] b = new byte[digest.GetDigestSize()]; - digest.DoFinal(b, 0); - return b; - } - - public static byte[] DoFinal( - IDigest digest, - byte[] input) - { - digest.BlockUpdate(input, 0, input.Length); - return DoFinal(digest); - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/security/SecureRandom.cs b/src/Renci.SshNet/Security/BouncyCastle/security/SecureRandom.cs deleted file mode 100644 index 6e86c47ca..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/security/SecureRandom.cs +++ /dev/null @@ -1,179 +0,0 @@ -using System; -using System.Threading; - -using Renci.SshNet.Security.Org.BouncyCastle.Crypto; -using Renci.SshNet.Security.Org.BouncyCastle.Crypto.Digests; -using Renci.SshNet.Security.Org.BouncyCastle.Crypto.Prng; -using Renci.SshNet.Security.Org.BouncyCastle.Utilities; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Security -{ - internal class SecureRandom - : Random - { - private static long counter = Times.NanoTime(); - - private static long NextCounterValue() - { - return Interlocked.Increment(ref counter); - } - - private static readonly SecureRandom master = new SecureRandom(new CryptoApiRandomGenerator()); - private static SecureRandom Master - { - get { return master; } - } - - private static DigestRandomGenerator CreatePrng(IDigest digest, bool autoSeed) - { - DigestRandomGenerator prng = new DigestRandomGenerator(digest); - if (autoSeed) - { - prng.AddSeedMaterial(NextCounterValue()); - prng.AddSeedMaterial(GetNextBytes(Master, digest.GetDigestSize())); - } - return prng; - } - - public static byte[] GetNextBytes(SecureRandom secureRandom, int length) - { - byte[] result = new byte[length]; - secureRandom.NextBytes(result); - return result; - } - - protected readonly IRandomGenerator generator; - - public SecureRandom() - : this(CreatePrng(new Sha256Digest(), true)) - { - } - - /// Use the specified instance of IRandomGenerator as random source. - /// - /// This constructor performs no seeding of either the IRandomGenerator or the - /// constructed SecureRandom. It is the responsibility of the client to provide - /// proper seed material as necessary/appropriate for the given IRandomGenerator - /// implementation. - /// - /// The source to generate all random bytes from. - public SecureRandom(IRandomGenerator generator) -#pragma warning disable CA5394 // Do not use insecure randomness - : base(0) -#pragma warning restore CA5394 // Do not use insecure randomness - { - this.generator = generator; - } - - public virtual byte[] GenerateSeed(int length) - { - return GetNextBytes(Master, length); - } - - public virtual void SetSeed(byte[] seed) - { - generator.AddSeedMaterial(seed); - } - - public virtual void SetSeed(long seed) - { - generator.AddSeedMaterial(seed); - } - - public override int Next() - { - return NextInt() & int.MaxValue; - } - - public override int Next(int maxValue) - { - - if (maxValue < 2) - { - if (maxValue < 0) - throw new ArgumentOutOfRangeException("maxValue", "cannot be negative"); - - return 0; - } - - int bits; - - // Test whether maxValue is a power of 2 - if ((maxValue & (maxValue - 1)) == 0) - { - bits = NextInt() & int.MaxValue; - return (int)(((long)bits * maxValue) >> 31); - } - - int result; - do - { - bits = NextInt() & int.MaxValue; - result = bits % maxValue; - } - while (bits - result + (maxValue - 1) < 0); // Ignore results near overflow - - return result; - } - - public override int Next(int minValue, int maxValue) - { - if (maxValue <= minValue) - { - if (maxValue == minValue) - return minValue; - - throw new ArgumentException("maxValue cannot be less than minValue"); - } - - int diff = maxValue - minValue; - if (diff > 0) - return minValue + Next(diff); - - for (;;) - { - int i = NextInt(); - - if (i >= minValue && i < maxValue) - return i; - } - } - - public override void NextBytes(byte[] buf) - { - generator.NextBytes(buf); - } - - public virtual void NextBytes(byte[] buf, int off, int len) - { - generator.NextBytes(buf, off, len); - } - - private static readonly double DoubleScale = System.Math.Pow(2.0, 64.0); - - public override double NextDouble() - { - return Convert.ToDouble((ulong) NextLong()) / DoubleScale; - } - - public virtual int NextInt() - { - byte[] bytes = new byte[4]; - NextBytes(bytes); - - uint result = bytes[0]; - result <<= 8; - result |= bytes[1]; - result <<= 8; - result |= bytes[2]; - result <<= 8; - result |= bytes[3]; - return (int)result; - } - - public virtual long NextLong() - { - return ((long)(uint) NextInt() << 32) | (long)(uint) NextInt(); - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/security/SecurityUtilityException.cs b/src/Renci.SshNet/Security/BouncyCastle/security/SecurityUtilityException.cs deleted file mode 100644 index acd208b36..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/security/SecurityUtilityException.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Security -{ -#if NETFRAMEWORK - [Serializable] -#endif - internal class SecurityUtilityException - : Exception - { - /** - * base constructor. - */ - public SecurityUtilityException() - { - } - - /** - * create a SecurityUtilityException with the given message. - * - * @param message the message to be carried with the exception. - */ - public SecurityUtilityException( - string message) - : base(message) - { - } - - public SecurityUtilityException( - string message, - Exception exception) - : base(message, exception) - { - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/util/Arrays.cs b/src/Renci.SshNet/Security/BouncyCastle/util/Arrays.cs deleted file mode 100644 index 3e8947548..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/util/Arrays.cs +++ /dev/null @@ -1,718 +0,0 @@ -using System; -using System.Text; - -using Renci.SshNet.Security.Org.BouncyCastle.Math; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Utilities -{ - /// General array utilities. - internal abstract class Arrays - { - public static readonly byte[] EmptyBytes = new byte[0]; - public static readonly int[] EmptyInts = new int[0]; - - public static bool AreAllZeroes(byte[] buf, int off, int len) - { - uint bits = 0; - for (int i = 0; i < len; ++i) - { - bits |= buf[off + i]; - } - return bits == 0; - } - - public static bool AreEqual( - bool[] a, - bool[] b) - { - if (a == b) - return true; - - if (a == null || b == null) - return false; - - return HaveSameContents(a, b); - } - - public static bool AreEqual( - char[] a, - char[] b) - { - if (a == b) - return true; - - if (a == null || b == null) - return false; - - return HaveSameContents(a, b); - } - - /// - /// Are two arrays equal. - /// - /// Left side. - /// Right side. - /// True if equal. - public static bool AreEqual( - byte[] a, - byte[] b) - { - if (a == b) - return true; - - if (a == null || b == null) - return false; - - return HaveSameContents(a, b); - } - - [Obsolete("Use 'AreEqual' method instead")] - public static bool AreSame( - byte[] a, - byte[] b) - { - return AreEqual(a, b); - } - - /// - /// A constant time equals comparison - does not terminate early if - /// test will fail. - /// - /// first array - /// second array - /// true if arrays equal, false otherwise. - public static bool ConstantTimeAreEqual( - byte[] a, - byte[] b) - { - int i = a.Length; - if (i != b.Length) - return false; - int cmp = 0; - while (i != 0) - { - --i; - cmp |= (a[i] ^ b[i]); - } - return cmp == 0; - } - - public static bool AreEqual( - int[] a, - int[] b) - { - if (a == b) - return true; - - if (a == null || b == null) - return false; - - return HaveSameContents(a, b); - } - - public static bool AreEqual(uint[] a, uint[] b) - { - if (a == b) - return true; - - if (a == null || b == null) - return false; - - return HaveSameContents(a, b); - } - - private static bool HaveSameContents( - bool[] a, - bool[] b) - { - int i = a.Length; - if (i != b.Length) - return false; - while (i != 0) - { - --i; - if (a[i] != b[i]) - return false; - } - return true; - } - - private static bool HaveSameContents( - char[] a, - char[] b) - { - int i = a.Length; - if (i != b.Length) - return false; - while (i != 0) - { - --i; - if (a[i] != b[i]) - return false; - } - return true; - } - - private static bool HaveSameContents( - byte[] a, - byte[] b) - { - int i = a.Length; - if (i != b.Length) - return false; - while (i != 0) - { - --i; - if (a[i] != b[i]) - return false; - } - return true; - } - - private static bool HaveSameContents( - int[] a, - int[] b) - { - int i = a.Length; - if (i != b.Length) - return false; - while (i != 0) - { - --i; - if (a[i] != b[i]) - return false; - } - return true; - } - - private static bool HaveSameContents(uint[] a, uint[] b) - { - int i = a.Length; - if (i != b.Length) - return false; - while (i != 0) - { - --i; - if (a[i] != b[i]) - return false; - } - return true; - } - - public static string ToString( - object[] a) - { - StringBuilder sb = new StringBuilder('['); - if (a.Length > 0) - { - sb.Append(a[0]); - for (int index = 1; index < a.Length; ++index) - { - sb.Append(", ").Append(a[index]); - } - } - sb.Append(']'); - return sb.ToString(); - } - - public static int GetHashCode(byte[] data) - { - if (data == null) - { - return 0; - } - - int i = data.Length; - int hc = i + 1; - - while (--i >= 0) - { - hc *= 257; - hc ^= data[i]; - } - - return hc; - } - - public static int GetHashCode(byte[] data, int off, int len) - { - if (data == null) - { - return 0; - } - - int i = len; - int hc = i + 1; - - while (--i >= 0) - { - hc *= 257; - hc ^= data[off + i]; - } - - return hc; - } - - public static int GetHashCode(int[] data) - { - if (data == null) - return 0; - - int i = data.Length; - int hc = i + 1; - - while (--i >= 0) - { - hc *= 257; - hc ^= data[i]; - } - - return hc; - } - - public static int GetHashCode(int[] data, int off, int len) - { - if (data == null) - return 0; - - int i = len; - int hc = i + 1; - - while (--i >= 0) - { - hc *= 257; - hc ^= data[off + i]; - } - - return hc; - } - - public static int GetHashCode(uint[] data) - { - if (data == null) - return 0; - - int i = data.Length; - int hc = i + 1; - - while (--i >= 0) - { - hc *= 257; - hc ^= (int)data[i]; - } - - return hc; - } - - public static int GetHashCode(uint[] data, int off, int len) - { - if (data == null) - return 0; - - int i = len; - int hc = i + 1; - - while (--i >= 0) - { - hc *= 257; - hc ^= (int)data[off + i]; - } - - return hc; - } - - public static int GetHashCode(ulong[] data) - { - if (data == null) - return 0; - - int i = data.Length; - int hc = i + 1; - - while (--i >= 0) - { - ulong di = data[i]; - hc *= 257; - hc ^= (int)di; - hc *= 257; - hc ^= (int)(di >> 32); - } - - return hc; - } - - public static int GetHashCode(ulong[] data, int off, int len) - { - if (data == null) - return 0; - - int i = len; - int hc = i + 1; - - while (--i >= 0) - { - ulong di = data[off + i]; - hc *= 257; - hc ^= (int)di; - hc *= 257; - hc ^= (int)(di >> 32); - } - - return hc; - } - - public static byte[] Clone( - byte[] data) - { - return data == null ? null : (byte[])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; - } - - public static int[] Clone( - int[] data) - { - return data == null ? null : (int[])data.Clone(); - } - - internal static uint[] Clone(uint[] data) - { - return data == null ? null : (uint[])data.Clone(); - } - - public static long[] Clone(long[] data) - { - return data == null ? null : (long[])data.Clone(); - } - - public static ulong[] Clone( - ulong[] data) - { - return data == null ? null : (ulong[]) data.Clone(); - } - - public static ulong[] Clone( - ulong[] data, - ulong[] 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; - } - - public static bool Contains(byte[] a, byte n) - { - for (int i = 0; i < a.Length; ++i) - { - if (a[i] == n) - return true; - } - return false; - } - - public static bool Contains(short[] a, short n) - { - for (int i = 0; i < a.Length; ++i) - { - if (a[i] == n) - return true; - } - return false; - } - - public static bool Contains(int[] a, int n) - { - for (int i = 0; i < a.Length; ++i) - { - if (a[i] == n) - return true; - } - return false; - } - - public static void Fill( - byte[] buf, - byte b) - { - int i = buf.Length; - while (i > 0) - { - buf[--i] = b; - } - } - - public static void Fill(byte[] buf, int from, int to, byte b) - { - for (int i = from; i < to; ++i) - { - buf[i] = b; - } - } - - public static byte[] CopyOf(byte[] data, int newLength) - { - byte[] tmp = new byte[newLength]; - Array.Copy(data, 0, tmp, 0, System.Math.Min(newLength, data.Length)); - return tmp; - } - - public static char[] CopyOf(char[] data, int newLength) - { - char[] tmp = new char[newLength]; - Array.Copy(data, 0, tmp, 0, System.Math.Min(newLength, data.Length)); - return tmp; - } - - public static int[] CopyOf(int[] data, int newLength) - { - int[] tmp = new int[newLength]; - Array.Copy(data, 0, tmp, 0, System.Math.Min(newLength, data.Length)); - return tmp; - } - - public static long[] CopyOf(long[] data, int newLength) - { - long[] tmp = new long[newLength]; - Array.Copy(data, 0, tmp, 0, System.Math.Min(newLength, data.Length)); - return tmp; - } - - public static BigInteger[] CopyOf(BigInteger[] data, int newLength) - { - BigInteger[] tmp = new BigInteger[newLength]; - Array.Copy(data, 0, tmp, 0, System.Math.Min(newLength, data.Length)); - return tmp; - } - - /** - * Make a copy of a range of bytes from the passed in data array. The range can - * extend beyond the end of the input array, in which case the return array will - * be padded with zeroes. - * - * @param data the array from which the data is to be copied. - * @param from the start index at which the copying should take place. - * @param to the final index of the range (exclusive). - * - * @return a new byte array containing the range given. - */ - public static byte[] CopyOfRange(byte[] data, int from, int to) - { - int newLength = GetLength(from, to); - byte[] tmp = new byte[newLength]; - Array.Copy(data, from, tmp, 0, System.Math.Min(newLength, data.Length - from)); - return tmp; - } - - public static int[] CopyOfRange(int[] data, int from, int to) - { - int newLength = GetLength(from, to); - int[] tmp = new int[newLength]; - Array.Copy(data, from, tmp, 0, System.Math.Min(newLength, data.Length - from)); - return tmp; - } - - public static long[] CopyOfRange(long[] data, int from, int to) - { - int newLength = GetLength(from, to); - long[] tmp = new long[newLength]; - Array.Copy(data, from, tmp, 0, System.Math.Min(newLength, data.Length - from)); - return tmp; - } - - public static BigInteger[] CopyOfRange(BigInteger[] data, int from, int to) - { - int newLength = GetLength(from, to); - BigInteger[] tmp = new BigInteger[newLength]; - Array.Copy(data, from, tmp, 0, System.Math.Min(newLength, data.Length - from)); - return tmp; - } - - private static int GetLength(int from, int to) - { - int newLength = to - from; - if (newLength < 0) - throw new ArgumentException(from + " > " + to); - return newLength; - } - - public static byte[] Append(byte[] a, byte b) - { - if (a == null) - return new byte[] { b }; - - int length = a.Length; - byte[] result = new byte[length + 1]; - Array.Copy(a, 0, result, 0, length); - result[length] = b; - return result; - } - - public static short[] Append(short[] a, short b) - { - if (a == null) - return new short[] { b }; - - int length = a.Length; - short[] result = new short[length + 1]; - Array.Copy(a, 0, result, 0, length); - result[length] = b; - return result; - } - - public static int[] Append(int[] a, int b) - { - if (a == null) - return new int[] { b }; - - int length = a.Length; - int[] result = new int[length + 1]; - Array.Copy(a, 0, result, 0, length); - result[length] = b; - return result; - } - - public static byte[] Concatenate(byte[] a, byte[] b) - { - if (a == null) - return Clone(b); - if (b == null) - return Clone(a); - - byte[] rv = new byte[a.Length + b.Length]; - Array.Copy(a, 0, rv, 0, a.Length); - Array.Copy(b, 0, rv, a.Length, b.Length); - return rv; - } - - public static byte[] ConcatenateAll(params byte[][] vs) - { - byte[][] nonNull = new byte[vs.Length][]; - int count = 0; - int totalLength = 0; - - for (int i = 0; i < vs.Length; ++i) - { - byte[] v = vs[i]; - if (v != null) - { - nonNull[count++] = v; - totalLength += v.Length; - } - } - - byte[] result = new byte[totalLength]; - int pos = 0; - - for (int j = 0; j < count; ++j) - { - byte[] v = nonNull[j]; - Array.Copy(v, 0, result, pos, v.Length); - pos += v.Length; - } - - return result; - } - - public static int[] Concatenate(int[] a, int[] b) - { - if (a == null) - return Clone(b); - if (b == null) - return Clone(a); - - int[] rv = new int[a.Length + b.Length]; - Array.Copy(a, 0, rv, 0, a.Length); - Array.Copy(b, 0, rv, a.Length, b.Length); - return rv; - } - - public static byte[] Prepend(byte[] a, byte b) - { - if (a == null) - return new byte[] { b }; - - int length = a.Length; - byte[] result = new byte[length + 1]; - Array.Copy(a, 0, result, 1, length); - result[0] = b; - return result; - } - - public static short[] Prepend(short[] a, short b) - { - if (a == null) - return new short[] { b }; - - int length = a.Length; - short[] result = new short[length + 1]; - Array.Copy(a, 0, result, 1, length); - result[0] = b; - return result; - } - - public static int[] Prepend(int[] a, int b) - { - if (a == null) - return new int[] { b }; - - int length = a.Length; - int[] result = new int[length + 1]; - Array.Copy(a, 0, result, 1, length); - result[0] = b; - return result; - } - - public static byte[] Reverse(byte[] a) - { - if (a == null) - return null; - - int p1 = 0, p2 = a.Length; - byte[] result = new byte[p2]; - - while (--p2 >= 0) - { - result[p2] = a[p1++]; - } - - return result; - } - - public static int[] Reverse(int[] a) - { - if (a == null) - return null; - - int p1 = 0, p2 = a.Length; - int[] result = new int[p2]; - - while (--p2 >= 0) - { - result[p2] = a[p1++]; - } - - return result; - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/util/BigIntegers.cs b/src/Renci.SshNet/Security/BouncyCastle/util/BigIntegers.cs deleted file mode 100644 index 6e1b8c855..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/util/BigIntegers.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System; - -using Renci.SshNet.Security.Org.BouncyCastle.Math; -using Renci.SshNet.Security.Org.BouncyCastle.Security; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Utilities -{ - /** - * BigInteger utilities. - */ - internal abstract class BigIntegers - { - private const int MaxIterations = 1000; - - /** - * Return the passed in value as an unsigned byte array. - * - * @param value value to be converted. - * @return a byte array without a leading zero byte if present in the signed encoding. - */ - public static byte[] AsUnsignedByteArray( - BigInteger n) - { - return n.ToByteArrayUnsigned(); - } - - /** - * Return the passed in value as an unsigned byte array of specified length, zero-extended as necessary. - * - * @param length desired length of result array. - * @param n value to be converted. - * @return a byte array of specified length, with leading zeroes as necessary given the size of n. - */ - public static byte[] AsUnsignedByteArray(int length, BigInteger n) - { - byte[] bytes = n.ToByteArrayUnsigned(); - - if (bytes.Length > length) - throw new ArgumentException("standard length exceeded", "n"); - - if (bytes.Length == length) - return bytes; - - byte[] tmp = new byte[length]; - Array.Copy(bytes, 0, tmp, tmp.Length - bytes.Length, bytes.Length); - return tmp; - } - - /** - * Return a random BigInteger not less than 'min' and not greater than 'max' - * - * @param min the least value that may be generated - * @param max the greatest value that may be generated - * @param random the source of randomness - * @return a random BigInteger value in the range [min,max] - */ - public static BigInteger CreateRandomInRange( - BigInteger min, - BigInteger max, - // TODO Should have been just Random class - SecureRandom random) - { - int cmp = min.CompareTo(max); - if (cmp >= 0) - { - if (cmp > 0) - throw new ArgumentException("'min' may not be greater than 'max'"); - - return min; - } - - if (min.BitLength > max.BitLength / 2) - { - return CreateRandomInRange(BigInteger.Zero, max.Subtract(min), random).Add(min); - } - - for (int i = 0; i < MaxIterations; ++i) - { - BigInteger x = new BigInteger(max.BitLength, random); - if (x.CompareTo(min) >= 0 && x.CompareTo(max) <= 0) - { - return x; - } - } - - // fall back to a faster (restricted) method - return new BigInteger(max.Subtract(min).BitLength - 1, random).Add(min); - } - - public static int GetUnsignedByteLength(BigInteger n) - { - return (n.BitLength + 7) / 8; - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/util/IMemoable.cs b/src/Renci.SshNet/Security/BouncyCastle/util/IMemoable.cs deleted file mode 100644 index 9f94275f4..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/util/IMemoable.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Utilities -{ - internal interface IMemoable - { - /// - /// Produce a copy of this object with its configuration and in its current state. - /// - /// - /// The returned object may be used simply to store the state, or may be used as a similar object - /// starting from the copied state. - /// - IMemoable Copy(); - - /// - /// Restore a copied object state into this object. - /// - /// - /// Implementations of this method should try to avoid or minimise memory allocation to perform the reset. - /// - /// an object originally {@link #copy() copied} from an object of the same type as this instance. - /// if the provided object is not of the correct type. - /// if the other parameter is in some other way invalid. - void Reset(IMemoable other); - } - -} - diff --git a/src/Renci.SshNet/Security/BouncyCastle/util/Integers.cs b/src/Renci.SshNet/Security/BouncyCastle/util/Integers.cs deleted file mode 100644 index 29a858cc5..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/util/Integers.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Utilities -{ - internal abstract class Integers - { - public static int RotateLeft(int i, int distance) - { - return (i << distance) ^ (int)((uint)i >> -distance); - } - - public static uint RotateLeft(uint i, int distance) - { - return (i << distance) ^ (i >> -distance); - } - - public static int RotateRight(int i, int distance) - { - return (int)((uint)i >> distance) ^ (i << -distance); - } - - public static uint RotateRight(uint i, int distance) - { - return (i >> distance) ^ (i << -distance); - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/util/MemoableResetException.cs b/src/Renci.SshNet/Security/BouncyCastle/util/MemoableResetException.cs deleted file mode 100644 index 3b5ac38c5..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/util/MemoableResetException.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Utilities -{ - /** - * Exception to be thrown on a failure to reset an object implementing Memoable. - * - * The exception extends InvalidCastException to enable users to have a single handling case, - * only introducing specific handling of this one if required. - * - */ - internal class MemoableResetException - : InvalidCastException - { - /** - * Basic Constructor. - * - * @param msg message to be associated with this exception. - */ - public MemoableResetException(string msg) - : base(msg) - { - } - } - -} - diff --git a/src/Renci.SshNet/Security/BouncyCastle/util/Times.cs b/src/Renci.SshNet/Security/BouncyCastle/util/Times.cs deleted file mode 100644 index 6ef1f65f7..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/util/Times.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Utilities -{ - internal sealed class Times - { - private static long NanosecondsPerTick = 100L; - - public static long NanoTime() - { - return DateTime.UtcNow.Ticks * NanosecondsPerTick; - } - } -} diff --git a/src/Renci.SshNet/Security/BouncyCastle/util/encoders/Hex.cs b/src/Renci.SshNet/Security/BouncyCastle/util/encoders/Hex.cs deleted file mode 100644 index 658eb6fec..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/util/encoders/Hex.cs +++ /dev/null @@ -1,129 +0,0 @@ -using System.IO; -using System.Text; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Utilities.Encoders -{ - /// - /// Class to decode and encode Hex. - /// - internal sealed class Hex - { - private static readonly HexEncoder encoder = new HexEncoder(); - - private Hex() - { - } - - public static string ToHexString( - byte[] data) - { - return ToHexString(data, 0, data.Length); - } - - public static string ToHexString( - byte[] data, - int off, - int length) - { - byte[] hex = Encode(data, off, length); - return Encoding.UTF8.GetString(hex, 0, hex.Length); - } - - /** - * encode the input data producing a Hex encoded byte array. - * - * @return a byte array containing the Hex encoded data. - */ - public static byte[] Encode( - byte[] data) - { - return Encode(data, 0, data.Length); - } - - /** - * encode the input data producing a Hex encoded byte array. - * - * @return a byte array containing the Hex encoded data. - */ - public static byte[] Encode( - byte[] data, - int off, - int length) - { - MemoryStream bOut = new MemoryStream(length * 2); - - encoder.Encode(data, off, length, bOut); - - return bOut.ToArray(); - } - - /** - * Hex encode the byte data writing it to the given output stream. - * - * @return the number of bytes produced. - */ - public static int Encode( - byte[] data, - Stream outStream) - { - return encoder.Encode(data, 0, data.Length, outStream); - } - - /** - * Hex encode the byte data writing it to the given output stream. - * - * @return the number of bytes produced. - */ - public static int Encode( - byte[] data, - int off, - int length, - Stream outStream) - { - return encoder.Encode(data, off, length, outStream); - } - - /** - * decode the Hex encoded input data. It is assumed the input data is valid. - * - * @return a byte array representing the decoded data. - */ - public static byte[] Decode( - byte[] data) - { - MemoryStream bOut = new MemoryStream((data.Length + 1) / 2); - - encoder.Decode(data, 0, data.Length, bOut); - - return bOut.ToArray(); - } - - /** - * decode the Hex encoded string data - whitespace will be ignored. - * - * @return a byte array representing the decoded data. - */ - public static byte[] Decode( - string data) - { - MemoryStream bOut = new MemoryStream((data.Length + 1) / 2); - - encoder.DecodeString(data, bOut); - - return bOut.ToArray(); - } - - /** - * decode the Hex encoded string data writing it to the given output stream, - * whitespace characters will be ignored. - * - * @return the number of bytes produced. - */ - public static int Decode( - string data, - Stream outStream) - { - return encoder.DecodeString(data, outStream); - } - } -} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/BouncyCastle/util/encoders/HexEncoder.cs b/src/Renci.SshNet/Security/BouncyCastle/util/encoders/HexEncoder.cs deleted file mode 100644 index dd4e1ec20..000000000 --- a/src/Renci.SshNet/Security/BouncyCastle/util/encoders/HexEncoder.cs +++ /dev/null @@ -1,174 +0,0 @@ -using System.IO; - -namespace Renci.SshNet.Security.Org.BouncyCastle.Utilities.Encoders -{ - internal class HexEncoder - { - protected readonly byte[] encodingTable = - { - (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7', - (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f' - }; - - /* - * set up the decoding table. - */ - protected readonly byte[] decodingTable = new byte[128]; - - protected void InitialiseDecodingTable() - { - Arrays.Fill(decodingTable, (byte)0xff); - - for (int i = 0; i < encodingTable.Length; i++) - { - decodingTable[encodingTable[i]] = (byte)i; - } - - decodingTable['A'] = decodingTable['a']; - decodingTable['B'] = decodingTable['b']; - decodingTable['C'] = decodingTable['c']; - decodingTable['D'] = decodingTable['d']; - decodingTable['E'] = decodingTable['e']; - decodingTable['F'] = decodingTable['f']; - } - - public HexEncoder() - { - InitialiseDecodingTable(); - } - - /** - * encode the input data producing a Hex output stream. - * - * @return the number of bytes produced. - */ - public int Encode( - byte[] data, - int off, - int length, - Stream outStream) - { - for (int i = off; i < (off + length); i++) - { - int v = data[i]; - - outStream.WriteByte(encodingTable[v >> 4]); - outStream.WriteByte(encodingTable[v & 0xf]); - } - - return length * 2; - } - - private static bool Ignore(char c) - { - return c == '\n' || c =='\r' || c == '\t' || c == ' '; - } - - /** - * decode the Hex encoded byte data writing it to the given output stream, - * whitespace characters will be ignored. - * - * @return the number of bytes produced. - */ - public int Decode( - byte[] data, - int off, - int length, - Stream outStream) - { - byte b1, b2; - int outLen = 0; - int end = off + length; - - while (end > off) - { - if (!Ignore((char)data[end - 1])) - { - break; - } - - end--; - } - - int i = off; - while (i < end) - { - while (i < end && Ignore((char)data[i])) - { - i++; - } - - b1 = decodingTable[data[i++]]; - - while (i < end && Ignore((char)data[i])) - { - i++; - } - - b2 = decodingTable[data[i++]]; - - if ((b1 | b2) >= 0x80) - throw new IOException("invalid characters encountered in Hex data"); - - outStream.WriteByte((byte)((b1 << 4) | b2)); - - outLen++; - } - - return outLen; - } - - /** - * decode the Hex encoded string data writing it to the given output stream, - * whitespace characters will be ignored. - * - * @return the number of bytes produced. - */ - public int DecodeString( - string data, - Stream outStream) - { - byte b1, b2; - int length = 0; - - int end = data.Length; - - while (end > 0) - { - if (!Ignore(data[end - 1])) - { - break; - } - - end--; - } - - int i = 0; - while (i < end) - { - while (i < end && Ignore(data[i])) - { - i++; - } - - b1 = decodingTable[data[i++]]; - - while (i < end && Ignore(data[i])) - { - i++; - } - - b2 = decodingTable[data[i++]]; - - if ((b1 | b2) >= 0x80) - throw new IOException("invalid characters encountered in Hex data"); - - outStream.WriteByte((byte)((b1 << 4) | b2)); - - length++; - } - - return length; - } - } -} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/KeyExchangeECDH.cs b/src/Renci.SshNet/Security/KeyExchangeECDH.cs index f5bd46a1f..88a76b81d 100644 --- a/src/Renci.SshNet/Security/KeyExchangeECDH.cs +++ b/src/Renci.SshNet/Security/KeyExchangeECDH.cs @@ -1,15 +1,15 @@ using System; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto.Agreement; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Security; + using Renci.SshNet.Common; using Renci.SshNet.Messages.Transport; -using Renci.SshNet.Security.Org.BouncyCastle.Asn1.X9; -using Renci.SshNet.Security.Org.BouncyCastle.Crypto.Agreement; -using Renci.SshNet.Security.Org.BouncyCastle.Crypto.Generators; -using Renci.SshNet.Security.Org.BouncyCastle.Crypto.Parameters; -using Renci.SshNet.Security.Org.BouncyCastle.Math.EC; -using Renci.SshNet.Security.Org.BouncyCastle.Security; - namespace Renci.SshNet.Security { internal abstract class KeyExchangeECDH : KeyExchangeEC diff --git a/src/Renci.SshNet/Security/KeyExchangeECDH256.cs b/src/Renci.SshNet/Security/KeyExchangeECDH256.cs index b09652de8..a519c1896 100644 --- a/src/Renci.SshNet/Security/KeyExchangeECDH256.cs +++ b/src/Renci.SshNet/Security/KeyExchangeECDH256.cs @@ -1,6 +1,7 @@ -using Renci.SshNet.Abstractions; -using Renci.SshNet.Security.Org.BouncyCastle.Asn1.Sec; -using Renci.SshNet.Security.Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Asn1.Sec; +using Org.BouncyCastle.Asn1.X9; + +using Renci.SshNet.Abstractions; namespace Renci.SshNet.Security { @@ -21,7 +22,7 @@ protected override X9ECParameters CurveParameter { get { - return SecNamedCurves.GetByName("P-256"); + return SecNamedCurves.GetByName("secp256r1"); } } diff --git a/src/Renci.SshNet/Security/KeyExchangeECDH384.cs b/src/Renci.SshNet/Security/KeyExchangeECDH384.cs index cba304305..e91dcf965 100644 --- a/src/Renci.SshNet/Security/KeyExchangeECDH384.cs +++ b/src/Renci.SshNet/Security/KeyExchangeECDH384.cs @@ -1,6 +1,7 @@ -using Renci.SshNet.Abstractions; -using Renci.SshNet.Security.Org.BouncyCastle.Asn1.Sec; -using Renci.SshNet.Security.Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Asn1.Sec; +using Org.BouncyCastle.Asn1.X9; + +using Renci.SshNet.Abstractions; namespace Renci.SshNet.Security { @@ -21,7 +22,7 @@ protected override X9ECParameters CurveParameter { get { - return SecNamedCurves.GetByName("P-384"); + return SecNamedCurves.GetByName("secp384r1"); } } diff --git a/src/Renci.SshNet/Security/KeyExchangeECDH521.cs b/src/Renci.SshNet/Security/KeyExchangeECDH521.cs index ce5b35515..9ed146e96 100644 --- a/src/Renci.SshNet/Security/KeyExchangeECDH521.cs +++ b/src/Renci.SshNet/Security/KeyExchangeECDH521.cs @@ -1,6 +1,7 @@ -using Renci.SshNet.Abstractions; -using Renci.SshNet.Security.Org.BouncyCastle.Asn1.Sec; -using Renci.SshNet.Security.Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Asn1.Sec; +using Org.BouncyCastle.Asn1.X9; + +using Renci.SshNet.Abstractions; namespace Renci.SshNet.Security { @@ -21,7 +22,7 @@ protected override X9ECParameters CurveParameter { get { - return SecNamedCurves.GetByName("P-521"); + return SecNamedCurves.GetByName("secp521r1"); } }
From Knuth Vol 2, pg 395.
kP
PreCompInfo
ECMultiplier
ECPoint
String
ECCurve
Fp
s0
s1
z2 + z = beta
z + 1
null
y2 + xy = x3 + ax2 + b
m
F2m
k
xm + - * xk + 1
f(z)
k1
xm + - * xk3 + xk2 + xk1 + 1
0
k2
k3
a
b
#Ea(F2m) = h * n
LongArray
k * this
SimpleBigDecimal
scale
value
bigInt / - * 2scale
bigInt
αu
a=0
ZTauElement
a=1
λ
Z[τ]
μ
R[τ]
λ = u + vτ
u
R
τ
λ = λ0 + λ1τ
λ0
λ1
lambda0
lambda1
n
λ = s k / n
c
Vm
Fm
τ()
AbstractF2mPoint
τ(p)
1
Uk-1
Uk
Vk-1
Vk
tw
mu = 1
tw = 6
mu = -1
tw = 10
curve
(τm - 1)/(τ - 1)
ρ := k partmod (τm - 1)/(τ - 1)
BigInteger
p
k * p
λ * p
[τ]
v
ECPoint p
WNafMultiplier
this
w
k = ∑i=0l-1 ki2i - *
ki
byte[]
- * {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply() - * WTauNafMultiplier.multiply()}
- * The exception extends InvalidCastException to enable users to have a single handling case, - * only introducing specific handling of this one if required. - *