-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathed25519.c
104 lines (87 loc) · 2.94 KB
/
ed25519.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include <ed25519/ed25519/crypto_verify.h>
#include <ed25519/ed25519.h>
#include <string.h>
#include "ge.h"
#include "sc.h"
ED25519_EXPORT int ed25519_create_keypair(private_key_t *sk, public_key_t *pk) {
if (!randombytes(sk->data, ed25519_privkey_SIZE))
return ED25519_ERROR; /* RNG failed, not enough entropy */
ed25519_derive_public_key(sk, pk); /* fill with data */
return ED25519_SUCCESS; /* ok */
}
ED25519_EXPORT void ed25519_derive_public_key(const private_key_t *sk, public_key_t *pk) {
unsigned char az[64];
ge_p3 A;
sha512(az, sk->data, ed25519_privkey_SIZE);
az[0] &= 248;
az[31] &= 63;
az[31] |= 64;
ge_scalarmult_base(&A, az);
ge_p3_tobytes(pk->data, &A);
}
ED25519_EXPORT void ed25519_sign(signature_t *sig, const unsigned char *msg,
unsigned long long msglen, const public_key_t *pk,
const private_key_t *sk) {
sha_context ctx;
unsigned char az[64];
unsigned char nonce[64]; // r
unsigned char hram[64];
ge_p3 R;
// TODO: it is possible to pre-calculate this hash while reading private key
sha512_init(&ctx);
sha512_update(&ctx, sk->data, ed25519_privkey_SIZE);
sha512_final(&ctx, az);
az[0] &= 248;
az[31] &= 63;
az[31] |= 64;
/* az: 64-byte H(sk) */
/* az: 32-byte scalar a, 32-byte randomizer z */
sha512_init(&ctx);
sha512_update(&ctx, /* z */ az + 32, 32);
sha512_update(&ctx, msg, msglen);
sha512_final(&ctx, nonce);
/* nonce: 64-byte H(z,msg) */
sc_reduce(nonce);
ge_scalarmult_base(&R, nonce);
ge_p3_tobytes(sig->data, &R);
/* sig: [32 bytes R | 32 bytes uninit] */
sha512_init(&ctx);
// first 32 bytes of signature
sha512_update(&ctx, /* R */ sig->data, 32);
sha512_update(&ctx, /* A */ pk->data, ed25519_pubkey_SIZE);
sha512_update(&ctx, msg, msglen);
sha512_final(&ctx, hram);
/* hram: 64-byte H(R,A,m) */
sc_reduce(hram);
sc_muladd(sig->data + 32, hram, az, nonce);
/* sig: [32 bytes R | 32 bytes S] */
}
ED25519_EXPORT int ed25519_verify(const signature_t *sig, const unsigned char *msg,
unsigned long long msglen, const public_key_t *pk) {
sha_context ctx;
unsigned char pkcopy[32];
unsigned char rcopy[32];
unsigned char hram[64];
unsigned char rcheck[32];
ge_p3 A;
ge_p2 R;
if (sig->data[63] & 224) goto badsig;
if (ge_frombytes_negate_vartime(&A, pk->data) != 0) goto badsig;
memcpy(pkcopy, pk->data, 32);
memcpy(rcopy, /* R, first 32 bytes */ sig->data, 32);
sha512_init(&ctx);
// first 32 bytes of signature
sha512_update(&ctx, /* R */ sig->data, 32);
sha512_update(&ctx, /* A */ pk->data, ed25519_pubkey_SIZE);
sha512_update(&ctx, msg, msglen);
sha512_final(&ctx, hram);
/* scs: S = nonce + H(R,A,m)a */
sc_reduce(hram);
ge_double_scalarmult_vartime(&R, hram, &A, /* S */ sig->data + 32);
ge_tobytes(rcheck, &R);
if (crypto_verify_32(rcopy, rcheck) == 0) {
return ED25519_SIGNATURE_VALID;
}
badsig:
return ED25519_SIGNATURE_INVALID;
}