void ed25519_sign(const unsigned char *m, size_t mlen, const ed25519_secret_key sk, const ed25519_public_key pk, ed25519_signature RS) { SHA512_CTX shactx; bignum256modm r, S, a; ge25519 MM16 R; hash_512bits extsk, hashr, hram; ed25519_extsk(extsk, sk); /* r = H(aExt[32..64], m) */ SHA512_Init(&shactx); SHA512_Update(&shactx, extsk + 32, 32); SHA512_Update(&shactx, m, mlen); SHA512_Final(hashr, &shactx); expand256_modm(r, hashr, 64); /* R = rB */ ge25519_scalarmult_base_niels(&R, r); ge25519_pack(RS, &R); /* S = H(R,A,m).. */ ed25519_hram(hram, RS, pk, m, mlen); expand256_modm(S, hram, 64); /* S = H(R,A,m)a */ expand256_modm(a, extsk, 32); mul256_modm(S, S, a); /* S = (r + H(R,A,m)a) */ add256_modm(S, S, r); /* S = (r + H(R,A,m)a) mod L */ contract256_modm(RS + 32, S); }
void ED25519_FN(ed25519_sign) (const unsigned char *m, size_t mlen, const ed25519_secret_key sk, const ed25519_public_key pk, ed25519_signature RS) { ed25519_hash_context ctx; bignum256modm r, S, a; ge25519 MM16 R; hash_512bits extsk, hashr, hram; ed25519_extsk(extsk, sk); /* r = H(aExt[32..64], m) */ ed25519_hash_init(&ctx); ed25519_hash_update(&ctx, extsk + 32, 32); ed25519_hash_update(&ctx, m, mlen); ed25519_hash_final(&ctx, hashr); expand256_modm(r, hashr, 64); /* R = rB */ ge25519_scalarmult_base_niels(&R, ge25519_niels_base_multiples, r); ge25519_pack(RS, &R); /* S = H(R,A,m).. */ ed25519_hram(hram, RS, pk, m, mlen); expand256_modm(S, hram, 64); /* S = H(R,A,m)a */ expand256_modm(a, extsk, 32); mul256_modm(S, S, a); /* S = (r + H(R,A,m)a) */ add256_modm(S, S, r); /* S = (r + H(R,A,m)a) mod L */ contract256_modm(RS + 32, S); }
int ed25519_donna_blind_secret_key(unsigned char *out, const unsigned char *inp, const unsigned char *param) { static const char str[] = "Derive temporary signing key hash input"; unsigned char tweak[64]; ed25519_hash_context ctx; bignum256modm ALIGN(16) sk, t; ed25519_donna_gettweak(tweak, param); expand256_modm(t, tweak, 32); expand256_modm(sk, inp, 32); mul256_modm(sk, sk, t); contract256_modm(out, sk); ed25519_hash_init(&ctx); ed25519_hash_update(&ctx, (const unsigned char*)str, strlen(str)); ed25519_hash_update(&ctx, inp + 32, 32); ed25519_hash_final(&ctx, tweak); memcpy(out + 32, tweak, 32); memwipe(sk, 0, sizeof(sk)); memwipe(t, 0, sizeof(t)); memwipe(tweak, 0, sizeof(tweak)); return 0; }
int ed25519_donna_blind_public_key(unsigned char *out, const unsigned char *inp, const unsigned char *param) { static const bignum256modm zero = { 0 }; unsigned char tweak[64]; unsigned char pkcopy[32]; ge25519 ALIGN(16) A, Aprime; bignum256modm ALIGN(16) t; ed25519_donna_gettweak(tweak, param); expand256_modm(t, tweak, 32); /* No "ge25519_unpack", negate the public key. */ memcpy(pkcopy, inp, 32); pkcopy[31] ^= (1<<7); ge25519_unpack_negative_vartime(&A, pkcopy); /* A' = [tweak] * A + [0] * basepoint. */ ge25519_double_scalarmult_vartime(&Aprime, &A, t, zero); ge25519_pack(out, &Aprime); memwipe(tweak, 0, sizeof(tweak)); memwipe(pkcopy, 0, sizeof(pkcopy)); memwipe(&A, 0, sizeof(A)); memwipe(&Aprime, 0, sizeof(Aprime)); memwipe(t, 0, sizeof(t)); return 0; }
int ed25519_donna_sign(unsigned char *sig, const unsigned char *m, size_t mlen, const unsigned char *sk, const unsigned char *pk) { ed25519_hash_context ctx; bignum256modm r = {0}, S, a; ge25519 ALIGN(16) R = {{0}, {0}, {0}, {0}}; hash_512bits hashr, hram; /* This is equivalent to the removed `ED25519_FN(ed25519_sign)` routine, * except that the key expansion step is omitted as sk already is in expanded * form. */ /* r = H(aExt[32..64], m) */ ed25519_hash_init(&ctx); ed25519_hash_update(&ctx, sk + 32, 32); ed25519_hash_update(&ctx, m, mlen); ed25519_hash_final(&ctx, hashr); expand256_modm(r, hashr, 64); /* R = rB */ ge25519_scalarmult_base_niels(&R, ge25519_niels_base_multiples, r); ge25519_pack(sig, &R); /* S = H(R,A,m).. */ ed25519_hram(hram, sig, pk, m, mlen); expand256_modm(S, hram, 64); /* S = H(R,A,m)a */ expand256_modm(a, sk, 32); mul256_modm(S, S, a); /* S = (r + H(R,A,m)a) */ add256_modm(S, S, r); /* S = (r + H(R,A,m)a) mod L */ contract256_modm(sig + 32, S); return 0; }
void ED25519_FN(ed25519_publickey) (const ed25519_secret_key sk, ed25519_public_key pk) { bignum256modm a; ge25519 MM16 A; hash_512bits extsk; /* A = aB */ ed25519_extsk(extsk, sk); expand256_modm(a, extsk, 32); ge25519_scalarmult_base_niels(&A, ge25519_niels_base_multiples, a); ge25519_pack(pk, &A); }
int ed25519_donna_pubkey(unsigned char *pk, const unsigned char *sk) { bignum256modm a = {0}; ge25519 ALIGN(16) A = {{0}, {0}, {0}, {0}}; /* A = aB */ expand256_modm(a, sk, 32); ge25519_scalarmult_base_niels(&A, ge25519_niels_base_multiples, a); ge25519_pack(pk, &A); return 0; }
int ED25519_FN(ed25519_sign_open) (const unsigned char *m, size_t mlen, const ed25519_public_key pk, const ed25519_signature RS) { ge25519 MM16 R, A; hash_512bits hash; bignum256modm hram, S; unsigned char checkR[32]; if ((RS[63] & 224) || !ge25519_unpack_negative_vartime(&A, pk)) return -1; /* hram = H(R,A,m) */ ed25519_hram(hash, RS, pk, m, mlen); expand256_modm(hram, hash, 64); /* S */ expand256_modm(S, RS + 32, 32); /* SB - H(R,A,m)A */ ge25519_double_scalarmult_vartime(&R, &A, hram, S); ge25519_pack(checkR, &R); /* check that R = SB - H(R,A,m)A */ return ed25519_verify(RS, checkR, 32) ? 0 : -1; }