1 #include "ed25519.h"
2 #include "ge.h"
3 #include "sc.h"
4 #include "sha512.h"
5 
6 
7 /* see http://crypto.stackexchange.com/a/6215/4697 */
ed25519_add_scalar(unsigned char * public_key,unsigned char * private_key,const unsigned char * scalar)8 void ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar) {
9     const unsigned char SC_1[32] = {1}; /* scalar with value 1 */
10 
11     unsigned char n[32];
12     ge_p3 nB;
13     ge_p1p1 A_p1p1;
14     ge_p3 A;
15     ge_p3 public_key_unpacked;
16     ge_cached T;
17 
18     sha512_context hash;
19     unsigned char hashbuf[64];
20 
21     int i;
22 
23     /* copy the scalar and clear highest bit */
24     for (i = 0; i < 31; ++i) {
25         n[i] = scalar[i];
26     }
27     n[31] = scalar[31] & 127;
28 
29     /* private key: a = n + t */
30     if (private_key) {
31         sc_muladd(private_key, SC_1, n, private_key);
32 
33         // https://github.com/orlp/ed25519/issues/3
34         sha512_init(&hash);
35         sha512_update(&hash, private_key + 32, 32);
36         sha512_update(&hash, scalar, 32);
37         sha512_final(&hash, hashbuf);
38         for (i = 0; i < 32; ++i) {
39             private_key[32 + i] = hashbuf[i];
40         }
41     }
42 
43     /* public key: A = nB + T */
44     if (public_key) {
45         /* if we know the private key we don't need a point addition, which is faster */
46         /* using a "timing attack" you could find out wether or not we know the private
47            key, but this information seems rather useless - if this is important pass
48            public_key and private_key seperately in 2 function calls */
49         if (private_key) {
50             ge_scalarmult_base(&A, private_key);
51         } else {
52             /* unpack public key into T */
53             ge_frombytes_negate_vartime(&public_key_unpacked, public_key);
54             fe_neg(public_key_unpacked.X, public_key_unpacked.X); /* undo negate */
55             fe_neg(public_key_unpacked.T, public_key_unpacked.T); /* undo negate */
56             ge_p3_to_cached(&T, &public_key_unpacked);
57 
58             /* calculate n*B */
59             ge_scalarmult_base(&nB, n);
60 
61             /* A = n*B + T */
62             ge_add(&A_p1p1, &nB, &T);
63             ge_p1p1_to_p3(&A, &A_p1p1);
64         }
65 
66         /* pack public key */
67         ge_p3_tobytes(public_key, &A);
68     }
69 }
70