diff --git a/ed25519.dll b/ed25519.dll index 7346468..7adac4f 100644 Binary files a/ed25519.dll and b/ed25519.dll differ diff --git a/readme.md b/readme.md index c4f6658..ff0945c 100644 --- a/readme.md +++ b/readme.md @@ -83,6 +83,13 @@ must be a readable 64 byte buffer. `message` must have at least `message_len` bytes to be read. `public_key` must be a 32 byte public key generated by `ed25519_create_keypair`. Returns 1 if the signature matches, 0 otherwise. +```c +void ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, + const unsigned char *scalar); +``` + +Adds `scalar` to the given keypair where scalar is a 32 byte buffer (possibly generated with `ed25519_create_seed`), generating a new keypair. You can calculate the public key sum without knowing the private key and vice versa by passing in NULL. This is useful for enforcing randomness on a keypair while only knowing the public key, among other things. + Example ------- ```c diff --git a/src/add_scalar.c b/src/add_scalar.c new file mode 100644 index 0000000..1575130 --- /dev/null +++ b/src/add_scalar.c @@ -0,0 +1,46 @@ +#include "ge.h" +#include "sc.h" + + +/* 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); + } + + if (public_key) { + /* 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); + } +} diff --git a/src/ed25519.h b/src/ed25519.h index 1d9cfa9..c1dc0d3 100644 --- a/src/ed25519.h +++ b/src/ed25519.h @@ -27,6 +27,7 @@ int ED25519_DECLSPEC ed25519_create_seed(unsigned char *seed); void ED25519_DECLSPEC ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed); void ED25519_DECLSPEC ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key); int ED25519_DECLSPEC ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *private_key); +void ED25519_DECLSPEC ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar); #ifdef __cplusplus diff --git a/test.c b/test.c index c8fc48a..3230dc0 100644 --- a/test.c +++ b/test.c @@ -3,13 +3,17 @@ #include #include -#define ED25519_DLL +//#define ED25519_DLL #include "src/ed25519.h" +#include "src/ge.h" +#include "src/sc.h" + const char message[] = "Hello, world!"; + int main(int argc, char *argv[]) { - unsigned char public_key[32], private_key[64], seed[32]; + unsigned char public_key[32], private_key[64], seed[32], scalar[32]; unsigned char signature[64]; clock_t start; @@ -30,6 +34,20 @@ int main(int argc, char *argv[]) { printf("invalid signature\n"); } + /* create scalar and add it to the keypair */ + ed25519_create_seed(scalar); + ed25519_add_scalar(public_key, private_key, scalar); + + /* create signature with the new keypair */ + ed25519_sign(signature, message, strlen(message), public_key, private_key); + + /* verify the signature with the new keypair */ + if (ed25519_verify(signature, message, strlen(message), public_key)) { + printf("valid signature\n"); + } else { + printf("invalid signature\n"); + } + /* make a slight adjustment and verify again */ signature[44] ^= 0x10; if (ed25519_verify(signature, message, strlen(message), public_key)) { @@ -66,6 +84,16 @@ int main(int argc, char *argv[]) { end = clock(); printf("%fus per signature\n", ((double) ((end - start) * 1000)) / CLOCKS_PER_SEC / i * 1000); + + + printf("testing scalar addition performance: "); + start = clock(); + for (i = 0; i < 10000; ++i) { + ed25519_add_scalar(public_key, private_key, scalar); + } + end = clock(); + + printf("%fus per signature\n", ((double) ((end - start) * 1000)) / CLOCKS_PER_SEC / i * 1000); return 0; }