//addKeys3 //aAbB = a*A + b*B where a, b are scalars, A, B are curve points //B must be input after applying "precomp" void addKeys3(key &aAbB, const key &a, const key &A, const key &b, const ge_dsmp B) { ge_p2 rv; ge_p3 A2; CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&A2, A.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__)); ge_double_scalarmult_precomp_vartime(&rv, a.bytes, &A2, b.bytes, B); ge_tobytes(aAbB.bytes, &rv); }
int crypto_sign_open( unsigned char *sm, unsigned long long smlen, const unsigned char *pk ) { unsigned char scopy[32]; unsigned char h[64]; unsigned char rcheck[32]; ge_p3 A; ge_p2 R; if (smlen < 64) goto badsig; if (sm[63] & 224) goto badsig; if (ge_frombytes_negate_vartime(&A,pk) != 0) goto badsig; memmove(scopy,sm + 32,32); memmove(sm + 32,pk,32); crypto_hash_sha512(h,sm,smlen); sc_reduce(h); ge_double_scalarmult_vartime(&R,h,&A,scopy); ge_tobytes(rcheck,&R); if (crypto_verify_32(rcheck,sm) == 0) return 0; badsig: return -1; }
int crypto_sign_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key) { unsigned char h[64]; unsigned char checker[32]; SHA512_CTX hash; ge_p3 A; ge_p2 R; if (signature[63] & 224) { return -1; } if (ge_frombytes_negate_vartime(&A, public_key) != 0) { return -2; } SHA512_Init(&hash); SHA512_Update(&hash, signature, 32); SHA512_Update(&hash, public_key, 32); SHA512_Update(&hash, message, message_len); SHA512_Final(h, &hash); sc_reduce(h); ge_double_scalarmult_vartime(&R, h, &A, signature + 32); ge_tobytes(checker, &R); if (!(crypto_verify_32(checker, signature) == 0)) { return -3; } return 0; }
//addKeys2 //aGbB = aG + bB where a, b are scalars, G is the basepoint and B is a point void addKeys2(key &aGbB, const key &a, const key &b, const key & B) { ge_p2 rv; ge_p3 B2; CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&B2, B.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__)); ge_double_scalarmult_base_vartime(&rv, b.bytes, &B2, a.bytes); ge_tobytes(aGbB.bytes, &rv); }
//does a * P where a is a scalar and P is an arbitrary point void scalarmultKey(key & aP, const key &P, const key &a) { ge_p3 A; ge_p2 R; CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&A, P.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__)); ge_scalarmult(&R, a.bytes, &A); ge_tobytes(aP.bytes, &R); }
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 h[64]; unsigned char checkr[32]; ge_p3 A; ge_p2 R; unsigned long long i; *mlen = -1; if (smlen < 64) return -1; if (sm[63] & 224) return -2; if (ge_frombytes_negate_vartime(&A,pk) != 0) return -3; for (i = 0;i < smlen;++i) m[i] = sm[i]; for (i = 0;i < 32;++i) m[32 + i] = pk[i]; SHA512(m, smlen, h); sc_reduce(h); ge_double_scalarmult_vartime(&R,h,&A,sm + 32); ge_tobytes(checkr,&R); if (crypto_verify_32(checkr,sm) != 0) { for (i = 0;i < smlen;++i) m[i] = 0; return crypto_verify_32(checkr,sm); } for (i = 0;i < smlen - 64;++i) m[i] = sm[64 + i]; for (i = smlen - 64;i < smlen;++i) m[i] = 0; *mlen = smlen - 64; return 0; }
int ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key) { unsigned char h[64]; unsigned char checker[32]; CC_SHA512_CTX hash; ge_p3 A; ge_p2 R; if (signature[63] & 224) { return 0; } if (ge_frombytes_negate_vartime(&A, public_key) != 0) { return 0; } CC_SHA512_Init(&hash); CC_SHA512_Update(&hash, signature, 32); CC_SHA512_Update(&hash, public_key, 32); CC_SHA512_Update_Long(&hash, message, message_len); CC_SHA512_Final(h, &hash); sc_reduce(h); ge_double_scalarmult_vartime(&R, h, &A, signature + 32); ge_tobytes(checker, &R); if (!consttime_equal(checker, signature)) { return 0; } return 1; }
int cced25519_verify(const struct ccdigest_info *di, size_t mlen, const void *inMsg, const ccec25519signature sig, const ccec25519pubkey pk) { const uint8_t * const m = (const uint8_t *) inMsg; ccdigest_di_decl(di, dc); uint8_t h[64]; uint8_t checkr[32]; ge_p3 A; ge_p2 R; ASSERT_DIGEST_SIZE(di); if (ge_frombytes_negate_vartime(&A,pk) != 0) return -1; ccdigest_init(di,dc); ccdigest_update(di,dc,32,sig); ccdigest_update(di,dc,32,pk); ccdigest_update(di,dc,mlen,m); ccdigest_final(di,dc,h); ccdigest_di_clear(di,dc); sc_reduce(h); ge_double_scalarmult_vartime(&R,h,&A,sig + 32); ge_tobytes(checkr,&R); return crypto_verify_32(checkr,sig); }
static themis_status_t ed_dbl_base_sign(uint8_t pos, const uint8_t *scalar1, const uint8_t *scalar2, const ge_p3 *base1, const ge_p3 *base2, uint8_t *signature) { uint8_t r1[ED25519_GE_LENGTH]; uint8_t r2[ED25519_GE_LENGTH]; ge_p3 R1; ge_p2 R2; uint8_t k[64]; soter_hash_ctx_t hash_ctx; size_t hash_length = 64; themis_status_t res; generate_random_32(r1); generate_random_32(r2); ge_scalarmult_blinded(&R1, r1, base2); ge_double_scalarmult_vartime(&R2, r2, base1, r1); res = soter_hash_init(&hash_ctx, SOTER_HASH_SHA512); if (THEMIS_SUCCESS != res) { return res; } ge_p3_tobytes(k, &R1); res = soter_hash_update(&hash_ctx, k, ED25519_GE_LENGTH); if (THEMIS_SUCCESS != res) { soter_hash_final(&hash_ctx, k, &hash_length); return res; } ge_tobytes(k, &R2); res = soter_hash_update(&hash_ctx, k, ED25519_GE_LENGTH); if (THEMIS_SUCCESS != res) { soter_hash_final(&hash_ctx, k, &hash_length); return res; } res = soter_hash_update(&hash_ctx, &pos, sizeof(pos)); if (THEMIS_SUCCESS != res) { soter_hash_final(&hash_ctx, k, &hash_length); return res; } res = soter_hash_final(&hash_ctx, k, &hash_length); if (THEMIS_SUCCESS == res) { sc_reduce(k); memcpy(signature, k, ED25519_GE_LENGTH); sc_muladd(signature + ED25519_GE_LENGTH, k, scalar1, r1); sc_muladd(signature + (2 * ED25519_GE_LENGTH), k, scalar2, r2); } return res; }
void crypto_ops::generate_key_image(const public_key &pub, const secret_key &sec, key_image &image) { ge_p3 point; ge_p2 point2; assert(sc_check(&sec) == 0); hash_to_ec(pub, point); ge_scalarmult(&point2, &sec, &point); ge_tobytes(&image, &point2); }
//Computes aH where H= toPoint(cn_fast_hash(G)), G the basepoint key scalarmultH(const key & a) { ge_p3 A; ge_p2 R; CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&A, H.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__)); ge_scalarmult(&R, a.bytes, &A); key aP; ge_tobytes(aP.bytes, &R); return aP; }
bool crypto_ops::check_ring_signature(const hash &prefix_hash, const key_image &image, const public_key *const *pubs, size_t pubs_count, const signature *sig) { size_t i; ge_p3 image_unp; ge_dsmp image_pre; ec_scalar sum, h; rs_comm *const buf = reinterpret_cast<rs_comm *>(alloca(rs_comm_size(pubs_count))); #if !defined(NDEBUG) for (i = 0; i < pubs_count; i++) { assert(check_key(*pubs[i])); } #endif if (ge_frombytes_vartime(&image_unp, &image) != 0) { return false; } ge_dsm_precomp(image_pre, &image_unp); sc_0(&sum); buf->h = prefix_hash; for (i = 0; i < pubs_count; i++) { ge_p2 tmp2; ge_p3 tmp3; if (sc_check(&sig[i].c) != 0 || sc_check(&sig[i].r) != 0) { return false; } if (ge_frombytes_vartime(&tmp3, &*pubs[i]) != 0) { abort(); } ge_double_scalarmult_base_vartime(&tmp2, &sig[i].c, &tmp3, &sig[i].r); ge_tobytes(&buf->ab[i].a, &tmp2); hash_to_ec(*pubs[i], tmp3); ge_double_scalarmult_precomp_vartime(&tmp2, &sig[i].r, &tmp3, &sig[i].c, image_pre); ge_tobytes(&buf->ab[i].b, &tmp2); sc_add(&sum, &sum, &sig[i].c); } hash_to_scalar(buf, rs_comm_size(pubs_count), h); sc_sub(&h, &h, &sum); return sc_isnonzero(&h) == 0; }
bool crypto_ops::generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation) { ge_p3 point; ge_p2 point2; ge_p1p1 point3; assert(sc_check(&key2) == 0); if (ge_frombytes_vartime(&point, &key1) != 0) { return false; } ge_scalarmult(&point2, &key2, &point); ge_mul8(&point3, &point2); ge_p1p1_to_p2(&point2, &point3); ge_tobytes(&derivation, &point2); return true; }
int crypto_sign_edwards25519sha512batch_open(unsigned char *m, unsigned long long *mlen_p, const unsigned char *sm, unsigned long long smlen, const unsigned char *pk) { unsigned char h[64]; unsigned char t1[32], t2[32]; unsigned long long mlen; ge_cached Ai; ge_p1p1 csa; ge_p2 cs; ge_p3 A; ge_p3 R; ge_p3 cs3; *mlen_p = 0; if (smlen < 64 || smlen > SIZE_MAX) { return -1; } mlen = smlen - 64; if (sm[smlen - 1] & 224) { return -1; } if (ge_frombytes_negate_vartime(&A, pk) != 0 || ge_frombytes_negate_vartime(&R, sm) != 0) { return -1; } ge_p3_to_cached(&Ai, &A); crypto_hash_sha512(h, sm, mlen + 32); sc_reduce(h); ge_scalarmult_vartime(&cs3, h, &R); ge_add(&csa, &cs3, &Ai); ge_p1p1_to_p2(&cs, &csa); ge_tobytes(t1, &cs); t1[31] ^= 1 << 7; ge_scalarmult_base(&R, sm + 32 + mlen); ge_p3_tobytes(t2, &R); if (crypto_verify_32(t1, t2) != 0) { return -1; } *mlen_p = mlen; memmove(m, sm + 32, mlen); return 0; }
bool crypto_ops::derive_public_key(const key_derivation &derivation, size_t output_index, const public_key &base, public_key &derived_key) { ec_scalar scalar; ge_p3 point1; ge_p3 point2; ge_cached point3; ge_p1p1 point4; ge_p2 point5; if (ge_frombytes_vartime(&point1, &base) != 0) { return false; } derivation_to_scalar(derivation, output_index, scalar); ge_scalarmult_base(&point2, &scalar); ge_p3_to_cached(&point3, &point2); ge_add(&point4, &point1, &point3); ge_p1p1_to_p2(&point5, &point4); ge_tobytes(&derived_key, &point5); return true; }
int crypto_sign_verify_detached(const unsigned char *sig, const unsigned char *m, unsigned long long mlen, const unsigned char *pk) { crypto_hash_sha512_state hs; unsigned char h[64]; unsigned char rcheck[32]; unsigned int i; unsigned char d = 0; ge_p3 A; ge_p2 R; #ifdef ED25519_PREVENT_MALLEABILITY if (crypto_sign_check_S_lt_l(sig + 32) != 0) { return -1; } #else if (sig[63] & 224) { return -1; } #endif if (ge_frombytes_negate_vartime(&A, pk) != 0) { return -1; } for (i = 0; i < 32; ++i) { d |= pk[i]; } if (d == 0) { return -1; } crypto_hash_sha512_init(&hs); crypto_hash_sha512_update(&hs, sig, 32); crypto_hash_sha512_update(&hs, pk, 32); crypto_hash_sha512_update(&hs, m, mlen); crypto_hash_sha512_final(&hs, h); sc_reduce(h); ge_double_scalarmult_vartime(&R, h, &A, sig + 32); ge_tobytes(rcheck, &R); return crypto_verify_32(rcheck, sig) | (-(rcheck - sig == 0)) | sodium_memcmp(sig, rcheck, 32); }
bool crypto_ops::check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig) { ge_p2 tmp2; ge_p3 tmp3; ec_scalar c; s_comm buf; assert(check_key(pub)); buf.h = prefix_hash; buf.key = pub; if (ge_frombytes_vartime(&tmp3, &pub) != 0) { abort(); } if (sc_check(&sig.c) != 0 || sc_check(&sig.r) != 0) { return false; } ge_double_scalarmult_base_vartime(&tmp2, &sig.c, &tmp3, &sig.r); ge_tobytes(&buf.comm, &tmp2); hash_to_scalar(&buf, sizeof(s_comm), c); sc_sub(&c, &c, &sig.c); return sc_isnonzero(&c) == 0; }
/* sig is array of bytes containing the signature siglen is the length of sig byte array msg the array of bytes containing the message msglen length of msg array stat will be 1 on successful verify and 0 on unsuccessful */ int wc_ed25519_verify_msg(byte* sig, word32 siglen, const byte* msg, word32 msglen, int* stat, ed25519_key* key) { byte rcheck[ED25519_KEY_SIZE]; byte h[SHA512_DIGEST_SIZE]; ge_p3 A; ge_p2 R; int ret; Sha512 sha; /* sanity check on arguments */ if (sig == NULL || msg == NULL || stat == NULL || key == NULL) return BAD_FUNC_ARG; /* set verification failed by default */ *stat = 0; /* check on basics needed to verify signature */ if (siglen < ED25519_SIG_SIZE || (sig[ED25519_SIG_SIZE-1] & 224)) return BAD_FUNC_ARG; /* uncompress A (public key), test if valid, and negate it */ if (ge_frombytes_negate_vartime(&A, key->p) != 0) return BAD_FUNC_ARG; /* find H(R,A,M) and store it as h */ ret = wc_InitSha512(&sha); if (ret != 0) return ret; ret = wc_Sha512Update(&sha, sig, ED25519_SIG_SIZE/2); if (ret != 0) return ret; ret = wc_Sha512Update(&sha, key->p, ED25519_PUB_KEY_SIZE); if (ret != 0) return ret; ret = wc_Sha512Update(&sha, msg, msglen); if (ret != 0) return ret; ret = wc_Sha512Final(&sha, h); if (ret != 0) return ret; sc_reduce(h); /* Uses a fast single-signature verification SB = R + H(R,A,M)A becomes SB - H(R,A,M)A saving decompression of R */ ret = ge_double_scalarmult_vartime(&R, h, &A, sig + (ED25519_SIG_SIZE/2)); if (ret != 0) return ret; ge_tobytes(rcheck, &R); /* comparison of R created to R in sig */ ret = ConstantCompare(rcheck, sig, ED25519_SIG_SIZE/2); if (ret != 0) return ret; /* set the verification status */ *stat = 1; return ret; }
//addKeys3 //aAbB = a*A + b*B where a, b are scalars, A, B are curve points //A and B must be input after applying "precomp" void addKeys3(key &aAbB, const key &a, const ge_dsmp A, const key &b, const ge_dsmp B) { ge_p2 rv; ge_double_scalarmult_precomp_vartime2(&rv, a.bytes, A, b.bytes, B); ge_tobytes(aAbB.bytes, &rv); }
void crypto_ops::generate_ring_signature(const hash &prefix_hash, const key_image &image, const public_key *const *pubs, size_t pubs_count, const secret_key &sec, size_t sec_index, signature *sig) { lock_guard<mutex> lock(random_lock); size_t i; ge_p3 image_unp; ge_dsmp image_pre; ec_scalar sum, k, h; rs_comm *const buf = reinterpret_cast<rs_comm *>(alloca(rs_comm_size(pubs_count))); assert(sec_index < pubs_count); #if !defined(NDEBUG) { ge_p3 t; public_key t2; key_image t3; assert(sc_check(&sec) == 0); ge_scalarmult_base(&t, &sec); ge_p3_tobytes(&t2, &t); assert(*pubs[sec_index] == t2); generate_key_image(*pubs[sec_index], sec, t3); assert(image == t3); for (i = 0; i < pubs_count; i++) { assert(check_key(*pubs[i])); } } #endif if (ge_frombytes_vartime(&image_unp, &image) != 0) { abort(); } ge_dsm_precomp(image_pre, &image_unp); sc_0(&sum); buf->h = prefix_hash; for (i = 0; i < pubs_count; i++) { ge_p2 tmp2; ge_p3 tmp3; if (i == sec_index) { random_scalar(k); ge_scalarmult_base(&tmp3, &k); ge_p3_tobytes(&buf->ab[i].a, &tmp3); hash_to_ec(*pubs[i], tmp3); ge_scalarmult(&tmp2, &k, &tmp3); ge_tobytes(&buf->ab[i].b, &tmp2); } else { random_scalar(sig[i].c); random_scalar(sig[i].r); if (ge_frombytes_vartime(&tmp3, &*pubs[i]) != 0) { abort(); } ge_double_scalarmult_base_vartime(&tmp2, &sig[i].c, &tmp3, &sig[i].r); ge_tobytes(&buf->ab[i].a, &tmp2); hash_to_ec(*pubs[i], tmp3); ge_double_scalarmult_precomp_vartime(&tmp2, &sig[i].r, &tmp3, &sig[i].c, image_pre); ge_tobytes(&buf->ab[i].b, &tmp2); sc_add(&sum, &sum, &sig[i].c); } } hash_to_scalar(buf, rs_comm_size(pubs_count), h); sc_sub(&sig[sec_index].c, &h, &sum); sc_mulsub(&sig[sec_index].r, &sig[sec_index].c, &sec, &k); }