/// <summary> /// Convert ECC point to Jacobian. /// </summary> /// <param name="p">ECC point.</param> /// <param name="A"></param> /// <param name="P">Prime number.</param> /// <returns></returns> private static GXEccPoint JacobianDouble(GXEccPoint p, GXBigInteger A, GXBigInteger P) { GXBigInteger ysq = new GXBigInteger(p.y); ysq.Multiply(p.y); ysq.Mod(P); GXBigInteger S = new GXBigInteger(p.x); S.Multiply(new GXBigInteger(4)); S.Multiply(ysq); S.Mod(P); GXBigInteger M = new GXBigInteger(p.x); M.Multiply(p.x); M.Multiply(new GXBigInteger(3)); GXBigInteger tmp = new GXBigInteger(p.z); tmp.Multiply(p.z); tmp.Multiply(p.z); tmp.Multiply(p.z); tmp.Multiply(A); M.Add(tmp); M.Mod(P); //nx GXBigInteger nx = new GXBigInteger(M); nx.Multiply(M); tmp = new GXBigInteger(S); tmp.Multiply(new GXBigInteger(2)); nx.Sub(tmp); nx.Mod(P); //ny GXBigInteger ny = new GXBigInteger(S); ny.Sub(nx); ny.Multiply(M); tmp = new GXBigInteger(ysq); tmp.Multiply(ysq); tmp.Multiply(new GXBigInteger(8)); ny.Sub(tmp); ny.Mod(P); //nz GXBigInteger nz = new GXBigInteger(p.y); nz.Multiply(p.z); nz.Multiply(new GXBigInteger(2)); nz.Mod(P); return(new GXEccPoint(nx, ny, nz)); }
public void Inv(GXBigInteger value) { if (!IsZero) { GXBigInteger lm = new GXBigInteger(1); GXBigInteger hm = new GXBigInteger(0); GXBigInteger low = new GXBigInteger(this); low.Mod(value); GXBigInteger high = new GXBigInteger(value); while (!(low.IsZero || low.IsOne)) { GXBigInteger r = new GXBigInteger(high); r.Div(low); GXBigInteger tmp = new GXBigInteger(lm); tmp.Multiply(r); GXBigInteger nm = new GXBigInteger(hm); nm.Sub(tmp); tmp = new GXBigInteger(low); tmp.Multiply(r); high.Sub(tmp); // lm, low, hm, high = nm, new, lm, low tmp = low; low = new GXBigInteger(high); high = tmp; hm = new GXBigInteger(lm); lm = new GXBigInteger(nm); } Data = lm.Data; negative = lm.negative; Mod(value); } }
public void Div(GXBigInteger value) { GXBigInteger current = new GXBigInteger(1); GXBigInteger denom = new GXBigInteger(value); GXBigInteger tmp = new GXBigInteger(this); bool neq = negative; negative = false; try { // while denom < this. while (denom.Compare(this) == -1) { current.Lshift(1); denom.Lshift(1); } //If overflow. if (denom.Compare(this) == 1) { if (current.IsOne) { Clear(); return; } Clear(); current.Rshift(1); denom.Rshift(1); while (!current.IsZero) { int r = tmp.Compare(denom); if (r == 1) { tmp.Sub(denom); Add(current); } else if (r == 0) { Add(current); break; } current.Rshift(1); denom.Rshift(1); } current.Data = Data; } } finally { negative = neq; } Data = current.Data; changed = true; }
public void Div(GXBigInteger value) { GXBigInteger current = new GXBigInteger(1); GXBigInteger denom = new GXBigInteger(value); GXBigInteger tmp = new GXBigInteger(this); bool neq = negative; negative = false; try { //Shift UInt32 values to make this faster. if (denom.Count < Count - 1) { UInt32[] tmp2 = new UInt32[Count - denom.Count - 1]; //Append UInt32 values. current.InsertRange(0, tmp2); denom.InsertRange(0, tmp2); current.changed = denom.changed = true; } // while denom < this. while (denom.Compare(this) == -1) { current.Lshift(1); denom.Lshift(1); } //If overflow. if (denom.Compare(this) == 1) { if (current.IsOne) { Clear(); return; } Clear(); current.Rshift(1); denom.Rshift(1); while (!current.IsZero) { int r = tmp.Compare(denom); if (r == 1) { tmp.Sub(denom); Add(current); } else if (r == 0) { Add(current); break; } current.Rshift(1); denom.Rshift(1); } current.Data = Data; } } finally { negative = neq; } Data = current.Data; changed = true; }
public void Sub(GXBigInteger value) { int c = Compare(value); if (c == 0) { Clear(); } else if (value.negative || c == -1) { if (!value.negative && !negative) { //If biger value is decreased from smaller value. GXBigInteger tmp = new GXBigInteger(value); tmp.Sub(this); Clear(); AddRange(tmp.Data); Count = tmp.Count; negative = true; changed = true; } else { //If negative value is decreased from the value. bool ret = value.negative; value.negative = false; try { Add(value); } finally { value.negative = ret; negative = !ret; } } } else { if (!value.IsZero) { if (IsZero) { negative = true; Clear(); AddRange(value.Data); Count = value.Count; } else { while (Count < value.Count) { Add(0); } byte borrow = 0; UInt64 tmp; int pos; for (pos = 0; pos != value.Count; ++pos) { tmp = Data[pos]; tmp += 0x100000000; tmp -= value.Data[pos]; tmp -= borrow; Data[pos] = (UInt32)tmp; borrow = (byte)((tmp < 0x100000000) ? 1 : 0); } if (borrow != 0) { for (; pos != Count; ++pos) { tmp = Data[pos]; tmp += 0x100000000; tmp -= borrow; Data[pos] = (UInt32)tmp; borrow = (byte)((tmp < 0x100000000) ? 1 : 0); if (borrow == 0) { break; } } } } changed = true; } } }
/// <summary> /// Y^2 = X^3 + A*X + B (mod p) /// </summary> /// <param name="p"></param> /// <param name="q"></param> /// <param name="A"></param> /// <param name="P">Prime number</param> private static void JacobianAdd(GXEccPoint p, GXEccPoint q, GXBigInteger A, GXBigInteger P) { if (!(p.y.IsZero || q.y.IsZero)) { GXBigInteger U1 = new GXBigInteger(p.x); U1.Multiply(q.z); U1.Multiply(q.z); U1.Mod(P); GXBigInteger U2 = new GXBigInteger(p.z); U2.Multiply(p.z); U2.Multiply(q.x); U2.Mod(P); GXBigInteger S1 = new GXBigInteger(p.y); S1.Multiply(q.z); S1.Multiply(q.z); S1.Multiply(q.z); S1.Mod(P); GXBigInteger S2 = new GXBigInteger(q.y); S2.Multiply(p.z); S2.Multiply(p.z); S2.Multiply(p.z); S2.Mod(P); if (U1.Compare(U2) == 0) { if (S1.Compare(S2) != 0) { p.x = p.y = new GXBigInteger(0); p.z = new GXBigInteger(1); } else { p.x = A; p.y = P; } } //H GXBigInteger H = U2; H.Sub(U1); //R GXBigInteger R = S2; R.Sub(S1); GXBigInteger H2 = new GXBigInteger(H); H2.Multiply(H); H2.Mod(P); GXBigInteger H3 = new GXBigInteger(H); H3.Multiply(H2); H3.Mod(P); GXBigInteger U1H2 = new GXBigInteger(U1); U1H2.Multiply(H2); U1H2.Mod(P); GXBigInteger tmp = new GXBigInteger(2); tmp.Multiply(U1H2); //nx GXBigInteger nx = new GXBigInteger(R); nx.Multiply(R); nx.Sub(H3); nx.Sub(tmp); nx.Mod(P); //ny GXBigInteger ny = R; tmp = new GXBigInteger(U1H2); tmp.Sub(nx); ny.Multiply(tmp); tmp = new GXBigInteger(S1); tmp.Multiply(H3); ny.Sub(tmp); ny.Mod(P); //nz GXBigInteger nz = H; nz.Multiply(p.z); nz.Multiply(q.z); nz.Mod(P); p.x = nx; p.y = ny; p.z = nz; } }