Commit ec4ece08 authored by Michael Hamburg's avatar Michael Hamburg

add decaf_edXXX_convert_public_key_to_xXXX; thanks Johan Pascal

parent 6e2ce520
......@@ -1318,6 +1318,50 @@ decaf_error_t decaf_x25519 (
return decaf_succeed_if(mask_to_bool(nz));
}
/* Thanks Johan Pascal */
void decaf_ed25519_convert_public_key_to_x25519 (
uint8_t x[DECAF_X25519_PUBLIC_BYTES],
const uint8_t ed[DECAF_EDDSA_25519_PUBLIC_BYTES]
) {
gf y;
{
uint8_t enc2[DECAF_EDDSA_25519_PUBLIC_BYTES];
memcpy(enc2,ed,sizeof(enc2));
/* retrieve y from the ed compressed point */
enc2[DECAF_EDDSA_25519_PUBLIC_BYTES-1] &= ~0x80;
ignore_result(gf_deserialize(y, enc2, 0));
decaf_bzero(enc2,sizeof(enc2));
}
{
gf n,d;
#if EDDSA_USE_SIGMA_ISOGENY
/* u = (1+y)/(1-y)*/
gf_add(n, y, ONE); /* n = y+1 */
gf_sub(d, ONE, y); /* d = 1-y */
gf_invert(d, d); /* d = 1/(1-y) */
gf_mul(y, n, d); /* u = (y+1)/(1-y) */
gf_serialize(x,y,1);
#else /* EDDSA_USE_SIGMA_ISOGENY */
/* u = y^2 * (1-dy^2) / (1-y^2) */
gf_sqr(n,y); /* y^2*/
gf_sub(d,ONE,n); /* 1-y^2*/
gf_invert(d,d); /* 1/(1-y^2)*/
gf_mul(y,n,d); /* y^2 / (1-y^2) */
gf_mulw(d,n,EDWARDS_D); /* dy^2*/
gf_sub(d, ONE, d); /* 1-dy^2*/
gf_mul(n, y, d); /* y^2 * (1-dy^2) / (1-y^2) */
gf_serialize(x,n,1);
#endif /* EDDSA_USE_SIGMA_ISOGENY */
decaf_bzero(y,sizeof(y));
decaf_bzero(n,sizeof(n));
decaf_bzero(d,sizeof(d));
}
}
void decaf_x25519_generate_key (
uint8_t out[X_PUBLIC_BYTES],
const uint8_t scalar[X_PRIVATE_BYTES]
......
......@@ -89,6 +89,21 @@ void decaf_ed25519_prehash_init (
hash_init(hash);
}
/* In this file because it uses the hash */
void decaf_ed25519_convert_private_key_to_x25519 (
uint8_t x[DECAF_X25519_PRIVATE_BYTES],
const uint8_t ed[DECAF_EDDSA_25519_PRIVATE_BYTES]
) {
/* pass the private key through hash_hash function */
/* and keep the first DECAF_X25519_PRIVATE_BYTES bytes */
hash_hash(
x,
DECAF_X25519_PRIVATE_BYTES,
ed,
DECAF_EDDSA_25519_PRIVATE_BYTES
);
}
void decaf_ed25519_derive_public_key (
uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES],
const uint8_t privkey[DECAF_EDDSA_25519_PRIVATE_BYTES]
......
......@@ -1318,6 +1318,50 @@ decaf_error_t decaf_x448 (
return decaf_succeed_if(mask_to_bool(nz));
}
/* Thanks Johan Pascal */
void decaf_ed448_convert_public_key_to_x448 (
uint8_t x[DECAF_X448_PUBLIC_BYTES],
const uint8_t ed[DECAF_EDDSA_448_PUBLIC_BYTES]
) {
gf y;
{
uint8_t enc2[DECAF_EDDSA_448_PUBLIC_BYTES];
memcpy(enc2,ed,sizeof(enc2));
/* retrieve y from the ed compressed point */
enc2[DECAF_EDDSA_448_PUBLIC_BYTES-1] &= ~0x80;
ignore_result(gf_deserialize(y, enc2, 0));
decaf_bzero(enc2,sizeof(enc2));
}
{
gf n,d;
#if EDDSA_USE_SIGMA_ISOGENY
/* u = (1+y)/(1-y)*/
gf_add(n, y, ONE); /* n = y+1 */
gf_sub(d, ONE, y); /* d = 1-y */
gf_invert(d, d); /* d = 1/(1-y) */
gf_mul(y, n, d); /* u = (y+1)/(1-y) */
gf_serialize(x,y,1);
#else /* EDDSA_USE_SIGMA_ISOGENY */
/* u = y^2 * (1-dy^2) / (1-y^2) */
gf_sqr(n,y); /* y^2*/
gf_sub(d,ONE,n); /* 1-y^2*/
gf_invert(d,d); /* 1/(1-y^2)*/
gf_mul(y,n,d); /* y^2 / (1-y^2) */
gf_mulw(d,n,EDWARDS_D); /* dy^2*/
gf_sub(d, ONE, d); /* 1-dy^2*/
gf_mul(n, y, d); /* y^2 * (1-dy^2) / (1-y^2) */
gf_serialize(x,n,1);
#endif /* EDDSA_USE_SIGMA_ISOGENY */
decaf_bzero(y,sizeof(y));
decaf_bzero(n,sizeof(n));
decaf_bzero(d,sizeof(d));
}
}
void decaf_x448_generate_key (
uint8_t out[X_PUBLIC_BYTES],
const uint8_t scalar[X_PRIVATE_BYTES]
......
......@@ -89,6 +89,21 @@ void decaf_ed448_prehash_init (
hash_init(hash);
}
/* In this file because it uses the hash */
void decaf_ed448_convert_private_key_to_x448 (
uint8_t x[DECAF_X448_PRIVATE_BYTES],
const uint8_t ed[DECAF_EDDSA_448_PRIVATE_BYTES]
) {
/* pass the private key through hash_hash function */
/* and keep the first DECAF_X448_PRIVATE_BYTES bytes */
hash_hash(
x,
DECAF_X448_PRIVATE_BYTES,
ed,
DECAF_EDDSA_448_PRIVATE_BYTES
);
}
void decaf_ed448_derive_public_key (
uint8_t pubkey[DECAF_EDDSA_448_PUBLIC_BYTES],
const uint8_t privkey[DECAF_EDDSA_448_PRIVATE_BYTES]
......
......@@ -192,6 +192,32 @@ decaf_error_t decaf_255_point_decode_like_eddsa_and_ignore_cofactor (
const uint8_t enc[DECAF_EDDSA_25519_PUBLIC_BYTES]
) API_VIS NONNULL NOINLINE;
/**
* @brief EdDSA to ECDH public key conversion
* Deserialize the point to get y on Edwards curve,
* Convert it to u coordinate on Montgomery curve.
*
* @param[out] x The ECDH public key as in RFC7748(point on Montgomery curve)
* @param[in] ed The EdDSA public key(point on Edwards curve)
*/
void decaf_ed25519_convert_public_key_to_x25519 (
uint8_t x[DECAF_X25519_PUBLIC_BYTES],
const uint8_t ed[DECAF_EDDSA_25519_PUBLIC_BYTES]
) API_VIS NONNULL NOINLINE;
/**
* @brief EdDSA to ECDH private key conversion
* Using the appropriate hash function, hash the EdDSA private key
* and keep only the lower bytes to get the ECDH private key
*
* @param[out] x The ECDH private key as in RFC7748
* @param[in] ed The EdDSA private key
*/
void decaf_ed25519_convert_private_key_to_x25519 (
uint8_t x[DECAF_X25519_PRIVATE_BYTES],
const uint8_t ed[DECAF_EDDSA_25519_PRIVATE_BYTES]
) API_VIS NONNULL NOINLINE;
#ifdef __cplusplus
} /* extern "C" */
#endif
......
......@@ -237,6 +237,13 @@ public:
memcpy(x,priv_.data(), priv_.size());
}
/** Convert to X format (to be used for key exchange) */
inline SecureBuffer convert_to_x() const {
SecureBuffer out(DECAF_X25519_PRIVATE_BYTES);
decaf_ed25519_convert_private_key_to_x25519(out.data(), priv_.data());
return out;
}
/** Return the corresponding public key */
inline MyPublicKey pub() const NOEXCEPT {
MyPublicKey pub(*this);
......@@ -403,6 +410,13 @@ public:
inline void serialize_into(unsigned char *x) const NOEXCEPT {
memcpy(x,pub_.data(), pub_.size());
}
/** Convert to X format (to be used for key exchange) */
inline SecureBuffer convert_to_x() const {
SecureBuffer out(DECAF_X25519_PRIVATE_BYTES);
decaf_ed25519_convert_public_key_to_x25519(out.data(), pub_.data());
return out;
}
}; /* class PublicKey */
}; /* template<> struct EdDSA<IsoEd25519> */
......
......@@ -191,6 +191,32 @@ decaf_error_t decaf_448_point_decode_like_eddsa_and_ignore_cofactor (
const uint8_t enc[DECAF_EDDSA_448_PUBLIC_BYTES]
) API_VIS NONNULL NOINLINE;
/**
* @brief EdDSA to ECDH public key conversion
* Deserialize the point to get y on Edwards curve,
* Convert it to u coordinate on Montgomery curve.
*
* @param[out] x The ECDH public key as in RFC7748(point on Montgomery curve)
* @param[in] ed The EdDSA public key(point on Edwards curve)
*/
void decaf_ed448_convert_public_key_to_x448 (
uint8_t x[DECAF_X448_PUBLIC_BYTES],
const uint8_t ed[DECAF_EDDSA_448_PUBLIC_BYTES]
) API_VIS NONNULL NOINLINE;
/**
* @brief EdDSA to ECDH private key conversion
* Using the appropriate hash function, hash the EdDSA private key
* and keep only the lower bytes to get the ECDH private key
*
* @param[out] x The ECDH private key as in RFC7748
* @param[in] ed The EdDSA private key
*/
void decaf_ed448_convert_private_key_to_x448 (
uint8_t x[DECAF_X448_PRIVATE_BYTES],
const uint8_t ed[DECAF_EDDSA_448_PRIVATE_BYTES]
) API_VIS NONNULL NOINLINE;
#ifdef __cplusplus
} /* extern "C" */
#endif
......
......@@ -237,6 +237,13 @@ public:
memcpy(x,priv_.data(), priv_.size());
}
/** Convert to X format (to be used for key exchange) */
inline SecureBuffer convert_to_x() const {
SecureBuffer out(DECAF_X448_PRIVATE_BYTES);
decaf_ed448_convert_private_key_to_x448(out.data(), priv_.data());
return out;
}
/** Return the corresponding public key */
inline MyPublicKey pub() const NOEXCEPT {
MyPublicKey pub(*this);
......@@ -403,6 +410,13 @@ public:
inline void serialize_into(unsigned char *x) const NOEXCEPT {
memcpy(x,pub_.data(), pub_.size());
}
/** Convert to X format (to be used for key exchange) */
inline SecureBuffer convert_to_x() const {
SecureBuffer out(DECAF_X448_PRIVATE_BYTES);
decaf_ed448_convert_public_key_to_x448(out.data(), pub_.data());
return out;
}
}; /* class PublicKey */
}; /* template<> struct EdDSA<Ed448Goldilocks> */
......
......@@ -1307,6 +1307,50 @@ decaf_error_t decaf_x$(gf_shortname) (
return decaf_succeed_if(mask_to_bool(nz));
}
/* Thanks Johan Pascal */
void decaf_ed$(gf_shortname)_convert_public_key_to_x$(gf_shortname) (
uint8_t x[DECAF_X$(gf_shortname)_PUBLIC_BYTES],
const uint8_t ed[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES]
) {
gf y;
{
uint8_t enc2[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES];
memcpy(enc2,ed,sizeof(enc2));
/* retrieve y from the ed compressed point */
enc2[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES-1] &= ~0x80;
ignore_result(gf_deserialize(y, enc2, 0));
decaf_bzero(enc2,sizeof(enc2));
}
{
gf n,d;
#if EDDSA_USE_SIGMA_ISOGENY
/* u = (1+y)/(1-y)*/
gf_add(n, y, ONE); /* n = y+1 */
gf_sub(d, ONE, y); /* d = 1-y */
gf_invert(d, d); /* d = 1/(1-y) */
gf_mul(y, n, d); /* u = (y+1)/(1-y) */
gf_serialize(x,y,1);
#else /* EDDSA_USE_SIGMA_ISOGENY */
/* u = y^2 * (1-dy^2) / (1-y^2) */
gf_sqr(n,y); /* y^2*/
gf_sub(d,ONE,n); /* 1-y^2*/
gf_invert(d,d); /* 1/(1-y^2)*/
gf_mul(y,n,d); /* y^2 / (1-y^2) */
gf_mulw(d,n,EDWARDS_D); /* dy^2*/
gf_sub(d, ONE, d); /* 1-dy^2*/
gf_mul(n, y, d); /* y^2 * (1-dy^2) / (1-y^2) */
gf_serialize(x,n,1);
#endif /* EDDSA_USE_SIGMA_ISOGENY */
decaf_bzero(y,sizeof(y));
decaf_bzero(n,sizeof(n));
decaf_bzero(d,sizeof(d));
}
}
void decaf_x$(gf_shortname)_generate_key (
uint8_t out[X_PUBLIC_BYTES],
const uint8_t scalar[X_PRIVATE_BYTES]
......
......@@ -80,6 +80,21 @@ void decaf_ed$(gf_shortname)_prehash_init (
hash_init(hash);
}
/* In this file because it uses the hash */
void decaf_ed$(gf_shortname)_convert_private_key_to_x$(gf_shortname) (
uint8_t x[DECAF_X$(gf_shortname)_PRIVATE_BYTES],
const uint8_t ed[DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES]
) {
/* pass the private key through hash_hash function */
/* and keep the first DECAF_X$(gf_shortname)_PRIVATE_BYTES bytes */
hash_hash(
x,
DECAF_X$(gf_shortname)_PRIVATE_BYTES,
ed,
DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES
);
}
void decaf_ed$(gf_shortname)_derive_public_key (
uint8_t pubkey[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES],
const uint8_t privkey[DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES]
......
......@@ -176,6 +176,32 @@ decaf_error_t $(c_ns)_point_decode_like_eddsa_and_ignore_cofactor (
const uint8_t enc[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES]
) API_VIS NONNULL NOINLINE;
/**
* @brief EdDSA to ECDH public key conversion
* Deserialize the point to get y on Edwards curve,
* Convert it to u coordinate on Montgomery curve.
*
* @param[out] x The ECDH public key as in RFC7748(point on Montgomery curve)
* @param[in] ed The EdDSA public key(point on Edwards curve)
*/
void decaf_ed$(gf_shortname)_convert_public_key_to_x$(gf_shortname) (
uint8_t x[DECAF_X$(gf_shortname)_PUBLIC_BYTES],
const uint8_t ed[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES]
) API_VIS NONNULL NOINLINE;
/**
* @brief EdDSA to ECDH private key conversion
* Using the appropriate hash function, hash the EdDSA private key
* and keep only the lower bytes to get the ECDH private key
*
* @param[out] x The ECDH private key as in RFC7748
* @param[in] ed The EdDSA private key
*/
void decaf_ed$(gf_shortname)_convert_private_key_to_x$(gf_shortname) (
uint8_t x[DECAF_X$(gf_shortname)_PRIVATE_BYTES],
const uint8_t ed[DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES]
) API_VIS NONNULL NOINLINE;
#ifdef __cplusplus
} /* extern "C" */
#endif
......@@ -221,6 +221,13 @@ public:
memcpy(x,priv_.data(), priv_.size());
}
/** Convert to X format (to be used for key exchange) */
inline SecureBuffer convert_to_x() const {
SecureBuffer out(DECAF_X$(gf_shortname)_PRIVATE_BYTES);
decaf_ed$(gf_shortname)_convert_private_key_to_x$(gf_shortname)(out.data(), priv_.data());
return out;
}
/** Return the corresponding public key */
inline MyPublicKey pub() const NOEXCEPT {
MyPublicKey pub(*this);
......@@ -387,6 +394,13 @@ public:
inline void serialize_into(unsigned char *x) const NOEXCEPT {
memcpy(x,pub_.data(), pub_.size());
}
/** Convert to X format (to be used for key exchange) */
inline SecureBuffer convert_to_x() const {
SecureBuffer out(DECAF_X$(gf_shortname)_PRIVATE_BYTES);
decaf_ed$(gf_shortname)_convert_public_key_to_x$(gf_shortname)(out.data(), pub_.data());
return out;
}
}; /* class PublicKey */
}; /* template<> struct EdDSA<$(cxx_ns)> */
......
......@@ -534,12 +534,54 @@ static void test_eddsa() {
}
/* Thanks Johan Pascal */
static void test_convert_eddsa_to_x() {
Test test("ECDH using EdDSA keys");
SpongeRng rng(Block("test_x_on_eddsa_key"),SpongeRng::DETERMINISTIC);
for (int i=0; i<NTESTS && test.passing_now; i++) {
/* generate 2 pairs of EdDSA keys */
typename EdDSA<Group>::PrivateKey alice_priv(rng);
typename EdDSA<Group>::PublicKey alice_pub(alice_priv);
typename EdDSA<Group>::PrivateKey bob_priv(rng);
typename EdDSA<Group>::PublicKey bob_pub(bob_priv);
/* convert them to ECDH format
* check public key value by computing it from direct conversion and regeneration from converted private)
*/
SecureBuffer alice_priv_x = alice_priv.convert_to_x();
SecureBuffer alice_pub_x_conversion = alice_pub.convert_to_x();
SecureBuffer alice_pub_x_generated = DhLadder::derive_public_key(alice_priv_x);
if (!memeq(alice_pub_x_conversion, alice_pub_x_generated)) {
test.fail();
printf(" Ed2X Public key convertion and regeneration from converted private key differs.\n");
}
SecureBuffer bob_priv_x = bob_priv.convert_to_x();
SecureBuffer bob_pub_x_conversion = bob_pub.convert_to_x();
SecureBuffer bob_pub_x_generated = DhLadder::derive_public_key(bob_priv_x);
if (!memeq(bob_pub_x_conversion, bob_pub_x_generated)) {
test.fail();
printf(" Ed2X Public key convertion and regeneration from converted private key differs.\n");
}
/* compute shared secrets and check they match */
SecureBuffer alice_shared = DhLadder::shared_secret(bob_pub_x_conversion, alice_priv_x);
SecureBuffer bob_shared = DhLadder::shared_secret(alice_pub_x_conversion, bob_priv_x);
if (!memeq(alice_shared, bob_shared)) {
test.fail();
printf(" ECDH shared secret mismatch.\n");
}
}
}
static void run() {
printf("Testing %s:\n",Group::name());
test_arithmetic();
test_elligator();
test_ec();
test_eddsa();
test_convert_eddsa_to_x();
test_cfrg_crypto();
test_cfrg_vectors();
printf("\n");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment