]> git.meshlink.io Git - meshlink/blob - src/ed25519/add_scalar.c
Use the canonical address exclusively for making outgoing meta-connections.
[meshlink] / src / ed25519 / add_scalar.c
1 #include "ed25519.h"
2 #include "ge.h"
3 #include "sc.h"
4
5
6 /* see http://crypto.stackexchange.com/a/6215/4697 */
7 void ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar) {
8     const unsigned char SC_1[32] = {1}; /* scalar with value 1 */
9     
10     unsigned char n[32]; 
11     ge_p3 nB;
12     ge_p1p1 A_p1p1;
13     ge_p3 A;
14     ge_p3 public_key_unpacked;
15     ge_cached T;
16
17     int i;
18
19     /* copy the scalar and clear highest bit */
20     for (i = 0; i < 31; ++i) {
21         n[i] = scalar[i];
22     }
23     n[31] = scalar[31] & 127;
24
25     /* private key: a = n + t */
26     if (private_key) {
27         sc_muladd(private_key, SC_1, n, private_key);
28     }
29
30     /* public key: A = nB + T */
31     if (public_key) {
32         /* if we know the private key we don't need a point addition, which is faster */
33         /* using a "timing attack" you could find out whether or not we know the private
34            key, but this information seems rather useless - if this is important pass
35            public_key and private_key separately in 2 function calls */
36         if (private_key) {
37             ge_scalarmult_base(&A, private_key);
38         } else {
39             /* unpack public key into T */
40             ge_frombytes_negate_vartime(&public_key_unpacked, public_key);
41             fe_neg(public_key_unpacked.X, public_key_unpacked.X); // undo negate
42             fe_neg(public_key_unpacked.T, public_key_unpacked.T); // undo negate
43             ge_p3_to_cached(&T, &public_key_unpacked);
44
45             /* calculate n*B */
46             ge_scalarmult_base(&nB, n);
47
48             /* A = n*B + T */
49             ge_add(&A_p1p1, &nB, &T);
50             ge_p1p1_to_p3(&A, &A_p1p1);
51         }
52             
53         /* pack public key */
54         ge_p3_tobytes(public_key, &A);
55     }
56 }