| #include "ed25519.h" |
| #include "ge.h" |
| #include "sc.h" |
| #include "sha512.h" |
| |
| |
| /* 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; |
| |
| sha512_context hash; |
| unsigned char hashbuf[64]; |
| |
| 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); |
| |
| // https://github.com/orlp/ed25519/issues/3 |
| sha512_init(&hash); |
| sha512_update(&hash, private_key + 32, 32); |
| sha512_update(&hash, scalar, 32); |
| sha512_final(&hash, hashbuf); |
| for (i = 0; i < 32; ++i) { |
| private_key[32 + i] = hashbuf[i]; |
| } |
| } |
| |
| /* 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); |
| } |
| } |