npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

noise-protocol

v3.0.2

Published

Javascript implementation of the Noise Protocol Framework based on libsodium

Downloads

643

Readme

noise-protocol

Build Status

Javascript implementation of the Noise Protocol Framework based on libsodium

:rotating_light: :warning: :rotating_light: BETA :rotating_light: :warning: :rotating_light:

Note that this implementation is low level and requires knowledge of the Noise Protocol Framework, and is aimed to be a building block for higher-level modules wishing to implement application-specific handshakes securely.

This module only implements the Noise_*_25519_ChaChaPoly_BLAKE2b handshake, meaning Curve25519 for DH, ChaCha20Poly1305 for AEAD and BLAKE2b for hashing.

Usage

var noise = require('noise-protocol')

var sClient = noise.keygen()
var sServer = noise.keygen()

// Initialize a Noise_KK_25519_ChaChaPoly_BLAKE2b handshake
var client = noise.initialize('KK', true, Buffer.alloc(0), sClient, null, sServer.publicKey)
var server = noise.initialize('KK', false, Buffer.alloc(0), sServer, null, sClient.publicKey)

var clientTx = Buffer.alloc(128)
var serverTx = Buffer.alloc(128)

var clientRx = Buffer.alloc(128)
var serverRx = Buffer.alloc(128)

// -> e, es, ss
noise.writeMessage(client, Buffer.alloc(0), clientTx)
noise.readMessage(server, clientTx.subarray(0, noise.writeMessage.bytes), serverRx)

// <- e, ee, se
var serverSplit = noise.writeMessage(server, Buffer.alloc(0), serverTx)
var clientSplit = noise.readMessage(client, serverTx.subarray(0, noise.writeMessage.bytes), clientRx)

// Safely dispose of finished HandshakeStates
noise.destroy(client)
noise.destroy(server)

// Can now do transport encryption with splits
console.log(serverSplit)
console.log(clientSplit)

API

Constants

  • noise.PKLEN length of a public key in bytes
  • noise.SKLEN length of a secret key in bytes

Supported Patterns

All one-way and fundamental handshake patterns are currently supported:

  • N
  • K
  • X
  • NN
  • KN
  • NK
  • KK
  • NX
  • KX
  • XN
  • IN
  • XK
  • IK
  • XX
  • IX

var handshakeState = noise.initialize(handshakePattern, initiator, prologue, [staticKeys], [ephemeralKeys], [remoteStaticKey], [remoteEphemeralKey])

Create a new Noise handshake instance with:

  • handshakePattern must be String and one of supported patterns
  • initiator must be Boolean
  • prologue must be Buffer. This can be an empty Buffer (Buffer.alloc(0)) if not used
  • staticKeys is local static keys as an object of {publicKey, secretKey}. This is only required if the handshake pattern mandates these as shared out of band (premessages)
  • ephemeralKeys is local ephemeral keys as an object of {publicKey, secretKey}. This is only required if the handshake pattern mandates these as shared out of band (premessages)
  • remoteStaticKey is a Buffer of PKLEN bytes. This is most likely not required
  • remoteEphemeralKey is a Buffer of PKLEN bytes. This is most likely not required

:alert: Key material passed in is copied into libsodium Secure Buffers, which can be cleared with noise.destroy(state). Be aware that you manually have to destroy this state object, unless you want to rely on GC clearing it for you.

Returns a HandshakeState object, which should be treated as an opaque object. This state is passed as the first argument to subsequent noise functions.

var maybeSplit = noise.writeMessage(state, payload, messageBuffer)

Process a new message pattern and write any output to be transmitted to the receiving party into messageBuffer. Any payload data can be passed as payload, or the empty Buffer in case of no payload.

  • state must be a HandshakeState as returned by noise.initialize
  • payload must be Buffer. Use the empty Buffer (Buffer.alloc(0)) in case of no payload. Whether it is safe to send a payload at a specific step of the handshake is at the discretion of the user. Please refer to Noise - 7.3. Handshake pattern validity
  • messageBuffer must be Buffer. In the worst case it requires PKLEN + PKLEN + MACLEN (32 + 32 + 16) bytes, for a two keys and a MAC, plus any bytes required for payload.byteLength + MACLEN (MACLEN = 16)

If no more message patterns are left to process, a Split will occur. Please see below for details. If more patterns are pending, nothing is returned.

The function may throw an error if:

  • There are no more message patterns to be processed (meaning a split already occurred)
  • The current state expects a message to be read and not written
  • The HandshakeState is invalid for the current message pattern
  • messageBuffer is too small to contain the required data
  • An encryption error occurred

In any of these cases there was a misuse and the HandshakeState should be noise.destroyed and connection aborted.

noise.writeMessage.bytes

This property is set after noise.writeMessage has been successfully executed and signals how many bytes were written to messageBuffer

var maybeSplit = noise.readMessage(state, message, payloadBuffer)

Process a new message pattern and read any input received from message. Any remaining data in message is treated as payload data and will be decrypted (depending on the HandshakeState) and written to payloadBuffer.

  • state must be a HandshakeState as returned by noise.initialize
  • message must be a Buffer, as produced by noise.writeMessage. Any framing or length information is left to the application as described in the Noise Specification.
  • payloadBuffer must be Buffer. Use the empty Buffer (Buffer.alloc(0)) if no payload is expected, though this may throw an error if a payload is attempted written

If no more message patterns are left to process, a Split will occur. Please see below for details. If more patterns are pending, nothing is returned.

The function may throw an error if:

  • There are no more message patterns to be processed (meaning a split already occurred)
  • The current state expects a message to be written and not read
  • The HandshakeState is invalid for the current message pattern
  • payloadBuffer is too small for the required data
  • An decryption error occurred

In any of these cases there was a misuse and the HandshakeState should be noise.destroyed and connection aborted.

noise.readMessage.bytes

This property is set after noise.readMessage has been successfully executed and signals how many bytes were written to payloadBuffer

noise.destroy(state)

Takes a HandshakeState and destroys all internal data (eg. securely zeros out data contained in Buffer-like objects and resets state). Use this to dispose of state objects after a split has occurred or upon error

Split

If no more message patterns are left to process, a Split will occur, as described in the Noise Specification. In this implementation an object with {tx: Buffer, rx: Buffer} will be returned, each being a sodium-native Secure Buffer containing a cipher state as a contiguous piece of memory. It is encoded as 32 byte k | 8 byte n, as describe in the Noise Specification. You can either choose to use these Buffers with the cipherState functions or extract values and use with another transport encryption, as long as you are aware of the security implication of either choice. For initiator and responder, tx and rx are opposite so a responders rx is equal to an initiators tx.

Custom algorithms

You can customise the handshake state by calling noise.createHandshake(algs) with algs = { dh, hash, cipher, cipherState, symmetricState }. Please refer to the respective implementations in the source to see how to swap pieces. Please note that this is dangerous, unless you've read the noise specification very carefully and know what you are doing. createHandshake will then return a new initialize function from which you can create start handshakes with your custom algorithms.

Install

npm install noise-protocol

Deviations from the Noise specification

  • Functions follow the fn(state, output, args...) convention
  • Names the 16 bytes for an authentication tag as MACLEN

Unsupported features

  • Any other cryptographic primitives than the ones mentioned above
  • PSK, fallback and deferred patterns. Support may be added at a later time

License

ISC