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
|
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "crypto_hash_sha512.h"
#include "crypto_vrf_rfc9381.h"
#include "private/ed25519_ref10.h"
#include "vrf_rfc9381.h"
#include "crypto_verify_16.h"
int
crypto_vrf_rfc9381_proof_to_hash(unsigned char *beta,
const unsigned char *pi)
{
ge25519_p3 Gamma;
unsigned char gamma_string[32];
if (ge25519_is_canonical(pi) == 0 ||
ge25519_frombytes(&Gamma, pi) != 0) {
return -1;
}
if (pi[48 + 31] & 240 &&
sc25519_is_canonical(pi + 48) == 0) {
return -1;
}
ge25519_clear_cofactor(&Gamma);
ge25519_p3_tobytes(gamma_string, &Gamma);
/* beta_string = Hash(suite_string || three_string || point_to_string(cofactor * Gamma) || zero_string ) */
crypto_hash_sha512_state hs;
crypto_hash_sha512_init(&hs);
crypto_hash_sha512_update(&hs, &SUITE, 1);
crypto_hash_sha512_update(&hs, &THREE, 1);
crypto_hash_sha512_update(&hs, gamma_string, 32);
crypto_hash_sha512_update(&hs, &ZERO, 1);
crypto_hash_sha512_final(&hs, beta);
return 0;
}
static int
vrf_verify(const unsigned char *pi,
const unsigned char *alpha, unsigned long long alphalen,
const ge25519_p3 *Y_point)
{
unsigned char H_string[32], U_string[32], V_string[32], Y_string[32];
unsigned char cn[32], c[32], s[32];
unsigned char string_to_hash[32 + alphalen], challenge[64];
crypto_hash_sha512_state hs;
ge25519_p2 U, V;
ge25519_p3 H, Gamma;
ge25519_p1p1 tmp_p1p1_point;
ge25519_cached tmp_cached_point;
ge25519_p3_tobytes(Y_string, Y_point);
if (ge25519_is_canonical(pi) == 0 ||
ge25519_frombytes(&Gamma, pi) != 0) {
return -1;
}
memmove(c, pi + 32, 16); /* c = pi[32:48] */
memmove(s, pi + 48, 32); /* s = pi[48:80] */
if (s[31] & 240 &&
sc25519_is_canonical(s) == 0) {
return -1;
}
memset(c + 16, 0, 16);
memmove(string_to_hash, Y_string, 32);
memmove(string_to_hash + 32, alpha, alphalen);
ge25519_from_string(H_string, "ECVRF_edwards25519_XMD:SHA-512_ELL2_NU_\4", string_to_hash, 32 + alphalen, 2); /* elligator2 */
ge25519_frombytes(&H, H_string);
sc25519_negate(cn, c); /* negate scalar c */
ge25519_double_scalarmult_vartime(&U, cn, Y_point, s, NULL);
ge25519_double_scalarmult_vartime(&V, cn, &Gamma, s, &H);
ge25519_tobytes(U_string, &U);
ge25519_tobytes(V_string, &V);
crypto_hash_sha512_init(&hs);
crypto_hash_sha512_update(&hs, &SUITE, 1);
crypto_hash_sha512_update(&hs, &TWO, 1);
crypto_hash_sha512_update(&hs, Y_string, 32);
crypto_hash_sha512_update(&hs, H_string, 32);
crypto_hash_sha512_update(&hs, pi, 32);
crypto_hash_sha512_update(&hs, U_string, 32);
crypto_hash_sha512_update(&hs, V_string, 32);
crypto_hash_sha512_update(&hs, &ZERO, 1);
crypto_hash_sha512_final(&hs, challenge);
return crypto_verify_16(c, challenge);
}
int
crypto_vrf_rfc9381_verify(unsigned char *output,
const unsigned char *pk,
const unsigned char *proof,
const unsigned char *msg, const unsigned long long msglen)
{
ge25519_p3 Y;
if (ge25519_frombytes(&Y, pk) == 0 && ge25519_has_small_order(&Y) == 0 &&
ge25519_is_canonical(pk) == 1 && (vrf_verify(proof, msg, msglen, &Y) == 0)) {
return crypto_vrf_rfc9381_proof_to_hash(output, proof);
} else {
return -1;
}
}
|