2 * implementing ed25519-sha512 from [1].
4 * This code is public domain.
6 * Philipp Lay <philipp.lay@illunis.net>
10 * [1] High-speed high-security signatures, 2011/09/26,
11 * Bernstein, Duif, Lange, Schwabe, Yang
28 #include "burnstack.h"
32 ed25519_key_setup(uint8_t out[SHA512_HASH_LENGTH],
33 const uint8_t sk[ED25519_KEY_LEN])
39 sha512_add(&hash, sk, ED25519_KEY_LEN);
40 sha512_final(&hash, out);
42 /* delete bit 255 and set bit 254 */
45 /* delete 3 lowest bits */
51 * genpub - derive public key from secret key
54 genpub(uint8_t pub[ED25519_KEY_LEN], const uint8_t sec[ED25519_KEY_LEN])
56 uint8_t h[SHA512_HASH_LENGTH];
60 /* derive secret and import it */
61 ed25519_key_setup(h, sec);
64 /* multiply with base point to calculate public key */
71 * ed25519_genpub - stack-clearing wrapper for genpub
74 ed25519_genpub(uint8_t pub[ED25519_KEY_LEN], const uint8_t sec[ED25519_KEY_LEN])
82 * sign - create ed25519 signature of data using secret key sec
85 sign(uint8_t sig[ED25519_SIG_LEN],
86 const uint8_t sec[ED25519_KEY_LEN],
87 const uint8_t pub[ED25519_KEY_LEN],
88 const uint8_t *data, size_t len)
91 uint8_t h[SHA512_HASH_LENGTH];
96 /* derive secret scalar a */
97 ed25519_key_setup(h, sec);
100 /* hash next 32 bytes together with data to form r */
102 sha512_add(&hash, h+32, 32);
103 sha512_add(&hash, data, len);
104 sha512_final(&hash, h);
105 sc_import(r, h, sizeof(h));
107 /* calculate R = r * B which form the first 256bit of the signature */
108 ed_scale_base(&R, r);
111 /* calculate t := Hash(export(R), export(A), data) mod m */
113 sha512_add(&hash, sig, 32);
114 sha512_add(&hash, pub, 32);
115 sha512_add(&hash, data, len);
116 sha512_final(&hash, h);
117 sc_import(t, h, sizeof(h));
119 /* calculate S := r + t*a mod m and finish the signature */
122 sc_export(sig+32, S);
127 * ed25519_sign - stack-cleaning wrapper for sign
130 ed25519_sign(uint8_t sig[ED25519_SIG_LEN],
131 const uint8_t sec[ED25519_KEY_LEN],
132 const uint8_t pub[ED25519_KEY_LEN],
133 const uint8_t *data, size_t len)
135 sign(sig, sec, pub, data, len);
141 * ed25519_verify - verifies an ed25519-signature of given data.
143 * note: this functions runs in vartime and does no stack cleanup, since
144 * all information are considered public.
146 * returns true if signature is ok and false otherwise.
149 ed25519_verify(const uint8_t sig[ED25519_SIG_LEN],
150 const uint8_t pub[ED25519_KEY_LEN],
151 const uint8_t *data, size_t len)
154 uint8_t h[SHA512_HASH_LENGTH];
159 /* import public key */
162 /* import S from second half of the signature */
163 sc_import(S, sig+32, 32);
165 /* calculate t := Hash(export(R), export(A), data) mod m */
167 sha512_add(&hash, sig, 32);
168 sha512_add(&hash, pub, 32);
169 sha512_add(&hash, data, len);
170 sha512_final(&hash, h);
173 /* verify signature (vartime!) */
176 ed_dual_scale(&C, S, t, &A);
177 ed_export(check, &C);
179 /* is export(C) == export(R) (vartime!) */
180 return (memcmp(check, sig, 32) == 0);
185 * pk_ed25519_to_x25519 - convert a ed25519 public key to x25519
188 pk_ed25519_to_x25519(uint8_t out[X25519_KEY_LEN], const uint8_t in[ED25519_KEY_LEN])
193 /* import ed25519 public key */
197 * We now have the point P = (x,y) on the curve
199 * x^2 + y^2 = 1 + (121665/121666)x^2y^2
201 * and want the u-component of the corresponding point
202 * on the birationally equivalent montgomery curve
204 * v^2 = u^3 + 486662 u^2 + u.
207 * From the paper [1] we get
209 * y = (u - 1) / (u + 1),
211 * which immediately yields
213 * u = (1 + y) / (1 - y)
215 * or, by using projective coordinantes,
217 * u = (z + y) / (z - y).
221 fld_add(u, P.z, P.y);
223 /* t <- (z - y)^-1 */
224 fld_sub(t, P.z, P.y);
227 /* u <- u * t = (z+y) / (z-y) */
230 /* export curve25519 public key */
237 * conv_sk_ed25519_to_x25519 - convert a ed25519 secret key to x25519 secret.
240 conv_sk_ed25519_to_x25519(uint8_t out[X25519_KEY_LEN], const uint8_t in[ED25519_KEY_LEN])
242 uint8_t h[SHA512_HASH_LENGTH];
243 ed25519_key_setup(h, in);
244 memcpy(out, h, X25519_KEY_LEN);
249 * sk_ed25519_to_x25519 - stack-clearing wrapper for conv_sk_ed25519_to_x25519.
252 sk_ed25519_to_x25519(uint8_t out[X25519_KEY_LEN], const uint8_t in[ED25519_KEY_LEN])
254 conv_sk_ed25519_to_x25519(out, in);
263 * Obsolete Interface, this will be removed in the future.
268 * eddsa_genpub - stack-clearing wrapper for genpub (obsolete interface!)
271 eddsa_genpub(uint8_t pub[32], const uint8_t sec[32])
279 * eddsa_sign - stack-cleaning wrapper for sign (obsolete interface!)
282 eddsa_sign(uint8_t sig[ED25519_SIG_LEN],
283 const uint8_t sec[ED25519_KEY_LEN],
284 const uint8_t pub[ED25519_KEY_LEN],
285 const uint8_t *data, size_t len)
287 sign(sig, sec, pub, data, len);
292 * eddsa_verify - verifies an ed25519 signature of given data.
293 * (obsolete interface!)
297 eddsa_verify(const uint8_t sig[ED25519_SIG_LEN],
298 const uint8_t pub[ED25519_KEY_LEN],
299 const uint8_t *data, size_t len)
301 return ed25519_verify(sig, pub, data, len);
305 * eddsa_pk_eddsa_to_dh - convert a ed25519 public key to x25519.
306 * (obsolete interface!)
309 eddsa_pk_eddsa_to_dh(uint8_t out[X25519_KEY_LEN], const uint8_t in[ED25519_KEY_LEN])
311 pk_ed25519_to_x25519(out, in);
316 * eddsa_sk_eddsa_to_dh - convert a ed25519 secret key to x25519 secret.
317 * (obsolete interface!)
320 eddsa_sk_eddsa_to_dh(uint8_t out[X25519_KEY_LEN], const uint8_t in[ED25519_KEY_LEN])
322 conv_sk_ed25519_to_x25519(out, in);