static int _crypto_scalarmult_ed25519(unsigned char *q, const unsigned char *n, const unsigned char *p, const int clamp) { unsigned char *t = q; ge25519_p3 Q; ge25519_p3 P; unsigned int i; if (ge25519_is_canonical(p) == 0 || ge25519_has_small_order(p) != 0 || ge25519_frombytes(&P, p) != 0 || ge25519_is_on_main_subgroup(&P) == 0) { return -1; } for (i = 0; i < 32; ++i) { t[i] = n[i]; } if (clamp != 0) { _crypto_scalarmult_ed25519_clamp(t); } ge25519_scalarmult(&Q, t, &P); ge25519_p3_tobytes(q, &Q); if (_crypto_scalarmult_ed25519_is_inf(q) != 0 || sodium_is_zero(n, 32)) { return -1; } return 0; }
int _crypto_sign_ed25519_detached(unsigned char *sig, unsigned long long *siglen_p, const unsigned char *m, unsigned long long mlen, const unsigned char *sk, int prehashed) { crypto_hash_sha512_state hs; unsigned char az[64]; unsigned char nonce[64]; unsigned char hram[64]; ge25519_p3 R; _crypto_sign_ed25519_ref10_hinit(&hs, prehashed); #ifdef ED25519_NONDETERMINISTIC memcpy(az, sk, 32); _crypto_sign_ed25519_synthetic_r_hv(&hs, nonce, az); #else crypto_hash_sha512(az, sk, 32); crypto_hash_sha512_update(&hs, az + 32, 32); #endif crypto_hash_sha512_update(&hs, m, mlen); crypto_hash_sha512_final(&hs, nonce); memmove(sig + 32, sk + 32, 32); sc25519_reduce(nonce); ge25519_scalarmult_base(&R, nonce); ge25519_p3_tobytes(sig, &R); _crypto_sign_ed25519_ref10_hinit(&hs, prehashed); crypto_hash_sha512_update(&hs, sig, 64); crypto_hash_sha512_update(&hs, m, mlen); crypto_hash_sha512_final(&hs, hram); sc25519_reduce(hram); _crypto_sign_ed25519_clamp(az); sc25519_muladd(sig + 32, hram, az, nonce); sodium_memzero(az, sizeof az); sodium_memzero(nonce, sizeof nonce); if (siglen_p != NULL) { *siglen_p = 64U; } return 0; }
static int _crypto_scalarmult_ed25519_base(unsigned char *q, const unsigned char *n, const int clamp) { unsigned char *t = q; ge25519_p3 Q; unsigned int i; for (i = 0; i < 32; ++i) { t[i] = n[i]; } if (clamp != 0) { _crypto_scalarmult_ed25519_clamp(t); } ge25519_scalarmult_base(&Q, t); ge25519_p3_tobytes(q, &Q); if (_crypto_scalarmult_ed25519_is_inf(q) != 0 || sodium_is_zero(n, 32)) { return -1; } return 0; }
int crypto_sign_ed25519_seed_keypair(unsigned char *pk, unsigned char *sk, const unsigned char *seed) { ge25519_p3 A; #ifdef ED25519_NONDETERMINISTIC memmove(sk, seed, 32); #else crypto_hash_sha512(sk, seed, 32); #endif 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; }