Skip to content
Snippets Groups Projects
Commit 8df2ab7c authored by David Baker's avatar David Baker
Browse files

Add signing class to the pk module

parent 45091c15
No related branches found
No related tags found
No related merge requests found
/* Copyright 2018 New Vector Ltd
/* Copyright 2018, 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -207,6 +207,48 @@ size_t olm_pk_get_private_key(
void *private_key, size_t private_key_length
);
typedef struct OlmPkSigning OlmPkSigning;
/* The size of a signing object in bytes */
size_t olm_pk_signing_size(void);
/** Initialise a signing object using the supplied memory
* The supplied memory must be at least olm_pk_sign_size() bytes */
OlmPkSigning *olm_pk_signing(
void * memory
);
/** A null terminated string describing the most recent error to happen to a
* signing object */
const char * olm_pk_signing_last_error(
OlmPkSigning * sign
);
/** Clears the memory used to back this signing object */
size_t olm_clear_pk_signing(
OlmPkSigning *sign
);
/**
* Initialise the signing object with a public/private keypair from a seed
*/
size_t olm_pk_signing_key_from_seed(
OlmPkSigning * sign,
void * pubkey, size_t pubkey_length,
void * seed, size_t seed_length
);
size_t olm_pk_sign_seed_length(void);
size_t olm_pk_sign_public_key_length(void);
size_t olm_pk_signature_length();
size_t olm_pk_sign(
OlmPkSigning *sign,
uint8_t const * message, size_t message_length,
uint8_t * signature, size_t signature_length
);
#ifdef __cplusplus
}
#endif
......
......@@ -271,3 +271,92 @@ PkDecryption.prototype['decrypt'] = restore_stack(function (
}
}
})
function PkSigning() {
var size = Module['_olm_pk_signing_size']();
this.buf = malloc(size);
this.ptr = Module['_olm_pk_signing'](this.buf);
}
function pk_signing_method(wrapped) {
return function() {
var result = wrapped.apply(this, arguments);
if (result === OLM_ERROR) {
var message = Pointer_stringify(
Module['_olm_pk_signing_last_error'](arguments[0])
);
throw new Error("OLM." + message);
}
return result;
}
}
PkSigning.prototype['free'] = function() {
Module['_olm_clear_pk_signing'](this.ptr);
free(this.ptr);
}
PkSigning.prototype['init_with_seed'] = restore_stack(function (seed) {
var seed_buffer = stack(seed.length);
Module['HEAPU8'].set(seed, seed_buffer);
var pubkey_length = pk_decryption_method(
Module['_olm_pk_sign_public_key_length']
)();
var pubkey_buffer = stack(pubkey_length + NULL_BYTE_PADDING_LENGTH);
try {
pk_signing_method(Module['_olm_pk_signing_key_from_seed'])(
this.ptr,
pubkey_buffer, pubkey_length,
seed_buffer, seed.length
);
} finally {
// clear out our copy of the seed
bzero(seed_buffer, seed.length);
}
return Pointer_stringify(pubkey_buffer);
});
PkSigning.prototype['generate_seed'] = restore_stack(function () {
var random_length = pk_decryption_method(
Module['_olm_pk_sign_seed_length']
)();
var random_buffer = random_stack(random_length);
var key_arr = new Uint8Array(
new Uint8Array(Module['HEAPU8'].buffer, random_buffer, random_length)
);
bzero(random_buffer, random_length);
return key_arr;
});
PkSigning.prototype['sign'] = restore_stack(function (message) {
// XXX: Should be able to sign any bytes rather than just strings,
// but this is consistent with encrypt for now.
//var message_buffer = stack(message.length);
//Module['HEAPU8'].set(message, message_buffer);
var message_buffer, message_length;
try {
message_length = lengthBytesUTF8(message)
message_buffer = malloc(message_length + 1);
stringToUTF8(message, message_buffer, message_length + 1);
var sig_length = pk_decryption_method(
Module['_olm_pk_signature_length']
)();
var sig_buffer = stack(sig_length + NULL_BYTE_PADDING_LENGTH);
pk_signing_method(Module['_olm_pk_sign'])(
this.ptr,
message_buffer, message_length,
sig_buffer, sig_length
);
return Pointer_stringify(sig_buffer);
} finally {
if (message_buffer !== undefined) {
// don't leave a copy of the plaintext in the heap.
bzero(message_buffer, message_length + 1);
free(message_buffer);
}
}
});
......@@ -534,6 +534,7 @@ olm_exports["Session"] = Session;
olm_exports["Utility"] = Utility;
olm_exports["PkEncryption"] = PkEncryption;
olm_exports["PkDecryption"] = PkDecryption;
olm_exports["PkSigning"] = PkSigning;
olm_exports["SAS"] = SAS;
olm_exports["get_library_version"] = restore_stack(function() {
......
......@@ -34,7 +34,6 @@ describe("olm", function() {
beforeEach(function(done) {
// This should really be in a beforeAll, but jasmine-node
// doesn't support that
debugger;
Olm.init().then(function() {
aliceAccount = new Olm.Account();
bobAccount = new Olm.Account();
......
/*
Copyright 2018 New Vector Ltd
Copyright 2018, 2019 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
......@@ -19,12 +19,13 @@ limitations under the License.
var Olm = require('../olm');
describe("pk", function() {
var encryption, decryption;
var encryption, decryption, signing;
beforeEach(function(done) {
Olm.init().then(function() {
encryption = new Olm.PkEncryption();
decryption = new Olm.PkDecryption();
signing = new Olm.PkSigning();
done();
});
......@@ -39,6 +40,10 @@ describe("pk", function() {
decryption.free();
decryption = undefined;
}
if (signing !== undefined) {
signing.free();
signing = undefined;
}
});
it('should import & export keys from private parts', function () {
......@@ -89,4 +94,29 @@ describe("pk", function() {
expect(decrypted).toEqual(TEST_TEXT);
new_decryption.free();
});
it('should sign and verify', function () {
var seed = new Uint8Array([
0x77, 0x07, 0x6D, 0x0A, 0x73, 0x18, 0xA5, 0x7D,
0x3C, 0x16, 0xC1, 0x72, 0x51, 0xB2, 0x66, 0x45,
0xDF, 0x4C, 0x2F, 0x87, 0xEB, 0xC0, 0x99, 0x2A,
0xB1, 0x77, 0xFB, 0xA5, 0x1D, 0xB9, 0x2C, 0x2A
]);
var TEST_TEXT = "We hold these truths to be self-evident, that all men are created equal, that they are endowed by their Creator with certain unalienable Rights, that among these are Life, Liberty and the pursuit of Happiness.";
//var seed = signing.generate_seed();
var pubkey = signing.init_with_seed(seed);
var sig = signing.sign(TEST_TEXT);
var util = new Olm.Utility();
util.ed25519_verify(pubkey, TEST_TEXT, sig);
var verifyFailure;
try {
util.ed25519_verify(pubkey, TEST_TEXT, 'p' + sig.slice(1));
} catch (e) {
verifyFailure = e;
}
expect(verifyFailure).not.toBeNull();
util.free();
});
});
/* Copyright 2018 New Vector Ltd
/* Copyright 2018, 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -409,4 +409,88 @@ size_t olm_pk_get_private_key(
return olm_pk_private_key_length();
}
struct OlmPkSigning {
OlmErrorCode last_error;
_olm_ed25519_key_pair key_pair;
};
size_t olm_pk_signing_size(void) {
return sizeof(OlmPkSigning);
}
OlmPkSigning *olm_pk_signing(void * memory) {
olm::unset(memory, sizeof(OlmPkSigning));
return new(memory) OlmPkSigning;
}
const char * olm_pk_signing_last_error(OlmPkSigning * sign) {
auto error = sign->last_error;
return _olm_error_to_string(error);
}
size_t olm_clear_pk_signing(OlmPkSigning *sign) {
/* Clear the memory backing the signing */
olm::unset(sign, sizeof(OlmPkSigning));
/* Initialise a fresh signing object in case someone tries to use it */
new(sign) OlmPkSigning();
return sizeof(OlmPkSigning);
}
size_t olm_pk_sign_seed_length(void) {
return ED25519_RANDOM_LENGTH;
}
size_t olm_pk_sign_public_key_length(void) {
return olm::encode_base64_length(ED25519_PUBLIC_KEY_LENGTH);
}
size_t olm_pk_signing_key_from_seed(
OlmPkSigning * signing,
void * pubkey, size_t pubkey_length,
void * seed, size_t seed_length
) {
if (pubkey_length < olm_pk_sign_public_key_length()) {
signing->last_error =
OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
return std::size_t(-1);
}
if (seed_length < olm_pk_sign_seed_length()) {
signing->last_error =
OlmErrorCode::OLM_INPUT_BUFFER_TOO_SMALL;
return std::size_t(-1);
}
_olm_crypto_ed25519_generate_key((uint8_t *) seed, &signing->key_pair);
olm::encode_base64(
(const uint8_t *)signing->key_pair.public_key.public_key,
ED25519_PUBLIC_KEY_LENGTH,
(uint8_t *)pubkey
);
return 0;
}
size_t olm_pk_signature_length() {
return olm::encode_base64_length(ED25519_SIGNATURE_LENGTH);
}
#include "olm/utility.hh"
size_t olm_pk_sign(
OlmPkSigning *signing,
uint8_t const * message, size_t message_length,
uint8_t * signature, size_t signature_length
) {
if (signature_length < olm_pk_signature_length()) {
signing->last_error = OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
return std::size_t(-1);
}
uint8_t *raw_sig = signature + olm_pk_signature_length() - ED25519_SIGNATURE_LENGTH;
_olm_crypto_ed25519_sign(
&signing->key_pair,
message, message_length, raw_sig
);
olm::encode_base64(raw_sig, ED25519_SIGNATURE_LENGTH, signature);
return olm_pk_signature_length();
}
}
......@@ -162,5 +162,75 @@ assert_equals(plaintext, plaintext_buffer, strlen((const char *)plaintext));
free(ciphertext);
free(plaintext_buffer);
}
{ /* Signing Test Case 1 */
TestCase test_case("Public Key Signing");
std::uint8_t signing_buffer[olm_pk_signing_size()];
OlmPkSigning *signing = olm_pk_signing(signing_buffer);
std::uint8_t seed[32] = {
0x77, 0x07, 0x6D, 0x0A, 0x73, 0x18, 0xA5, 0x7D,
0x3C, 0x16, 0xC1, 0x72, 0x51, 0xB2, 0x66, 0x45,
0xDF, 0x4C, 0x2F, 0x87, 0xEB, 0xC0, 0x99, 0x2A,
0xB1, 0x77, 0xFB, 0xA5, 0x1D, 0xB9, 0x2C, 0x2A
};
//const std::uint8_t *pub_key = (std::uint8_t *) "hSDwCYkwp1R0i33ctD73Wg2/Og0mOBr066SpjqqbTmoK";
char pubkey[olm_pk_sign_public_key_length() + 1];
olm_pk_signing_key_from_seed(
signing,
pubkey, sizeof(pubkey),
seed, sizeof(seed)
);
printf("pubkey: %s\n", pubkey);
char *message = strdup("We hold these truths to be self-evident, that all men are created equal, that they are endowed by their Creator with certain unalienable Rights, that among these are Life, Liberty and the pursuit of Happiness.");
std::uint8_t *sig_buffer = (std::uint8_t *) malloc(olm_pk_signature_length() + 1);
olm_pk_sign(
signing,
(const uint8_t *)message, strlen(message),
sig_buffer, olm_pk_signature_length()
);
printf("sig: %s\n", sig_buffer);
void * utility_buffer = malloc(::olm_utility_size());
::OlmUtility * utility = ::olm_utility(utility_buffer);
size_t result;
result = ::olm_ed25519_verify(
utility,
pubkey, olm_pk_sign_public_key_length(),
message, strlen(message),
sig_buffer, olm_pk_signature_length()
);
assert_equals((size_t)0, result);
sig_buffer[5] = 'm';
result = ::olm_ed25519_verify(
utility,
pubkey, olm_pk_sign_public_key_length(),
message, strlen(message),
sig_buffer, olm_pk_signature_length()
);
assert_equals((size_t)-1, result);
free(message);
free(sig_buffer);
olm_clear_pk_signing(signing);
}
}
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