Add functions for signing and verifying messages using curve25519 keys
This commit is contained in:
parent
3ce450fc19
commit
315caaba7e
8 changed files with 176 additions and 3 deletions
|
@ -48,6 +48,25 @@ void curve25519_shared_secret(
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/** Signs the message using our private key.
|
||||||
|
* The output buffer must be at least 64 bytes long. */
|
||||||
|
void curve25519_sign(
|
||||||
|
Curve25519KeyPair const & our_key,
|
||||||
|
std::uint8_t const * message, std::size_t message_length,
|
||||||
|
std::uint8_t * output
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/** Verify thei message using their public key.
|
||||||
|
* The signature input buffer must be 64 bytes long.
|
||||||
|
* Returns true if the signature is valid. */
|
||||||
|
bool curve25519_verify(
|
||||||
|
Curve25519PublicKey const & their_key,
|
||||||
|
std::uint8_t const * message, std::size_t message_length,
|
||||||
|
std::uint8_t const * signature
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
struct Aes256Key {
|
struct Aes256Key {
|
||||||
static const int LENGTH = 32;
|
static const int LENGTH = 32;
|
||||||
std::uint8_t key[32];
|
std::uint8_t key[32];
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "fixedint.h"
|
#include "fixedint.h"
|
||||||
#include "fe.h"
|
#include "fe.h"
|
||||||
|
|
||||||
|
#ifndef ED25519_LOAD_BYTES
|
||||||
|
#define ED25519_LOAD_BYTES
|
||||||
|
|
||||||
/*
|
/*
|
||||||
helper functions
|
helper functions
|
||||||
|
@ -26,7 +28,7 @@ static uint64_t load_4(const unsigned char *in) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
h = 0
|
h = 0
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#include "fixedint.h"
|
#include "fixedint.h"
|
||||||
#include "sc.h"
|
#include "sc.h"
|
||||||
|
|
||||||
|
#ifndef ED25519_LOAD_BYTES
|
||||||
|
#define ED25519_LOAD_BYTES
|
||||||
|
|
||||||
static uint64_t load_3(const unsigned char *in) {
|
static uint64_t load_3(const unsigned char *in) {
|
||||||
uint64_t result;
|
uint64_t result;
|
||||||
|
|
||||||
|
@ -22,6 +25,8 @@ static uint64_t load_4(const unsigned char *in) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Input:
|
Input:
|
||||||
s[0]+256*s[1]+...+256^63*s[63] = s
|
s[0]+256*s[1]+...+256^63*s[63] = s
|
||||||
|
|
43
lib/ed25519_additions.c
Normal file
43
lib/ed25519_additions.c
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
void convert_curve25519_to_ed25519(
|
||||||
|
unsigned char * public_key,
|
||||||
|
unsigned char * signature
|
||||||
|
) {
|
||||||
|
fe mont_x, mont_x_minus_one, mont_x_plus_one, inv_mont_x_plus_one;
|
||||||
|
fe one;
|
||||||
|
fe ed_y;
|
||||||
|
|
||||||
|
fe_frombytes(mont_x, public_key);
|
||||||
|
fe_1(one);
|
||||||
|
fe_sub(mont_x_minus_one, mont_x, one);
|
||||||
|
fe_add(mont_x_plus_one, mont_x, one);
|
||||||
|
fe_invert(inv_mont_x_plus_one, mont_x_plus_one);
|
||||||
|
fe_mul(ed_y, mont_x_minus_one, inv_mont_x_plus_one);
|
||||||
|
fe_tobytes(public_key, ed_y);
|
||||||
|
|
||||||
|
public_key[31] &= 0x7F;
|
||||||
|
public_key[31] |= (signature[63] & 0x80);
|
||||||
|
signature[63] &= 0x7F;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void convert_ed25519_to_curve25519(
|
||||||
|
unsigned char const * public_key,
|
||||||
|
unsigned char * signature
|
||||||
|
) {
|
||||||
|
unsigned char sign_bit = public_key[31] & 0x80;
|
||||||
|
signature[63] &= 0x7F;
|
||||||
|
signature[63] |= sign_bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ed25519_keypair(
|
||||||
|
unsigned char * private_key,
|
||||||
|
unsigned char * public_key
|
||||||
|
) {
|
||||||
|
ge_p3 A;
|
||||||
|
private_key[0] &= 248;
|
||||||
|
private_key[31] &= 63;
|
||||||
|
private_key[31] |= 64;
|
||||||
|
ge_scalarmult_base(&A, private_key);
|
||||||
|
ge_p3_tobytes(public_key, &A);
|
||||||
|
}
|
|
@ -28,6 +28,38 @@ int curve25519_donna(
|
||||||
#include "crypto-algorithms/aes.h"
|
#include "crypto-algorithms/aes.h"
|
||||||
#include "crypto-algorithms/sha256.h"
|
#include "crypto-algorithms/sha256.h"
|
||||||
|
|
||||||
|
int 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_verify(
|
||||||
|
const unsigned char *signature,
|
||||||
|
const unsigned char *message, size_t message_len,
|
||||||
|
const unsigned char *public_key
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
void convert_curve25519_to_ed25519(
|
||||||
|
unsigned char * public_key,
|
||||||
|
unsigned char * signature
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
void convert_ed25519_to_curve25519(
|
||||||
|
unsigned char const * public_key,
|
||||||
|
unsigned char * signature
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
void ed25519_keypair(
|
||||||
|
unsigned char * private_key,
|
||||||
|
unsigned char * public_key
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -124,6 +156,41 @@ void axolotl::curve25519_shared_secret(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void axolotl::curve25519_sign(
|
||||||
|
axolotl::Curve25519KeyPair const & our_key,
|
||||||
|
std::uint8_t const * message, std::size_t message_length,
|
||||||
|
std::uint8_t * output
|
||||||
|
) {
|
||||||
|
std::uint8_t private_key[32];
|
||||||
|
std::uint8_t public_key[32];
|
||||||
|
std::memcpy(private_key, our_key.private_key, 32);
|
||||||
|
::ed25519_keypair(private_key, public_key);
|
||||||
|
::ed25519_sign(
|
||||||
|
output,
|
||||||
|
message, message_length,
|
||||||
|
public_key, private_key
|
||||||
|
);
|
||||||
|
::convert_ed25519_to_curve25519(public_key, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool axolotl::curve25519_verify(
|
||||||
|
axolotl::Curve25519PublicKey const & their_key,
|
||||||
|
std::uint8_t const * message, std::size_t message_length,
|
||||||
|
std::uint8_t const * signature
|
||||||
|
) {
|
||||||
|
std::uint8_t public_key[32];
|
||||||
|
std::uint8_t signature_buffer[64];
|
||||||
|
std::memcpy(public_key, their_key.public_key, 32);
|
||||||
|
std::memcpy(signature_buffer, signature, 64);
|
||||||
|
::convert_curve25519_to_ed25519(public_key, signature_buffer);
|
||||||
|
return 0 != ::ed25519_verify(
|
||||||
|
signature,
|
||||||
|
message, message_length,
|
||||||
|
public_key
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
std::size_t axolotl::aes_encrypt_cbc_length(
|
std::size_t axolotl::aes_encrypt_cbc_length(
|
||||||
std::size_t input_length
|
std::size_t input_length
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -16,4 +16,12 @@ extern "C" {
|
||||||
#include "crypto-algorithms/sha256.c"
|
#include "crypto-algorithms/sha256.c"
|
||||||
#include "crypto-algorithms/aes.c"
|
#include "crypto-algorithms/aes.c"
|
||||||
#include "curve25519-donna/curve25519-donna.c"
|
#include "curve25519-donna/curve25519-donna.c"
|
||||||
|
#define select ed25519_select
|
||||||
|
#include "ed25519/src/fe.c"
|
||||||
|
#include "ed25519/src/sc.c"
|
||||||
|
#include "ed25519/src/ge.c"
|
||||||
|
#include "ed25519/src/sha512.c"
|
||||||
|
#include "ed25519/src/verify.c"
|
||||||
|
#include "ed25519/src/sign.c"
|
||||||
|
#include "ed25519_additions.c"
|
||||||
}
|
}
|
||||||
|
|
4
test.py
4
test.py
|
@ -23,10 +23,10 @@ if not os.path.exists("build"):
|
||||||
test_files = glob.glob("tests/test_*.cpp")
|
test_files = glob.glob("tests/test_*.cpp")
|
||||||
source_files = glob.glob("src/*.cpp")
|
source_files = glob.glob("src/*.cpp")
|
||||||
|
|
||||||
compile_args = "g++ -Itests/include -Iinclude -Ilib --std=c++11".split()
|
compile_args = "g++ -g -O0 -Itests/include -Iinclude -Ilib --std=c++11".split()
|
||||||
compile_args += source_files
|
compile_args += source_files
|
||||||
|
|
||||||
for test_file in test_files:
|
for test_file in test_files:
|
||||||
exe_file = "build/" + test_file[:4]
|
exe_file = "build/" + test_file[5:-4]
|
||||||
subprocess.check_call(compile_args + [test_file, "-o", exe_file])
|
subprocess.check_call(compile_args + [test_file, "-o", exe_file])
|
||||||
subprocess.check_call([exe_file])
|
subprocess.check_call([exe_file])
|
||||||
|
|
|
@ -83,6 +83,35 @@ assert_equals(expected_agreement, actual_agreement, 32);
|
||||||
} /* Curve25529 Test Case 1 */
|
} /* Curve25529 Test Case 1 */
|
||||||
|
|
||||||
|
|
||||||
|
{ /* Signature Test Cast 1 */
|
||||||
|
TestCase test_case("Signature Test Case 1");
|
||||||
|
|
||||||
|
std::uint8_t private_key[33] = "This key is a string of 32 bytes";
|
||||||
|
std::uint8_t message[] = "message";
|
||||||
|
std::size_t message_length = sizeof(message) - 1;
|
||||||
|
|
||||||
|
axolotl::Curve25519KeyPair key_pair;
|
||||||
|
axolotl::generate_key(private_key, key_pair);
|
||||||
|
|
||||||
|
std::uint8_t signature[64];
|
||||||
|
|
||||||
|
axolotl::curve25519_sign(
|
||||||
|
key_pair, message, message_length, signature
|
||||||
|
);
|
||||||
|
|
||||||
|
bool result = axolotl::curve25519_verify(
|
||||||
|
key_pair, message, message_length, signature
|
||||||
|
);
|
||||||
|
assert_equals(true, result);
|
||||||
|
|
||||||
|
message[0] = 'n';
|
||||||
|
result = axolotl::curve25519_verify(
|
||||||
|
key_pair, message, message_length, signature
|
||||||
|
);
|
||||||
|
assert_equals(false, result);
|
||||||
|
|
||||||
|
} /* Signature Test Cast 1 */
|
||||||
|
|
||||||
{ /* AES Test Case 1 */
|
{ /* AES Test Case 1 */
|
||||||
|
|
||||||
TestCase test_case("AES Test Case 1");
|
TestCase test_case("AES Test Case 1");
|
||||||
|
|
Loading…
Reference in a new issue