]> git.codecow.com Git - Monocypher.git/commitdiff
Added X25519 -> EdDSA public key conversion
authorLoup Vaillant <loup@loup-vaillant.fr>
Sat, 7 Jan 2023 11:48:35 +0000 (12:48 +0100)
committerLoup Vaillant <loup@loup-vaillant.fr>
Sat, 7 Jan 2023 12:00:33 +0000 (13:00 +0100)
Also removed the private conversions (users can use the relevant hash
function instead), and renamed the existing conversion to fit the new
functionality set better.

Combined with the EdDSA building blocks, this should be enough to
implement XEdDSA.

See #227

13 files changed:
doc/man/man3/advanced/crypto_eddsa_to_x25519.3monocypher [moved from doc/man/man3/advanced/crypto_from_eddsa_private.3monocypher with 74% similarity]
doc/man/man3/advanced/crypto_from_eddsa_public.3monocypher [deleted symlink]
doc/man/man3/advanced/crypto_x25519_to_eddsa.3monocypher [new symlink]
doc/man/man3/optional/crypto_from_ed25519_private.3monocypher [deleted file]
doc/man/man3/optional/crypto_from_ed25519_public.3monocypher [deleted symlink]
src/monocypher.c
src/monocypher.h
src/optional/monocypher-ed25519.c
src/optional/monocypher-ed25519.h
tests/test.c
tests/tis-ci-gen-config.sh
tests/tis-ci.c
tis.config

similarity index 74%
rename from doc/man/man3/advanced/crypto_from_eddsa_private.3monocypher
rename to doc/man/man3/advanced/crypto_eddsa_to_x25519.3monocypher
index 0c22d65e97f77d2f2b6cdb053b2d8e828499fd72..1f1e50967cb4f6d0f540446c7a573fa451bcf1e6 100644 (file)
@@ -9,6 +9,7 @@
 .\" ----------------------------------------------------------------------------
 .\"
 .\" Copyright (c) 2020, 2022 Fabio Scotoni
+.\" Copyright (c) 2023 Loup Vaillant
 .\" All rights reserved.
 .\"
 .\"
@@ -38,7 +39,7 @@
 .\"
 .\" ----------------------------------------------------------------------------
 .\"
-.\" Written in 2020 and 2022 by Fabio Scotoni
+.\" Written in 2020, 2022, and 2023 by Fabio Scotoni and Loup Vaillant
 .\"
 .\" To the extent possible under law, the author(s) have dedicated all copyright
 .\" and related neighboring rights to this software to the public domain
 .\" with this software.  If not, see
 .\" <https://creativecommons.org/publicdomain/zero/1.0/>
 .\"
-.Dd February 13, 2022
-.Dt CRYPTO_FROM_EDDSA_PRIVATE 3MONOCYPHER
+.Dd January 7, 2023
+.Dt CRYPTO_FROM_EDDSA_TO_X25519 3MONOCYPHER
 .Os
 .Sh NAME
-.Nm crypto_from_eddsa_private ,
-.Nm crypto_from_eddsa_public
-.Nd conversion of key pairs for EdDSA with BLAKE2b to X25519 key pairs
+.Nm crypto_eddsa_to_x25519 ,
+.Nm crypto_x25519_to_eddsa
+.Nd conversion of public keys between EdDSA and X25519
 .Sh SYNOPSIS
 .In monocypher.h
 .Ft void
-.Fo crypto_from_eddsa_private
+.Fo crypto_eddsa_to_x25519
 .Fa "uint8_t x25519[32]"
 .Fa "const uint8_t eddsa[32]"
 .Fc
 .Ft void
-.Fo crypto_from_eddsa_public
-.Fa "uint8_t x25519[32]"
-.Fa "const uint8_t eddsa[32]"
+.Fo crypto_x25519_to_eddsa
+.Fa "uint8_t eddsa[32]"
+.Fa "const uint8_t x25519[32]"
 .Fc
 .Sh DESCRIPTION
-These functions convert keys for use with
-.Xr crypto_sign 3monocypher
-(EdDSA with the BLAKE2b hash function)
-to keys for use with
-.Xr crypto_x25519 3monocypher
-and
+These functions convert between public keys for use with
+.Xr crypto_eddsa_sign 3monocypher
+and keys for use with
 .Xr crypto_x25519 3monocypher .
 This may be useful in some resource-constrained contexts or when no
 other key is available \(en for example when retrieving SSH public keys
 from GitHub and reusing the SSH public keys as X25519 public keys.
 .Pp
 The
-.Fn crypto_from_eddsa_private
-function converts an EdDSA (with BLAKE2b) private key to an X25519
-private key.
-The
-.Fn crypto_from_eddsa_public
+.Fn crypto_eddsa_to_x25519
 function converts an EdDSA public key to an X25519 public key.
-.Pp
-X25519 key pairs cannot be converted back to EdDSA key pairs.
-The conversion of private keys is specific to EdDSA with BLAKE2b because
-of the way EdDSA works.
-In particular, this means that the output of
-.Fn crypto_from_eddsa_private
-differs from
-.Xr crypto_from_ed25519_private 3monocypher
-in the optional code.
-However, the output of
-.Fn crypto_from_eddsa_public
-is identical to
-.Xr crypto_from_ed25519_public 3monocypher .
+The
+.Fn crypto_x25519_to_eddsa
+function converts an X25519 public key to an EdDSA public key.
 .Pp
 The arguments are:
 .Bl -tag -width Ds
 .It Fa eddsa
-The signing public key or private key to convert to a X25519 public key
-or private key, respectively.
+The EdDSA signing public key.
 .It Fa x25519
-The converted private key or public key.
+The X25519 key exchange public key.
 .El
 .Pp
 The arguments may overlap or point at the same buffer.
@@ -115,7 +98,7 @@ These functions return nothing.
 They cannot fail.
 .Sh SEE ALSO
 .Xr crypto_x25519 3monocypher ,
-.Xr crypto_sign_public_key 3monocypher ,
+.Xr crypto_eddsa_key_pair 3monocypher ,
 .Xr intro 3monocypher
 .Sh HISTORY
 The
@@ -123,6 +106,15 @@ The
 and
 .Fn crypto_from_eddsa_public
 functions first appeared in Monocypher 3.1.0.
+In Monocypher 4.0.0,
+.Fn crypto_from_eddsa_private
+was removed,
+.Fn crypto_x25519_to_eddsa
+was added,
+and
+.Fn crypto_from_eddsa_public
+was renamed
+.Fn crypto_eddsa_to_x25519 .
 .Sh SECURITY CONSIDERATIONS
 It is generally considered poor form to reuse the same key for different
 purposes.
diff --git a/doc/man/man3/advanced/crypto_from_eddsa_public.3monocypher b/doc/man/man3/advanced/crypto_from_eddsa_public.3monocypher
deleted file mode 120000 (symlink)
index 9766c25..0000000
+++ /dev/null
@@ -1 +0,0 @@
-crypto_from_eddsa_private.3monocypher
\ No newline at end of file
diff --git a/doc/man/man3/advanced/crypto_x25519_to_eddsa.3monocypher b/doc/man/man3/advanced/crypto_x25519_to_eddsa.3monocypher
new file mode 120000 (symlink)
index 0000000..8d7c433
--- /dev/null
@@ -0,0 +1 @@
+crypto_eddsa_to_x25519.3monocypher
\ No newline at end of file
diff --git a/doc/man/man3/optional/crypto_from_ed25519_private.3monocypher b/doc/man/man3/optional/crypto_from_ed25519_private.3monocypher
deleted file mode 100644 (file)
index 328eb82..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-.\" This file is dual-licensed.  Choose whichever you want.
-.\"
-.\" The first licence is a regular 2-clause BSD licence.  The second licence
-.\" is the CC-0 from Creative Commons. It is intended to release Monocypher
-.\" to the public domain.  The BSD licence serves as a fallback option.
-.\"
-.\" SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
-.\"
-.\" ----------------------------------------------------------------------------
-.\"
-.\" Copyright (c) 2020 Fabio Scotoni
-.\" All rights reserved.
-.\"
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions are
-.\" met:
-.\"
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\"
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the
-.\"    distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-.\"
-.\" ----------------------------------------------------------------------------
-.\"
-.\" Written in 2020 by Fabio Scotoni
-.\"
-.\" To the extent possible under law, the author(s) have dedicated all copyright
-.\" and related neighboring rights to this software to the public domain
-.\" worldwide.  This software is distributed without any warranty.
-.\"
-.\" You should have received a copy of the CC0 Public Domain Dedication along
-.\" with this software.  If not, see
-.\" <https://creativecommons.org/publicdomain/zero/1.0/>
-.\"
-.Dd May 24, 2020
-.Dt CRYPTO_FROM_ED25519_PRIVATE 3MONOCYPHER
-.Os
-.Sh NAME
-.Nm crypto_from_ed25519_private ,
-.Nm crypto_from_ed25519_public
-.Nd conversion of key pairs for EdDSA with BLAKE2b to X25519 key pairs
-.Sh SYNOPSIS
-.In monocypher-ed25519.h
-.Ft void
-.Fo crypto_from_ed25519_private
-.Fa "uint8_t x25519[32]"
-.Fa "const uint8_t eddsa[32]"
-.Fc
-.Ft void
-.Fo crypto_from_ed25519_public
-.Fa "uint8_t x25519[32]"
-.Fa "const uint8_t eddsa[32]"
-.Fc
-.Sh DESCRIPTION
-These functions work like
-.Xr crypto_from_eddsa_private 3monocypher
-and
-.Xr crypto_from_eddsa_public 3monocypher ,
-except that they operate on Ed25519 key pairs
-rather than key pairs for EdDSA with BLAKE2b.
-Please see the documentation for those functions for details.
-.Sh IMPLEMENTATION DETAILS
-.Fn crypto_from_ed25519_public
-is actually implemented as a macro that aliases to
-.Xr crypto_from_eddsa_public 3monocypher .
-.Sh HISTORY
-The
-.Fn crypto_from_ed25519_private
-and
-.Fn crypto_from_ed25519_public
-functions first appeared in Monocypher 3.1.0.
diff --git a/doc/man/man3/optional/crypto_from_ed25519_public.3monocypher b/doc/man/man3/optional/crypto_from_ed25519_public.3monocypher
deleted file mode 120000 (symlink)
index 8c31b15..0000000
+++ /dev/null
@@ -1 +0,0 @@
-crypto_from_ed25519_private.3monocypher
\ No newline at end of file
index b05a0b3311d628c50abda5f3ae9ccbb90e75b98c..3be9f52abb847ca1f15d9856f5d3559ebf6d43af 100644 (file)
@@ -2313,19 +2313,13 @@ int crypto_eddsa_check(const u8  signature[64], const u8 public_key[32],
        return crypto_eddsa_check_equation(signature, public_key, h_ram);
 }
 
-///////////////////////
-/// 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);
-}
-
-void crypto_from_eddsa_public(u8 x25519[32], const u8 eddsa[32])
+/////////////////////////
+/// EdDSA <--> X25519 ///
+/////////////////////////
+void crypto_eddsa_to_x25519(u8 x25519[32], const u8 eddsa[32])
 {
+       // (u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)
+       // Only converting y to u, the sign of x is ignored.
        fe t1, t2;
        fe_frombytes(t2, eddsa);
        fe_add(t1, fe_one, t2);
@@ -2337,6 +2331,21 @@ void crypto_from_eddsa_public(u8 x25519[32], const u8 eddsa[32])
        WIPE_BUFFER(t2);
 }
 
+void crypto_x25519_to_eddsa(uint8_t eddsa[32], const uint8_t x25519[32])
+{
+       // (x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))
+       // Only converting u to y, x is assumed positive.
+       fe t1, t2;
+       fe_frombytes(t2, x25519);
+       fe_sub(t1, t2, fe_one);
+       fe_add(t2, t2, fe_one);
+       fe_invert(t2, t2);
+       fe_mul(t1, t1, t2);
+       fe_tobytes(eddsa, t1);
+       WIPE_BUFFER(t1);
+       WIPE_BUFFER(t2);
+}
+
 /////////////////////////////////////////////
 /// Dirty ephemeral public key generation ///
 /////////////////////////////////////////////
index 74941543bcd742979da2b9d27421e5b7e918db69..d4078dab4460a1e07cfb88cc2d333347d8be5cea 100644 (file)
@@ -310,10 +310,10 @@ int crypto_eddsa_check_equation(const uint8_t signature[64],
                                 const uint8_t public_key[32],
                                 const uint8_t h_ram[32]);
 
-// 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]);
+// EdDSA <--> X25519
+// -----------------
+void crypto_eddsa_to_x25519(uint8_t x25519[32], const uint8_t eddsa[32]);
+void crypto_x25519_to_eddsa(uint8_t eddsa[32], const uint8_t x25519[32]);
 
 
 // Elligator 2
index 4602615336281369069436a42f69e09e1aae9b2f..497464603faefeb03db5c04a5b453bbb3b883b10 100644 (file)
@@ -394,14 +394,6 @@ int crypto_ed25519_check(const u8  signature[64], const u8 public_key[32],
        return crypto_eddsa_check_equation(signature, public_key, h_ram);
 }
 
-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);
-}
-
 #ifdef MONOCYPHER_CPP_NAMESPACE
 }
 #endif
index 255157324f1f671a835222d8c0f7f9fa62847449..2f7b414a2cf69a1436d8bff730b1979176bdaef7 100644 (file)
@@ -117,9 +117,6 @@ int crypto_ed25519_check(const uint8_t  signature [64],
                          const uint8_t  public_key[32],
                          const uint8_t *message, size_t message_size);
 
-void crypto_from_ed25519_private(uint8_t x25519[32], const uint8_t eddsa[32]);
-#define crypto_from_ed25519_public crypto_from_eddsa_public
-
 #ifdef __cplusplus
 }
 #endif
index d2e30ac11b2e8739ed9810bcddb15a2b03de8a74..6236b2395c1801e935e7425b840fef0e4eb5299d 100644 (file)
@@ -246,7 +246,6 @@ static void test_chacha20()
        }
 }
 
-
 /////////////////
 /// Poly 1305 ///
 /////////////////
@@ -462,7 +461,6 @@ static void test_sha512()
        }
 }
 
-
 ////////////////////
 /// HMAC SHA 512 ///
 ////////////////////
@@ -733,7 +731,6 @@ static void test_x25519()
        }
 }
 
-
 /////////////
 /// EdDSA ///
 /////////////
@@ -1026,32 +1023,26 @@ static void test_elligator()
        }
 }
 
-
 ////////////////////////
 /// X25519 <-> EdDSA ///
 ////////////////////////
 static void test_conversions()
 {
-       printf("\tfrom_eddsa\n");
+       printf("\tX25519 <-> EdDSA\n");
        FOR (i, 0, 32) {
-               RANDOM_INPUT(ed_seed, 32);
-               u8 secret   [64];
-               u8 public   [32]; crypto_eddsa_key_pair(secret, public, ed_seed);
-               u8 x_private[32]; crypto_from_eddsa_private(x_private, secret);
-               u8 x_public1[32]; crypto_from_eddsa_public (x_public1, public);
-               u8 x_public2[32]; crypto_x25519_public_key (x_public2, x_private);
+               RANDOM_INPUT(e_seed, 32);
+               u8 secret    [64];
+               u8 e_public1[32]; crypto_eddsa_key_pair(secret, e_public1, e_seed);
+               u8 x_private[64]; crypto_blake2b          (x_private, secret, 32);
+               u8 x_public1[32]; crypto_eddsa_to_x25519  (x_public1, e_public1);
+               u8 x_public2[32]; crypto_x25519_public_key(x_public2, x_private);
                ASSERT_EQUAL(x_public1, x_public2, 32);
-       }
 
-       printf("\tfrom_ed25519\n");
-       FOR (i, 0, 32) {
-               RANDOM_INPUT(ed_seed, 32);
-               u8 secret   [64];
-               u8 public   [32]; crypto_ed25519_key_pair(secret, public, ed_seed);
-               u8 x_private[32]; crypto_from_ed25519_private(x_private, secret);
-               u8 x_public1[32]; crypto_from_ed25519_public (x_public1, public);
-               u8 x_public2[32]; crypto_x25519_public_key (x_public2, x_private);
-               ASSERT_EQUAL(x_public1, x_public2, 32);
+               u8 e_public2[32]; crypto_x25519_to_eddsa  (e_public2, x_public1);
+               ASSERT((e_public2[31] & 0x80) == 0); // x coordinate always positive
+
+               e_public1[31] &= 0x7f;               // y coordinate back to original
+               ASSERT_EQUAL(e_public1, e_public2, 32);
        }
 }
 
index 7270505501fa824dfe38d2214c0598ddf2499a21..fa0e5200dc4016b42e863bef7605e8c805bde889 100755 (executable)
@@ -73,8 +73,7 @@ for entry_point in      \
     "v_ed_25519_check"  \
     "v_elligator_dir"   \
     "v_elligator_inv"   \
-    "p_from_eddsa"      \
-    "p_from_ed25519"    \
+    "p_eddsa_x25519"    \
     "p_dirty"           \
     "p_x25519_inverse"  \
     "p_verify16"        \
index 80e9e317f3a549229adeec485ce5dde6fb7ad23e..31fe93f77a2a3c3cd46a5c11b7b6b1864504addd 100644 (file)
@@ -252,33 +252,22 @@ static void elligator_inv(vector_reader *reader)
 }
 
 //@ ensures \result == 0;
-static int p_from_eddsa()
+static int p_eddsa_x25519()
 {
-       int status = 0;
-       RANDOM_INPUT(ed_seed, 32);
-       u8 secret   [64];
-       u8 public   [32];  crypto_eddsa_key_pair(secret, public, ed_seed);
-       u8 x_private[32];  crypto_from_eddsa_private(x_private, secret);
-       u8 x_public1[32];  crypto_from_eddsa_public (x_public1, 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;
-}
-
-//@ ensures \result == 0;
-static int p_from_ed25519()
-{
-       int status = 0;
-       RANDOM_INPUT(ed_seed, 32);
-       u8 secret   [64];
-       u8 public   [32];  crypto_ed25519_key_pair(secret, public, ed_seed);
-       u8 x_private[32];  crypto_from_ed25519_private(x_private, secret);
-       u8 x_public1[32];  crypto_from_ed25519_public (x_public1, 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;
+       RANDOM_INPUT(e_seed, 32);
+       u8 secret    [64];
+       u8 e_public1[32]; crypto_eddsa_key_pair(secret, e_public1, e_seed);
+       u8 x_private[64]; crypto_blake2b          (x_private, secret, 32);
+       u8 x_public1[32]; crypto_eddsa_to_x25519  (x_public1, e_public1);
+       u8 x_public2[32]; crypto_x25519_public_key(x_public2, x_private);
+       ASSERT_EQUAL(x_public1, x_public2, 32);
+
+       u8 e_public2[32]; crypto_x25519_to_eddsa  (e_public2, x_public1);
+       ASSERT((e_public2[31] & 0x80) == 0); // x coordinate always positive
+
+       e_public1[31] &= 0x7f;               // y coordinate back to original
+       ASSERT_EQUAL(e_public1, e_public2, 32);
+       return 0;
 }
 
 //@ ensures \result == 0;
@@ -430,8 +419,7 @@ int main(void) {
        ASSERT(v_elligator_dir () == 0);
        ASSERT(v_elligator_inv () == 0);
 
-       ASSERT(p_from_eddsa    () == 0);
-       ASSERT(p_from_ed25519  () == 0);
+       ASSERT(p_eddsa_x25519  () == 0);
        ASSERT(p_dirty         () == 0);
        ASSERT(p_x25519_inverse() == 0);
        ASSERT(p_verify16      () == 0);
index f7e92348a599830f0b4222aef1e313930b799d84..bff0a04e7478d8b47d9f102e28aae195c7649f0f 100644 (file)
 , "no-results"    : true
 , "main"          : "v_elligator_inv"
 },
-{ "name"          : "p_from_eddsa - sparc_32"
+{ "name"          : "p_eddsa_x25519 - sparc_32"
 , "files"         :
   [ "src/monocypher.c"
   , "src/optional/monocypher-ed25519.c"
 , "cpp-extra-args": "-Isrc -Isrc/optional -Itests"
 , "machdep"       : "sparc_32"
 , "no-results"    : true
-, "main"          : "p_from_eddsa"
+, "main"          : "p_eddsa_x25519"
 },
-{ "name"          : "p_from_eddsa - x86_32"
+{ "name"          : "p_eddsa_x25519 - x86_32"
 , "files"         :
   [ "src/monocypher.c"
   , "src/optional/monocypher-ed25519.c"
 , "cpp-extra-args": "-Isrc -Isrc/optional -Itests"
 , "machdep"       : "x86_32"
 , "no-results"    : true
-, "main"          : "p_from_eddsa"
+, "main"          : "p_eddsa_x25519"
 },
-{ "name"          : "p_from_eddsa - x86_16"
+{ "name"          : "p_eddsa_x25519 - x86_16"
 , "files"         :
   [ "src/monocypher.c"
   , "src/optional/monocypher-ed25519.c"
 , "cpp-extra-args": "-Isrc -Isrc/optional -Itests"
 , "machdep"       : "x86_16"
 , "no-results"    : true
-, "main"          : "p_from_eddsa"
+, "main"          : "p_eddsa_x25519"
 },
-{ "name"          : "p_from_eddsa - x86_win64"
+{ "name"          : "p_eddsa_x25519 - x86_win64"
 , "files"         :
   [ "src/monocypher.c"
   , "src/optional/monocypher-ed25519.c"
 , "cpp-extra-args": "-Isrc -Isrc/optional -Itests"
 , "machdep"       : "x86_win64"
 , "no-results"    : true
-, "main"          : "p_from_eddsa"
+, "main"          : "p_eddsa_x25519"
 },
-{ "name"          : "p_from_eddsa - armeb_eabi"
+{ "name"          : "p_eddsa_x25519 - armeb_eabi"
 , "files"         :
   [ "src/monocypher.c"
   , "src/optional/monocypher-ed25519.c"
 , "cpp-extra-args": "-Isrc -Isrc/optional -Itests"
 , "machdep"       : "armeb_eabi"
 , "no-results"    : true
-, "main"          : "p_from_eddsa"
+, "main"          : "p_eddsa_x25519"
 },
-{ "name"          : "p_from_eddsa - arm_eabi"
+{ "name"          : "p_eddsa_x25519 - arm_eabi"
 , "files"         :
   [ "src/monocypher.c"
   , "src/optional/monocypher-ed25519.c"
 , "cpp-extra-args": "-Isrc -Isrc/optional -Itests"
 , "machdep"       : "arm_eabi"
 , "no-results"    : true
-, "main"          : "p_from_eddsa"
+, "main"          : "p_eddsa_x25519"
 },
-{ "name"          : "p_from_eddsa - aarch64"
+{ "name"          : "p_eddsa_x25519 - aarch64"
 , "files"         :
   [ "src/monocypher.c"
   , "src/optional/monocypher-ed25519.c"
 , "cpp-extra-args": "-Isrc -Isrc/optional -Itests"
 , "machdep"       : "aarch64"
 , "no-results"    : true
-, "main"          : "p_from_eddsa"
+, "main"          : "p_eddsa_x25519"
 },
-{ "name"          : "p_from_eddsa - rv64ifdq"
+{ "name"          : "p_eddsa_x25519 - rv64ifdq"
 , "files"         :
   [ "src/monocypher.c"
   , "src/optional/monocypher-ed25519.c"
 , "cpp-extra-args": "-Isrc -Isrc/optional -Itests"
 , "machdep"       : "rv64ifdq"
 , "no-results"    : true
-, "main"          : "p_from_eddsa"
+, "main"          : "p_eddsa_x25519"
 },
-{ "name"          : "p_from_eddsa - mips_64"
+{ "name"          : "p_eddsa_x25519 - mips_64"
 , "files"         :
   [ "src/monocypher.c"
   , "src/optional/monocypher-ed25519.c"
 , "cpp-extra-args": "-Isrc -Isrc/optional -Itests"
 , "machdep"       : "mips_64"
 , "no-results"    : true
-, "main"          : "p_from_eddsa"
+, "main"          : "p_eddsa_x25519"
 },
-{ "name"          : "p_from_eddsa - ppc_64"
+{ "name"          : "p_eddsa_x25519 - ppc_64"
 , "files"         :
   [ "src/monocypher.c"
   , "src/optional/monocypher-ed25519.c"
 , "cpp-extra-args": "-Isrc -Isrc/optional -Itests"
 , "machdep"       : "ppc_64"
 , "no-results"    : true
-, "main"          : "p_from_eddsa"
-},
-{ "name"          : "p_from_ed25519 - sparc_32"
-, "files"         :
-  [ "src/monocypher.c"
-  , "src/optional/monocypher-ed25519.c"
-  , "tests/utils.c"
-  , "tests/tis-ci.c"
-  ]
-, "cpp-extra-args": "-Isrc -Isrc/optional -Itests"
-, "machdep"       : "sparc_32"
-, "no-results"    : true
-, "main"          : "p_from_ed25519"
-},
-{ "name"          : "p_from_ed25519 - x86_32"
-, "files"         :
-  [ "src/monocypher.c"
-  , "src/optional/monocypher-ed25519.c"
-  , "tests/utils.c"
-  , "tests/tis-ci.c"
-  ]
-, "cpp-extra-args": "-Isrc -Isrc/optional -Itests"
-, "machdep"       : "x86_32"
-, "no-results"    : true
-, "main"          : "p_from_ed25519"
-},
-{ "name"          : "p_from_ed25519 - x86_16"
-, "files"         :
-  [ "src/monocypher.c"
-  , "src/optional/monocypher-ed25519.c"
-  , "tests/utils.c"
-  , "tests/tis-ci.c"
-  ]
-, "cpp-extra-args": "-Isrc -Isrc/optional -Itests"
-, "machdep"       : "x86_16"
-, "no-results"    : true
-, "main"          : "p_from_ed25519"
-},
-{ "name"          : "p_from_ed25519 - x86_win64"
-, "files"         :
-  [ "src/monocypher.c"
-  , "src/optional/monocypher-ed25519.c"
-  , "tests/utils.c"
-  , "tests/tis-ci.c"
-  ]
-, "cpp-extra-args": "-Isrc -Isrc/optional -Itests"
-, "machdep"       : "x86_win64"
-, "no-results"    : true
-, "main"          : "p_from_ed25519"
-},
-{ "name"          : "p_from_ed25519 - armeb_eabi"
-, "files"         :
-  [ "src/monocypher.c"
-  , "src/optional/monocypher-ed25519.c"
-  , "tests/utils.c"
-  , "tests/tis-ci.c"
-  ]
-, "cpp-extra-args": "-Isrc -Isrc/optional -Itests"
-, "machdep"       : "armeb_eabi"
-, "no-results"    : true
-, "main"          : "p_from_ed25519"
-},
-{ "name"          : "p_from_ed25519 - arm_eabi"
-, "files"         :
-  [ "src/monocypher.c"
-  , "src/optional/monocypher-ed25519.c"
-  , "tests/utils.c"
-  , "tests/tis-ci.c"
-  ]
-, "cpp-extra-args": "-Isrc -Isrc/optional -Itests"
-, "machdep"       : "arm_eabi"
-, "no-results"    : true
-, "main"          : "p_from_ed25519"
-},
-{ "name"          : "p_from_ed25519 - aarch64"
-, "files"         :
-  [ "src/monocypher.c"
-  , "src/optional/monocypher-ed25519.c"
-  , "tests/utils.c"
-  , "tests/tis-ci.c"
-  ]
-, "cpp-extra-args": "-Isrc -Isrc/optional -Itests"
-, "machdep"       : "aarch64"
-, "no-results"    : true
-, "main"          : "p_from_ed25519"
-},
-{ "name"          : "p_from_ed25519 - rv64ifdq"
-, "files"         :
-  [ "src/monocypher.c"
-  , "src/optional/monocypher-ed25519.c"
-  , "tests/utils.c"
-  , "tests/tis-ci.c"
-  ]
-, "cpp-extra-args": "-Isrc -Isrc/optional -Itests"
-, "machdep"       : "rv64ifdq"
-, "no-results"    : true
-, "main"          : "p_from_ed25519"
-},
-{ "name"          : "p_from_ed25519 - mips_64"
-, "files"         :
-  [ "src/monocypher.c"
-  , "src/optional/monocypher-ed25519.c"
-  , "tests/utils.c"
-  , "tests/tis-ci.c"
-  ]
-, "cpp-extra-args": "-Isrc -Isrc/optional -Itests"
-, "machdep"       : "mips_64"
-, "no-results"    : true
-, "main"          : "p_from_ed25519"
-},
-{ "name"          : "p_from_ed25519 - ppc_64"
-, "files"         :
-  [ "src/monocypher.c"
-  , "src/optional/monocypher-ed25519.c"
-  , "tests/utils.c"
-  , "tests/tis-ci.c"
-  ]
-, "cpp-extra-args": "-Isrc -Isrc/optional -Itests"
-, "machdep"       : "ppc_64"
-, "no-results"    : true
-, "main"          : "p_from_ed25519"
+, "main"          : "p_eddsa_x25519"
 },
 { "name"          : "p_dirty - sparc_32"
 , "files"         :