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

forward-secrecy

v1.0.2

Published

Javascript implementation of the Axolotl key-ratcheting protocol using the NaCl crypto library

Downloads

4

Readme

Overview

forward-secrecy is a simple implementation of the Axolotl key-ratcheting protocol written in Javascript. It uses NaCl (in this case, TweetNacl) for encryption, meaning sessions are secured with Curve25519 keys and Salsa20 encryption.

The primary goal of this project is to have a simple, easy-to-understand implementation of the ratcheting protocol so that developers can easily understand how the internals work. As such, the entirety of the protocol implementation code is contained in one thoroughly-commented file.

This library does not handle pre-key generation and other things necessary for a fully turnkey solution. If you're looking for such things, check out a much more complete implementation of Axolotl:

https://github.com/joebandenburg/libaxolotl-javascript

forward-secrecy deals strictly with only the code necessary for the protocol itself to work. Some knowledge of how asymmetric crypto systems work is assumed. In the interest of keeping the code concise, you are expected to handle key storage, transmission, and creation yourself.

This library has not been audited, meaning that it is absolutely unsafe to use for any real security. You have been warned.

Installation

Simply install the library with NPM:

npm install forward-secrecy

And then require the project:

var SecretSession = require('forward-secrecy')

This is compatible with browsers using tools such as browserify or webpack.

Usage

This library implements the no-header-keys, role-select version of Axolotl. Meaning, headers are not encrypted, and when setting up a session, you must explicitely set your role as the initiator or the receiver.

It also depends on TweetNacl's implementation of keypairs for all keys.

The hardest part about using this library for beginners will be understanding key generation, transmission, and which keys to use where.

Example:

var aliceSession = new SecretSession();

aliceSession
    .identity(YOUR_IDENTITY_KEYS)
    .handshake(YOUR_HANDSHAKE_KEYS)
    .theirIdentity(OTHER_PARTY_IDENTITY.publicKey)
    .theirHandshake(OTHER_PARTY_HANDSHAKE.publicKey)
    .setRole('initiator')
    .computeMasterKey()
    .then(function () { console.log('ready!'); })

YOUR_IDENTITY_KEYS should be a NaCl keypair created from TweetNacl, which you should store securely and keep indefinitely.

YOUR_HANDSHAKE_KEYS are a temporary key set (commonly called pre-keys) which are used to setup the session. These also need to be stored securely, but can be safely discarded after the session has been setup.

OTHER_PARTY_IDENTITY is the other party's identity public key, which ensures the identity of the remote party. This key needs to be obtained in a secure, trusted manner, and held indefinitely. There will be no security at all in the protocol if this key is not obtained safely.

OTHER_PARTY_HANDSHAKE is the other party's handshake key, which allows you to setup a new session with the other party. This key also should be obtained securely, but doesn't need strict verification, because if it is not one the other party controls, the handshake will fail AS LONG AS THEIR IDENTITY KEY IS TRUSTED. If the identity key is compromised, another party could easily perform a man-in-the-middle attack.

In order for the receiver to start communicating, the initiator must first send their handshake public key to the receiving party, as well as inform them of which of the receiver's public handshake keys they used to setup the session so that the reciever will pick the right handshake key pair.

var bobSession = new SecretSession();

bobSession
    .identity(YOUR_IDENTITY_KEYS)
    .handshake(YOUR_HANDSHAKE_KEYS)
    .theirIdentity(OTHER_PARTY_IDENTITY.publicKey)
    .theirHandshake(OTHER_PARTY_HANDSHAKE.publicKey)
    .setRole('receiver')
    .computeMasterKey()
    .then(function () { console.log('ready!'); })

If everything is done correctly, you will now be able to exchange messages using the encrypt() and decrypt() methods.

Example:

aliceSession.encrypt('Hello Bob!').then(function (encryptedMessage) {
	bobSession.decrypt(encryptedMessage).then(function (result) {
		// result.cleartext should equal "Hello Bob!"
	})
})

That's it! Easy, right?

If you'd like to be able to resume these sessions at a later time, simply pass a storage function to the session:

aliceSession.storage(function (data, callback) {
	// Note that the session object is highly sensitive, and should be encrypted! Not stored in plaintext like we are doing here.
	localStorage['session'] = JSON.stringify(data)
	
	// Callback on success.
	callback()
})

Then, when you'd like to resume a session, you can simply setup a new session and call resume() on it with the data you saved:

aliceSession = new SecretSession().resume(JSON.parse(localStorage['session']))

It bears repeating: The session object is highly sensitive! Do not save it to disk or other locations without first encrypting it using another method.