summaryrefslogtreecommitdiffstats
path: root/3rd_party/ed25519/add_scalar.c
diff options
context:
space:
mode:
Diffstat (limited to '3rd_party/ed25519/add_scalar.c')
-rw-r--r--3rd_party/ed25519/add_scalar.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/3rd_party/ed25519/add_scalar.c b/3rd_party/ed25519/add_scalar.c
new file mode 100644
index 0000000..7528a7a
--- /dev/null
+++ b/3rd_party/ed25519/add_scalar.c
@@ -0,0 +1,69 @@
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 */
8void 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}