Example #1
0
void ge_neg(ge_p3* r, const ge_p3 *p)
{
  fe_neg(r->X, p->X);
  fe_copy(r->Y, p->Y);
  fe_copy(r->Z, p->Z);
  fe_neg(r->T, p->T);
}
void ge_montx_to_p2(ge_p2* p, const fe u, const unsigned char ed_sign_bit)
{
  fe x, y, A, v, v2, iv, nx;

  fe_frombytes(A, A_bytes); 

  /* given u, recover edwards y */
  /* given u, recover v */
  /* given u and v, recover edwards x */

  fe_montx_to_edy(y, u);       /* y = (u - 1) / (u + 1) */

  fe_mont_rhs(v2, u);          /* v^2 = u(u^2 + Au + 1) */
  fe_sqrt(v, v2);              /* v = sqrt(v^2) */

  fe_mul(x, u, A);             /* x = u * sqrt(-(A+2)) */
  fe_invert(iv, v);            /* 1/v */
  fe_mul(x, x, iv);            /* x = (u/v) * sqrt(-(A+2)) */

  fe_neg(nx, x);               /* negate x to match sign bit */
  fe_cmov(x, nx, fe_isnegative(x) ^ ed_sign_bit);

  fe_copy(p->X, x);
  fe_copy(p->Y, y);
  fe_1(p->Z);

 /* POSTCONDITION: check that p->X and p->Y satisfy the Ed curve equation */
 /* -x^2 + y^2 = 1 + dx^2y^2 */
#ifndef NDEBUG
  {
  fe one, d, x2, y2, x2y2, dx2y2;

  unsigned char dbytes[32] = {
  0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75,
  0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00,
  0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c,
  0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52
  };
  
  fe_frombytes(d, dbytes);
  fe_1(one);
  fe_sq(x2, p->X);                /* x^2 */
  fe_sq(y2, p->Y);                /* y^2 */

  fe_mul(dx2y2, x2, y2);           /* x^2y^2 */
  fe_mul(dx2y2, dx2y2, d);         /* dx^2y^2 */
  fe_add(dx2y2, dx2y2, one);       /* dx^2y^2 + 1 */

  fe_neg(x2y2, x2);                /* -x^2 */
  fe_add(x2y2, x2y2, y2);          /* -x^2 + y^2 */

  assert(fe_isequal(x2y2, dx2y2));
  }
#endif
}
Example #3
0
/* see http://crypto.stackexchange.com/a/6215/4697 */
void ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar) {
    const unsigned char SC_1[32] = {1}; /* scalar with value 1 */
    
    unsigned char n[32]; 
    ge_p3 nB;
    ge_p1p1 A_p1p1;
    ge_p3 A;
    ge_p3 public_key_unpacked;
    ge_cached T;

    int i;

    /* copy the scalar and clear highest bit */
    for (i = 0; i < 31; ++i) {
        n[i] = scalar[i];
    }
    n[31] = scalar[31] & 127;

    /* private key: a = n + t */
    if (private_key) {
        sc_muladd(private_key, SC_1, n, private_key);
    }

    /* public key: A = nB + T */
    if (public_key) {
        /* if we know the private key we don't need a point addition, which is faster */
        /* using a "timing attack" you could find out wether or not we know the private
           key, but this information seems rather useless - if this is important pass
           public_key and private_key seperately in 2 function calls */
        if (private_key) {
            ge_scalarmult_base(&A, private_key);
        } else {
            /* unpack public key into T */
            ge_frombytes_negate_vartime(&public_key_unpacked, public_key);
            fe_neg(public_key_unpacked.X, public_key_unpacked.X); // undo negate
            fe_neg(public_key_unpacked.T, public_key_unpacked.T); // undo negate
            ge_p3_to_cached(&T, &public_key_unpacked);

            /* calculate n*B */
            ge_scalarmult_base(&nB, n);

            /* A = n*B + T */
            ge_add(&A_p1p1, &nB, &T);
            ge_p1p1_to_p3(&A, &A_p1p1);
        }
            
        /* pack public key */
        ge_p3_tobytes(public_key, &A);
    }
}
Example #4
0
/*
   Test if the public key can be uncommpressed and negate it (-X,Y,Z,-T)
   return 0 on success
 */
int ge_frombytes_negate_vartime(ge_p3 *p,const unsigned char *s)
{

    byte parity;
    byte x[F25519_SIZE];
    byte y[F25519_SIZE];
    byte a[F25519_SIZE];
    byte b[F25519_SIZE];
    byte c[F25519_SIZE];
    int ret = 0;

    /* unpack the key s */
    parity = s[31] >> 7;
    fe_copy(y, s);
    y[31] &= 127;

    fe_mul__distinct(c, y, y);
    fe_mul__distinct(b, c, ed25519_d);
    fe_add(a, b, f25519_one);
    fe_inv__distinct(b, a);
    fe_sub(a, c, f25519_one);
    fe_mul__distinct(c, a, b);
    fe_sqrt(a, c);
    fe_neg(b, a);
    fe_select(x, a, b, (a[0] ^ parity) & 1);

    /* test that x^2 is equal to c */
    fe_mul__distinct(a, x, x);
    fe_normalize(a);
    fe_normalize(c);
    ret |= ConstantCompare(a, c, F25519_SIZE);

    /* project the key s onto p */
    fe_copy(p->X, x);
    fe_copy(p->Y, y);
    fe_load(p->Z, 1);
    fe_mul__distinct(p->T, x, y);

    /* negate, the point becomes (-X,Y,Z,-T) */
    fe_neg(p->X,p->X);
    fe_neg(p->T,p->T);

    return ret;
}
Example #5
0
void ed25519_double(ge_p3 *r, const ge_p3 *p)
{
    /* Explicit formulas database: dbl-2008-hwcd
     *
     * source 2008 Hisil--Wong--Carter--Dawson,
     *     http://eprint.iacr.org/2008/522, Section 3.3
     * compute A = X1^2
     * compute B = Y1^2
     * compute C = 2 Z1^2
     * compute D = a A
     * compute E = (X1+Y1)^2-A-B
     * compute G = D + B
     * compute F = G - C
     * compute H = D - B
     * compute X3 = E F
     * compute Y3 = G H
     * compute T3 = E H
     * compute Z3 = F G
     */
    byte a[F25519_SIZE];
    byte b[F25519_SIZE];
    byte c[F25519_SIZE];
    byte e[F25519_SIZE];
    byte f[F25519_SIZE];
    byte g[F25519_SIZE];
    byte h[F25519_SIZE];

    /* A = X1^2 */
    fe_mul__distinct(a, p->X, p->X);

    /* B = Y1^2 */
    fe_mul__distinct(b, p->Y, p->Y);

    /* C = 2 Z1^2 */
    fe_mul__distinct(c, p->Z, p->Z);
    fe_add(c, c, c);

    /* D = a A (alter sign) */
    /* E = (X1+Y1)^2-A-B */
    fe_add(f, p->X, p->Y);
    fe_mul__distinct(e, f, f);
    fe_sub(e, e, a);
    fe_sub(e, e, b);

    /* G = D + B */
    fe_sub(g, b, a);

    /* F = G - C */
    fe_sub(f, g, c);

    /* H = D - B */
    fe_neg(h, b);
    fe_sub(h, h, a);

    /* X3 = E F */
    fe_mul__distinct(r->X, e, f);

    /* Y3 = G H */
    fe_mul__distinct(r->Y, g, h);

    /* T3 = E H */
    fe_mul__distinct(r->T, e, h);

    /* Z3 = F G */
    fe_mul__distinct(r->Z, f, g);
}