| @@ -1318,6 +1318,50 @@ decaf_error_t decaf_x25519 ( | |||||
| return decaf_succeed_if(mask_to_bool(nz)); | 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 ( | void decaf_x25519_generate_key ( | ||||
| uint8_t out[X_PUBLIC_BYTES], | uint8_t out[X_PUBLIC_BYTES], | ||||
| const uint8_t scalar[X_PRIVATE_BYTES] | const uint8_t scalar[X_PRIVATE_BYTES] | ||||
| @@ -89,6 +89,21 @@ void decaf_ed25519_prehash_init ( | |||||
| hash_init(hash); | 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 ( | void decaf_ed25519_derive_public_key ( | ||||
| uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES], | uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES], | ||||
| const uint8_t privkey[DECAF_EDDSA_25519_PRIVATE_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)); | 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 ( | void decaf_x448_generate_key ( | ||||
| uint8_t out[X_PUBLIC_BYTES], | uint8_t out[X_PUBLIC_BYTES], | ||||
| const uint8_t scalar[X_PRIVATE_BYTES] | const uint8_t scalar[X_PRIVATE_BYTES] | ||||
| @@ -89,6 +89,21 @@ void decaf_ed448_prehash_init ( | |||||
| hash_init(hash); | 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 ( | void decaf_ed448_derive_public_key ( | ||||
| uint8_t pubkey[DECAF_EDDSA_448_PUBLIC_BYTES], | uint8_t pubkey[DECAF_EDDSA_448_PUBLIC_BYTES], | ||||
| const uint8_t privkey[DECAF_EDDSA_448_PRIVATE_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] | const uint8_t enc[DECAF_EDDSA_25519_PUBLIC_BYTES] | ||||
| ) API_VIS NONNULL NOINLINE; | ) 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 | #ifdef __cplusplus | ||||
| } /* extern "C" */ | } /* extern "C" */ | ||||
| #endif | #endif | ||||
| @@ -237,6 +237,13 @@ public: | |||||
| memcpy(x,priv_.data(), priv_.size()); | 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 */ | /** Return the corresponding public key */ | ||||
| inline MyPublicKey pub() const NOEXCEPT { | inline MyPublicKey pub() const NOEXCEPT { | ||||
| MyPublicKey pub(*this); | MyPublicKey pub(*this); | ||||
| @@ -403,6 +410,13 @@ public: | |||||
| inline void serialize_into(unsigned char *x) const NOEXCEPT { | inline void serialize_into(unsigned char *x) const NOEXCEPT { | ||||
| memcpy(x,pub_.data(), pub_.size()); | 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 */ | }; /* class PublicKey */ | ||||
| }; /* template<> struct EdDSA<IsoEd25519> */ | }; /* 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] | const uint8_t enc[DECAF_EDDSA_448_PUBLIC_BYTES] | ||||
| ) API_VIS NONNULL NOINLINE; | ) 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 | #ifdef __cplusplus | ||||
| } /* extern "C" */ | } /* extern "C" */ | ||||
| #endif | #endif | ||||
| @@ -237,6 +237,13 @@ public: | |||||
| memcpy(x,priv_.data(), priv_.size()); | 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 */ | /** Return the corresponding public key */ | ||||
| inline MyPublicKey pub() const NOEXCEPT { | inline MyPublicKey pub() const NOEXCEPT { | ||||
| MyPublicKey pub(*this); | MyPublicKey pub(*this); | ||||
| @@ -403,6 +410,13 @@ public: | |||||
| inline void serialize_into(unsigned char *x) const NOEXCEPT { | inline void serialize_into(unsigned char *x) const NOEXCEPT { | ||||
| memcpy(x,pub_.data(), pub_.size()); | 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 */ | }; /* class PublicKey */ | ||||
| }; /* template<> struct EdDSA<Ed448Goldilocks> */ | }; /* template<> struct EdDSA<Ed448Goldilocks> */ | ||||
| @@ -1307,6 +1307,50 @@ decaf_error_t decaf_x$(gf_shortname) ( | |||||
| return decaf_succeed_if(mask_to_bool(nz)); | 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 ( | void decaf_x$(gf_shortname)_generate_key ( | ||||
| uint8_t out[X_PUBLIC_BYTES], | uint8_t out[X_PUBLIC_BYTES], | ||||
| const uint8_t scalar[X_PRIVATE_BYTES] | const uint8_t scalar[X_PRIVATE_BYTES] | ||||
| @@ -80,6 +80,21 @@ void decaf_ed$(gf_shortname)_prehash_init ( | |||||
| hash_init(hash); | 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 ( | void decaf_ed$(gf_shortname)_derive_public_key ( | ||||
| uint8_t pubkey[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES], | uint8_t pubkey[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES], | ||||
| const uint8_t privkey[DECAF_EDDSA_$(gf_shortname)_PRIVATE_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] | const uint8_t enc[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES] | ||||
| ) API_VIS NONNULL NOINLINE; | ) 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 | #ifdef __cplusplus | ||||
| } /* extern "C" */ | } /* extern "C" */ | ||||
| #endif | #endif | ||||
| @@ -221,6 +221,13 @@ public: | |||||
| memcpy(x,priv_.data(), priv_.size()); | 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 */ | /** Return the corresponding public key */ | ||||
| inline MyPublicKey pub() const NOEXCEPT { | inline MyPublicKey pub() const NOEXCEPT { | ||||
| MyPublicKey pub(*this); | MyPublicKey pub(*this); | ||||
| @@ -387,6 +394,13 @@ public: | |||||
| inline void serialize_into(unsigned char *x) const NOEXCEPT { | inline void serialize_into(unsigned char *x) const NOEXCEPT { | ||||
| memcpy(x,pub_.data(), pub_.size()); | 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 */ | }; /* class PublicKey */ | ||||
| }; /* template<> struct EdDSA<$(cxx_ns)> */ | }; /* 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() { | static void run() { | ||||
| printf("Testing %s:\n",Group::name()); | printf("Testing %s:\n",Group::name()); | ||||
| test_arithmetic(); | test_arithmetic(); | ||||
| test_elligator(); | test_elligator(); | ||||
| test_ec(); | test_ec(); | ||||
| test_eddsa(); | test_eddsa(); | ||||
| test_convert_eddsa_to_x(); | |||||
| test_cfrg_crypto(); | test_cfrg_crypto(); | ||||
| test_cfrg_vectors(); | test_cfrg_vectors(); | ||||
| printf("\n"); | printf("\n"); | ||||