<PackageReference Include="SSH.NET" Version="2024.1.0" />

ECCurve

abstract class ECCurve
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.Utilities; using System; using System.Collections; using System.Collections.Generic; namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC { internal abstract class ECCurve { 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 eCCurve = outer.CloneCurve(); if (eCCurve == outer) throw new InvalidOperationException("implementation returned current curve"); eCCurve.m_coord = coord; eCCurve.m_endomorphism = endomorphism; eCCurve.m_multiplier = multiplier; return eCCurve; } } private class DefaultLookupTable : ECLookupTable { private readonly ECCurve m_outer; private readonly byte[] m_table; private readonly int m_size; public virtual int Size => m_size; internal DefaultLookupTable(ECCurve outer, byte[] table, int size) { m_outer = outer; m_table = table; m_size = size; } public virtual ECPoint Lookup(int index) { int num = (m_outer.FieldSize + 7) / 8; byte[] array = new byte[num]; byte[] array2 = new byte[num]; int num2 = 0; for (int i = 0; i < m_size; i++) { byte b = (byte)((i ^ index) - 1 >> 31); for (int j = 0; j < num; j++) { array[j] ^= (byte)(m_table[num2 + j] & b); array2[j] ^= (byte)(m_table[num2 + num + j] & b); } num2 += num * 2; } ECFieldElement x = m_outer.FromBigInteger(new BigInteger(1, array)); ECFieldElement y = m_outer.FromBigInteger(new BigInteger(1, array2)); return m_outer.CreateRawPoint(x, y, false); } } 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; protected readonly IFiniteField m_field; protected ECFieldElement m_a; protected ECFieldElement m_b; protected BigInteger m_order; protected BigInteger m_cofactor; protected int m_coord; protected ECEndomorphism m_endomorphism; protected ECMultiplier m_multiplier; public abstract int FieldSize { get; } public abstract ECPoint Infinity { get; } public virtual IFiniteField Field => m_field; public virtual ECFieldElement A => m_a; public virtual ECFieldElement B => m_b; public virtual BigInteger Order => m_order; public virtual BigInteger Cofactor => m_cofactor; public virtual int CoordinateSystem => m_coord; public static int[] GetAllCoordinateSystems() { return new int[8] { 0, 1, 2, 3, 4, 5, 6, 7 }; } protected ECCurve(IFiniteField field) { m_field = field; } public abstract ECFieldElement FromBigInteger(BigInteger x); public abstract bool IsValidFieldElement(BigInteger x); public virtual Config Configure() { return new Config(this, m_coord, m_endomorphism, m_multiplier); } public virtual ECPoint ValidatePoint(BigInteger x, BigInteger y) { ECPoint eCPoint = CreatePoint(x, y); if (!eCPoint.IsValid()) throw new ArgumentException("Invalid point coordinates"); return eCPoint; } public virtual ECPoint ValidatePoint(BigInteger x, BigInteger y, bool withCompression) { ECPoint eCPoint = CreatePoint(x, y, withCompression); if (!eCPoint.IsValid()) throw new ArgumentException("Invalid point coordinates"); return eCPoint; } 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 == 0; } public virtual PreCompInfo GetPreCompInfo(ECPoint point, string name) { CheckPoint(point); IDictionary preCompTable = default(IDictionary); lock (point) { preCompTable = point.m_preCompTable; } if (preCompTable == null) return null; lock (preCompTable) { return (PreCompInfo)preCompTable[name]; } } public virtual PreCompInfo Precompute(ECPoint point, string name, IPreCompCallback callback) { CheckPoint(point); IDictionary dictionary = default(IDictionary); lock (point) { dictionary = point.m_preCompTable; if (dictionary == null) dictionary = (point.m_preCompTable = new Dictionary<object, object>(4)); } lock (dictionary) { PreCompInfo preCompInfo = (PreCompInfo)dictionary[name]; PreCompInfo preCompInfo2 = callback.Precompute(preCompInfo); if (preCompInfo2 != preCompInfo) dictionary[name] = preCompInfo2; return preCompInfo2; } } public virtual ECPoint ImportPoint(ECPoint p) { if (this == p.Curve) return p; if (p.IsInfinity) return Infinity; p = p.Normalize(); return CreatePoint(p.XCoord.ToBigInteger(), p.YCoord.ToBigInteger(), p.IsCompressed); } public virtual void NormalizeAll(ECPoint[] points) { NormalizeAll(points, 0, points.Length, null); } public virtual void NormalizeAll(ECPoint[] points, int off, int len, ECFieldElement iso) { CheckPoints(points, off, len); int coordinateSystem = CoordinateSystem; if (coordinateSystem == 0 || coordinateSystem == 5) { if (iso != null) throw new ArgumentException("not valid for affine coordinates", "iso"); } else { ECFieldElement[] array = new ECFieldElement[len]; int[] array2 = new int[len]; int num = 0; for (int i = 0; i < len; i++) { ECPoint eCPoint = points[off + i]; if (eCPoint != null && (iso != null || !eCPoint.IsNormalized())) { array[num] = eCPoint.GetZCoord(0); array2[num++] = off + i; } } if (num != 0) { ECAlgorithms.MontgomeryTrick(array, 0, num, iso); for (int j = 0; j < num; j++) { int num3 = array2[j]; points[num3] = points[num3].Normalize(array[j]); } } } } public virtual ECLookupTable CreateCacheSafeLookupTable(ECPoint[] points, int off, int len) { int num = (FieldSize + 7) / 8; byte[] array = new byte[len * num * 2]; int num2 = 0; for (int i = 0; i < len; i++) { ECPoint obj = points[off + i]; byte[] array2 = obj.RawXCoord.ToBigInteger().ToByteArray(); byte[] array3 = obj.RawYCoord.ToBigInteger().ToByteArray(); int num3 = (array2.Length > num) ? 1 : 0; int num4 = array2.Length - num3; int num5 = (array3.Length > num) ? 1 : 0; int num6 = array3.Length - num5; Array.Copy(array2, num3, array, num2 + num - num4, num4); num2 += num; Array.Copy(array3, num5, array, num2 + num - num6, num6); num2 += num; } return new DefaultLookupTable(this, array, len); } protected virtual void CheckPoint(ECPoint point) { if (point == null || 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"); int num = 0; while (true) { if (num >= len) return; ECPoint eCPoint = points[off + num]; if (eCPoint != null && this != eCPoint.Curve) break; num++; } throw new ArgumentException("entries must be null or on this curve", "points"); } public virtual bool Equals(ECCurve other) { if (this == other) return true; if (other == null) return false; if (Field.Equals(other.Field) && A.ToBigInteger().Equals(other.A.ToBigInteger())) return B.ToBigInteger().Equals(other.B.ToBigInteger()); return false; } 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; } public virtual ECMultiplier GetMultiplier() { lock (this) { if (m_multiplier == null) m_multiplier = CreateDefaultMultiplier(); return m_multiplier; } } public virtual ECPoint DecodePoint(byte[] encoded) { ECPoint eCPoint = null; int num = (FieldSize + 7) / 8; byte b = encoded[0]; switch (b) { case 0: if (encoded.Length != 1) throw new ArgumentException("Incorrect length for infinity encoding", "encoded"); eCPoint = Infinity; break; case 2: case 3: { if (encoded.Length != num + 1) throw new ArgumentException("Incorrect length for compressed encoding", "encoded"); int yTilde = b & 1; BigInteger x3 = new BigInteger(1, encoded, 1, num); eCPoint = DecompressPoint(yTilde, x3); if (!eCPoint.ImplIsValid(true, true)) throw new ArgumentException("Invalid point"); break; } case 4: { if (encoded.Length != 2 * num + 1) throw new ArgumentException("Incorrect length for uncompressed encoding", "encoded"); BigInteger x2 = new BigInteger(1, encoded, 1, num); BigInteger y = new BigInteger(1, encoded, 1 + num, num); eCPoint = ValidatePoint(x2, y); break; } case 6: case 7: { if (encoded.Length != 2 * num + 1) throw new ArgumentException("Incorrect length for hybrid encoding", "encoded"); BigInteger x = new BigInteger(1, encoded, 1, num); BigInteger bigInteger = new BigInteger(1, encoded, 1 + num, num); if (bigInteger.TestBit(0) != (b == 7)) throw new ArgumentException("Inconsistent Y coordinate in hybrid encoding", "encoded"); eCPoint = ValidatePoint(x, bigInteger); break; } default: throw new FormatException("Invalid point encoding " + b.ToString()); } if (b != 0 && eCPoint.IsInfinity) throw new ArgumentException("Invalid infinity encoding", "encoded"); return eCPoint; } } }