From 8df2ab7c07938c3bb24f6b44b8615f8371c0048b Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 29 Jan 2019 20:47:41 +0000 Subject: Add signing class to the pk module --- javascript/olm_pk.js | 89 +++++++++++++++++++++++++++++++++++++++++++++ javascript/olm_post.js | 1 + javascript/test/olm.spec.js | 1 - javascript/test/pk.spec.js | 34 ++++++++++++++++- 4 files changed, 122 insertions(+), 3 deletions(-) (limited to 'javascript') diff --git a/javascript/olm_pk.js b/javascript/olm_pk.js index 81dbad4..9159fbf 100644 --- a/javascript/olm_pk.js +++ b/javascript/olm_pk.js @@ -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); + } + } +}); diff --git a/javascript/olm_post.js b/javascript/olm_post.js index 3bf0d66..a3a3ef4 100644 --- a/javascript/olm_post.js +++ b/javascript/olm_post.js @@ -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() { diff --git a/javascript/test/olm.spec.js b/javascript/test/olm.spec.js index 77dd712..a698314 100644 --- a/javascript/test/olm.spec.js +++ b/javascript/test/olm.spec.js @@ -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(); diff --git a/javascript/test/pk.spec.js b/javascript/test/pk.spec.js index b4b119e..f212b96 100644 --- a/javascript/test/pk.spec.js +++ b/javascript/test/pk.spec.js @@ -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"); 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(); + }); }); -- cgit v1.2.3