//for curve points: AB = A + B void addKeys(key &AB, const key &A, const key &B) { ge_p3 B2, A2; CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&B2, B.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__)); CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&A2, A.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__)); ge_cached tmp2; ge_p3_to_cached(&tmp2, &B2); ge_p1p1 tmp3; ge_add(&tmp3, &A2, &tmp2); ge_p1p1_to_p3(&A2, &tmp3); ge_p3_tobytes(AB.bytes, &A2); }
/* 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_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; }