return crypto_check_final(actx);
}
+///////////////////////
+/// EdDSA to X25519 ///
+///////////////////////
+void crypto_from_eddsa_private(u8 x25519[32], const u8 eddsa[32])
+{
+ u8 a[64];
+ crypto_blake2b(a, eddsa, 32);
+ COPY(x25519, a, 32);
+ WIPE_BUFFER(a);
+}
+
+static const fe fe_one = {1};
+
+void crypto_from_eddsa_public(u8 x25519[32], const u8 eddsa[32])
+{
+ fe t1, t2;
+ fe_frombytes(t2, eddsa);
+ fe_add(t1, fe_one, t2);
+ fe_sub(t2, fe_one, t2);
+ fe_invert(t2, t2);
+ fe_mul(t1, t1, t2);
+ fe_tobytes(x25519, t1);
+ WIPE_BUFFER(t1);
+ WIPE_BUFFER(t2);
+}
+
/////////////////////////////////////////////
/// Dirty ephemeral public key generation ///
/////////////////////////////////////////////
544946, -16816446, 4011309, -653372, 10741468,
};
static const fe A2 = {12721188, 3529, 0, 0, 0, 0, 0, 0, 0, 0};
- static const fe one = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
// Representatives are encoded in 254 bits.
// The two most significant ones are random padding that must be ignored.
fe r, u, t1, t2, t3;
fe_frombytes(r, clamped);
fe_sq2(t1, r);
- fe_add(u, t1, one);
+ fe_add(u, t1, fe_one);
fe_sq (t2, u);
fe_mul(t3, A2, t1);
fe_sub(t3, t3, t2);
int is_square = invsqrt(t1, t1);
fe_sq(u, r);
fe_mul(u, u, ufactor);
- fe_ccopy(u, one, is_square);
+ fe_ccopy(u, fe_one, is_square);
fe_sq (t1, t1);
fe_mul(u, u, A);
fe_mul(u, u, t3);
const uint8_t public_key[32],
const crypto_sign_vtable *hash);
+// EdDSA to X25519
+// ---------------
+void crypto_from_eddsa_private(uint8_t x25519[32], const uint8_t eddsa[32]);
+void crypto_from_eddsa_public (uint8_t x25519[32], const uint8_t eddsa[32]);
+
// Elligator 2
// -----------
/// Utilities ///
/////////////////
#define FOR(i, min, max) for (size_t i = min; i < max; i++)
+#define COPY(dst, src, size) FOR(i, 0, size) (dst)[i] = (src)[i]
#define ZERO(buf, size) FOR(i, 0, size) (buf)[i] = 0
#define WIPE_CTX(ctx) crypto_wipe(ctx , sizeof(*(ctx)))
+#define WIPE_BUFFER(buffer) crypto_wipe(buffer, sizeof(buffer))
#define MIN(a, b) ((a) <= (b) ? (a) : (b))
#define ALIGN(x, block_size) ((~(x) + 1) & ((block_size) - 1))
typedef uint8_t u8;
crypto_ed25519_check_update(actx, message, message_size);
return crypto_ed25519_check_final(actx);
}
+
+void crypto_from_ed25519_private(u8 x25519[32], const u8 eddsa[32])
+{
+ u8 a[64];
+ crypto_sha512(a, eddsa, 32);
+ COPY(x25519, a, 32);
+ WIPE_BUFFER(a);
+}
#define crypto_ed25519_check_update crypto_check_update
#define crypto_ed25519_check_final crypto_check_final
+void crypto_from_ed25519_private(uint8_t x25519[32], const uint8_t eddsa[32]);
+#define crypto_from_ed25519_public crypto_from_eddsa_public
+
#endif // ED25519_H
return status;
}
+int p_from_eddsa()
+{
+ int status = 0;
+ FOR (i, 0, 32) {
+ RANDOM_INPUT(ed_private, 32);
+ u8 ed_public[32]; crypto_sign_public_key (ed_public, ed_private);
+ u8 x_private[32]; crypto_from_eddsa_private(x_private, ed_private);
+ u8 x_public1[32]; crypto_from_eddsa_public (x_public1, ed_public);
+ u8 x_public2[32]; crypto_x25519_public_key (x_public2, x_private);
+ status |= memcmp(x_public1, x_public2, 32);
+ }
+ printf("%s: from_eddsa\n", status != 0 ? "FAILED" : "OK");
+ return status;
+}
+
+int p_from_ed25519()
+{
+ int status = 0;
+ FOR (i, 0, 32) {
+ RANDOM_INPUT(ed_private, 32);
+ u8 ed_public[32]; crypto_ed25519_public_key (ed_public, ed_private);
+ u8 x_private[32]; crypto_from_ed25519_private(x_private, ed_private);
+ u8 x_public1[32]; crypto_from_ed25519_public (x_public1, ed_public);
+ u8 x_public2[32]; crypto_x25519_public_key (x_public2, x_private);
+ status |= memcmp(x_public1, x_public2, 32);
+ }
+ printf("%s: from_ed25519\n", status != 0 ? "FAILED" : "OK");
+ return status;
+}
+
#define TEST(name, nb_inputs) vector_test(name, #name, nb_inputs, \
nb_##name##_vectors, \
name##_vectors, \
status |= p_elligator_key_pair();
status |= p_elligator_key_pair_overlap();
status |= p_x25519_inverse();
- printf("\n%s\n\n", status != 0 ? "SOME TESTS FAILED" : "All tests OK!");
+ status |= p_from_eddsa();
+ status |= p_from_ed25519();
+ printf("\n%s\n\n", status != 0 ? "SOME TESTS FAILED" : "All tests OK!");
return status;
}