Skip to content
Snippets Groups Projects
Commit 315caaba authored by Mark Haines's avatar Mark Haines
Browse files

Add functions for signing and verifying messages using curve25519 keys

parent 3ce450fc
No related branches found
No related tags found
No related merge requests found
......@@ -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 {
static const int LENGTH = 32;
std::uint8_t key[32];
......
#include "fixedint.h"
#include "fe.h"
#ifndef ED25519_LOAD_BYTES
#define ED25519_LOAD_BYTES
/*
helper functions
......@@ -26,7 +28,7 @@ static uint64_t load_4(const unsigned char *in) {
return result;
}
#endif
/*
h = 0
......
#include "fixedint.h"
#include "sc.h"
#ifndef ED25519_LOAD_BYTES
#define ED25519_LOAD_BYTES
static uint64_t load_3(const unsigned char *in) {
uint64_t result;
......@@ -22,6 +25,8 @@ static uint64_t load_4(const unsigned char *in) {
return result;
}
#endif
/*
Input:
s[0]+256*s[1]+...+256^63*s[63] = s
......
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/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 input_length
) {
......
......@@ -16,4 +16,12 @@ extern "C" {
#include "crypto-algorithms/sha256.c"
#include "crypto-algorithms/aes.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"
}
......@@ -23,10 +23,10 @@ if not os.path.exists("build"):
test_files = glob.glob("tests/test_*.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
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([exe_file])
......@@ -83,6 +83,35 @@ assert_equals(expected_agreement, actual_agreement, 32);
} /* 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 */
TestCase test_case("AES Test Case 1");
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment