added key exchange
This commit is contained in:
parent
2e17ca4ed8
commit
ae9d05be04
BIN
ed25519.dll
BIN
ed25519.dll
Binary file not shown.
53
readme.md
53
readme.md
@ -2,24 +2,29 @@ Ed25519
|
||||
=======
|
||||
|
||||
This is a portable implementation of [Ed25519](http://ed25519.cr.yp.to/) based
|
||||
on the SUPERCOP "ref10" implementation. All code is in the public domain.
|
||||
on the SUPERCOP "ref10" implementation. Additionally there is key exchanging
|
||||
and scalar addition included to further aid building a PKI using Ed25519. All
|
||||
code is in the public domain.
|
||||
|
||||
All code is pure ANSI C without any dependencies, except for the random seed
|
||||
generation which uses standard OS cryptography APIs (`CryptGenRandom` on Windows, `/dev/urandom` on *nix). If you wish to be entirely
|
||||
portable define `ED25519_NO_SEED`. This disables the `ed25519_create_seed`
|
||||
function, so if your application requires key generation you must supply your
|
||||
own seeding function (which is simply a 32 byte cryptographic random number generator).
|
||||
generation which uses standard OS cryptography APIs (`CryptGenRandom` on
|
||||
Windows, `/dev/urandom` on nix). If you wish to be entirely portable define
|
||||
`ED25519_NO_SEED`. This disables the `ed25519_create_seed` function, so if your
|
||||
application requires key generation you must supply your own seeding function
|
||||
(which is simply a 256 byte cryptographic random number generator).
|
||||
|
||||
|
||||
Performance
|
||||
-----------
|
||||
|
||||
On a machine with an Intel Pentium B970 @ 2.3GHz I got the following speeds (running
|
||||
on only one a single core):
|
||||
On a Windows machine with an Intel Pentium B970 @ 2.3GHz I got the following
|
||||
speeds (running on only one a single core):
|
||||
|
||||
Seed + key generation: 345us
|
||||
Message signing (short message): 256us
|
||||
Message verifying (short message): 777us
|
||||
Seed + key generation: 489us
|
||||
Message signing (short message): 251us
|
||||
Message verifying (short message): 772us
|
||||
Scalar addition: 358us
|
||||
Key exchange: 724us
|
||||
|
||||
The speeds on other machines may vary. Sign/verify times will be higher with
|
||||
longer messages.
|
||||
@ -33,8 +38,9 @@ Simply add all .c and .h files in the `src/` folder to your project and include
|
||||
library, only copy `ed25519.h` and define `ED25519_DLL` before importing. A
|
||||
windows DLL is pre-built.
|
||||
|
||||
There are no defined types for seeds, private keys, public keys or signatures.
|
||||
Instead simple `unsigned char` buffers are used with the following sizes:
|
||||
There are no defined types for seeds, private keys, public keys, shared secrets
|
||||
or signatures. Instead simple `unsigned char` buffers are used with the
|
||||
following sizes:
|
||||
|
||||
```c
|
||||
unsigned char seed[32];
|
||||
@ -42,6 +48,7 @@ unsigned char signature[64];
|
||||
unsigned char public_key[32];
|
||||
unsigned char private_key[64];
|
||||
unsigned char scalar[32];
|
||||
unsigned char shared_secret[32];
|
||||
```
|
||||
|
||||
API
|
||||
@ -91,12 +98,24 @@ Adds `scalar` to the given key pair where scalar is a 32 byte buffer (possibly
|
||||
generated with `ed25519_create_seed`), generating a new key pair. You can
|
||||
calculate the public key sum without knowing the private key and vice versa by
|
||||
passing in `NULL` for the key you don't know. This is useful for enforcing
|
||||
randomness on a key pair while only knowing the public key, among other things.
|
||||
Warning: the last bit of the scalar is ignored - if comparing scalars make sure
|
||||
to clear it with `scalar[31] &= 127`.
|
||||
randomness on a key pair by a third party while only knowing the public key,
|
||||
among other things. Warning: the last bit of the scalar is ignored - if
|
||||
comparing scalars make sure to clear it with `scalar[31] &= 127`.
|
||||
|
||||
|
||||
```c
|
||||
void ed25519_key_exchange(unsigned char *shared_secret,
|
||||
const unsigned char *public_key, const unsigned char *private_key);
|
||||
```
|
||||
|
||||
Performs a key exchange on the given public key and private key, producing a
|
||||
shared secret. It is recommended to hash the shared secret before using it.
|
||||
`shared_secret` must be a 32 byte writable buffer where the shared secret will
|
||||
be stored.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
```c
|
||||
unsigned char seed[32], public_key[32], private_key[64], signature[64];
|
||||
const unsigned char message[] = "TEST MESSAGE";
|
||||
@ -119,3 +138,7 @@ if (ed25519_verify(signature, message, strlen(message), public_key)) {
|
||||
printf("invalid signature\n");
|
||||
}
|
||||
```
|
||||
|
||||
License
|
||||
-------
|
||||
All code is in the public domain.
|
||||
|
@ -28,6 +28,7 @@ void ED25519_DECLSPEC ed25519_create_keypair(unsigned char *public_key, unsigned
|
||||
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);
|
||||
void ED25519_DECLSPEC ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
79
src/key_exchange.c
Normal file
79
src/key_exchange.c
Normal file
@ -0,0 +1,79 @@
|
||||
#include "ed25519.h"
|
||||
#include "fe.h"
|
||||
|
||||
void ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key) {
|
||||
unsigned char e[32];
|
||||
unsigned int i;
|
||||
|
||||
fe x1;
|
||||
fe x2;
|
||||
fe z2;
|
||||
fe x3;
|
||||
fe z3;
|
||||
fe tmp0;
|
||||
fe tmp1;
|
||||
|
||||
int pos;
|
||||
unsigned int swap;
|
||||
unsigned int b;
|
||||
|
||||
/* copy the private key and make sure it's valid */
|
||||
for (i = 0; i < 32; ++i) {
|
||||
e[i] = private_key[i];
|
||||
}
|
||||
|
||||
e[0] &= 248;
|
||||
e[31] &= 63;
|
||||
e[31] |= 64;
|
||||
|
||||
/* unpack the public key and convert edwards to montgomery */
|
||||
/* due to CodesInChaos */
|
||||
fe_frombytes(x1, public_key);
|
||||
fe_1(tmp1);
|
||||
fe_add(tmp0, x1, tmp1);
|
||||
fe_sub(tmp1, tmp1, x1);
|
||||
fe_invert(tmp1, tmp1);
|
||||
fe_mul(x1, tmp0, tmp1);
|
||||
|
||||
fe_1(x2);
|
||||
fe_0(z2);
|
||||
fe_copy(x3, x1);
|
||||
fe_1(z3);
|
||||
|
||||
swap = 0;
|
||||
for (pos = 254; pos >= 0; --pos) {
|
||||
b = e[pos / 8] >> (pos & 7);
|
||||
b &= 1;
|
||||
swap ^= b;
|
||||
fe_cswap(x2, x3, swap);
|
||||
fe_cswap(z2, z3, swap);
|
||||
swap = b;
|
||||
|
||||
/* from montgomery.h */
|
||||
fe_sub(tmp0, x3, z3);
|
||||
fe_sub(tmp1, x2, z2);
|
||||
fe_add(x2, x2, z2);
|
||||
fe_add(z2, x3, z3);
|
||||
fe_mul(z3, tmp0, x2);
|
||||
fe_mul(z2, z2, tmp1);
|
||||
fe_sq(tmp0, tmp1);
|
||||
fe_sq(tmp1, x2);
|
||||
fe_add(x3, z3, z2);
|
||||
fe_sub(z2, z3, z2);
|
||||
fe_mul(x2, tmp1, tmp0);
|
||||
fe_sub(tmp1, tmp1, tmp0);
|
||||
fe_sq(z2, z2);
|
||||
fe_mul121666(z3, tmp1);
|
||||
fe_sq(x3, x3);
|
||||
fe_add(tmp0, tmp0, z3);
|
||||
fe_mul(z3, x1, z2);
|
||||
fe_mul(z2, tmp1, tmp0);
|
||||
}
|
||||
|
||||
fe_cswap(x2, x3, swap);
|
||||
fe_cswap(z2, z3, swap);
|
||||
|
||||
fe_invert(z2, z2);
|
||||
fe_mul(x2, x2, z2);
|
||||
fe_tobytes(shared_secret, x2);
|
||||
}
|
32
test.c
32
test.c
@ -14,6 +14,8 @@ const char message[] = "Hello, world!";
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
unsigned char public_key[32], private_key[64], seed[32], scalar[32];
|
||||
unsigned char other_public_key[32], other_private_key[64];
|
||||
unsigned char shared_secret[32], other_shared_secret[32];
|
||||
unsigned char signature[64];
|
||||
|
||||
clock_t start;
|
||||
@ -56,6 +58,27 @@ int main(int argc, char *argv[]) {
|
||||
printf("correctly detected signature change\n");
|
||||
}
|
||||
|
||||
/* generate two keypairs for testing key exchange */
|
||||
ed25519_create_seed(seed);
|
||||
ed25519_create_keypair(public_key, private_key, seed);
|
||||
ed25519_create_seed(seed);
|
||||
ed25519_create_keypair(other_public_key, other_private_key, seed);
|
||||
|
||||
/* create two shared secrets - from both perspectives - and check if they're equal */
|
||||
ed25519_key_exchange(shared_secret, other_public_key, private_key);
|
||||
ed25519_key_exchange(other_shared_secret, public_key, other_private_key);
|
||||
|
||||
for (i = 0; i < 32; ++i) {
|
||||
if (shared_secret[i] != other_shared_secret[i]) {
|
||||
printf("key exchange was incorrect\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 32) {
|
||||
printf("key exchange was correct\n");
|
||||
}
|
||||
|
||||
/* test performance */
|
||||
printf("testing key generation performance: ");
|
||||
start = clock();
|
||||
@ -93,6 +116,15 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
end = clock();
|
||||
|
||||
printf("%fus per signature\n", ((double) ((end - start) * 1000)) / CLOCKS_PER_SEC / i * 1000);
|
||||
|
||||
printf("testing key exchange performance: ");
|
||||
start = clock();
|
||||
for (i = 0; i < 10000; ++i) {
|
||||
ed25519_key_exchange(shared_secret, other_public_key, private_key);
|
||||
}
|
||||
end = clock();
|
||||
|
||||
printf("%fus per signature\n", ((double) ((end - start) * 1000)) / CLOCKS_PER_SEC / i * 1000);
|
||||
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user