aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Haines <mark.haines@matrix.org>2015-03-03 11:18:07 +0000
committerMark Haines <mark.haines@matrix.org>2015-03-03 11:18:07 +0000
commit315caaba7e83eb6680a0407ea13e04b5f7739788 (patch)
tree23141186153b59f493e9e8e09fc1f207a6f8cee4
parent3ce450fc1984ac480ae158a40d60e9d42f77f74a (diff)
Add functions for signing and verifying messages using curve25519 keys
-rw-r--r--include/axolotl/crypto.hh19
-rw-r--r--lib/ed25519/src/fe.c4
-rw-r--r--lib/ed25519/src/sc.c5
-rw-r--r--lib/ed25519_additions.c43
-rw-r--r--src/crypto.cpp67
-rw-r--r--src/libs.cpp8
-rwxr-xr-xtest.py4
-rw-r--r--tests/test_crypto.cpp29
8 files changed, 176 insertions, 3 deletions
diff --git a/include/axolotl/crypto.hh b/include/axolotl/crypto.hh
index 162099f..d772f46 100644
--- a/include/axolotl/crypto.hh
+++ b/include/axolotl/crypto.hh
@@ -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];
diff --git a/lib/ed25519/src/fe.c b/lib/ed25519/src/fe.c
index 448e3e9..07f9f05 100644
--- a/lib/ed25519/src/fe.c
+++ b/lib/ed25519/src/fe.c
@@ -1,6 +1,8 @@
#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
diff --git a/lib/ed25519/src/sc.c b/lib/ed25519/src/sc.c
index ca5bad2..a883907 100644
--- a/lib/ed25519/src/sc.c
+++ b/lib/ed25519/src/sc.c
@@ -1,6 +1,9 @@
#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
diff --git a/lib/ed25519_additions.c b/lib/ed25519_additions.c
new file mode 100644
index 0000000..5fa0c68
--- /dev/null
+++ b/lib/ed25519_additions.c
@@ -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);
+}
diff --git a/src/crypto.cpp b/src/crypto.cpp
index 57f31cd..24a8136 100644
--- a/src/crypto.cpp
+++ b/src/crypto.cpp
@@ -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
) {
diff --git a/src/libs.cpp b/src/libs.cpp
index 61bb86c..6757574 100644
--- a/src/libs.cpp
+++ b/src/libs.cpp
@@ -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"
}
diff --git a/test.py b/test.py
index 336591c..06d4552 100755
--- a/test.py
+++ b/test.py
@@ -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])
diff --git a/tests/test_crypto.cpp b/tests/test_crypto.cpp
index 1c068c4..3ec5360 100644
--- a/tests/test_crypto.cpp
+++ b/tests/test_crypto.cpp
@@ -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");