public FastECPoint Multiply(FastInteger b) { if (b.Sign == -1) { throw new FormatException("The multiplicator cannot be negative"); } //b = b % Secp256k1.N; FastInteger exp = (b * 3) ^ b; FastECPoint result = FastECPoint.Infinity; FastECPoint affine = this.Normalize(); FastECPoint negative = affine.Negate(); int high = exp.BitsCount; FastInteger bit = FastInteger.One << high; for (int i = high; --i >= 0; bit >>= 1) { result = result.Twice(); if (!(exp & bit).IsZero) { result = result.Add(!(b & bit).IsZero ? negative : affine); } } result = result.Normalize(); return(result); }
public FastInteger ModPow(FastInteger power, FastInteger prime, Func <FastInteger, FastInteger> modPFunction) { FastInteger a = this; if (power.IsNegative) { a = a.ModInverse(prime); power = -power; } int highestBitPosition = power.Digits * 31 - 1; while (highestBitPosition >= 0 && !power.GetBitAt(highestBitPosition)) { highestBitPosition--; } FastInteger result = highestBitPosition < 0 ? One : a; for (int i = highestBitPosition; --i >= 0;) { result = modPFunction(result.Square()); if (power.GetBitAt(i)) { result = modPFunction(result * a); } } var diff = result - prime; return(diff.IsNegative ? result : diff); }
private static void remodP(ref FastInteger x) { while (x >= Secp256k1.FP) { x -= Secp256k1.FP; } while (x < 0) { x += Secp256k1.FP; } }
private static FastInteger modP(FastInteger x) { while (true) { var high = x >> 256; if (high.IsZero) { return(x); } x = (x & LowMask) + high * 0x1000003D1; } }
public FastInteger ShanksSqrt(FastInteger p, Func <FastInteger, FastInteger> modPFunction) { if (this.ModPow((p - 1) >> 1, p, modPFunction) == (p - 1)) { return(-1); } //No Sqrt Exists if ((p.LowestByte & 3) == 3) { var result = this.ModPow((p + 1) >> 2, p, modPFunction); return(result); } throw new NotImplementedException("Not a special prime modulo."); }
/// <summary> /// return this / n modulo p. /// </summary> /// <param name="n"></param> /// <param name="p"></param> /// <returns></returns> public FastInteger DivideModulo(FastInteger n, FastInteger p) { if (n.IsZero) { return(n); } if (p.IsZero) { return(p); } FastInteger a = this; //x * a + u1 * b = n FastInteger c = 0; //y * c + u2 * d = p FastInteger x = n; while (p.IsEven) { p >>= 1; } FastInteger y = p; while (x.IsEven) { x >>= 1; a = a.IsEven ? a >> 1 : (a + p) >> 1; } while (!x.IsZero) { while (x.IsEven) { x >>= 1; a = a.IsEven ? a >> 1 : (a + p) >> 1; } FastInteger diff = x - y; if (diff.IsNegative) { y = x; x = -diff; FastInteger temp = a; a = c; c = temp; } else { x = diff; } a -= c; if (a.IsNegative) { a += p; } } return(c); }
public static byte[] ToByteArrayUnsigned(this FastInteger i, bool bigEndian) { byte[] bytes = i.ToByteArray(); int length = bytes.Length; while (length > 1 && ((bytes[length - 1] == 0 && bytes[length - 2] < 128) || (bytes[length - 1] == 255 && bytes[length - 2] >= 128))) { length--; } Array.Resize(ref bytes, length); if (bigEndian) { Array.Reverse(bytes, 0, bytes.Length); } return(bytes); }
public static FastInteger operator +(FastInteger number1, FastInteger number2) { int digits1 = number1.Digits; int digits2 = number2.Digits; if (digits1 < digits2) { int temp1 = digits1; digits1 = digits2; digits2 = temp1; FastInteger temp2 = number1; number1 = number2; number2 = temp2; } if (number2.IsZero) { return(number1); } int bitcount = 1 + Math.Max(number1.BitsCount, number2.BitsCount); int[] result = new int[(bitcount + 30) / 31]; int carry = 0; for (int i = 0; i < digits2; i++) { carry += (number1.bits[i] & LowMask) + (number2.bits[i] & LowMask); result[i] = carry & LowMask; carry = (carry >> 31) & 1; } for (int i = digits2; i < digits1; i++) { carry += (number1.bits[i] & LowMask) + number2.Extender; result[i] = carry & LowMask; carry = (carry >> 31) & 1; } carry += (number1.IsNegative ? -1 : 0) + (number2.IsNegative ? -1 : 0); if (carry == -1) { result[digits1 - 1] |= -1 << 31; } if (digits1 < result.Length) { result[digits1] = carry; } return(new FastInteger(result)); }
public static FastInteger operator ^(FastInteger x, FastInteger y) { if (x.Digits < y.Digits) { FastInteger temp = x; x = y; y = temp; } if (y.IsZero) { return(x); } int[] result = new int[x.Digits]; for (int i = y.Digits; --i >= 0;) { result[i] = (x.bits[i] ^ y.bits[i]) & LowMask; } for (int i = y.Digits; i < x.Digits; i++) { result[i] = (x.bits[i] ^ y.Extender) & LowMask; } result[result.Length - 1] |= (x.Extender ^ y.Extender) << 31; return(new FastInteger(result)); }
public FastECPoint(byte[] bytes, bool isCompressed) { this._x = bytes.Take(256 / 8).ToFastIntegerUnsigned(false); if (isCompressed) { var x2 = modP(this.X.Square()); var x3 = modP(x2 * this.X); this._y = (x3 + 7).ShanksSqrt(Secp256k1.FP, modP); byte lowerY = this._y.LowestByte; if (lowerY != bytes[256 / 8]) { this._y = Secp256k1.FP - this._y; lowerY = this._y.LowestByte; if (lowerY != bytes[256 / 8]) { throw new InvalidOperationException("Compressed bytes verification byte failed."); } } } else { this._y = bytes.Skip(256 / 8).Take(256 / 8).ToFastIntegerUnsigned(false); } }
public override string ToString() { FastInteger x = this; bool negative = x.IsNegative; if (negative) { x = -x; } StringBuilder sb = new StringBuilder(); int[] bits = new int[x.bits.Length]; x.bits.CopyTo(bits, 0); do { long mod = 0; for (int i = bits.Length; --i >= 0;) { mod = (mod << 31) + bits[i]; bits[i] = (int)Math.DivRem(mod, 10L, out mod); } sb.Append((char)('0' + mod)); } while (bits.Any(b => b != 0)); if (negative) { sb.Append('-'); } for (int i = 0, j = sb.Length - 1; i < j; i++, j--) { char c = sb[i]; sb[i] = sb[j]; sb[j] = c; } return(sb.ToString()); }
public FastInteger ModInverse(FastInteger p) { return(One.DivideModulo(this, p)); }
public static FastInteger ToFastInteger(this ulong[] bits) { FastInteger result = new FastInteger(bits.SelectMany(l => BitConverter.GetBytes(l)).Concat(Enumerable.Repeat((byte)0, 1)).ToArray()); return(result); }
public FastECPoint(FastInteger x, FastInteger y, bool isInfinity) { _x = x; _y = y; _isInfinity = isInfinity; }
public static FastInteger Abs(FastInteger number) { return(number.IsNegative ? -number : number); }
public static bool UnitTest() { Random random = new Random(1001); for (int i = 10000; --i >= 0;) { byte[] bytes1 = new byte[31 + random.Next(2)]; byte[] bytes2 = new byte[31 + random.Next(2)]; random.NextBytes(bytes1); random.NextBytes(bytes2); BigInteger n1 = new BigInteger(bytes1); BigInteger n2 = new BigInteger(bytes2); FastInteger f1 = new FastInteger(bytes1); FastInteger f2 = new FastInteger(bytes2); if (n1.ToString() != f1.ToString()) { System.Diagnostics.Debugger.Break(); } if (n2.ToString() != f2.ToString()) { System.Diagnostics.Debugger.Break(); } BigInteger a1 = n1 + n2; FastInteger a2 = f1 + f2; if (a1.ToString() != a2.ToString()) { var by1 = a1.ToByteArray(); var by2 = a2.ToByteArray(); System.Diagnostics.Debugger.Break(); } BigInteger s1 = n1 - n2; FastInteger s2 = f1 - f2; if (s1.ToString() != s2.ToString()) { var by1 = s1.ToByteArray(); var by2 = s2.ToByteArray(); System.Diagnostics.Debugger.Break(); } BigInteger m1 = n1 * n2; FastInteger m2 = f1 * f2; if (m1.ToString() != m2.ToString()) { System.Diagnostics.Debugger.Break(); } int shrvalue = random.Next(256) + 1; BigInteger sh1 = n1 >> shrvalue; FastInteger sh2 = f1 >> shrvalue; if (sh1.ToString() != sh2.ToString()) { System.Diagnostics.Debugger.Break(); } if ((-f1).ToString() != (-n1).ToString() || (-f2).ToString() != (-n2).ToString()) { System.Diagnostics.Debugger.Break(); } int shlvalue = random.Next(256) + 1; BigInteger shl1 = n1 << shlvalue; FastInteger shl2 = f1 << shlvalue; if (shl1.ToString() != shl2.ToString()) { System.Diagnostics.Debugger.Break(); } BigInteger and1 = n1 & n2; FastInteger and2 = f1 & f2; if (and1.ToString() != and2.ToString()) { System.Diagnostics.Debugger.Break(); } BigInteger xor1 = n1 ^ n2; FastInteger xor2 = f1 ^ f2; if (xor1.ToString() != xor2.ToString()) { System.Diagnostics.Debugger.Break(); } } return(true); }
public static FastInteger Square(this FastInteger x) { return(x * x); }
public FastECPoint(FastInteger x, FastInteger y) { _x = x; _y = y; }
public FastECPoint(FastInteger x, FastInteger y, FastInteger z, bool isInfinity) : this(x, y, isInfinity) { _z = z; }
public static string FastIntegerToHex(FastInteger value) { return(BytesToHex(value.ToByteArrayUnsigned(true))); }
public static string ToHex(this FastInteger b) { return(Hex.FastIntegerToHex(b)); }