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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
#include <string.h>
#include "crypto_additions.h"
#include "gen_x.h"
#include "gen_constants.h"
#include "gen_eddsa.h"
#include "gen_veddsa.h"
#include "gen_crypto_additions.h"
#include "zeroize.h"
static int convert_25519_pubkey(unsigned char* ed_pubkey_bytes, const unsigned char* x25519_pubkey_bytes) {
fe u;
fe y;
/* Convert the X25519 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
*/
if (!fe_isreduced(x25519_pubkey_bytes))
return -1;
fe_frombytes(u, x25519_pubkey_bytes);
fe_montx_to_edy(y, u);
fe_tobytes(ed_pubkey_bytes, y);
return 0;
}
static int calculate_25519_keypair(unsigned char* K_bytes, unsigned char* k_scalar,
const unsigned char* x25519_privkey_scalar)
{
unsigned char kneg[SCALARLEN];
ge_p3 ed_pubkey_point;
unsigned char sign_bit = 0;
if (SCALARLEN != 32)
return -1;
/* Convert the Curve25519 privkey to an Ed25519 public key */
ge_scalarmult_base(&ed_pubkey_point, x25519_privkey_scalar);
ge_p3_tobytes(K_bytes, &ed_pubkey_point);
/* Force Edwards sign bit to zero */
sign_bit = (K_bytes[31] & 0x80) >> 7;
memcpy(k_scalar, x25519_privkey_scalar, 32);
sc_neg(kneg, k_scalar);
sc_cmov(k_scalar, kneg, sign_bit);
K_bytes[31] &= 0x7F;
zeroize(kneg, SCALARLEN);
return 0;
}
int generalized_xeddsa_25519_sign(unsigned char* signature_out,
const unsigned char* x25519_privkey_scalar,
const unsigned char* msg, const unsigned long msg_len,
const unsigned char* random,
const unsigned char* customization_label,
const unsigned long customization_label_len)
{
unsigned char K_bytes[POINTLEN];
unsigned char k_scalar[SCALARLEN];
int retval = -1;
if (calculate_25519_keypair(K_bytes, k_scalar, x25519_privkey_scalar) != 0)
return -1;
retval = generalized_eddsa_25519_sign(signature_out,
K_bytes, k_scalar,
msg, msg_len, random,
customization_label, customization_label_len);
zeroize(k_scalar, SCALARLEN);
return retval;
}
int generalized_xveddsa_25519_sign(
unsigned char* signature_out,
const unsigned char* x25519_privkey_scalar,
const unsigned char* msg,
const unsigned long msg_len,
const unsigned char* random,
const unsigned char* customization_label,
const unsigned long customization_label_len)
{
unsigned char K_bytes[POINTLEN];
unsigned char k_scalar[SCALARLEN];
int retval = -1;
if (calculate_25519_keypair(K_bytes, k_scalar, x25519_privkey_scalar) != 0)
return -1;
retval = generalized_veddsa_25519_sign(signature_out, K_bytes, k_scalar,
msg, msg_len, random,
customization_label, customization_label_len);
zeroize(k_scalar, SCALARLEN);
return retval;
}
int generalized_xeddsa_25519_verify(
const unsigned char* signature,
const unsigned char* x25519_pubkey_bytes,
const unsigned char* msg,
const unsigned long msg_len,
const unsigned char* customization_label,
const unsigned long customization_label_len)
{
unsigned char K_bytes[POINTLEN];
if (convert_25519_pubkey(K_bytes, x25519_pubkey_bytes) != 0)
return -1;
return generalized_eddsa_25519_verify(signature, K_bytes, msg, msg_len,
customization_label, customization_label_len);
}
int generalized_xveddsa_25519_verify(
unsigned char* vrf_out,
const unsigned char* signature,
const unsigned char* x25519_pubkey_bytes,
const unsigned char* msg,
const unsigned long msg_len,
const unsigned char* customization_label,
const unsigned long customization_label_len)
{
unsigned char K_bytes[POINTLEN];
if (convert_25519_pubkey(K_bytes, x25519_pubkey_bytes) != 0)
return -1;
return generalized_veddsa_25519_verify(vrf_out, signature, K_bytes, msg, msg_len,
customization_label, customization_label_len);
}
|