@richardhopton/noise-c.wasm
Version:
rweather/noise-c compiled to WebAssembly using Emscripten and optimized for small size
672 lines (671 loc) • 24.8 kB
JavaScript
// Generated by LiveScript 1.6.0
/**
* @package noise-c.wasm
* @author Nazar Mokrynskyi <nazar@mokrynskyi.com>
* @license 0BSD
*/
(function(){
var random_bytes;
if (typeof crypto !== 'undefined') {
/**
* @param {number} size
*
* @return {!Uint8Array}
*/
random_bytes = function(size){
var array;
array = new Uint8Array(size);
crypto.getRandomValues(array);
return array;
};
} else {
/**
* @param {string} size
*
* @return {!Uint8Array}
*/
random_bytes = require('crypto').randomBytes;
}
function CreateLib(lib, constants, arg1, arg2){
var options, callback, allocate, allocate_pointer;
options = typeof arg1 === 'function' ? {} : arg1;
callback = arg2 || arg1;
if (typeof callback !== 'function') {
throw new TypeError('noise-c.wasm: Callback is not a function');
}
lib(options).then(lib => {
lib['_random_bytes'] = random_bytes;
allocate = lib['allocateBytes'];
allocate_pointer = lib['allocatePointer'];
function allocate_buffer(data, size){
var tmp, buffer;
tmp = allocate_pointer();
lib._NoiseBuffer_create(tmp, data, size, data.length);
buffer = tmp.dereference();
tmp.free();
return buffer;
}
function assert_no_error(error, object_to_free){
var key, ref$, code;
if (error === constants.NOISE_ERROR_NONE) {
return;
}
for (key in ref$ = constants) {
code = ref$[key];
if (code === error) {
if (object_to_free) {
try {
object_to_free.free();
} catch (e$) {}
}
throw new Error(key);
}
}
}
/**
* Create a new X25519 or X448 keypair
*
* @param {number} curve_id constants.NOISE_DH_CURVE25519 or constants.NOISE_DH_CURVE448
*
* @return {!Uint8Array[]} `[private_key, public_key]`
*
* @throws {TypeError} In case incorrect `curve_id` specified
*/
function CreateKeyPair(curve_id){
var tmp, error, dh, e, key_length, private_buffer, public_buffer, private_key, public_key;
if (!(curve_id === constants.NOISE_DH_CURVE448 || curve_id === constants.NOISE_DH_CURVE25519)) {
throw new TypeError('Invalid keypair type');
}
tmp = allocate_pointer();
error = lib._noise_dhstate_new_by_id(tmp, curve_id);
assert_no_error(error, tmp);
dh = tmp.dereference();
tmp.free();
error = lib._noise_dhstate_generate_keypair(dh);
try {
assert_no_error(error);
} catch (e$) {
e = e$;
lib._noise_dhstate_free(dh);
throw e;
}
if (curve_id === constants.NOISE_DH_CURVE448) {
key_length = 56;
} else {
key_length = 32;
}
private_buffer = allocate(key_length);
public_buffer = allocate(key_length);
error = lib._noise_dhstate_get_keypair(dh, private_buffer, private_buffer.length, public_buffer, public_buffer.length);
lib._noise_dhstate_free(dh);
try {
assert_no_error(error);
private_key = private_buffer.get();
private_buffer.free();
public_key = public_buffer.get();
public_buffer.free();
return [private_key, public_key];
} catch (e$) {
e = e$;
private_buffer.free();
public_buffer.free();
throw e;
}
}
/**
* The CipherState object, API is close to the spec: http://noiseprotocol.org/noise.html#the-cipherstate-object
*
* NOTE: If you ever get an exception with Error object, whose message is one of constants.NOISE_ERROR_* keys, object is no longer usable and there is no need
* to call free() method, as it was called for you automatically already (except in EncryptWithAd and DecryptWithAd)
*
* @param {string} cipher constants.NOISE_CIPHER_CHACHAPOLY, constants.NOISE_CIPHER_AESGCM, etc.
*/
function CipherState(cipher){
var tmp, error;
if (!(this instanceof CipherState)) {
return new CipherState(cipher);
}
tmp = allocate_pointer();
error = lib._noise_cipherstate_new_by_id(tmp, cipher);
assert_no_error(error, tmp);
this._state = tmp.dereference();
this._mac_length = lib._noise_cipherstate_get_mac_length(this._state);
tmp.free();
}
CipherState.prototype = {
/**
* @param {Uint8Array} key
*/
InitializeKey: function(key){
var error;
key = allocate(0, key);
error = lib._noise_cipherstate_init_key(this._state, key, key.length);
key.free();
assert_no_error(error, this);
},
HasKey: function(){
return lib._noise_cipherstate_has_key(this._state) === 1;
}
/**
* @param {number} nonce
*/,
SetNonce: function(nonce){
var error;
error = lib._noise_cipherstate_set_nonce(this._state, nonce);
assert_no_error(error, this);
}
/**
* @param {Uint8Array} ad
* @param {Uint8Array} plaintext
*
* @return {Uint8Array}
*/,
EncryptWithAd: function(ad, plaintext){
var buffer, error, ciphertext;
ad = allocate(0, ad);
plaintext = allocate(plaintext.length + this._mac_length, plaintext);
buffer = allocate_buffer(plaintext, plaintext.length - this._mac_length);
error = lib._noise_cipherstate_encrypt_with_ad(this._state, ad, ad.length, buffer);
ciphertext = plaintext.get();
ad.free();
plaintext.free();
buffer.free();
assert_no_error(error);
return ciphertext;
}
/**
* @param {Uint8Array} ad
* @param {Uint8Array} ciphertext
*
* @return {Uint8Array}
*/,
DecryptWithAd: function(ad, ciphertext){
var buffer, error, plaintext;
ad = allocate(0, ad);
ciphertext = allocate(0, ciphertext);
buffer = allocate_buffer(ciphertext, ciphertext.length);
error = lib._noise_cipherstate_decrypt_with_ad(this._state, ad, ad.length, buffer);
plaintext = ciphertext.get().slice(0, ciphertext.length - this._mac_length);
ad.free();
ciphertext.free();
buffer.free();
assert_no_error(error);
return plaintext;
}
/**
* @return {boolean}
*/,
Rekey: function(){
throw 'Not implemented';
}
/**
* Call this when object is not needed anymore to avoid memory leaks
*/,
free: function(){
var error;
error = lib._noise_cipherstate_free(this._state);
delete this._state;
delete this._mac_length;
assert_no_error(error);
}
};
Object.defineProperty(CipherState.prototype, 'constructor', {
enumerable: false,
value: CipherState
});
function CipherState_split(state){
this._state = state;
this._mac_length = lib._noise_cipherstate_get_mac_length(this._state);
}
CipherState_split.prototype = Object.create(CipherState.prototype);
Object.defineProperty(CipherState_split.prototype, 'constructor', {
enumerable: false,
value: CipherState_split
});
/**
* The SymmetricState object, API is close to the spec: http://noiseprotocol.org/noise.html#the-symmetricstate-object
*
* NOTE: If you ever get an exception with Error object, whose message is one of constants.NOISE_ERROR_* keys, object is no longer usable and there is no need
* to call free() method, as it was called for you automatically already
*
* @param {string} protocol_name The name of the Noise protocol to use, for instance, Noise_N_25519_ChaChaPoly_BLAKE2b
*/
function SymmetricState(protocol_name){
var tmp, error, this$ = this;
if (!(this instanceof SymmetricState)) {
return new SymmetricState(protocol_name);
}
tmp = allocate_pointer();
protocol_name = allocate(0, protocol_name);
error = lib._noise_symmetricstate_new_by_name(tmp, protocol_name);
assert_no_error(error, tmp);
this._state = tmp.dereference();
tmp.free();
protocol_name.free();
Object.defineProperty(this, '_mac_length', {
configurable: true,
get: function(){
var mac_length;
mac_length = lib._noise_symmetricstate_get_mac_length(this$._state);
if (mac_length > 0) {
this$._mac_length = mac_length;
}
return mac_length;
}
});
}
SymmetricState.prototype = {
/**
* @param {Uint8Array} input_key_material
*/
MixKey: function(input_key_material){
var error;
input_key_material = allocate(0, input_key_material);
error = lib._noise_symmetricstate_mix_key(this._state, input_key_material, input_key_material.length);
input_key_material.free();
assert_no_error(error, this);
}
/**
* @param {Uint8Array} data
*/,
MixHash: function(data){
var error;
data = allocate(0, data);
error = lib._noise_symmetricstate_mix_hash(this._state, data, data.length);
data.free();
assert_no_error(error, this);
}
/**
* @param {Uint8Array} input_key_material
*/,
MixKeyAndHash: function(input_key_material){
var tmp, length, ck, data;
this.MixKey(input_key_material);
tmp = allocate_pointer();
length = lib._SymmetricState_get_ck(this._state, tmp);
ck = tmp.dereference(length);
tmp.free();
data = ck.get();
ck.free();
this.MixHash(data);
}
/**
* @param {Uint8Array} plaintext
*
* @return {Uint8Array}
*/,
EncryptAndHash: function(plaintext){
var buffer, error, ciphertext;
plaintext = allocate(plaintext.length + this._mac_length, plaintext);
buffer = allocate_buffer(plaintext, plaintext.length - this._mac_length);
error = lib._noise_symmetricstate_encrypt_and_hash(this._state, buffer);
ciphertext = plaintext.get();
plaintext.free();
buffer.free();
assert_no_error(error, this);
return ciphertext;
}
/**
* @param {Uint8Array} ciphertext
*
* @return {Uint8Array}
*/,
DecryptAndHash: function(ciphertext){
var buffer, error, plaintext;
ciphertext = allocate(0, ciphertext);
buffer = allocate_buffer(ciphertext, ciphertext.length);
error = lib._noise_symmetricstate_decrypt_and_hash(this._state, buffer);
plaintext = ciphertext.get().slice(0, ciphertext.length - this._mac_length);
ciphertext.free();
buffer.free();
assert_no_error(error, this);
return plaintext;
}
/**
* @return {CipherState[]}
*/,
Split: function(){
var tmp1, tmp2, error, e, cs1, cs2;
tmp1 = allocate_pointer();
tmp2 = allocate_pointer();
error = lib._noise_symmetricstate_split(this._state, tmp1, tmp2);
try {
assert_no_error(error);
} catch (e$) {
e = e$;
tmp1.free();
tmp2.free();
throw e;
}
cs1 = new CipherState_split(tmp1.dereference());
cs2 = new CipherState_split(tmp2.dereference());
tmp1.free();
tmp2.free();
try {
this.free();
} catch (e$) {
e = e$;
try {
cs1.free();
} catch (e$) {}
try {
cs2.free();
} catch (e$) {}
throw e;
}
return [cs1, cs2];
}
/**
* Call this when object is not needed anymore to avoid memory leaks
*/,
free: function(){
var error;
error = lib._noise_symmetricstate_free(this._state);
delete this._state;
delete this._mac_length;
assert_no_error(error);
}
};
Object.defineProperty(SymmetricState.prototype, 'constructor', {
enumerable: false,
value: SymmetricState
});
/**
* The HandshakeState object, API is close to the spec: http://noiseprotocol.org/noise.html#the-handshakestate-object
*
* NOTE: If you ever get an exception with Error object, whose message is one of constants.NOISE_ERROR_* keys, object is no longer usable and there is no need
* to call free() method, as it was called for you automatically already (except in ReadMessage with fallback_supported == true)
*
* @param {string} protocol_name The name of the Noise protocol to use, for instance, Noise_N_25519_ChaChaPoly_BLAKE2b
* @param {number} role The role for the new object, either constants.NOISE_ROLE_INITIATOR or constants.NOISE_ROLE_RESPONDER
*/
function HandshakeState(protocol_name, role){
var tmp, error;
if (!(this instanceof HandshakeState)) {
return new HandshakeState(protocol_name, role);
}
tmp = allocate_pointer();
protocol_name = allocate(0, protocol_name);
error = lib._noise_handshakestate_new_by_name(tmp, protocol_name, role);
protocol_name.free();
assert_no_error(error, tmp);
this._state = tmp.dereference();
tmp.free();
}
HandshakeState.prototype = {
/**
* Must be called after object creation and after switch to a fallback handshake.
*
* In case of fallback handshake it is not required to specify values that are the same as in previous Initialize() call, those will be used by default
*
* @param {null|Uint8Array} prologue Prologue value
* @param {null|Uint8Array} s Local static private key
* @param {null|Uint8Array} rs Remote static public key
* @param {null|Uint8Array} psk Pre-shared symmetric key
*/
Initialize: function(prologue, s, rs, psk){
var error, dh;
prologue == null && (prologue = null);
s == null && (s = null);
rs == null && (rs = null);
psk == null && (psk = null);
if (prologue) {
prologue = allocate(0, prologue);
error = lib._noise_handshakestate_set_prologue(this._state, prologue, prologue.length);
prologue.free();
assert_no_error(error, this);
}
if (psk && lib._noise_handshakestate_needs_pre_shared_key(this._state) === 1) {
psk = allocate(0, psk);
error = lib._noise_handshakestate_set_pre_shared_key(this._state, psk, psk.length);
psk.free();
assert_no_error(error, this);
}
if (lib._noise_handshakestate_needs_local_keypair(this._state) === 1) {
if (!s) {
throw new Error('Local static private key (s) required, but not provided');
}
dh = lib._noise_handshakestate_get_local_keypair_dh(this._state);
s = allocate(0, s);
error = lib._noise_dhstate_set_keypair_private(dh, s, s.length);
s.free();
assert_no_error(error, this);
}
if (lib._noise_handshakestate_needs_remote_public_key(this._state) === 1) {
if (!rs) {
throw new Error('Remote static public key (rs) required, but not provided');
}
dh = lib._noise_handshakestate_get_remote_public_key_dh(this._state);
rs = allocate(0, rs);
error = lib._noise_dhstate_set_public_key(dh, rs, rs.length);
rs.free();
assert_no_error(error, this);
}
error = lib._noise_handshakestate_start(this._state);
assert_no_error(error, this);
}
/**
* @return {number} One of constants.NOISE_ACTION_*
*/,
GetAction: function(){
return lib._noise_handshakestate_get_action(this._state);
}
/**
* Might be called when GetAction() returned constants.NOISE_ACTION_FAILED and switching to fallback protocol is desired, don't forget to call Initialize()
* after FallbackTo()
*
* @param {number} pattern_id One of constants.NOISE_PATTERN_*_FALLBACK*
*/,
FallbackTo: function(pattern_id){
var error;
pattern_id == null && (pattern_id = constants.NOISE_PATTERN_XX_FALLBACK);
error = lib._noise_handshakestate_fallback_to(this._state, pattern_id);
assert_no_error(error, this);
}
/**
* @param {null|Uint8Array} payload null if no payload is required
*
* @return {Uint8Array} Message that should be sent to the other side
*/,
WriteMessage: function(payload){
var message, message_buffer, payload_buffer, error, e, message_length, real_message;
payload == null && (payload = null);
message = allocate(constants.NOISE_MAX_PAYLOAD_LEN);
message_buffer = allocate_buffer(message, 0);
payload_buffer = null;
if (payload) {
payload = allocate(0, payload);
payload_buffer = allocate_buffer(payload, payload.length);
}
error = lib._noise_handshakestate_write_message(this._state, message_buffer, payload_buffer);
if (payload) {
payload.free();
payload_buffer.free();
}
try {
assert_no_error(error, this);
} catch (e$) {
e = e$;
message.free();
message_buffer.free();
throw e;
}
message_length = lib._NoiseBuffer_get_size(message_buffer);
real_message = message.get().slice(0, message_length);
message.free();
message_buffer.free();
return real_message;
}
/**
* @param {Uint8Array} message Message received from the other side
* @param {boolean} payload_needed false if the application does not need the message payload
* @param {boolean} fallback_supported true if application is ready to switch to fallback pattern (will throw, but without free() call on read failure)
*
* @return {null|Uint8Array}
*/,
ReadMessage: function(message, payload_needed, fallback_supported){
var message_buffer, payload_buffer, payload, error, e, real_payload, payload_length;
payload_needed == null && (payload_needed = false);
fallback_supported == null && (fallback_supported = false);
message = allocate(0, message);
message_buffer = allocate_buffer(message, message.length);
payload_buffer = null;
if (payload_needed) {
payload = allocate(constants.NOISE_MAX_PAYLOAD_LEN);
payload_buffer = allocate_buffer(payload, payload.length);
}
error = lib._noise_handshakestate_read_message(this._state, message_buffer, payload_buffer);
message.free();
message_buffer.free();
try {
assert_no_error(error, fallback_supported ? undefined : this);
} catch (e$) {
e = e$;
if (payload_needed) {
payload.free();
payload_buffer.free();
}
throw e;
}
real_payload = null;
if (payload_needed) {
payload_length = lib._NoiseBuffer_get_size(payload_buffer);
real_payload = payload.get().slice(0, payload_length);
payload.free();
payload_buffer.free();
}
return real_payload;
}
/**
* @return {CipherState[]} [send, receive]
*/,
Split: function(){
var tmp1, tmp2, error, e, cs1, cs2;
tmp1 = allocate_pointer();
tmp2 = allocate_pointer();
error = lib._noise_handshakestate_split(this._state, tmp1, tmp2);
try {
assert_no_error(error, this);
} catch (e$) {
e = e$;
tmp1.free();
tmp2.free();
throw e;
}
cs1 = new CipherState_split(tmp1.dereference());
cs2 = new CipherState_split(tmp2.dereference());
tmp1.free();
tmp2.free();
try {
this.free();
} catch (e$) {
e = e$;
try {
cs1.free();
} catch (e$) {}
try {
cs2.free();
} catch (e$) {}
throw e;
}
return [cs1, cs2];
}
/**
* Gets the channel binding has if the handshake is completed otherwise throws `Error`
*
* @return {Uint8Array}
*
* @throws {Error}
*/,
GetHandshakeHash: function(){
var hash_buffer, error, hs_id, real_hash, e;
hash_buffer = allocate(64);
error = lib._noise_handshakestate_get_handshake_hash(this._state, hash_buffer, hash_buffer.length);
try {
assert_no_error(error);
hs_id = lib._NoiseHandshakeState_get_hash_id(this._state);
switch (hs_id) {
case constants.NOISE_HASH_BLAKE2s:
case constants.NOISE_HASH_SHA256:
real_hash = hash_buffer.get().slice(0, 32);
break;
case constants.NOISE_HASH_BLAKE2b:
case constants.NOISE_HASH_SHA512:
real_hash = hash_buffer.get();
break;
default:
throw new Error("invalid hash id:" + hs_id);
}
hash_buffer.free();
hash_buffer = null;
} catch (e$) {
e = e$;
hash_buffer.free();
hash_buffer = null;
throw e;
}
return real_hash;
}
/**
* Gets raw remote static public key if available
*
* @return {Uint8Array} `null` if not available
*/,
GetRemotePublicKey: function(){
var dhs, key_length, key_buffer, error, real_key, e;
if (lib._noise_handshakestate_has_remote_public_key(this._state)) {
dhs = lib._noise_handshakestate_get_remote_public_key_dh(this._state);
key_length = lib._noise_dhstate_get_public_key_length(dhs);
if (key_length) {
key_buffer = allocate(key_length);
error = lib._noise_dhstate_get_public_key(dhs, key_buffer, key_length);
dhs = null;
try {
assert_no_error(error);
real_key = key_buffer.get();
key_buffer.free();
return real_key;
} catch (e$) {
e = e$;
key_buffer.free();
throw e;
}
}
}
return null;
}
/**
* Call this when object is not needed anymore to avoid memory leaks
*/,
free: function(){
var error;
error = lib._noise_handshakestate_free(this._state);
delete this._state;
assert_no_error(error);
}
};
Object.defineProperty(HandshakeState.prototype, 'constructor', {
enumerable: false,
value: HandshakeState
});
callback({
'constants': constants,
'CipherState': CipherState,
'SymmetricState': SymmetricState,
'HandshakeState': HandshakeState,
'CreateKeyPair': CreateKeyPair,
'_lib_internal': lib
});
});
}
function Wrapper(lib, constants){
return CreateLib.bind(this, lib, constants);
}
if (typeof define === 'function' && define['amd']) {
define(['./noise-c', './constants'], Wrapper);
} else if (typeof exports === 'object') {
module.exports = Wrapper(require('./noise-c'), require('./constants'));
} else {
this['noise_c_wasm'] = Wrapper(this['__noise_c_wasm'], this['__noise_c_wasm_constants']);
}
}).call(this);