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 ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key) { sha512_context hash; unsigned char hram[64]; unsigned char r[64]; ge_p3 R; sha512_init(&hash); sha512_update(&hash, private_key + 32, 32); sha512_update(&hash, message, message_len); sha512_final(&hash, r); sc_reduce(r); ge_scalarmult_base(&R, r); ge_p3_tobytes(signature, &R); sha512_init(&hash); sha512_update(&hash, signature, 32); sha512_update(&hash, public_key, 32); sha512_update(&hash, message, message_len); sha512_final(&hash, hram); sc_reduce(hram); sc_muladd(signature + 32, hram, private_key, r); }
void Sign_signMsg(uint8_t keyPair[64], struct Message* msg, struct Random* rand) { // az is set to the secret key followed by another secret value // which since we don't have a secret seed in this algorithm is just the // hash of the secret key and 32 bytes of random uint8_t az[64]; uint8_t r[64]; ge_p3 R; uint8_t hram[64]; Bits_memcpy(az, keyPair, 32); Random_bytes(rand, &az[32], 32); crypto_hash_sha512(az,az,64); Bits_memcpy(az, keyPair, 32); az[0] &= 248; az[31] &= 63; az[31] |= 64; // hash message + secret number Message_push(msg, &az[32], 32, NULL); crypto_hash_sha512(r, msg->bytes, msg->length); // Replace secret number with public key Bits_memcpy(msg->bytes, &keyPair[32], 32); // push pointMul(r) to message sc_reduce(r); ge_scalarmult_base(&R,r); Message_shift(msg, 32, NULL); ge_p3_tobytes(msg->bytes,&R); crypto_hash_sha512(hram, msg->bytes, msg->length); sc_reduce(hram); sc_muladd(&msg->bytes[32], hram, az, r); }
int crypto_sign( unsigned char *sm,unsigned long long *smlen, const unsigned char *m,unsigned long long mlen, const unsigned char *sk ) { unsigned char az[64]; unsigned char r[64]; unsigned char hram[64]; ge_p3 R; unsigned long long i; crypto_hash_sha512(az,sk,32); az[0] &= 248; az[31] &= 63; az[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] = az[32 + i]; crypto_hash_sha512(r,sm + 32,mlen + 32); for (i = 0;i < 32;++i) sm[32 + i] = sk[32 + i]; sc_reduce(r); ge_scalarmult_base(&R,r); ge_p3_tobytes(sm,&R); crypto_hash_sha512(hram,sm,mlen + 64); sc_reduce(hram); sc_muladd(sm + 32,hram,az,r); return 0; }
static themis_status_t ed_point_sign(uint8_t pos, const uint8_t *scalar, const ge_p3 *point, uint8_t *signature) { uint8_t r[ED25519_GE_LENGTH]; ge_p3 R; uint8_t k[64]; soter_hash_ctx_t hash_ctx; size_t hash_length = 64; themis_status_t res; generate_random_32(r); ge_scalarmult_base(&R, r); ge_p3_tobytes(k, &R); res = soter_hash_init(&hash_ctx, SOTER_HASH_SHA512); if (THEMIS_SUCCESS != res) { return res; } 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_scalarmult_blinded(&R, r, point); ge_p3_tobytes(k, &R); 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) { return res; } if (THEMIS_SUCCESS == res) { sc_reduce(k); memcpy(signature, k, ED25519_GE_LENGTH); sc_muladd(signature + ED25519_GE_LENGTH, k, scalar, r); } return res; }
void ed25519_sign(unsigned char *signature, const unsigned char *message, int32_t message_len, const unsigned char *public_key, const unsigned char *private_key) { sha3_context ctx; unsigned char hram[64]; unsigned char r[64]; ge_p3 R; sha3_init512(&ctx); sha3_update(&ctx, private_key + 32, 32); sha3_update(&ctx, message, message_len); sha3_finalize(&ctx, &r); sc_reduce(r); ge_scalarmult_base(&R, r); ge_p3_tobytes(signature, &R); sha3_init512(&ctx); sha3_update(&ctx, signature, 32); sha3_update(&ctx, public_key, 32); sha3_update(&ctx, message, message_len); sha3_finalize(&ctx, hram); sc_reduce(hram); sc_muladd(signature + 32, hram, private_key, r); }
/* see http://crypto.stackexchange.com/a/6215/4697 */ void ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar) { const unsigned char SC_1[32] = {1}; /* scalar with value 1 */ unsigned char n[32]; ge_p3 nB; ge_p1p1 A_p1p1; ge_p3 A; ge_p3 public_key_unpacked; ge_cached T; int i; /* copy the scalar and clear highest bit */ for (i = 0; i < 31; ++i) { n[i] = scalar[i]; } n[31] = scalar[31] & 127; /* private key: a = n + t */ if (private_key) { sc_muladd(private_key, SC_1, n, private_key); } /* public key: A = nB + T */ if (public_key) { /* if we know the private key we don't need a point addition, which is faster */ /* using a "timing attack" you could find out wether or not we know the private key, but this information seems rather useless - if this is important pass public_key and private_key seperately in 2 function calls */ if (private_key) { ge_scalarmult_base(&A, private_key); } else { /* unpack public key into T */ ge_frombytes_negate_vartime(&public_key_unpacked, public_key); fe_neg(public_key_unpacked.X, public_key_unpacked.X); // undo negate fe_neg(public_key_unpacked.T, public_key_unpacked.T); // undo negate ge_p3_to_cached(&T, &public_key_unpacked); /* calculate n*B */ ge_scalarmult_base(&nB, n); /* A = n*B + T */ ge_add(&A_p1p1, &nB, &T); ge_p1p1_to_p3(&A, &A_p1p1); } /* pack public key */ ge_p3_tobytes(public_key, &A); } }
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]; ge_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); sc_reduce(nonce); ge_scalarmult_base(&R, nonce); ge_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); sc_reduce(hram); _crypto_sign_ed25519_clamp(az); sc_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; }
int crypto_sign_detached(unsigned char *sig, unsigned long long *siglen, const unsigned char *m, unsigned long long mlen, const unsigned char *sk) { crypto_hash_sha512_state hs; unsigned char pk[32]; unsigned char az[64]; unsigned char nonce[64]; unsigned char hram[64]; ge_p3 R; memmove(pk, sk + 32, 32); crypto_hash_sha512(az, sk, 32); az[0] &= 248; az[31] &= 63; az[31] |= 64; crypto_hash_sha512_init(&hs); crypto_hash_sha512_update(&hs, az + 32, 32); crypto_hash_sha512_update(&hs, m, mlen); crypto_hash_sha512_final(&hs, nonce); memmove(sig + 32, pk, 32); sc_reduce(nonce); ge_scalarmult_base(&R, nonce); ge_p3_tobytes(sig, &R); crypto_hash_sha512_init(&hs); crypto_hash_sha512_update(&hs, sig, 64); crypto_hash_sha512_update(&hs, m, mlen); crypto_hash_sha512_final(&hs, hram); sc_reduce(hram); sc_muladd(sig + 32, hram, az, nonce); sodium_memzero(az, sizeof az); sodium_memzero(nonce, sizeof nonce); if (siglen != NULL) { *siglen = 64U; } return 0; }
/* NEW: Compare to pristine crypto_sign() Uses explicit private key for nonce derivation and as scalar, instead of deriving both from a master key. */ int crypto_sign_modified( unsigned char *sm, const unsigned char *m,unsigned long long mlen, const unsigned char *sk, const unsigned char* pk, const unsigned char* random ) { unsigned char nonce[64]; unsigned char hram[64]; ge_p3 R; int count=0; memmove(sm + 64,m,mlen); memmove(sm + 32,sk,32); /* NEW: Use privkey directly for nonce derivation */ /* NEW : add prefix to separate hash uses - see .h */ sm[0] = 0xFE; for (count = 1; count < 32; count++) sm[count] = 0xFF; /* NEW: add suffix of random data */ memmove(sm + mlen + 64, random, 64); crypto_hash_sha512(nonce,sm,mlen + 128); memmove(sm + 32,pk,32); sc_reduce(nonce); ge_scalarmult_base(&R,nonce); ge_p3_tobytes(sm,&R); crypto_hash_sha512(hram,sm,mlen + 64); sc_reduce(hram); sc_muladd(sm + 32,hram,sk,nonce); /* NEW: Use privkey directly */ /* NEW: Try to erase any traces of privkey or nonce left in the stack from sc_muladd. */ zeroize_stack(); zeroize(nonce, 64); return 0; }
int crypto_sign( unsigned char *sig, const unsigned char *m, size_t mlen, const unsigned char *sk,const unsigned char *pk ) { unsigned char nonce[64]; unsigned char hram[64]; ge_p3 R; crypto_hash_sha512_2(nonce, sk+32, 32, m, mlen); sc_reduce(nonce); ge_scalarmult_base(&R,nonce); ge_p3_tobytes(sig,&R); crypto_hash_sha512_3(hram, sig, 32, pk, 32, m, mlen); sc_reduce(hram); sc_muladd(sig + 32,hram,sk,nonce); return 0; }
int crypto_sign_edwards25519sha512batch(unsigned char *sm, unsigned long long *smlen_p, const unsigned char *m, unsigned long long mlen, const unsigned char *sk) { crypto_hash_sha512_state hs; unsigned char nonce[64]; unsigned char hram[64]; unsigned char sig[64]; ge_p3 A; ge_p3 R; crypto_hash_sha512_init(&hs); crypto_hash_sha512_update(&hs, sk + 32, 32); crypto_hash_sha512_update(&hs, m, mlen); crypto_hash_sha512_final(&hs, nonce); ge_scalarmult_base(&A, sk); ge_p3_tobytes(sig + 32, &A); sc_reduce(nonce); ge_scalarmult_base(&R, nonce); ge_p3_tobytes(sig, &R); crypto_hash_sha512_init(&hs); crypto_hash_sha512_update(&hs, sig, 32); crypto_hash_sha512_update(&hs, m, mlen); crypto_hash_sha512_final(&hs, hram); sc_reduce(hram); sc_muladd(sig + 32, hram, nonce, sk); sodium_memzero(hram, sizeof hram); memmove(sm + 32, m, (size_t) mlen); memcpy(sm, sig, 32); memcpy(sm + 32 + mlen, sig + 32, 32); *smlen_p = mlen + 64U; return 0; }
void ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key) { CC_SHA512_CTX hash; unsigned char hram[64]; unsigned char r[64]; ge_p3 R; CC_SHA512_Init(&hash); CC_SHA512_Update(&hash, private_key + 32, 32); CC_SHA512_Update_Long(&hash, message, message_len); CC_SHA512_Final(r, &hash); sc_reduce(r); ge_scalarmult_base(&R, r); ge_p3_tobytes(signature, &R); 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(hram, &hash); sc_reduce(hram); sc_muladd(signature + 32, hram, private_key, r); }
/* in contains the message to sign inlen is the length of the message to sign out is the buffer to write the signature outLen [in/out] input size of out buf output gets set as the final length of out key is the ed25519 key to use when signing return 0 on success */ int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out, word32 *outLen, ed25519_key* key) { ge_p3 R; byte nonce[SHA512_DIGEST_SIZE]; byte hram[SHA512_DIGEST_SIZE]; byte az[ED25519_PRV_KEY_SIZE]; Sha512 sha; int ret; /* sanity check on arguments */ if (in == NULL || out == NULL || outLen == NULL || key == NULL) return BAD_FUNC_ARG; /* check and set up out length */ if (*outLen < ED25519_SIG_SIZE) { *outLen = ED25519_SIG_SIZE; return BUFFER_E; } *outLen = ED25519_SIG_SIZE; /* step 1: create nonce to use where nonce is r in r = H(h_b, ... ,h_2b-1,M) */ ret = wc_Sha512Hash(key->k, ED25519_KEY_SIZE, az); if (ret != 0) return ret; /* apply clamp */ az[0] &= 248; az[31] &= 63; /* same than az[31] &= 127 because of az[31] |= 64 */ az[31] |= 64; ret = wc_InitSha512(&sha); if (ret != 0) return ret; ret = wc_Sha512Update(&sha, az + ED25519_KEY_SIZE, ED25519_KEY_SIZE); if (ret != 0) return ret; ret = wc_Sha512Update(&sha, in, inlen); if (ret != 0) return ret; ret = wc_Sha512Final(&sha, nonce); if (ret != 0) return ret; sc_reduce(nonce); /* step 2: computing R = rB where rB is the scalar multiplication of r and B */ ge_scalarmult_base(&R,nonce); ge_p3_tobytes(out,&R); /* step 3: hash R + public key + message getting H(R,A,M) then creating S = (r + H(R,A,M)a) mod l */ ret = wc_InitSha512(&sha); if (ret != 0) return ret; ret = wc_Sha512Update(&sha, out, 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, in, inlen); if (ret != 0) return ret; ret = wc_Sha512Final(&sha, hram); if (ret != 0) return ret; sc_reduce(hram); sc_muladd(out + (ED25519_SIG_SIZE/2), hram, az, nonce); return ret; }