summaryrefslogtreecommitdiff
path: root/libs/libsodium/src/crypto_vrf/rfc9381/prove.c
blob: 1dffed277478069012d0ffc423fe24321f031feb (plain)
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
#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;
}