mirror of
https://github.com/jedisct1/libsodium.git
synced 2024-12-23 12:05:11 -07:00
RFC9381 ECVRF implementation (#1188)
* Version 12 of ECVRF * Incorrect ordering of function inputs * Identation and notation * single multiscalar multiplication function Also changed the style of tests, where the expected output is in vrf.exp rather than in test data (following the style of the hashing). * declarations inside the if code block * identation of test_data * Rename to RFC9381 * Move declarations to top of block * Check small order over deserialised PK * Include from_string functions in ed25519_ref10 * Update quirks.h --------- Co-authored-by: Frank Denis <124872+jedisct1@users.noreply.github.com>
This commit is contained in:
parent
43173b8354
commit
7978205916
1
.gitignore
vendored
1
.gitignore
vendored
@ -166,6 +166,7 @@ test/default/stream2
|
|||||||
test/default/stream3
|
test/default/stream3
|
||||||
test/default/stream4
|
test/default/stream4
|
||||||
test/default/verify1
|
test/default/verify1
|
||||||
|
test/default/vrf
|
||||||
test/default/xchacha20
|
test/default/xchacha20
|
||||||
test/js.done
|
test/js.done
|
||||||
testing
|
testing
|
||||||
|
@ -99,6 +99,12 @@ libsodium_la_SOURCES = \
|
|||||||
crypto_stream/xsalsa20/stream_xsalsa20.c \
|
crypto_stream/xsalsa20/stream_xsalsa20.c \
|
||||||
crypto_verify/verify.c \
|
crypto_verify/verify.c \
|
||||||
include/sodium/private/asm_cet.h \
|
include/sodium/private/asm_cet.h \
|
||||||
|
crypto_vrf/crypto_vrf.c \
|
||||||
|
crypto_vrf/rfc9381/keypair.c \
|
||||||
|
crypto_vrf/rfc9381/prove.c \
|
||||||
|
crypto_vrf/rfc9381/verify.c \
|
||||||
|
crypto_vrf/rfc9381/vrf.c \
|
||||||
|
crypto_vrf/rfc9381/vrf_rfc9381.h \
|
||||||
include/sodium/private/chacha20_ietf_ext.h \
|
include/sodium/private/chacha20_ietf_ext.h \
|
||||||
include/sodium/private/common.h \
|
include/sodium/private/common.h \
|
||||||
include/sodium/private/ed25519_ref10.h \
|
include/sodium/private/ed25519_ref10.h \
|
||||||
|
@ -65,41 +65,12 @@ crypto_core_ed25519_from_uniform(unsigned char *p, const unsigned char *r)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define HASH_GE_L 48U
|
|
||||||
|
|
||||||
static int
|
|
||||||
_string_to_points(unsigned char * const px, const size_t n,
|
|
||||||
const char *ctx, const unsigned char *msg, size_t msg_len,
|
|
||||||
int hash_alg)
|
|
||||||
{
|
|
||||||
unsigned char h[crypto_core_ed25519_HASHBYTES];
|
|
||||||
unsigned char h_be[2U * HASH_GE_L];
|
|
||||||
size_t i, j;
|
|
||||||
|
|
||||||
if (n > 2U) {
|
|
||||||
abort(); /* LCOV_EXCL_LINE */
|
|
||||||
}
|
|
||||||
if (core_h2c_string_to_hash(h_be, n * HASH_GE_L, ctx, msg, msg_len,
|
|
||||||
hash_alg) != 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
COMPILER_ASSERT(sizeof h >= HASH_GE_L);
|
|
||||||
for (i = 0U; i < n; i++) {
|
|
||||||
for (j = 0U; j < HASH_GE_L; j++) {
|
|
||||||
h[j] = h_be[i * HASH_GE_L + HASH_GE_L - 1U - j];
|
|
||||||
}
|
|
||||||
memset(&h[j], 0, (sizeof h) - j);
|
|
||||||
ge25519_from_hash(&px[i * crypto_core_ed25519_BYTES], h);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
crypto_core_ed25519_from_string(unsigned char p[crypto_core_ed25519_BYTES],
|
crypto_core_ed25519_from_string(unsigned char p[crypto_core_ed25519_BYTES],
|
||||||
const char *ctx, const unsigned char *msg,
|
const char *ctx, const unsigned char *msg,
|
||||||
size_t msg_len, int hash_alg)
|
size_t msg_len, int hash_alg)
|
||||||
{
|
{
|
||||||
return _string_to_points(p, 1, ctx, msg, msg_len, hash_alg);
|
return ge25519_from_string(p, ctx, msg, msg_len, hash_alg);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -107,12 +78,7 @@ crypto_core_ed25519_from_string_ro(unsigned char p[crypto_core_ed25519_BYTES],
|
|||||||
const char *ctx, const unsigned char *msg,
|
const char *ctx, const unsigned char *msg,
|
||||||
size_t msg_len, int hash_alg)
|
size_t msg_len, int hash_alg)
|
||||||
{
|
{
|
||||||
unsigned char px[2 * crypto_core_ed25519_BYTES];
|
return ge25519_from_string_ro(p, ctx, msg, msg_len, hash_alg);
|
||||||
|
|
||||||
if (_string_to_points(px, 2, ctx, msg, msg_len, hash_alg) != 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return crypto_core_ed25519_add(p, &px[0], &px[crypto_core_ed25519_BYTES]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "crypto_verify_32.h"
|
#include "crypto_verify_32.h"
|
||||||
|
#include "../core_h2c.h"
|
||||||
#include "private/common.h"
|
#include "private/common.h"
|
||||||
#include "private/ed25519_ref10.h"
|
#include "private/ed25519_ref10.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
@ -742,68 +743,76 @@ ge25519_tobytes(unsigned char *s, const ge25519_p2 *h)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* Precomputation of a base point, to use in multiscalar multiplication algorithm A,3A,5A,7A,9A,11A,13A,15A
|
||||||
|
*/
|
||||||
|
static void point_precomputation(ge25519_cached cached[8], const ge25519_p3 *base) {
|
||||||
|
ge25519_p1p1 t;
|
||||||
|
ge25519_p3 u;
|
||||||
|
ge25519_p3 A;
|
||||||
|
|
||||||
|
// Precomputation of values of A
|
||||||
|
ge25519_p3_to_cached(&cached[0], base);
|
||||||
|
|
||||||
|
ge25519_p3_dbl(&t, base);
|
||||||
|
ge25519_p1p1_to_p3(&A, &t);
|
||||||
|
|
||||||
|
ge25519_add_cached(&t, &A, &cached[0]);
|
||||||
|
ge25519_p1p1_to_p3(&u, &t);
|
||||||
|
ge25519_p3_to_cached(&cached[1], &u);
|
||||||
|
|
||||||
|
ge25519_add_cached(&t, &A, &cached[1]);
|
||||||
|
ge25519_p1p1_to_p3(&u, &t);
|
||||||
|
ge25519_p3_to_cached(&cached[2], &u);
|
||||||
|
|
||||||
|
ge25519_add_cached(&t, &A, &cached[2]);
|
||||||
|
ge25519_p1p1_to_p3(&u, &t);
|
||||||
|
ge25519_p3_to_cached(&cached[3], &u);
|
||||||
|
|
||||||
|
ge25519_add_cached(&t, &A, &cached[3]);
|
||||||
|
ge25519_p1p1_to_p3(&u, &t);
|
||||||
|
ge25519_p3_to_cached(&cached[4], &u);
|
||||||
|
|
||||||
|
ge25519_add_cached(&t, &A, &cached[4]);
|
||||||
|
ge25519_p1p1_to_p3(&u, &t);
|
||||||
|
ge25519_p3_to_cached(&cached[5], &u);
|
||||||
|
|
||||||
|
ge25519_add_cached(&t, &A, &cached[5]);
|
||||||
|
ge25519_p1p1_to_p3(&u, &t);
|
||||||
|
ge25519_p3_to_cached(&cached[6], &u);
|
||||||
|
|
||||||
|
ge25519_add_cached(&t, &A, &cached[6]);
|
||||||
|
ge25519_p1p1_to_p3(&u, &t);
|
||||||
|
ge25519_p3_to_cached(&cached[7], &u);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Variable time double scalar multiplication with variable bases
|
||||||
r = a * A + b * B
|
r = a * A + b * B
|
||||||
where a = a[0]+256*a[1]+...+256^31 a[31].
|
where a = a[0]+256*a[1]+...+256^31 a[31].
|
||||||
and b = b[0]+256*b[1]+...+256^31 b[31].
|
and b = b[0]+256*b[1]+...+256^31 b[31].
|
||||||
B is the Ed25519 base point (x,4/5) with x positive.
|
|
||||||
|
|
||||||
Only used for signatures verification.
|
If a null pointer is passed as an argument for B, the function uses
|
||||||
|
the precomputed values of the base point for the scalar multiplication.
|
||||||
|
|
||||||
|
Only used for ed25519 and VRF verification.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
ge25519_double_scalarmult_vartime(ge25519_p2 *r, const unsigned char *a,
|
ge25519_double_scalarmult_vartime(ge25519_p2 *r, const unsigned char *a,
|
||||||
const ge25519_p3 *A, const unsigned char *b)
|
const ge25519_p3 *A, const unsigned char *b,
|
||||||
|
const ge25519_p3 *B)
|
||||||
{
|
{
|
||||||
static const ge25519_precomp Bi[8] = {
|
|
||||||
#ifdef HAVE_TI_MODE
|
|
||||||
# include "fe_51/base2.h"
|
|
||||||
#else
|
|
||||||
# include "fe_25_5/base2.h"
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
signed char aslide[256];
|
signed char aslide[256];
|
||||||
signed char bslide[256];
|
signed char bslide[256];
|
||||||
ge25519_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */
|
ge25519_cached Ai[8];
|
||||||
ge25519_p1p1 t;
|
ge25519_p1p1 t;
|
||||||
ge25519_p3 u;
|
ge25519_p3 u;
|
||||||
ge25519_p3 A2;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
slide_vartime(aslide, a);
|
slide_vartime(aslide, a);
|
||||||
slide_vartime(bslide, b);
|
slide_vartime(bslide, b);
|
||||||
|
|
||||||
ge25519_p3_to_cached(&Ai[0], A);
|
point_precomputation(Ai, A);
|
||||||
|
|
||||||
ge25519_p3_dbl(&t, A);
|
|
||||||
ge25519_p1p1_to_p3(&A2, &t);
|
|
||||||
|
|
||||||
ge25519_add_cached(&t, &A2, &Ai[0]);
|
|
||||||
ge25519_p1p1_to_p3(&u, &t);
|
|
||||||
ge25519_p3_to_cached(&Ai[1], &u);
|
|
||||||
|
|
||||||
ge25519_add_cached(&t, &A2, &Ai[1]);
|
|
||||||
ge25519_p1p1_to_p3(&u, &t);
|
|
||||||
ge25519_p3_to_cached(&Ai[2], &u);
|
|
||||||
|
|
||||||
ge25519_add_cached(&t, &A2, &Ai[2]);
|
|
||||||
ge25519_p1p1_to_p3(&u, &t);
|
|
||||||
ge25519_p3_to_cached(&Ai[3], &u);
|
|
||||||
|
|
||||||
ge25519_add_cached(&t, &A2, &Ai[3]);
|
|
||||||
ge25519_p1p1_to_p3(&u, &t);
|
|
||||||
ge25519_p3_to_cached(&Ai[4], &u);
|
|
||||||
|
|
||||||
ge25519_add_cached(&t, &A2, &Ai[4]);
|
|
||||||
ge25519_p1p1_to_p3(&u, &t);
|
|
||||||
ge25519_p3_to_cached(&Ai[5], &u);
|
|
||||||
|
|
||||||
ge25519_add_cached(&t, &A2, &Ai[5]);
|
|
||||||
ge25519_p1p1_to_p3(&u, &t);
|
|
||||||
ge25519_p3_to_cached(&Ai[6], &u);
|
|
||||||
|
|
||||||
ge25519_add_cached(&t, &A2, &Ai[6]);
|
|
||||||
ge25519_p1p1_to_p3(&u, &t);
|
|
||||||
ge25519_p3_to_cached(&Ai[7], &u);
|
|
||||||
|
|
||||||
ge25519_p2_0(r);
|
ge25519_p2_0(r);
|
||||||
|
|
||||||
@ -824,12 +833,31 @@ ge25519_double_scalarmult_vartime(ge25519_p2 *r, const unsigned char *a,
|
|||||||
ge25519_sub_cached(&t, &u, &Ai[(-aslide[i]) / 2]);
|
ge25519_sub_cached(&t, &u, &Ai[(-aslide[i]) / 2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bslide[i] > 0) {
|
if (B == NULL) {
|
||||||
ge25519_p1p1_to_p3(&u, &t);
|
static const ge25519_precomp Bi[8] = {
|
||||||
ge25519_add_precomp(&t, &u, &Bi[bslide[i] / 2]);
|
#ifdef HAVE_TI_MODE
|
||||||
} else if (bslide[i] < 0) {
|
# include "fe_51/base2.h"
|
||||||
ge25519_p1p1_to_p3(&u, &t);
|
#else
|
||||||
ge25519_sub_precomp(&t, &u, &Bi[(-bslide[i]) / 2]);
|
# include "fe_25_5/base2.h"
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
if (bslide[i] > 0) {
|
||||||
|
ge25519_p1p1_to_p3(&u, &t);
|
||||||
|
ge25519_add_precomp(&t, &u, &Bi[bslide[i] / 2]);
|
||||||
|
} else if (bslide[i] < 0) {
|
||||||
|
ge25519_p1p1_to_p3(&u, &t);
|
||||||
|
ge25519_sub_precomp(&t, &u, &Bi[(-bslide[i]) / 2]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ge25519_cached Bi[8];
|
||||||
|
point_precomputation(Bi, B);
|
||||||
|
if (bslide[i] > 0) {
|
||||||
|
ge25519_p1p1_to_p3(&u, &t);
|
||||||
|
ge25519_add_cached(&t, &u, &Bi[bslide[i] / 2]);
|
||||||
|
} else if (bslide[i] < 0) {
|
||||||
|
ge25519_p1p1_to_p3(&u, &t);
|
||||||
|
ge25519_sub_cached(&t, &u, &Bi[(-bslide[i]) / 2]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ge25519_p1p1_to_p2(r, &t);
|
ge25519_p1p1_to_p2(r, &t);
|
||||||
@ -2224,6 +2252,29 @@ sc25519_invert(unsigned char recip[32], const unsigned char s[32])
|
|||||||
sc25519_sqmul(recip, 8, _11101011);
|
sc25519_sqmul(recip, 8, _11101011);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 2^252+27742317777372353535851937790883648493 */
|
||||||
|
static const unsigned char L[] = {
|
||||||
|
0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7,
|
||||||
|
0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
sc25519_negate(unsigned char neg[32], const unsigned char s[32])
|
||||||
|
{
|
||||||
|
unsigned char t_[64];
|
||||||
|
unsigned char s_[64];
|
||||||
|
|
||||||
|
memset(t_, 0, sizeof t_);
|
||||||
|
memset(s_, 0, sizeof s_);
|
||||||
|
memcpy(t_ + 32, L,
|
||||||
|
32);
|
||||||
|
memcpy(s_, s, 32);
|
||||||
|
sodium_sub(t_, s_, sizeof t_);
|
||||||
|
sc25519_reduce(t_);
|
||||||
|
memcpy(neg, t_, 32);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Input:
|
Input:
|
||||||
s[0]+256*s[1]+...+256^63*s[63] = s
|
s[0]+256*s[1]+...+256^63*s[63] = s
|
||||||
@ -2700,6 +2751,68 @@ ge25519_from_uniform(unsigned char s[32], const unsigned char r[32])
|
|||||||
ge25519_p3_tobytes(s, &p3);
|
ge25519_p3_tobytes(s, &p3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define HASH_GE_L 48U
|
||||||
|
|
||||||
|
static int
|
||||||
|
_string_to_points(unsigned char * const px, const size_t n,
|
||||||
|
const char *ctx, const unsigned char *msg, size_t msg_len,
|
||||||
|
int hash_alg)
|
||||||
|
{
|
||||||
|
unsigned char h[64];
|
||||||
|
unsigned char h_be[2U * HASH_GE_L];
|
||||||
|
size_t i, j;
|
||||||
|
|
||||||
|
if (n > 2U) {
|
||||||
|
abort(); /* LCOV_EXCL_LINE */;
|
||||||
|
}
|
||||||
|
if (core_h2c_string_to_hash(h_be, n * HASH_GE_L, ctx, msg, msg_len,
|
||||||
|
hash_alg) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
COMPILER_ASSERT(sizeof h >= HASH_GE_L);
|
||||||
|
for (i = 0U; i < n; i++) {
|
||||||
|
for (j = 0U; j < HASH_GE_L; j++) {
|
||||||
|
h[j] = h_be[i * HASH_GE_L + HASH_GE_L - 1U - j];
|
||||||
|
}
|
||||||
|
memset(&h[j], 0, (sizeof h) - j);
|
||||||
|
ge25519_from_hash(&px[i * 32], h);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ge25519_from_string(unsigned char p[32],
|
||||||
|
const char *ctx, const unsigned char *msg,
|
||||||
|
size_t msg_len, int hash_alg)
|
||||||
|
{
|
||||||
|
return _string_to_points(p, 1, ctx, msg, msg_len, hash_alg);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ge25519_from_string_ro(unsigned char p[32],
|
||||||
|
const char *ctx, const unsigned char *msg,
|
||||||
|
size_t msg_len, int hash_alg)
|
||||||
|
{
|
||||||
|
unsigned char px[64];
|
||||||
|
ge25519_p3 p_p3, q_p3, r_p3;
|
||||||
|
|
||||||
|
if (_string_to_points(px, 2, ctx, msg, msg_len, hash_alg) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ge25519_frombytes(&p_p3, &px[0]) != 0 || ge25519_is_on_curve(&p_p3) == 0 ||
|
||||||
|
ge25519_frombytes(&q_p3, &px[32]) != 0 || ge25519_is_on_curve(&q_p3) == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ge25519_p3_add(&r_p3, &p_p3, &q_p3);
|
||||||
|
ge25519_p3_tobytes(p, &r_p3);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fe25519_reduce64(fe25519 fe_f, const unsigned char h[64])
|
fe25519_reduce64(fe25519 fe_f, const unsigned char h[64])
|
||||||
{
|
{
|
||||||
|
@ -55,7 +55,7 @@ _crypto_sign_ed25519_verify_detached(const unsigned char *sig,
|
|||||||
crypto_hash_sha512_final(&hs, h);
|
crypto_hash_sha512_final(&hs, h);
|
||||||
sc25519_reduce(h);
|
sc25519_reduce(h);
|
||||||
|
|
||||||
ge25519_double_scalarmult_vartime(&sb_ah_p2, h, &A, sig + 32);
|
ge25519_double_scalarmult_vartime(&sb_ah_p2, h, &A, sig + 32, NULL);
|
||||||
ge25519_p2_to_p3(&sb_ah, &sb_ah_p2);
|
ge25519_p2_to_p3(&sb_ah, &sb_ah_p2);
|
||||||
ge25519_p3_sub(&check, &expected_r, &sb_ah);
|
ge25519_p3_sub(&check, &expected_r, &sb_ah);
|
||||||
|
|
||||||
|
72
src/libsodium/crypto_vrf/crypto_vrf.c
Normal file
72
src/libsodium/crypto_vrf/crypto_vrf.c
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
|
||||||
|
#include "crypto_vrf.h"
|
||||||
|
|
||||||
|
size_t
|
||||||
|
crypto_vrf_publickeybytes(void)
|
||||||
|
{
|
||||||
|
return crypto_vrf_PUBLICKEYBYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
crypto_vrf_secretkeybytes(void)
|
||||||
|
{
|
||||||
|
return crypto_vrf_SECRETKEYBYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
crypto_vrf_seedbytes(void)
|
||||||
|
{
|
||||||
|
return crypto_vrf_SEEDBYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
crypto_vrf_proofbytes(void)
|
||||||
|
{
|
||||||
|
return crypto_vrf_PROOFBYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
crypto_vrf_outputbytes(void)
|
||||||
|
{
|
||||||
|
return crypto_vrf_OUTPUTBYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
crypto_vrf_primitive(void)
|
||||||
|
{
|
||||||
|
return crypto_vrf_PRIMITIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
crypto_vrf_keypair(unsigned char *pk, unsigned char *sk)
|
||||||
|
{
|
||||||
|
return crypto_vrf_rfc9381_keypair(pk, sk);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
crypto_vrf_seed_keypair(unsigned char *pk, unsigned char *sk,
|
||||||
|
const unsigned char *seed)
|
||||||
|
{
|
||||||
|
return crypto_vrf_rfc9381_seed_keypair(pk, sk, seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
crypto_vrf_prove(unsigned char *proof, const unsigned char *m, const unsigned long long mlen,
|
||||||
|
const unsigned char *skpk)
|
||||||
|
{
|
||||||
|
return crypto_vrf_rfc9381_prove(proof, m, mlen, skpk);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
crypto_vrf_verify(unsigned char *output, const unsigned char *pk,
|
||||||
|
const unsigned char *proof, const unsigned char *m,
|
||||||
|
const unsigned long long mlen)
|
||||||
|
{
|
||||||
|
return crypto_vrf_rfc9381_verify(output, pk, proof, m, mlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
crypto_vrf_proof_to_hash(unsigned char *hash, const unsigned char *proof)
|
||||||
|
{
|
||||||
|
return crypto_vrf_rfc9381_proof_to_hash(hash, proof);
|
||||||
|
}
|
40
src/libsodium/crypto_vrf/rfc9381/keypair.c
Normal file
40
src/libsodium/crypto_vrf/rfc9381/keypair.c
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "crypto_hash_sha512.h"
|
||||||
|
#include "crypto_vrf_rfc9381.h"
|
||||||
|
#include "private/ed25519_ref10.h"
|
||||||
|
#include "randombytes.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
crypto_vrf_rfc9381_seed_keypair(unsigned char *pk, unsigned char *sk,
|
||||||
|
const unsigned char *seed)
|
||||||
|
{
|
||||||
|
ge25519_p3 A;
|
||||||
|
|
||||||
|
crypto_hash_sha512(sk, seed, 32);
|
||||||
|
sk[0] &= 248;
|
||||||
|
sk[31] &= 127;
|
||||||
|
sk[31] |= 64;
|
||||||
|
|
||||||
|
ge25519_scalarmult_base(&A, sk);
|
||||||
|
ge25519_p3_tobytes(pk, &A);
|
||||||
|
|
||||||
|
memmove(sk, seed, 32);
|
||||||
|
memmove(sk + 32, pk, 32);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
crypto_vrf_rfc9381_keypair(unsigned char *pk, unsigned char *sk)
|
||||||
|
{
|
||||||
|
unsigned char seed[32];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
randombytes_buf(seed, sizeof seed);
|
||||||
|
ret = crypto_vrf_rfc9381_seed_keypair(pk, sk, seed);
|
||||||
|
sodium_memzero(seed, sizeof seed);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
69
src/libsodium/crypto_vrf/rfc9381/prove.c
Normal file
69
src/libsodium/crypto_vrf/rfc9381/prove.c
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "crypto_hash_sha512.h"
|
||||||
|
#include "crypto_vrf_rfc9381.h"
|
||||||
|
#include "private/ed25519_ref10.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "vrf_rfc9381.h"
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
crypto_vrf_rfc9381_prove(unsigned char *proof,
|
||||||
|
const unsigned char *m, unsigned long long mlen,
|
||||||
|
const unsigned char *sk)
|
||||||
|
{
|
||||||
|
|
||||||
|
crypto_hash_sha512_state hs;
|
||||||
|
unsigned char az[64];
|
||||||
|
unsigned char H_string[32];
|
||||||
|
unsigned char kB_string[32], kH_string[32];
|
||||||
|
unsigned char string_to_hash[32 + mlen];
|
||||||
|
unsigned char challenge[64], nonce[64];
|
||||||
|
ge25519_p3 H, Gamma, kB, kH;
|
||||||
|
|
||||||
|
crypto_hash_sha512(az, sk, 32);
|
||||||
|
az[0] &= 248;
|
||||||
|
az[31] &= 127;
|
||||||
|
az[31] |= 64;
|
||||||
|
|
||||||
|
memmove(string_to_hash, sk + 32, 32);
|
||||||
|
memmove(string_to_hash + 32, m, mlen);
|
||||||
|
ge25519_from_string(H_string, "ECVRF_edwards25519_XMD:SHA-512_ELL2_NU_\4", string_to_hash, 32 + mlen, 2); /* elligator2 */
|
||||||
|
|
||||||
|
ge25519_frombytes(&H, H_string);
|
||||||
|
ge25519_scalarmult(&Gamma, az, &H);
|
||||||
|
|
||||||
|
crypto_hash_sha512_init(&hs);
|
||||||
|
crypto_hash_sha512_update(&hs, az + 32, 32);
|
||||||
|
crypto_hash_sha512_update(&hs, H_string, 32);
|
||||||
|
crypto_hash_sha512_final(&hs, nonce);
|
||||||
|
|
||||||
|
sc25519_reduce(nonce);
|
||||||
|
ge25519_scalarmult_base(&kB, nonce);
|
||||||
|
ge25519_scalarmult(&kH, nonce, &H);
|
||||||
|
|
||||||
|
ge25519_p3_tobytes(proof, &Gamma);
|
||||||
|
ge25519_p3_tobytes(kB_string, &kB);
|
||||||
|
ge25519_p3_tobytes(kH_string, &kH);
|
||||||
|
|
||||||
|
crypto_hash_sha512_init(&hs);
|
||||||
|
crypto_hash_sha512_update(&hs, &SUITE, 1);
|
||||||
|
crypto_hash_sha512_update(&hs, &TWO, 1);
|
||||||
|
crypto_hash_sha512_update(&hs, sk + 32, 32);
|
||||||
|
crypto_hash_sha512_update(&hs, H_string, 32);
|
||||||
|
crypto_hash_sha512_update(&hs, proof, 32);
|
||||||
|
crypto_hash_sha512_update(&hs, kB_string, 32);
|
||||||
|
crypto_hash_sha512_update(&hs, kH_string, 32);
|
||||||
|
crypto_hash_sha512_update(&hs, &ZERO, 1);
|
||||||
|
crypto_hash_sha512_final(&hs, challenge);
|
||||||
|
|
||||||
|
memmove(proof + 32, challenge, 16);
|
||||||
|
memset(challenge + 16, 0, 48); /* we zero out the last 48 bytes of the challenge */
|
||||||
|
sc25519_muladd(proof + 48, challenge, az, nonce);
|
||||||
|
|
||||||
|
sodium_memzero(az, sizeof az);
|
||||||
|
sodium_memzero(nonce, sizeof nonce);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
116
src/libsodium/crypto_vrf/rfc9381/verify.c
Normal file
116
src/libsodium/crypto_vrf/rfc9381/verify.c
Normal file
@ -0,0 +1,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;
|
||||||
|
}
|
||||||
|
}
|
31
src/libsodium/crypto_vrf/rfc9381/vrf.c
Normal file
31
src/libsodium/crypto_vrf/rfc9381/vrf.c
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#include "crypto_vrf_rfc9381.h"
|
||||||
|
|
||||||
|
size_t
|
||||||
|
crypto_vrf_rfc9381_bytes(void)
|
||||||
|
{
|
||||||
|
return crypto_vrf_rfc9381_BYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
crypto_vrf_rfc9381_outputbytes(void)
|
||||||
|
{
|
||||||
|
return crypto_vrf_rfc9381_OUTPUTBYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
crypto_vrf_rfc9381_seedbytes(void)
|
||||||
|
{
|
||||||
|
return crypto_vrf_rfc9381_SEEDBYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
crypto_vrf_rfc9381_publickeybytes(void)
|
||||||
|
{
|
||||||
|
return crypto_vrf_rfc9381_PUBLICKEYBYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
crypto_vrf_rfc9381_secretkeybytes(void)
|
||||||
|
{
|
||||||
|
return crypto_vrf_rfc9381_SECRETKEYBYTES;
|
||||||
|
}
|
10
src/libsodium/crypto_vrf/rfc9381/vrf_rfc9381.h
Normal file
10
src/libsodium/crypto_vrf/rfc9381/vrf_rfc9381.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#ifndef vrf_rfc9381_H
|
||||||
|
#define vrf_rfc9381_H
|
||||||
|
|
||||||
|
static const unsigned char SUITE = 0x04; /* ECVRF-ED25519-SHA512-ELL2 */
|
||||||
|
|
||||||
|
static const unsigned char ZERO = 0x00;
|
||||||
|
static const unsigned char TWO = 0x02;
|
||||||
|
static const unsigned char THREE = 0x03;
|
||||||
|
|
||||||
|
#endif
|
@ -59,6 +59,8 @@ SODIUM_EXPORT = \
|
|||||||
sodium/crypto_verify_16.h \
|
sodium/crypto_verify_16.h \
|
||||||
sodium/crypto_verify_32.h \
|
sodium/crypto_verify_32.h \
|
||||||
sodium/crypto_verify_64.h \
|
sodium/crypto_verify_64.h \
|
||||||
|
sodium/crypto_vrf.h \
|
||||||
|
sodium/crypto_vrf_rfc9381.h \
|
||||||
sodium/export.h \
|
sodium/export.h \
|
||||||
sodium/randombytes.h \
|
sodium/randombytes.h \
|
||||||
sodium/randombytes_internal_random.h \
|
sodium/randombytes_internal_random.h \
|
||||||
|
@ -51,6 +51,8 @@
|
|||||||
#include "sodium/crypto_verify_16.h"
|
#include "sodium/crypto_verify_16.h"
|
||||||
#include "sodium/crypto_verify_32.h"
|
#include "sodium/crypto_verify_32.h"
|
||||||
#include "sodium/crypto_verify_64.h"
|
#include "sodium/crypto_verify_64.h"
|
||||||
|
#include "sodium/crypto_vrf.h"
|
||||||
|
#include "sodium/crypto_vrf_rfc9381.h"
|
||||||
#include "sodium/randombytes.h"
|
#include "sodium/randombytes.h"
|
||||||
#include "sodium/randombytes_internal_random.h"
|
#include "sodium/randombytes_internal_random.h"
|
||||||
#include "sodium/randombytes_sysrandom.h"
|
#include "sodium/randombytes_sysrandom.h"
|
||||||
|
75
src/libsodium/include/sodium/crypto_vrf.h
Normal file
75
src/libsodium/include/sodium/crypto_vrf.h
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#ifndef crypto_vrf_H
|
||||||
|
#define crypto_vrf_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* THREAD SAFETY: crypto_vrf_keypair() is thread-safe,
|
||||||
|
* provided that sodium_init() was called before.
|
||||||
|
*
|
||||||
|
* Other functions, including crypto_vrf_keypair_from_seed(), are always thread-safe.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "crypto_vrf_rfc9381.h"
|
||||||
|
#include "export.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
# ifdef __GNUC__
|
||||||
|
# pragma GCC diagnostic ignored "-Wlong-long"
|
||||||
|
# endif
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define crypto_vrf_PROOFBYTES crypto_vrf_rfc9381_BYTES
|
||||||
|
SODIUM_EXPORT
|
||||||
|
size_t crypto_vrf_bytes(void);
|
||||||
|
|
||||||
|
#define crypto_vrf_OUTPUTBYTES crypto_vrf_rfc9381_OUTPUTBYTES
|
||||||
|
SODIUM_EXPORT
|
||||||
|
size_t crypto_vrf_outputbytes(void);
|
||||||
|
|
||||||
|
#define crypto_vrf_SEEDBYTES crypto_vrf_rfc9381_SEEDBYTES
|
||||||
|
SODIUM_EXPORT
|
||||||
|
size_t crypto_vrf_seedbytes(void);
|
||||||
|
|
||||||
|
#define crypto_vrf_PUBLICKEYBYTES crypto_vrf_rfc9381_PUBLICKEYBYTES
|
||||||
|
SODIUM_EXPORT
|
||||||
|
size_t crypto_vrf_publickeybytes(void);
|
||||||
|
|
||||||
|
#define crypto_vrf_SECRETKEYBYTES crypto_vrf_rfc9381_SECRETKEYBYTES
|
||||||
|
SODIUM_EXPORT
|
||||||
|
size_t crypto_vrf_secretkeybytes(void);
|
||||||
|
|
||||||
|
#define crypto_vrf_PRIMITIVE "rfc9381"
|
||||||
|
SODIUM_EXPORT
|
||||||
|
const char *crypto_vrf_primitive(void);
|
||||||
|
|
||||||
|
SODIUM_EXPORT
|
||||||
|
int crypto_vrf_keypair(unsigned char *pk, unsigned char *sk)
|
||||||
|
__attribute__ ((nonnull));
|
||||||
|
|
||||||
|
SODIUM_EXPORT
|
||||||
|
int crypto_vrf_seed_keypair(unsigned char *pk, unsigned char *sk,
|
||||||
|
const unsigned char *seed)
|
||||||
|
__attribute__ ((nonnull));
|
||||||
|
|
||||||
|
SODIUM_EXPORT
|
||||||
|
int crypto_vrf_prove(unsigned char *proof, const unsigned char *m,
|
||||||
|
unsigned long long mlen, const unsigned char *sk)
|
||||||
|
__attribute__ ((nonnull));
|
||||||
|
|
||||||
|
SODIUM_EXPORT
|
||||||
|
int crypto_vrf_verify(unsigned char *output,
|
||||||
|
const unsigned char *pk,
|
||||||
|
const unsigned char *proof,
|
||||||
|
const unsigned char *m, unsigned long long mlen)
|
||||||
|
__attribute__ ((warn_unused_result)) __attribute__ ((nonnull));
|
||||||
|
|
||||||
|
SODIUM_EXPORT
|
||||||
|
int crypto_vrf_proof_to_hash(unsigned char *hash, const unsigned char *proof);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
78
src/libsodium/include/sodium/crypto_vrf_rfc9381.h
Normal file
78
src/libsodium/include/sodium/crypto_vrf_rfc9381.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
|
||||||
|
#ifndef crypto_vrf_rfc9381_H
|
||||||
|
#define crypto_vrf_rfc9381_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "export.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
# ifdef __GNUC__
|
||||||
|
# pragma GCC diagnostic ignored "-Wlong-long"
|
||||||
|
# endif
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define crypto_vrf_rfc9381_BYTES 80U
|
||||||
|
SODIUM_EXPORT
|
||||||
|
size_t crypto_vrf_rfc9381_bytes(void);
|
||||||
|
|
||||||
|
#define crypto_vrf_rfc9381_OUTPUTBYTES 64U
|
||||||
|
SODIUM_EXPORT
|
||||||
|
size_t crypto_vrf_rfc9381_outputbytes(void);
|
||||||
|
|
||||||
|
#define crypto_vrf_rfc9381_SEEDBYTES 32U
|
||||||
|
SODIUM_EXPORT
|
||||||
|
size_t crypto_vrf_rfc9381_seedbytes(void);
|
||||||
|
|
||||||
|
#define crypto_vrf_rfc9381_PUBLICKEYBYTES 32U
|
||||||
|
SODIUM_EXPORT
|
||||||
|
size_t crypto_vrf_rfc9381_publickeybytes(void);
|
||||||
|
|
||||||
|
#define crypto_vrf_rfc9381_SECRETKEYBYTES 64U
|
||||||
|
SODIUM_EXPORT
|
||||||
|
size_t crypto_vrf_rfc9381_secretkeybytes(void);
|
||||||
|
|
||||||
|
SODIUM_EXPORT
|
||||||
|
int crypto_vrf_rfc9381_prove(unsigned char *proof,
|
||||||
|
const unsigned char *m,
|
||||||
|
unsigned long long mlen, const unsigned char *sk);
|
||||||
|
|
||||||
|
SODIUM_EXPORT
|
||||||
|
int crypto_vrf_rfc9381_verify(unsigned char *output,
|
||||||
|
const unsigned char *pk,
|
||||||
|
const unsigned char *proof,
|
||||||
|
const unsigned char *m,
|
||||||
|
unsigned long long mlen)
|
||||||
|
__attribute__ ((warn_unused_result)) __attribute__ ((nonnull));
|
||||||
|
|
||||||
|
SODIUM_EXPORT
|
||||||
|
int crypto_vrf_rfc9381_proof_to_hash(unsigned char *hash,
|
||||||
|
const unsigned char *proof)
|
||||||
|
__attribute__ ((nonnull));
|
||||||
|
|
||||||
|
SODIUM_EXPORT
|
||||||
|
int crypto_vrf_rfc9381_keypair(unsigned char *pk, unsigned char *sk)
|
||||||
|
__attribute__ ((nonnull));
|
||||||
|
|
||||||
|
SODIUM_EXPORT
|
||||||
|
int crypto_vrf_rfc9381_seed_keypair(unsigned char *pk,
|
||||||
|
unsigned char *sk,
|
||||||
|
const unsigned char *seed)
|
||||||
|
__attribute__ ((nonnull));
|
||||||
|
|
||||||
|
SODIUM_EXPORT
|
||||||
|
void crypto_vrf_rfc9381_sk_to_seed(unsigned char *seed,
|
||||||
|
const unsigned char *sk)
|
||||||
|
__attribute__ ((nonnull));
|
||||||
|
|
||||||
|
SODIUM_EXPORT
|
||||||
|
void crypto_vrf_rfc9381_sk_to_pk(unsigned char *pk,
|
||||||
|
const unsigned char *sk)
|
||||||
|
__attribute__ ((nonnull));
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -96,7 +96,8 @@ void ge25519_scalarmult_base(ge25519_p3 *h, const unsigned char *a);
|
|||||||
|
|
||||||
void ge25519_double_scalarmult_vartime(ge25519_p2 *r, const unsigned char *a,
|
void ge25519_double_scalarmult_vartime(ge25519_p2 *r, const unsigned char *a,
|
||||||
const ge25519_p3 *A,
|
const ge25519_p3 *A,
|
||||||
const unsigned char *b);
|
const unsigned char *b,
|
||||||
|
const ge25519_p3 *B);
|
||||||
|
|
||||||
void ge25519_scalarmult(ge25519_p3 *h, const unsigned char *a,
|
void ge25519_scalarmult(ge25519_p3 *h, const unsigned char *a,
|
||||||
const ge25519_p3 *p);
|
const ge25519_p3 *p);
|
||||||
@ -115,6 +116,14 @@ void ge25519_from_uniform(unsigned char s[32], const unsigned char r[32]);
|
|||||||
|
|
||||||
void ge25519_from_hash(unsigned char s[32], const unsigned char h[64]);
|
void ge25519_from_hash(unsigned char s[32], const unsigned char h[64]);
|
||||||
|
|
||||||
|
int ge25519_from_string(unsigned char p[32],
|
||||||
|
const char *ctx, const unsigned char *msg,
|
||||||
|
size_t msg_len, int hash_alg);
|
||||||
|
|
||||||
|
int ge25519_from_string_ro(unsigned char p[32],
|
||||||
|
const char *ctx, const unsigned char *msg,
|
||||||
|
size_t msg_len, int hash_alg);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Ristretto group
|
Ristretto group
|
||||||
*/
|
*/
|
||||||
@ -132,6 +141,8 @@ void ristretto255_from_hash(unsigned char s[32], const unsigned char h[64]);
|
|||||||
|
|
||||||
void sc25519_invert(unsigned char recip[32], const unsigned char s[32]);
|
void sc25519_invert(unsigned char recip[32], const unsigned char s[32]);
|
||||||
|
|
||||||
|
void sc25519_negate(unsigned char neg[32], const unsigned char s[32]);
|
||||||
|
|
||||||
void sc25519_reduce(unsigned char s[64]);
|
void sc25519_reduce(unsigned char s[64]);
|
||||||
|
|
||||||
void sc25519_mul(unsigned char s[32], const unsigned char a[32],
|
void sc25519_mul(unsigned char s[32], const unsigned char a[32],
|
||||||
@ -142,4 +153,6 @@ void sc25519_muladd(unsigned char s[32], const unsigned char a[32],
|
|||||||
|
|
||||||
int sc25519_is_canonical(const unsigned char s[32]);
|
int sc25519_is_canonical(const unsigned char s[32]);
|
||||||
|
|
||||||
|
void ge25519_clear_cofactor(ge25519_p3 *p3);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -54,6 +54,8 @@
|
|||||||
#define ge25519_clear_cofactor _sodium_ge25519_clear_cofactor
|
#define ge25519_clear_cofactor _sodium_ge25519_clear_cofactor
|
||||||
#define ge25519_double_scalarmult_vartime _sodium_ge25519_double_scalarmult_vartime
|
#define ge25519_double_scalarmult_vartime _sodium_ge25519_double_scalarmult_vartime
|
||||||
#define ge25519_from_hash _sodium_ge25519_from_hash
|
#define ge25519_from_hash _sodium_ge25519_from_hash
|
||||||
|
#define ge25519_from_string _sodium_ge25519_from_string
|
||||||
|
#define ge25519_from_string_ro _sodium_ge25519_from_string_ro
|
||||||
#define ge25519_from_uniform _sodium_ge25519_from_uniform
|
#define ge25519_from_uniform _sodium_ge25519_from_uniform
|
||||||
#define ge25519_frombytes _sodium_ge25519_frombytes
|
#define ge25519_frombytes _sodium_ge25519_frombytes
|
||||||
#define ge25519_frombytes_negate_vartime _sodium_ge25519_frombytes_negate_vartime
|
#define ge25519_frombytes_negate_vartime _sodium_ge25519_frombytes_negate_vartime
|
||||||
@ -77,6 +79,7 @@
|
|||||||
#define sc25519_is_canonical _sodium_sc25519_is_canonical
|
#define sc25519_is_canonical _sodium_sc25519_is_canonical
|
||||||
#define sc25519_mul _sodium_sc25519_mul
|
#define sc25519_mul _sodium_sc25519_mul
|
||||||
#define sc25519_muladd _sodium_sc25519_muladd
|
#define sc25519_muladd _sodium_sc25519_muladd
|
||||||
|
#define sc25519_negate _sodium_sc25519_negate
|
||||||
#define sc25519_reduce _sodium_sc25519_reduce
|
#define sc25519_reduce _sodium_sc25519_reduce
|
||||||
#define softaes_block_encrypt _sodium_softaes_block_encrypt
|
#define softaes_block_encrypt _sodium_softaes_block_encrypt
|
||||||
|
|
||||||
|
@ -86,6 +86,7 @@ EXTRA_DIST = \
|
|||||||
stream3.exp \
|
stream3.exp \
|
||||||
stream4.exp \
|
stream4.exp \
|
||||||
verify1.exp \
|
verify1.exp \
|
||||||
|
vrf.exp \
|
||||||
xchacha20.exp
|
xchacha20.exp
|
||||||
|
|
||||||
DISTCLEANFILES = \
|
DISTCLEANFILES = \
|
||||||
@ -171,6 +172,7 @@ DISTCLEANFILES = \
|
|||||||
stream3.res \
|
stream3.res \
|
||||||
stream4.res \
|
stream4.res \
|
||||||
verify1.res \
|
verify1.res \
|
||||||
|
vrf.res \
|
||||||
xchacha20.res
|
xchacha20.res
|
||||||
|
|
||||||
AM_CPPFLAGS = \
|
AM_CPPFLAGS = \
|
||||||
@ -253,7 +255,8 @@ TESTS_TARGETS = \
|
|||||||
stream2 \
|
stream2 \
|
||||||
stream3 \
|
stream3 \
|
||||||
stream4 \
|
stream4 \
|
||||||
verify1
|
verify1 \
|
||||||
|
vrf
|
||||||
|
|
||||||
if !EMSCRIPTEN
|
if !EMSCRIPTEN
|
||||||
TESTS_TARGETS += \
|
TESTS_TARGETS += \
|
||||||
@ -511,6 +514,9 @@ stream4_LDADD = $(TESTS_LDADD)
|
|||||||
verify1_SOURCE = cmptest.h verify1.c
|
verify1_SOURCE = cmptest.h verify1.c
|
||||||
verify1_LDADD = $(TESTS_LDADD)
|
verify1_LDADD = $(TESTS_LDADD)
|
||||||
|
|
||||||
|
vrf_SOURCE = cmptest.h vrf.c
|
||||||
|
vrf_LDADD = $(TESTS_LDADD)
|
||||||
|
|
||||||
xchacha20_SOURCE = cmptest.h xchacha20.c
|
xchacha20_SOURCE = cmptest.h xchacha20.c
|
||||||
xchacha20_LDADD = $(TESTS_LDADD)
|
xchacha20_LDADD = $(TESTS_LDADD)
|
||||||
|
|
||||||
|
91
test/default/vrf.c
Normal file
91
test/default/vrf.c
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
|
||||||
|
#define TEST_NAME "vrf"
|
||||||
|
#include "cmptest.h"
|
||||||
|
|
||||||
|
typedef struct TestData_ {
|
||||||
|
const char seed[2 * 32 + 1];
|
||||||
|
} TestData;
|
||||||
|
/*
|
||||||
|
* Test data taken from https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-09#appendix-A.4
|
||||||
|
* which contains the seeds. The expected values for the pk, proof and output are in vrf.exp
|
||||||
|
*/
|
||||||
|
static const TestData test_data[] = {
|
||||||
|
{"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"},
|
||||||
|
{"4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb"},
|
||||||
|
{"c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7"},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const unsigned char messages[3][2] = {{0x00}, {0x72}, {0xaf, 0x82}};
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
unsigned char *seed;
|
||||||
|
unsigned char sk[64];
|
||||||
|
unsigned char pk[32];
|
||||||
|
unsigned char proof[80];
|
||||||
|
unsigned char output[64];
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
char pk_hex[32 * 2 + 1];
|
||||||
|
char proof_hex[80 * 2 + 1];
|
||||||
|
char output_hex[64 * 2 + 1];
|
||||||
|
|
||||||
|
seed = (unsigned char *) sodium_malloc(crypto_vrf_rfc9381_SEEDBYTES);
|
||||||
|
|
||||||
|
assert(crypto_vrf_rfc9381_SECRETKEYBYTES == 64);
|
||||||
|
assert(crypto_vrf_rfc9381_PUBLICKEYBYTES == 32);
|
||||||
|
assert(crypto_vrf_rfc9381_SEEDBYTES == 32);
|
||||||
|
assert(crypto_vrf_rfc9381_BYTES == 80);
|
||||||
|
assert(crypto_vrf_rfc9381_OUTPUTBYTES == 64);
|
||||||
|
|
||||||
|
for (i = 0U; i < (sizeof test_data) / (sizeof test_data[0]); i++) {
|
||||||
|
sodium_hex2bin(seed, 32,
|
||||||
|
test_data[i].seed, (size_t) -1U, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
crypto_vrf_rfc9381_seed_keypair(pk, sk, seed);
|
||||||
|
printf("%s\n", sodium_bin2hex(pk_hex, sizeof pk_hex, pk, sizeof pk));
|
||||||
|
|
||||||
|
if (crypto_vrf_rfc9381_prove(proof, messages[i], i, sk) != 0){
|
||||||
|
printf("crypto_vrf_prove() error: [%u]\n", i);
|
||||||
|
}
|
||||||
|
printf("%s\n", sodium_bin2hex(proof_hex, sizeof proof_hex, proof, sizeof proof));
|
||||||
|
|
||||||
|
if (crypto_vrf_rfc9381_verify(output, pk, proof, messages[i], i) != 0){
|
||||||
|
printf("verify error: [%u]\n", i);
|
||||||
|
}
|
||||||
|
printf("%s\n", sodium_bin2hex(output_hex, sizeof output_hex, output, sizeof output));
|
||||||
|
|
||||||
|
proof[0] ^= 0x01;
|
||||||
|
if (crypto_vrf_rfc9381_verify(output, pk, proof, messages[i], i) == 0){
|
||||||
|
printf("verify succeeded with bad gamma: [%u]\n", i);
|
||||||
|
}
|
||||||
|
proof[0] ^= 0x01;
|
||||||
|
proof[32] ^= 0x01;
|
||||||
|
if (crypto_vrf_rfc9381_verify(output, pk, proof, messages[i], i) == 0){
|
||||||
|
printf("verify succeeded with bad c value: [%u]\n", i);
|
||||||
|
}
|
||||||
|
proof[32] ^= 0x01;
|
||||||
|
proof[48] ^= 0x01;
|
||||||
|
if (crypto_vrf_rfc9381_verify(output, pk, proof, messages[i], i) == 0){
|
||||||
|
printf("verify succeeded with bad s value: [%u]\n", i);
|
||||||
|
}
|
||||||
|
proof[48] ^= 0x01;
|
||||||
|
proof[79] ^= 0x80;
|
||||||
|
if (crypto_vrf_rfc9381_verify(output, pk, proof, messages[i], i) == 0){
|
||||||
|
printf("verify succeeded with bad s value (high-order-bit flipped): [%u]\n", i);
|
||||||
|
}
|
||||||
|
proof[79] ^= 0x80;
|
||||||
|
|
||||||
|
if (i > 0) {
|
||||||
|
if (crypto_vrf_rfc9381_verify(output, pk, proof, messages[i], i-1) == 0){
|
||||||
|
printf("verify succeeded with truncated message: [%u]\n", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (crypto_vrf_rfc9381_proof_to_hash(output, proof) != 0){
|
||||||
|
printf("crypto_vrf_proof_to_hash() error: [%u]\n", i);
|
||||||
|
}
|
||||||
|
printf("%s\n\n", sodium_bin2hex(output_hex, sizeof output_hex, output, sizeof output));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
15
test/default/vrf.exp
Normal file
15
test/default/vrf.exp
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a
|
||||||
|
7d9c633ffeee27349264cf5c667579fc583b4bda63ab71d001f89c10003ab46f14adf9a3cd8b8412d9038531e865c341cafa73589b023d14311c331a9ad15ff2fb37831e00f0acaa6d73bc9997b06501
|
||||||
|
9d574bf9b8302ec0fc1e21c3ec5368269527b87b462ce36dab2d14ccf80c53cccf6758f058c5b1c856b116388152bbe509ee3b9ecfe63d93c3b4346c1fbc6c54
|
||||||
|
9d574bf9b8302ec0fc1e21c3ec5368269527b87b462ce36dab2d14ccf80c53cccf6758f058c5b1c856b116388152bbe509ee3b9ecfe63d93c3b4346c1fbc6c54
|
||||||
|
|
||||||
|
3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c
|
||||||
|
47b327393ff2dd81336f8a2ef10339112401253b3c714eeda879f12c509072ef055b48372bb82efbdce8e10c8cb9a2f9d60e93908f93df1623ad78a86a028d6bc064dbfc75a6a57379ef855dc6733801
|
||||||
|
38561d6b77b71d30eb97a062168ae12b667ce5c28caccdf76bc88e093e4635987cd96814ce55b4689b3dd2947f80e59aac7b7675f8083865b46c89b2ce9cc735
|
||||||
|
38561d6b77b71d30eb97a062168ae12b667ce5c28caccdf76bc88e093e4635987cd96814ce55b4689b3dd2947f80e59aac7b7675f8083865b46c89b2ce9cc735
|
||||||
|
|
||||||
|
fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025
|
||||||
|
926e895d308f5e328e7aa159c06eddbe56d06846abf5d98c2512235eaa57fdce35b46edfc655bc828d44ad09d1150f31374e7ef73027e14760d42e77341fe05467bb286cc2c9d7fde29120a0b2320d04
|
||||||
|
121b7f9b9aaaa29099fc04a94ba52784d44eac976dd1a3cca458733be5cd090a7b5fbd148444f17f8daf1fb55cb04b1ae85a626e30a54b4b0f8abf4a43314a58
|
||||||
|
121b7f9b9aaaa29099fc04a94ba52784d44eac976dd1a3cca458733be5cd090a7b5fbd148444f17f8daf1fb55cb04b1ae85a626e30a54b4b0f8abf4a43314a58
|
||||||
|
|
@ -637,6 +637,27 @@ crypto_verify_32
|
|||||||
crypto_verify_32_bytes
|
crypto_verify_32_bytes
|
||||||
crypto_verify_64
|
crypto_verify_64
|
||||||
crypto_verify_64_bytes
|
crypto_verify_64_bytes
|
||||||
|
crypto_vrf_keypair
|
||||||
|
crypto_vrf_outputbytes
|
||||||
|
crypto_vrf_primitive
|
||||||
|
crypto_vrf_proof_to_hash
|
||||||
|
crypto_vrf_proofbytes
|
||||||
|
crypto_vrf_prove
|
||||||
|
crypto_vrf_publickeybytes
|
||||||
|
crypto_vrf_rfc9381_bytes
|
||||||
|
crypto_vrf_rfc9381_keypair
|
||||||
|
crypto_vrf_rfc9381_outputbytes
|
||||||
|
crypto_vrf_rfc9381_proof_to_hash
|
||||||
|
crypto_vrf_rfc9381_prove
|
||||||
|
crypto_vrf_rfc9381_publickeybytes
|
||||||
|
crypto_vrf_rfc9381_secretkeybytes
|
||||||
|
crypto_vrf_rfc9381_seed_keypair
|
||||||
|
crypto_vrf_rfc9381_seedbytes
|
||||||
|
crypto_vrf_rfc9381_verify
|
||||||
|
crypto_vrf_secretkeybytes
|
||||||
|
crypto_vrf_seed_keypair
|
||||||
|
crypto_vrf_seedbytes
|
||||||
|
crypto_vrf_verify
|
||||||
escrypt_PBKDF2_SHA256
|
escrypt_PBKDF2_SHA256
|
||||||
escrypt_alloc_region
|
escrypt_alloc_region
|
||||||
escrypt_free_local
|
escrypt_free_local
|
||||||
@ -653,6 +674,8 @@ fe25519_tobytes
|
|||||||
ge25519_clear_cofactor
|
ge25519_clear_cofactor
|
||||||
ge25519_double_scalarmult_vartime
|
ge25519_double_scalarmult_vartime
|
||||||
ge25519_from_hash
|
ge25519_from_hash
|
||||||
|
ge25519_from_string
|
||||||
|
ge25519_from_string_ro
|
||||||
ge25519_from_uniform
|
ge25519_from_uniform
|
||||||
ge25519_frombytes
|
ge25519_frombytes
|
||||||
ge25519_frombytes_negate_vartime
|
ge25519_frombytes_negate_vartime
|
||||||
@ -686,6 +709,7 @@ sc25519_invert
|
|||||||
sc25519_is_canonical
|
sc25519_is_canonical
|
||||||
sc25519_mul
|
sc25519_mul
|
||||||
sc25519_muladd
|
sc25519_muladd
|
||||||
|
sc25519_negate
|
||||||
sc25519_reduce
|
sc25519_reduce
|
||||||
sodium_add
|
sodium_add
|
||||||
sodium_allocarray
|
sodium_allocarray
|
||||||
|
Loading…
Reference in New Issue
Block a user