kmackay / micro-ecc

ECDH and ECDSA for 8-bit, 32-bit, and 64-bit processors.
BSD 2-Clause "Simplified" License
1.26k stars 460 forks source link

Point addition of same point #217

Open yasmineantille opened 1 year ago

yasmineantille commented 1 year ago

I am trying to use this library to assert the following: X + X = X * 2 where X is a point on the elliptic curve and adding it to itself should equal the result of scalar multiplication of the point with '2'. For the addition I've written the following method:

/* uECC_addition() function
Perform point addition for two valid points on the curve.

This function is only optimized for uECC_VLI_NATIVE_LITTLE_ENDIAN.

Usage: Compute the sum of two points on the curve. R = P + Q

Inputs:
    result  - The address where resulting point should be written to
    P       - The point P
    Q       - The point Q

Returns 1 if the sum point is valid, 0 if it is invalid.
 */
int uECC_addition(uint8_t * result, uint8_t * P, uint8_t * Q, uECC_Curve curve)
{
    const wordcount_t num_bytes = curve->num_bytes;
    const wordcount_t num_words = curve->num_words;

    // Allocate proper memory for the two points and output result in native type
    uECC_word_t _p[uECC_MAX_WORDS * 2];
    uECC_word_t _q[uECC_MAX_WORDS * 2];
    uECC_word_t _result[uECC_MAX_WORDS * 2];
    uECC_word_t X1[uECC_MAX_WORDS], Y1[uECC_MAX_WORDS], X2[uECC_MAX_WORDS], Y2[uECC_MAX_WORDS];
    uECC_word_t z[uECC_MAX_WORDS];

    // Convert points from uint8_t format to native format to check if valid points
    uECC_vli_bytesToNative(_p, P, num_bytes);
    uECC_vli_bytesToNative(_p + num_words, P + num_bytes, num_bytes);
    uECC_vli_bytesToNative(_q, Q, num_bytes);
    uECC_vli_bytesToNative(_q + num_words, Q + num_bytes, num_bytes);

    // Make sure receiving points are valid
    if (!uECC_valid_point(_p, curve) || !uECC_valid_point(_q, curve)) {
        return 5;
    }

    // convert points to projective coordinates
    uECC_vli_bytesToNative(X1, P, num_bytes);
    uECC_vli_bytesToNative(Y1, P + num_bytes, num_bytes);
    uECC_vli_bytesToNative(X2, Q, num_bytes);
    uECC_vli_bytesToNative(Y2, Q + num_bytes, num_bytes);

    uECC_vli_modSub(z, X2, X1, curve->p, num_words);
    XYcZ_add(X1, Y1, X2, Y2, curve);
    uECC_vli_modInv(z, z, curve->p, num_words);
    // Apply Z coordinate to the result
    apply_z(X2, Y2, z, curve);

    uECC_vli_set(_result, X2, num_words);
    uECC_vli_set(_result + num_words, Y2, num_words);

    // Check if the resulting point is on the curve
    if (!uECC_valid_point(_result, curve)) {
        return 0;
    }

    // Convert resulting point to uint8_t format
    uECC_vli_nativeToBytes(result, num_bytes, _q);
    uECC_vli_nativeToBytes(result + num_bytes, num_bytes, _q + num_words);

    return 1;
}

However, this does not return a valid point when input of P and Q is the same. Can you tell me if there is a bug in the code or if there seems to be something else going wrong? I'd appreciate the help!