| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
#ifndef CURVE25519_I64_H |
|
2
|
|
|
|
|
|
|
#define CURVE25519_I64_H 1 |
|
3
|
|
|
|
|
|
|
/* |
|
4
|
|
|
|
|
|
|
Modified by mko. |
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
*/ |
|
7
|
|
|
|
|
|
|
/* Generic 64-bit integer implementation of Curve25519 ECDH |
|
8
|
|
|
|
|
|
|
* Written by Matthijs van Duin, 200608242056 |
|
9
|
|
|
|
|
|
|
* Public domain. |
|
10
|
|
|
|
|
|
|
* |
|
11
|
|
|
|
|
|
|
* Based on work by Daniel J Bernstein, http://cr.yp.to/ecdh.html |
|
12
|
|
|
|
|
|
|
*/ |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
#include |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
typedef unsigned char k25519[32]; /* any type of key */ |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
extern const k25519 zero25519; /* 0 */ |
|
19
|
|
|
|
|
|
|
extern const k25519 prime25519; /* the prime 2^255-19 */ |
|
20
|
|
|
|
|
|
|
extern const k25519 order25519; /* group order (a prime near 2^252+2^124) */ |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
typedef k25519 pub25519; /* public key */ |
|
24
|
|
|
|
|
|
|
typedef k25519 priv25519; /* private key (for key agreement) */ |
|
25
|
|
|
|
|
|
|
typedef k25519 spriv25519; /* private key for signing */ |
|
26
|
|
|
|
|
|
|
typedef k25519 sec25519; /* shared secret */ |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
/********* KEY AGREEMENT *********/ |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
/* internal function - do not use directly */ |
|
33
|
|
|
|
|
|
|
void core25519(k25519 P, spriv25519 s, const priv25519 k, const k25519 G); |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
/* Private key clamping |
|
37
|
|
|
|
|
|
|
* k [out] your private key for key agreement |
|
38
|
|
|
|
|
|
|
* k [in] 32 random bytes |
|
39
|
|
|
|
|
|
|
*/ |
|
40
|
|
|
|
|
|
|
static inline |
|
41
|
6
|
|
|
|
|
|
void clamp25519(priv25519 k) { |
|
42
|
6
|
|
|
|
|
|
k[31] &= 0x7F; |
|
43
|
6
|
|
|
|
|
|
k[31] |= 0x40; |
|
44
|
6
|
|
|
|
|
|
k[ 0] &= 0xF8; |
|
45
|
6
|
|
|
|
|
|
} |
|
46
|
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
/* Key-pair generation |
|
50
|
|
|
|
|
|
|
* P [out] your public key |
|
51
|
|
|
|
|
|
|
* s [out] your private key for signing |
|
52
|
|
|
|
|
|
|
* k [out] your private key for key agreement |
|
53
|
|
|
|
|
|
|
* k [in] 32 random bytes |
|
54
|
|
|
|
|
|
|
* s may be NULL if you don't care |
|
55
|
|
|
|
|
|
|
* |
|
56
|
|
|
|
|
|
|
* WARNING: if s is not NULL, this function has data-dependent timing */ |
|
57
|
|
|
|
|
|
|
static inline |
|
58
|
|
|
|
|
|
|
void keygen25519(pub25519 P, spriv25519 s, priv25519 k) { |
|
59
|
|
|
|
|
|
|
clamp25519(k); |
|
60
|
|
|
|
|
|
|
core25519(P, s, k, NULL); |
|
61
|
|
|
|
|
|
|
} |
|
62
|
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
/* Key agreement |
|
66
|
|
|
|
|
|
|
* Z [out] shared secret (needs hashing before use) |
|
67
|
|
|
|
|
|
|
* k [in] your private key for key agreement |
|
68
|
|
|
|
|
|
|
* P [in] peer's public key |
|
69
|
|
|
|
|
|
|
* Buffers may overlap. */ |
|
70
|
|
|
|
|
|
|
static inline |
|
71
|
|
|
|
|
|
|
void curve25519(sec25519 Z, const priv25519 k, const pub25519 P) { |
|
72
|
|
|
|
|
|
|
core25519(Z, NULL, k, P); |
|
73
|
|
|
|
|
|
|
} |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
/********* DIGITAL SIGNATURES *********/ |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
/* deterministic EC-KCDSA |
|
79
|
|
|
|
|
|
|
* |
|
80
|
|
|
|
|
|
|
* s is the private key for signing |
|
81
|
|
|
|
|
|
|
* P is the corresponding public key |
|
82
|
|
|
|
|
|
|
* Z is the context data (signer public key or certificate, etc) |
|
83
|
|
|
|
|
|
|
* |
|
84
|
|
|
|
|
|
|
* signing: |
|
85
|
|
|
|
|
|
|
* |
|
86
|
|
|
|
|
|
|
* m = hash(Z, message) |
|
87
|
|
|
|
|
|
|
* x = hash(m, s) |
|
88
|
|
|
|
|
|
|
* keygen25519(Y, NULL, x); |
|
89
|
|
|
|
|
|
|
* r = hash(Y); |
|
90
|
|
|
|
|
|
|
* h = m XOR r |
|
91
|
|
|
|
|
|
|
* sign25519(v, h, x, s); |
|
92
|
|
|
|
|
|
|
* |
|
93
|
|
|
|
|
|
|
* output (v,r) as the signature |
|
94
|
|
|
|
|
|
|
* |
|
95
|
|
|
|
|
|
|
* verification: |
|
96
|
|
|
|
|
|
|
* |
|
97
|
|
|
|
|
|
|
* m = hash(Z, message); |
|
98
|
|
|
|
|
|
|
* h = m XOR r |
|
99
|
|
|
|
|
|
|
* verify25519(Y, v, h, P) |
|
100
|
|
|
|
|
|
|
* |
|
101
|
|
|
|
|
|
|
* confirm r == hash(Y) |
|
102
|
|
|
|
|
|
|
* |
|
103
|
|
|
|
|
|
|
* It would seem to me that it would be simpler to have the signer directly do |
|
104
|
|
|
|
|
|
|
* h = hash(m, Y) and send that to the recipient instead of r, who can verify |
|
105
|
|
|
|
|
|
|
* the signature by checking h == hash(m, Y). If there are any problems with |
|
106
|
|
|
|
|
|
|
* such a scheme, please let me know. |
|
107
|
|
|
|
|
|
|
* |
|
108
|
|
|
|
|
|
|
* Also, EC-KCDSA (like most DS algorithms) picks x random, which is a waste of |
|
109
|
|
|
|
|
|
|
* perfectly good entropy, but does allow Y to be calculated in advance of (or |
|
110
|
|
|
|
|
|
|
* parallel to) hashing the message. |
|
111
|
|
|
|
|
|
|
*/ |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
/* Signature generation primitive, calculates (x-h)s mod q |
|
115
|
|
|
|
|
|
|
* v [out] signature value |
|
116
|
|
|
|
|
|
|
* h [in] signature hash (of message, signature pub key, and context data) |
|
117
|
|
|
|
|
|
|
* x [in] signature private key |
|
118
|
|
|
|
|
|
|
* s [in] private key for signing |
|
119
|
|
|
|
|
|
|
* returns true on success, false on failure (use different x or h) |
|
120
|
|
|
|
|
|
|
*/ |
|
121
|
|
|
|
|
|
|
int sign25519(k25519 v, const k25519 h, const priv25519 x, const spriv25519 s); |
|
122
|
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
/* Signature verification primitive, calculates Y = vP + hG |
|
125
|
|
|
|
|
|
|
* Y [out] signature public key |
|
126
|
|
|
|
|
|
|
* v [in] signature value |
|
127
|
|
|
|
|
|
|
* h [in] signature hash |
|
128
|
|
|
|
|
|
|
* P [in] public key |
|
129
|
|
|
|
|
|
|
*/ |
|
130
|
|
|
|
|
|
|
void verify25519(pub25519 Y, const k25519 v, const k25519 h, const pub25519 P); |
|
131
|
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
#endif |