Add signing class to the pk module
This commit is contained in:
parent
45091c158d
commit
8df2ab7c07
7 changed files with 320 additions and 5 deletions
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright 2018 New Vector Ltd
|
/* Copyright 2018, 2019 New Vector Ltd
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#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["Utility"] = Utility;
|
||||||
olm_exports["PkEncryption"] = PkEncryption;
|
olm_exports["PkEncryption"] = PkEncryption;
|
||||||
olm_exports["PkDecryption"] = PkDecryption;
|
olm_exports["PkDecryption"] = PkDecryption;
|
||||||
|
olm_exports["PkSigning"] = PkSigning;
|
||||||
olm_exports["SAS"] = SAS;
|
olm_exports["SAS"] = SAS;
|
||||||
|
|
||||||
olm_exports["get_library_version"] = restore_stack(function() {
|
olm_exports["get_library_version"] = restore_stack(function() {
|
||||||
|
|
|
@ -34,7 +34,6 @@ describe("olm", function() {
|
||||||
beforeEach(function(done) {
|
beforeEach(function(done) {
|
||||||
// This should really be in a beforeAll, but jasmine-node
|
// This should really be in a beforeAll, but jasmine-node
|
||||||
// doesn't support that
|
// doesn't support that
|
||||||
debugger;
|
|
||||||
Olm.init().then(function() {
|
Olm.init().then(function() {
|
||||||
aliceAccount = new Olm.Account();
|
aliceAccount = new Olm.Account();
|
||||||
bobAccount = new Olm.Account();
|
bobAccount = new Olm.Account();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2018 New Vector Ltd
|
Copyright 2018, 2019 New Vector Ltd
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with 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');
|
var Olm = require('../olm');
|
||||||
|
|
||||||
describe("pk", function() {
|
describe("pk", function() {
|
||||||
var encryption, decryption;
|
var encryption, decryption, signing;
|
||||||
|
|
||||||
beforeEach(function(done) {
|
beforeEach(function(done) {
|
||||||
Olm.init().then(function() {
|
Olm.init().then(function() {
|
||||||
encryption = new Olm.PkEncryption();
|
encryption = new Olm.PkEncryption();
|
||||||
decryption = new Olm.PkDecryption();
|
decryption = new Olm.PkDecryption();
|
||||||
|
signing = new Olm.PkSigning();
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -39,6 +40,10 @@ describe("pk", function() {
|
||||||
decryption.free();
|
decryption.free();
|
||||||
decryption = undefined;
|
decryption = undefined;
|
||||||
}
|
}
|
||||||
|
if (signing !== undefined) {
|
||||||
|
signing.free();
|
||||||
|
signing = undefined;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should import & export keys from private parts', function () {
|
it('should import & export keys from private parts', function () {
|
||||||
|
@ -89,4 +94,29 @@ describe("pk", function() {
|
||||||
expect(decrypted).toEqual(TEST_TEXT);
|
expect(decrypted).toEqual(TEST_TEXT);
|
||||||
new_decryption.free();
|
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();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
86
src/pk.cpp
86
src/pk.cpp
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright 2018 New Vector Ltd
|
/* Copyright 2018, 2019 New Vector Ltd
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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();
|
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(ciphertext);
|
||||||
free(plaintext_buffer);
|
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue