// Step 3 // y = (sk_r + c * sk) mod #(B) with sk secret int schnorr_id_response(uint8_t response[SCHNORR_ID_RESPONSEBYTES], const uint8_t sk[SCHNORR_SECRETKEYBYTES], const uint8_t sk_r[SCHNORR_SECRETKEYBYTES], const uint8_t challenge[SCHNORR_ID_CHALLENGEBYTES]) { sc25519 sc_sk; sc25519 sc_sk_r; sc25519 sc_challenge; sc25519_from32bytes(&sc_sk, sk); sc25519_from32bytes(&sc_sk_r, sk_r); sc25519_from_challenge_bytes(&sc_challenge, challenge); sc25519_mul(&sc_sk, &sc_sk, &sc_challenge); sc25519_add(&sc_sk, &sc_sk, &sc_sk_r); sc25519_to32bytes(response, &sc_sk); return 0; }
int schnorr_publickey(uint8_t pk[SCHNORR_PUBLICKEYBYTES], const uint8_t sk[SCHNORR_SECRETKEYBYTES]) { sc25519 sc_sk; ge25519 ge_pk; sc25519_from32bytes(&sc_sk, sk); ge25519_scalarmult_base(&ge_pk, &sc_sk); ge25519_pack(pk, &ge_pk); return 0; }
int crypto_sign_ed25519( unsigned char *sm,unsigned long long *smlen, const unsigned char *m,unsigned long long mlen, const unsigned char *sk ) { sc25519 sck, scs, scsk; ge25519 ger; unsigned char r[32]; unsigned char s[32]; unsigned char extsk[64]; unsigned long long i; unsigned char hmg[crypto_hash_sha512_BYTES]; unsigned char hram[crypto_hash_sha512_BYTES]; crypto_hash_sha512(extsk, sk, 32); extsk[0] &= 248; extsk[31] &= 127; extsk[31] |= 64; *smlen = mlen+64; for(i=0;i<mlen;i++) sm[64 + i] = m[i]; for(i=0;i<32;i++) sm[32 + i] = extsk[32+i]; crypto_hash_sha512(hmg, sm+32, mlen+32); /* Generate k as h(extsk[32],...,extsk[63],m) */ /* Computation of R */ sc25519_from64bytes(&sck, hmg); ge25519_scalarmult_base(&ger, &sck); ge25519_pack(r, &ger); /* Computation of s */ for(i=0;i<32;i++) sm[i] = r[i]; get_hram(hram, sm, sk+32, sm, mlen+64); sc25519_from64bytes(&scs, hram); sc25519_from32bytes(&scsk, extsk); sc25519_mul(&scs, &scs, &scsk); sc25519_add(&scs, &scs, &sck); sc25519_to32bytes(s,&scs); /* cat s */ for(i=0;i<32;i++) sm[32 + i] = s[i]; return 0; }
void test_sc25519_mul() { unsigned char a[32], b[32]; sc25519 fa, fb, fr; int n; for(n=0;n<NTESTS;n++) { randombytes(a,32); randombytes(b,32); sc25519_from32bytes(&fa, a); sc25519_from32bytes(&fb, b); sc25519_mul(&fr, &fa, &fb); print("("); sc25519_print(&fa); print("*"); sc25519_print(&fb); print(") % 7237005577332262213973186563042994240857116359379907606001950938285454250989 -"); sc25519_print(&fr); print("\r\n"); } }
void sc25519_random(sc25519 *r, int c) { unsigned char x[32]; simpleot_randombytes(x, 32); if (c == 0) { x[31] &= 15; } else { x[0] &= 248; x[31] &= 127; } sc25519_from32bytes(r, x); }
int crypto_sign_open( unsigned char *m,unsigned long long *mlen, const unsigned char *sm,unsigned long long smlen, const unsigned char *pk ) { unsigned char pkcopy[32]; unsigned char rcopy[32]; unsigned char hram[64]; unsigned char rcheck[32]; ge25519 get1, get2; sc25519 schram, scs; if (smlen < 64) goto badsig; if (sm[63] & 224) goto badsig; if (ge25519_unpackneg_vartime(&get1,pk)) goto badsig; memmove(pkcopy,pk,32); memmove(rcopy,sm,32); sc25519_from32bytes(&scs, sm+32); memmove(m,sm,smlen); memmove(m + 32,pkcopy,32); crypto_hash_sha512(hram,m,smlen); sc25519_from64bytes(&schram, hram); ge25519_double_scalarmult_vartime(&get2, &get1, &schram, &ge25519_base, &scs); ge25519_pack(rcheck, &get2); if (crypto_verify_32(rcopy,rcheck) == 0) { memmove(m,m + 64,smlen - 64); memset(m + smlen - 64,0,64); *mlen = smlen - 64; return 0; } badsig: *mlen = (unsigned long long) -1; memset(m,0,smlen); return -1; }
int crypto_sign_ed25519_open( unsigned char *m,unsigned long long *mlen, const unsigned char *sm,unsigned long long smlen, const unsigned char *pk ) { unsigned int i; int ret; unsigned char t2[32]; ge25519 get1, get2; sc25519 schram, scs; unsigned char hram[crypto_hash_sha512_BYTES]; *mlen = (unsigned long long) -1; if (smlen < 64) return -1; if (ge25519_unpackneg_vartime(&get1, pk)) return -1; get_hram(hram,sm,pk,m,smlen); sc25519_from64bytes(&schram, hram); sc25519_from32bytes(&scs, sm+32); ge25519_double_scalarmult_vartime(&get2, &get1, &schram, &ge25519_base, &scs); ge25519_pack(t2, &get2); ret = crypto_verify_32(sm, t2); if (!ret) { for(i=0;i<smlen-64;i++) m[i] = sm[i + 64]; *mlen = smlen-64; } else { for(i=0;i<smlen-64;i++) m[i] = 0; } return ret; }
// Step 3 bis // verify pk_r = y.B - c.pk with pk = sk.B int schnorr_id_verify(const uint8_t pk[SCHNORR_PUBLICKEYBYTES], const uint8_t pk_r[SCHNORR_PUBLICKEYBYTES], const uint8_t challenge[SCHNORR_ID_CHALLENGEBYTES], const uint8_t response[SCHNORR_ID_RESPONSEBYTES]) { ge25519 ge_pk_neg; sc25519 sc_challenge; sc25519 sc_response; ge25519 ge_pk_r_verifier; uint8_t pk_r_verifier[SCHNORR_PUBLICKEYBYTES]; if (ge25519_unpackneg_vartime(&ge_pk_neg, pk)) return -1; sc25519_from_challenge_bytes(&sc_challenge, challenge); sc25519_from32bytes(&sc_response, response); ge25519_double_scalarmult_vartime(&ge_pk_r_verifier, &ge_pk_neg, &sc_challenge, &ge25519_base, &sc_response); ge25519_pack(pk_r_verifier, &ge_pk_r_verifier); return verify_32(pk_r, pk_r_verifier); }
int crypto_sign_ed25519_keypair( unsigned char *pk, unsigned char *sk ) { sc25519 scsk; ge25519 gepk; unsigned char extsk[64]; int i; randombytes(sk, 32); crypto_hash_sha512(extsk, sk, 32); extsk[0] &= 248; extsk[31] &= 127; extsk[31] |= 64; sc25519_from32bytes(&scsk,extsk); ge25519_scalarmult_base(&gepk, &scsk); ge25519_pack(pk, &gepk); for(i=0;i<32;i++) sk[32 + i] = pk[i]; return 0; }
int crypto_sign_open_batch( unsigned char* const m[],unsigned long long mlen[], unsigned char* const sm[],const unsigned long long smlen[], unsigned char* const pk[], unsigned long long num ) { int ret = 0; unsigned long long i, j; shortsc25519 r[MAXBATCH]; sc25519 scalars[2*MAXBATCH+1]; ge25519 points[2*MAXBATCH+1]; unsigned char hram[crypto_hash_sha512_BYTES]; unsigned long long batchsize; for (i = 0;i < num;++i) mlen[i] = -1; while (num >= 3) { batchsize = num; if (batchsize > MAXBATCH) batchsize = MAXBATCH; for (i = 0;i < batchsize;++i) if (smlen[i] < 64) goto fallback; randombytes((unsigned char*)r,sizeof(shortsc25519) * batchsize); /* Computing scalars[0] = ((r1s1 + r2s2 + ...)) */ for(i=0;i<batchsize;i++) { sc25519_from32bytes(&scalars[i], sm[i]+32); sc25519_mul_shortsc(&scalars[i], &scalars[i], &r[i]); } for(i=1;i<batchsize;i++) sc25519_add(&scalars[0], &scalars[0], &scalars[i]); /* Computing scalars[1] ... scalars[batchsize] as r[i]*H(R[i],A[i],m[i]) */ for(i=0;i<batchsize;i++) { get_hram(hram, sm[i], pk[i], m[i], smlen[i]); sc25519_from64bytes(&scalars[i+1],hram); sc25519_mul_shortsc(&scalars[i+1],&scalars[i+1],&r[i]); } /* Setting scalars[batchsize+1] ... scalars[2*batchsize] to r[i] */ for(i=0;i<batchsize;i++) sc25519_from_shortsc(&scalars[batchsize+i+1],&r[i]); /* Computing points */ points[0] = ge25519_base; for(i=0;i<batchsize;i++) if (ge25519_unpackneg_vartime(&points[i+1], pk[i])) goto fallback; for(i=0;i<batchsize;i++) if (ge25519_unpackneg_vartime(&points[batchsize+i+1], sm[i])) goto fallback; ge25519_multi_scalarmult_vartime(points, points, scalars, 2*batchsize+1); if (ge25519_isneutral_vartime(points)) { for(i=0;i<batchsize;i++) { for(j=0;j<smlen[i]-64;j++) m[i][j] = sm[i][j + 64]; mlen[i] = smlen[i]-64; } } else { fallback: for (i = 0;i < batchsize;++i) ret |= crypto_sign_open(m[i], &mlen[i], sm[i], smlen[i], pk[i]); } m += batchsize; mlen += batchsize; sm += batchsize; smlen += batchsize; pk += batchsize; num -= batchsize; } for (i = 0;i < num;++i) ret |= crypto_sign_open(m[i], &mlen[i], sm[i], smlen[i], pk[i]); return ret; }