E mais um passo concluído...
Já tenho a função para a operação Add() a funcionar. Mais uma vez deixo aqui o código para me ir servindo quase como que um snapshot do que vou fazendo. Amanhã talvez não pegue nisto porque vou ter uma brincadeira de amigos e sou capaz de não chegar a casa direito. heheh
O próximo passo é uma função Multiply() que vai usar estas duas Double() e Add().
#include
#include
#include
typedef struct{
mpz_t x;
mpz_t y;
}gmp_coord;
void ecdsa_double(gmp_coord point, gmp_coord* newPoint,
mpz_t opa, mpz_t opP){
mpz_t opPow, opSum, opMult, opInv, opSlope, opSub;
mpz_t tmp, tmp1, tmp2, tmp3;
mpz_inits(opPow, opSum, opMult, opInv, opSlope, opSub, NULL);
mpz_inits(tmp, tmp1, tmp2, tmp3, NULL);
// Compute the operations needed in the numerator of (3X² + a) / (2Y)
mpz_pow_ui(opPow, point.x, 2); // X²
mpz_set_ui(tmp, 3);
mpz_mul(opMult, opPow, tmp); // 3X²
mpz_add(opSum, opMult, opa); // 3X² + a
// Compute the operations needed in the denominator of (3X² + a) / (2Y)
mpz_set_ui(tmp1, 2);
mpz_mul(tmp2, point.y, tmp1); // 2Y
mpz_invert(opInv, tmp2, opP); // 1/(2Y)
// Compute the operation needed in the equation (3X² + a) / (2Y)
mpz_mul(tmp3, opSum, opInv); // (3X² + a) / (2Y)
// Compute the operation ((3X² + a) / (2Y)) % p
mpz_mod(opSlope, tmp3, opP);
// Compute the new X coord of the doubled point
mpz_inits(opPow, opMult, NULL);
mpz_pow_ui(opPow, opSlope, 2); // opSlope²
mpz_mul(opMult, point.x, tmp1); // 2X
mpz_sub(opSub, opPow, opMult); // opSlope² - 2x
mpz_mod(newPoint->x, opSub, opP); // (opSlope² - 2x) % p
// Compute the new Y coord of the doubled point
mpz_inits(opSub, opMult, tmp, NULL);
mpz_sub(opSub, point.x, newPoint->x); // (x - X)
mpz_mul(opMult, opSlope, opSub); // opSlope(x - X)
mpz_sub(tmp, opMult, point.y); // opSlope(x - X) - y
mpz_mod(newPoint->y, tmp, opP); // (opSlope(x - X) - y) % p
mpz_clears(opPow, opSum, opMult, opInv, opSlope, opSub, NULL);
mpz_clears(tmp, tmp1, tmp2, tmp3, NULL);
}
int ecdsa_add(gmp_coord pointa, gmp_coord pointb, gmp_coord* newPoint,
mpz_t opA, mpz_t opP){
mpz_t opSlope, opSub, opSub1, opInv, opPow, opMult;
mpz_inits(opSlope, opSub, opSub1, opInv, opPow, opMult, NULL);
if(!(mpz_cmp(pointa.x, pointb.x) && mpz_cmp(pointa.y, pointb.y))){
ecdsa_double(pointa, newPoint, opA, opP);
}else{
// Computation of opSlope = (y - Y) / (x - X)
mpz_sub(opSub, pointa.y, pointb.y); // (y - Y)
mpz_sub(opSub1, pointa.x, pointb.x); // (x - X)
mpz_invert(opInv, opSub1, opP); // 1 / (x - X)
mpz_mul(opMult, opSub, opInv); // (y - Y) * (1 / (x - X))
mpz_mod(opSlope, opMult, opP); // (y - Y) * (1 / (x - X)) % p
// Computation of nX = opSlope² - x - X
mpz_inits(opPow, opSub, opSub1, NULL);
mpz_pow_ui(opPow, opSlope, 2); // opSlope²
mpz_sub(opSub, opPow, pointa.x); // opSlope² - x
mpz_sub(opSub1, opSub, pointb.x); // (opSlope² - x) - X
mpz_mod(newPoint->x, opSub1, opP);// ((opSlope² - x) - X) % p
// Computation of nY = opSlope(x - nX) - Y
mpz_inits(opSub, opMult, opSub1, NULL);
mpz_sub(opSub, pointa.x, newPoint->x); // (x - nX)
mpz_mul(opMult, opSlope, opSub); // opSlope(x - nX)
mpz_sub(opSub1, opMult, pointa.y); // opSlope(x - nX) - Y
mpz_mod(newPoint->y, opSub1, opP);// (opSlope(x - nX) - Y) % p
}
mpz_clears(opSlope, opSub, opSub1, opInv, opPow, opMult, NULL);
return 0;
}
int main(void){
mpz_t a, b, n, P;
gmp_coord G, pointP, doubleP, pointQ;
gmp_coord pointAdd;
mpz_inits(a, b, n, P, G.x, G.y, NULL);
mpz_inits(pointP.x, pointP.y, doubleP.x, doubleP.y, pointQ.x, pointQ.y, pointAdd.x, pointAdd.y, NULL);
mpz_set_str(a, "0000000000000000000000000000000000000000000000000000000000000000", 16);
mpz_set_str(b, "0000000000000000000000000000000000000000000000000000000000000007", 16);
mpz_set_str(n, "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16);
// mpz_set_str(P, "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc2f", 16);
mpz_set_str(P, "61", 16);
mpz_set_str(G.x, "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", 16);
mpz_set_str(G.y, "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", 16);
mpz_set_str(pointP.x, "3d", 16); // 61
mpz_set_str(pointP.y, "45", 16); // 69
mpz_set_str(pointQ.x, "15", 16); // 15
mpz_set_str(pointQ.y, "1b", 16); // 27
ecdsa_double(pointP, &doubleP, a, P);
gmp_printf("2P.x: 0x%Zx =-= 2P.y: 0x%Zx\n", doubleP.x, doubleP.y);
gmp_printf("2P.x: %Zd =-= 2P.y: %Zd\n", doubleP.x, doubleP.y);
ecdsa_add(pointP, pointQ, &pointAdd, a, P);
gmp_printf("(P + Q).x: %Zd =-= (P + Q).y: %Zd\n", pointAdd.x, pointAdd.y);
mpz_clears(a, b, n, P, G.x, G.y, pointP.x, pointP.y, doubleP.x, doubleP.y, pointQ.x, pointQ.y, pointAdd.x, pointAdd.y, NULL);
return 0;
}