Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
This repository was archived by the owner on Sep 3, 2020. It is now read-only.

Noise Protocol implementation wrapping noise-c.wasm but with a *slightly* easier API. | Moved tohttps://tcrowe.commons.host/contact

License

NotificationsYou must be signed in to change notification settings

tcrowe/noise-wasm-wrapper

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Handshake, encrypt, and decrypt with noise.

It wrapsnoise-c.wasm into aslightly easier API. Being that it depends on wasm it should work in the browser and nodejs.

The examples use a TCP server but you could use other protocols likeUTP. It just assumes the stream or socket have the.write function so it can handshake. After the handshake you getencrypt anddecrypt methods for the rest.

The hope is that it's a useful and robust module which can be depended on as a fundamental building block for bigger things. Maybe someone who knows how can roll this into a duplex stream module to make it easier.

Usage

In short it's like this:

const{ createKeyPair, createNoise}require("noise-wasm-wrapper");// const socket = (net socket or stream)createKeyPair(function(err,keyPair){createNoise({ keyPair},function({ handshake}){handshake({ socket},function(err,{ encrypt, decrypt}){socket.on("data",chunk=>console.log(decrypt(chunk)));socket.write(encrypt(Buffer.from("encrypt me pls")));});});});

Create key pairs

Create key pairs for the local and remote nodes../examples/create-key-pairs.js

node ./examples/create-key-pairs.js

constfs=require("fs");constpath=require("path");const{ createKeyPair}=require("noise-wasm-wrapper");constinitiatorKeyPairPath=path.join(__dirname,"initiator-keypair.json");constresponderKeyPairPath=path.join(__dirname,"responder-keypair.json");/** * Create a callback that saves the key pair *@method saveKeyPair *@param {string} absolutePath *@returns {function} */functionsaveKeyPair(absolutePath){/**   * Write file   *@method saveKeyPairInner   *@param {object} [err]   *@param {object} [keyPair]   */returnfunctionsaveKeyPairCallback(err,keyPair){if(err!==null&&err!==undefined){console.error("error creating key pair",err);return;}letop=JSON.stringify(keyPair);fs.writeFile(absolutePath,op,function(err){if(err!==null&&err!==undefined){returnconsole.error("error saving key pair",absolutePath,err);}console.log("saved",absolutePath);});};}createKeyPair(saveKeyPair(initiatorKeyPairPath));createKeyPair(saveKeyPair(responderKeyPairPath));

Responder

Create responder socket. The resonder waits until the initiator initiates the handshake../examples/responder.js

node ./examples/responder.js

const{ createServer}=require("net");constisNil=require("lodash/isNil");constnoise=require("../src");constkeyPair=require("./responder-keypair.json");constnoiseOpts={ keyPair};constport=14912;consthost="127.0.0.1";letresponder;letintervals=[];constintervalDelay=500;// time between messages/** * Try to gracefully shutdown so the port doesn't stay active *@method shutdown *@param {number} code */functionshutdown(code=0){// stop the serverif(isNil(responder)===false){try{responder.close();}catch(err){console.error("error closing responder",err);}}// stop timersintervals.forEach(interval=>clearInterval(interval));process.exit(code);}//// 1. Wait for a connection//responder=createServer(function(socket){console.log("responder connection");//// 2. Make some Noise!//noise.createNoise(noiseOpts,function(err,{ handshake}){if(isNil(err)===false){console.error("error creating noise objec",err);returnshutdown(1);}socket.on("error",function(err){console.error("responder socket error",err);});socket.on("close",function(){console.log("responder socket close");});//// 3. Wait for handshake//handshake({ socket},function(err,res){if(isNil(err)===false){console.error("error handshaking socket",err);returnshutdown(1);}//// 4. Send and receive encrypted data//const{ encrypt, decrypt}=res;console.log("responder handshake success");socket.on("data",function(chunk){//// decrypt incoming data//letop=decrypt(chunk);op=Buffer.from(op);op=op.toString();console.log("responder decrypted:",op);});//// Encrypt outgoing data//letcounter=0;constinterval=setInterval(function(){letop=`responder message${counter}`;op=Buffer.from(op);op=encrypt(op);socket.write(op);counter+=1;},intervalDelay);intervals.push(interval);socket.on("close",function(){intervals=intervals.filter(function(item){if(item===interval){clearInterval(interval);returnfalse;}returntrue;});});});});});responder.on("error",function(err){console.error("responder error",err);shutdown(1);});responder.listen(port,host,function(err){if(isNil(err)===false){console.error("error listening",err);returnshutdown(1);}console.log(`responder listening tcp://${host}:${port}`);});

Initiator

Create the initiator and start the handshake with the responder../examples/initiator.js

node ./examples/inititator.js

const{ connect}=require("net");constisNil=require("lodash/isNil");constnoise=require("../src");constkeyPair=require("./initiator-keypair.json");constremotePublicKey=require("./responder-keypair.json").publicKey;constnoiseOpts={mode:"initiator", keyPair, remotePublicKey};constport=14912;consthost="127.0.0.1";letinterval;constintervalDelay=500;// time between messagesletinitiator;/** * Try to gracefully shutdown *@method shutdown *@param {number} code */functionshutdown(code=0){// stop the serverif(isNil(initiator)===false){try{initiator.end();}catch(err){console.error("error closing initiator",err);}}// stop timersif(isNil(interval)===false){clearInterval(interval);}process.exit(code);}//// 1. Make some Noise!//noise.createNoise(noiseOpts,function(err,{ handshake}){if(isNil(err)===false){console.error("error creating noise objec",err);returnshutdown(1);}//// 2. Connect to the responder//initiator=connect({ port, host},function(){console.log("initiator connected");//// 3. Initiate the handshake//handshake({socket:initiator},function(err,res){if(isNil(err)===false){console.error("error handshaking socket",err);returnshutdown(1);}//// 4. Send and receive encrypted data//const{ encrypt, decrypt}=res;console.log("initiator handshake success");initiator.on("data",function(chunk){//// decrypt incoming data//letop=decrypt(chunk);op=Buffer.from(op);op=op.toString();console.log("initiator decrypted:",op);});//// Encrypt outgoing data//letcounter=0;interval=setInterval(function(){letop=`initiator message${counter}`;op=Buffer.from(op);op=encrypt(op);initiator.write(op);counter+=1;},intervalDelay);});});initiator.on("error",function(err){console.error("initiator error",err);shutdown(1);});initiator.on("close",function(){console.log("initiator close");shutdown();});});

API

createKeyPair

The default curve id isNOISE_DH_CURVE25519.

Create the public and private key pair@method createKeyPair@param {string} [curveId]@param {function} done

You can review hekey pair curve id list. At the time of writing this only two work,NOISE_DH_CURVE25519 andNOISE_DH_CURVE448.

const{ createKeyPair}=require("noise-wasm-wrapper");createKeyPair(function(err,keyPair){console.log("err",err);console.log("keyPair",keyPair);});

createNoise

Create the noise object with the configurations for your network.

The callback provides (err, { noise, handshakeState, handshake })

  • {object} error
  • {object} response
  • {object} response.noise
  • {object} response.handshakeState noise wasm handshake object
  • {function} response.handshake

@method createNoise

  • @param {object} opts
  • @param {string} [opts.pattern="XK"]
  • @param {string} [opts.curve="25519"]
  • @param {string} [opts.cipher="ChaChaPoly"]
  • @param {string} [opts.hash="BLAKE2b"]
  • @param {string|buffer} [opts.prologue] shared secret message
  • @param {string|buffer} [opts.psk] pre-shared symmetric key
  • @param {string} [opts.mode="responder"] "initiator" or "responder"
  • @param {object} opts.keyPair
  • @param {array|buffer} opts.keyPair.publicKey
  • @param {array|buffer} opts.keyPair.privateKey
  • @param {array|buffer} [opts.remotePublicKey] required if initiator
  • @param {function} done
const{ createNoise}=require("noise-wasm-wrapper");// get the key pairs// const responderKeyPair = { publicKey: [...], privateKey: [...]}// const initiatorKeyPair = { publicKey: [...], privateKey: [...]}// create responder noise instancecreateNoise({keyPair:responderKeyPair},function({ handshake}){// go handshake the stream});// create initiator noise instancecreateNoise({keyPair:initiatorKeyPair,remotePublicKey:responderKeyPair.publicKey},function({ handshake}){// go handshake the stream});

handshake

Once youcreateNoise you'll get a handshake function. It will listen for or initiate the handshake with the peer.

The callback provides:

  • {object} error
  • {object} response.handshakeState
  • {function} response.encrypt
  • {function} response.decrypt
  • {function} response.getRemotePublicKey
  • {function} response.getHandshakeHash

@method handshake

  • @param {object} options.socket
  • @param {number} [options.maxHandshakeOperations=12]
  • @param {function} done

HandshakeState

cipherStateSend andcipherStateReceive are from aCipherState created by callingHandshakeState.Split().

Development

# clean up coverage files and eslint cachenpm run clean# run for continuous development tasksnpm run dev# run before publishing to ensure tests runnpm run prd# other tasks which can be run individuallynpm run dev-eslintnpm run dev-testnpm runtestnpm run coveragenpm run prd-eslint

Todo

  • Possibly bugs out if trying to send data too quickly after the handshake
  • PSK(pre-shared symmetric key) feature withSymmetricState
  • It should be determined when we should callfree() if needed as well.
  • getRemotePublicKey implemented, not tested
  • getHandshakeHash implemented, not tested

Copying, license, and contributing

Copyright (C) Tony Crowegithub@tonycrowe.com (https://tcrowe.github.io) 2018

Thank you for using and contributing to make noise-wasm-wrapper better.

⚠️ Please runnpm run prd before submitting a patch.

⚖️ noise-wasm-wrapper is Free Software protected by the GPL 3.0 license. See./COPYING for more information. (free as in freedom)

About

Noise Protocol implementation wrapping noise-c.wasm but with a *slightly* easier API. | Moved tohttps://tcrowe.commons.host/contact

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp