int ecCheck (const ecPoint *p) /* confirm that y^2 + x*y = x^3 + EC_B for point p */ { gfPoint t1, t2, t3, b; b[0] = 1; b[1] = EC_B; gfSquare (t1, p->y); gfMultiply (t2, p->x, p->y); gfAdd (t1, t1, t2); /* t1 := y^2 + x*y */ gfSquare (t2, p->x); gfMultiply (t3, t2, p->x); gfAdd (t2, t3, b); /*/ t2 := x^3 + EC_B */ return gfEqual (t1, t2); } /* ecCheck */
void RSCoder16::MakeEncoderMatrix() { // Create Cauchy encoder generator matrix. Skip trivial "1" diagonal rows, // which would just copy source data to destination. for (uint I = 0; I < NR; I++) for (uint J = 0; J < ND; J++) MX[I * ND + J] = gfInv( gfAdd( (I+ND), J) ); }
void ecSub (ecPoint *p, const ecPoint *r) /* sets p := p - r */ { ecPoint t; gfCopy (t.x, r->x); gfAdd (t.y, r->x, r->y); ecAdd (p, &t); } /* ecSub */
int ecCalcY (ecPoint *p, int ybit) /* given the x coordinate of p, evaluate y such that y^2 + x*y = x^3 + EC_B */ { gfPoint a, b, t; b[0] = 1; b[1] = EC_B; if (p->x[0] == 0) { /* elliptic equation reduces to y^2 = EC_B: */ gfSquareRoot (p->y, EC_B); return 1; } /* evaluate alpha = x^3 + b = (x^2)*x + EC_B: */ gfSquare (t, p->x); /* keep t = x^2 for beta evaluation */ gfMultiply (a, t, p->x); gfAdd (a, a, b); /* now a == alpha */ if (a[0] == 0) { p->y[0] = 0; /* destroy potentially sensitive data: */ gfClear (a); gfClear (t); return 1; } /* evaluate beta = alpha/x^2 = x + EC_B/x^2 */ gfSmallDiv (t, EC_B); gfInvert (a, t); gfAdd (a, p->x, a); /* now a == beta */ /* check if a solution exists: */ if (gfTrace (a) != 0) { /* destroy potentially sensitive data: */ gfClear (a); gfClear (t); return 0; /* no solution */ } /* solve equation t^2 + t + beta = 0 so that gfYbit(t) == ybit: */ gfQuadSolve (t, a); if (gfYbit (t) != ybit) { t[1] ^= 1; } /* compute y = x*t: */ gfMultiply (p->y, p->x, t); /* destroy potentially sensitive data: */ gfClear (a); gfClear (t); return 1; } /* ecCalcY */
void ecDouble (ecPoint *p) /* sets p := 2*p */ { gfPoint lambda, t1, t2; /* evaluate lambda = x + y/x: */ gfInvert (t1, p->x); gfMultiply (lambda, p->y, t1); gfAdd (lambda, lambda, p->x); /* evaluate x3 = lambda^2 + lambda: */ gfSquare (t1, lambda); gfAdd (t1, t1, lambda); /* now t1 = x3 */ /* evaluate y3 = x^2 + lambda*x3 + x3: */ gfSquare (p->y, p->x); gfMultiply (t2, lambda, t1); gfAdd (p->y, p->y, t2); gfAdd (p->y, p->y, t1); /* deposit the value of x3: */ gfCopy (p->x, t1); } /* ecDouble */
static int gfSlowTrace (const gfPoint p) /* slowly evaluates to the trace of p (or an error code) */ { int i; gfPoint t; assert (logt != NULL && expt != NULL); assert (p != NULL); gfCopy (t, p); for (i = 1; i < GF_M; i++) { gfSquare (t, t); gfAdd (t, t, p); } return t[0] != 0; } /* gfSlowTrace */
void RSCoder16::MakeDecoderMatrix() { // Create Cauchy decoder matrix. Skip trivial rows matching valid data // units and containing "1" on main diagonal. Such rows would just copy // source data to destination and they have no real value for us. // Include rows only for broken data units and replace them by first // available valid recovery code rows. for (uint Flag=0, R=ND, Dest=0; Flag < ND; Flag++) if (!ValidFlags[Flag]) // For every broken data unit. { while (!ValidFlags[R]) // Find a valid recovery unit. R++; for (uint J = 0; J < ND; J++) // And place its row to matrix. MX[Dest*ND + J] = gfInv( gfAdd(R,J) ); Dest++; R++; } }
void ecAdd (ecPoint *p, const ecPoint *q) /* sets p := p + q */ { gfPoint lambda, t, tx, ty, x3; /* first check if there is indeed work to do (q != 0): */ if (q->x[0] != 0 || q->y[0] != 0) { if (p->x[0] != 0 || p->y[0] != 0) { /* p != 0 and q != 0 */ if (gfEqual (p->x, q->x)) { /* either p == q or p == -q: */ if (gfEqual (p->y, q->y)) { /* points are equal; double p: */ ecDouble (p); } else { /* must be inverse: result is zero */ /* (should assert that q->y = p->x + p->y) */ p->x[0] = p->y[0] = 0; } } else { /* p != 0, q != 0, p != q, p != -q */ /* evaluate lambda = (y1 + y2)/(x1 + x2): */ gfAdd (ty, p->y, q->y); gfAdd (tx, p->x, q->x); gfInvert (t, tx); gfMultiply (lambda, ty, t); /* evaluate x3 = lambda^2 + lambda + x1 + x2: */ gfSquare (x3, lambda); gfAdd (x3, x3, lambda); gfAdd (x3, x3, tx); /* evaluate y3 = lambda*(x1 + x3) + x3 + y1: */ gfAdd (tx, p->x, x3); gfMultiply (t, lambda, tx); gfAdd (t, t, x3); gfAdd (p->y, t, p->y); /* deposit the value of x3: */ gfCopy (p->x, x3); } } else { /* just copy q into p: */ gfCopy (p->x, q->x); gfCopy (p->y, q->y); } } } /* ecAdd */
// ----------------------------------------------------------------------------- int main () // ----------------------------------------------------------------------------- { // verify basic operations (mul, add, div): // a+b = b+a // a*b = b*a // a+(b+c) = (a+b)+c // a*(b*c) = (a*b)*c // a*c + b*c = (a+b)*c // a*(b/a) = b (if a != 0) gfInit(); for (int a=0; a<GF_N; a++) { for (int b=0; b<GF_N; b++) { if (gfAdd(a, b) != gfAdd(b, a)) return 1; if (gfMul(a, b) != gfMul(b, a)) return 2; if (gfMul(a, b) != gfMul(b, a)) return 2; for (int c=0; c<GF_N; c++) { if (gfAdd(a, gfAdd(b, c)) != gfAdd(gfAdd(a, b), c)) return 3; if (gfMul(a, gfMul(b, c)) != gfMul(gfMul(a, b), c)) return 4; if (gfAdd(gfMul(a, c), gfMul(b, c)) != gfMul(gfAdd(a, b), c)) return 5; } if (a != GF_0) if (gfMul(a, gfDiv(b, a)) != b) return 6; } } // verify polynomial operations: // A = BQ + R const int M = GF_N; // max deg gfExp A[M+1]; int nA; gfExp B[M+1]; int nB; gfExp Q[M+1]; int nQ; gfExp R1[M+2]; gfExp* R = R1 + 1; int nR; gfExp Z[M+1]; int nZ; gfExp Z1[2*M]; int nZ1; gfExp Z2[2*M]; int nZ2; gfExp* P = R; int nP; // alias gfExp* N = B; int nN; // alias gfExp* Y = Q; int nY; // alias gfExp Mem[8*(M+1) + 3]; // // -------------------- test polDiv, polMul, gfPolAdd(): -------------------- // for (int test=0; test<100000; test++) { // // // clear all -- should not be required: // // for (int i=0; i<=M; i++) // // A[i] = B[i] = Q[i] = R[i] = Z[i] = 0; // // R[-1] = 0; // nB = randInt(0, M); // nA = randInt(nB, M); // randPol(A, nA); // randPol(B, nB); // if (gfPolDeg(B, nB) == -1) // avoid dividing by B=0 // continue; // nB = polDiv(A, nA, B, nB, Q, &nQ, R, &nR); // nZ = gfPolMul(Q, nQ, B, nB, Z); // B * Q // if (nZ > nA) // return 7; // nZ = gfPolAdd(Z, nZ, R, nR, Z); // + R // if (! polCmp(Z, A, nZ, nA)) // return 8; // } // // -------------------- test gfPolEEA(): -------------------- // for (int test=0; test<100000; test++) { // nN = randInt(1, M); // nA = randInt(0, nN-1); // randPol(A, nA); // randPol(N, nN); // if (gfPolDeg(A, nA) == -1) // avoid dividing by A=0 // continue; // gfPolEEA(N, nN, A, nA, P, &nP, Q, &nQ, Mem); // nZ1 = gfPolMul(P, nP, N, nN, Z1); // nZ2 = gfPolMul(Q, nQ, A, nA, Z2); // if (! polCmp(Z1, Z2, nZ1, nZ2)) // return 9; // } // -------------------- test gfPolEvalSeq() against gfPolEval(): -------------------- for (int test=0; test<10000; test++) { nA = randInt(0, GF_N - 2); // limit of gfPolEvalSeq() nY = randInt(0, M); gfVec* Yv = Y; randPol(A, nA); gfExp x = GF_Z(1);//randE1(); gfPolEvalSeq(A, nA, Yv, nY, x); for (int i=0; i<=nY; i++) { gfExp y2 = gfPolEval(A, nA, x); gfExp y1 = gfV2E[Yv[nY-i]]; if (y2 != y1) return 10; x = gfMul(x, GF_Z(1)); } } return 0; }
void ecNegate (ecPoint *p) /* sets p := -p */ { gfAdd (p->y, p->x, p->y); } /* ecNegate */