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
|
#include <string.h>
#include "ge.h"
#include "crypto_additions.h"
#include "zeroize.h"
#include "xeddsa.h"
#include "crypto_verify_32.h"
int xed25519_sign(unsigned char* signature_out,
const unsigned char* curve25519_privkey,
const unsigned char* msg, const unsigned long msg_len,
const unsigned char* random)
{
unsigned char a[32], aneg[32];
unsigned char A[32];
ge_p3 ed_pubkey_point;
unsigned char *sigbuf; /* working buffer */
unsigned char sign_bit = 0;
if ((sigbuf = malloc(msg_len + 128)) == 0) {
memset(signature_out, 0, 64);
return -1;
}
/* Convert the Curve25519 privkey to an Ed25519 public key */
ge_scalarmult_base(&ed_pubkey_point, curve25519_privkey);
ge_p3_tobytes(A, &ed_pubkey_point);
/* Force Edwards sign bit to zero */
sign_bit = (A[31] & 0x80) >> 7;
memcpy(a, curve25519_privkey, 32);
sc_neg(aneg, a);
sc_cmov(a, aneg, sign_bit);
A[31] &= 0x7F;
/* Perform an Ed25519 signature with explicit private key */
crypto_sign_modified(sigbuf, msg, msg_len, a, A, random);
memmove(signature_out, sigbuf, 64);
zeroize(a, 32);
zeroize(aneg, 32);
free(sigbuf);
return 0;
}
int xed25519_verify(const unsigned char* signature,
const unsigned char* curve25519_pubkey,
const unsigned char* msg, const unsigned long msg_len)
{
fe u;
fe y;
unsigned char ed_pubkey[32];
unsigned char strict[32];
unsigned char verifybuf[MAX_MSG_LEN + 64]; /* working buffer */
unsigned char verifybuf2[MAX_MSG_LEN + 64]; /* working buffer #2 */
if (msg_len > MAX_MSG_LEN) {
return -1;
}
/* Convert the Curve25519 public key into an Ed25519 public key.
y = (u - 1) / (u + 1)
NOTE: u=-1 is converted to y=0 since fe_invert is mod-exp
*/
fe_frombytes(u, curve25519_pubkey);
fe_tobytes(strict, u);
if (crypto_verify_32(strict, curve25519_pubkey) != 0)
return 0;
fe_montx_to_edy(y, u);
fe_tobytes(ed_pubkey, y);
memmove(verifybuf, signature, 64);
memmove(verifybuf+64, msg, msg_len);
/* Then perform a normal Ed25519 verification, return 0 on success */
/* The below call has a strange API: */
/* verifybuf = R || S || message */
/* verifybuf2 = internal to next call gets a copy of verifybuf, S gets
replaced with pubkey for hashing */
return crypto_sign_open_modified(verifybuf2, verifybuf, 64 + msg_len, ed_pubkey);
}
|