/** * Verifies a ecdsa signature. * * For a description of this algorithm see * https://en.wikipedia.org/wiki/Elliptic_Curve_DSA#Signature_verification_algorithm * * input: * x: x coordinate of the public key (32 bytes) * y: y coordinate of the public key (32 bytes) * e: hash to verify the signature of (32 bytes) * r: r value of the signature (32 bytes) * s: s value of the signature (32 bytes) * * return: * 0: signature is ok * -1: signature check failed the signature is invalid */ int ecc_ecdsa_validate(const uint32_t *x, const uint32_t *y, const uint32_t *e, const uint32_t *r, const uint32_t *s) { uint32_t w[8]; uint32_t tmp[16]; uint32_t u1[9]; uint32_t u2[9]; uint32_t tmp1_x[8]; uint32_t tmp1_y[8]; uint32_t tmp2_x[8]; uint32_t tmp2_y[8]; uint32_t tmp3_x[8]; uint32_t tmp3_y[8]; // 3. Calculate w = s^{-1} \pmod{n} fieldInv(s, ecc_order_m, ecc_order_r, w); // 4. Calculate u_1 = zw \pmod{n} fieldMult(e, w, tmp, arrayLength); fieldModO(tmp, u1, 16); // 4. Calculate u_2 = rw \pmod{n} fieldMult(r, w, tmp, arrayLength); fieldModO(tmp, u2, 16); // 5. Calculate the curve point (x_1, y_1) = u_1 * G + u_2 * Q_A. // tmp1 = u_1 * G ecc_ec_mult(ecc_g_point_x, ecc_g_point_y, u1, tmp1_x, tmp1_y); // tmp2 = u_2 * Q_A ecc_ec_mult(x, y, u2, tmp2_x, tmp2_y); // tmp3 = tmp1 + tmp2 ec_add(tmp1_x, tmp1_y, tmp2_x, tmp2_y, tmp3_x, tmp3_y); // TODO: this u_1 * G + u_2 * Q_A could be optimiced with Straus's algorithm. return isSame(tmp3_x, r, arrayLength) ? 0 : -1; }
int main(int argc, char* argv[]) { if(argc < 2) { printf("Usage: secp256r1mult K\n"); exit(-1); } str2hex((void*)sk, argv[1], strlen(argv[1])); ecc_ec_mult(ecc_g_point_x, ecc_g_point_y, sk, pkx, pky); //Print256(sk); fieldModO(pkx, pkx, 8); //Print256((unsigned char *)pkx); Print256_nbo((unsigned char *)pkx); printf("\n"); return 0; }
/** * Calculate the ecdsa signature. * * For a description of this algorithm see * https://en.wikipedia.org/wiki/Elliptic_Curve_DSA#Signature_generation_algorithm * * input: * d: private key on the curve secp256r1 (32 bytes) * e: hash to sign (32 bytes) * k: random data, this must be changed for every signature (32 bytes) * * output: * r: r value of the signature (36 bytes) * s: s value of the signature (36 bytes) * * return: * 0: everything is ok * -1: can not create signature, try again with different k. */ int ecc_ecdsa_sign(const uint32_t *d, const uint32_t *e, const uint32_t *k, uint32_t *r, uint32_t *s) { uint32_t tmp1[16]; uint32_t tmp2[9]; uint32_t tmp3[9]; if (isZero(k)) return -1; // 4. Calculate the curve point (x_1, y_1) = k * G. ecc_ec_mult(ecc_g_point_x, ecc_g_point_y, k, r, tmp1); // 5. Calculate r = x_1 \pmod{n}. fieldModO(r, r, 8); // 5. If r = 0, go back to step 3. if (isZero(r)) return -1; // 6. Calculate s = k^{-1}(z + r d_A) \pmod{n}. // 6. r * d fieldMult(r, d, tmp1, arrayLength); fieldModO(tmp1, tmp2, 16); // 6. z + (r d) tmp1[8] = add(e, tmp2, tmp1, 8); fieldModO(tmp1, tmp3, 9); // 6. k^{-1} fieldInv(k, ecc_order_m, ecc_order_r, tmp2); // 6. (k^{-1}) (z + (r d)) fieldMult(tmp2, tmp3, tmp1, arrayLength); fieldModO(tmp1, s, 16); // 6. If s = 0, go back to step 3. if (isZero(s)) return -1; return 0; }