- Table of Contents (you are here)
- Getting Started
- SodiumPlus Methods
- AEAD (XChaCha20-Poly1305)
- Shared-key authentication
- Authenticated public-key encryption
- Sealed boxes (anonymous public-key encryption)
- General-purpose cryptographic hash
- Key derivation
- Key exchange
- Password-based key derivation
- Password hashing and storage
- Scalar multiplication over Curve25519 (advanced)
- Shared-key authenticated encryption
- Short-input hashing
- Digital signatures
- Randomness
You always want to use SodiumPlus
from within an asynchronous function.
const { SodiumPlus } = require('sodium-plus');
let sodium;
async function myFunction() {
if (!sodium) sodium = await SodiumPlus.auto();
// Now you can use sodium.FUNCTION_NAME_HERE()
}
All cryptographic secrets are contained within a CryptographyKey
object
(or one of its derived classes). You can create and access them like so:
const { CryptographyKey } = require('sodium-plus');
let buf = Buffer.alloc(32);
let key = new CryptographyKey(buf);
// If you do this, the internal buffer will not be visible!
console.log(key);
// CryptographyKey {}
// You'll need to do this instead:
console.log(key.getBuffer());
// <Buffer d9 ff 60 6b ff 96 f6 26 05 53 07 39 ef b5 a5 8b 26 0c 72 9e 1b b7 e4 97 fe 09 de 07 86 8a 0c b6>
The following classes inherit from CryptographyKey
:
Ed25519PublicKey
-- Ed25519 public keyEd25519SecretKey
-- Ed25519 secret keyX25519PublicKey
-- X25519 public keyX25519SecretKey
-- X25519 secret key
This describes the methods in the public API for Sodium-Plus. If you're not sure which method to use, please refer to the Libsodium Quick Reference for guidance.
Decrypt a message (and optional associated data) with XChaCha20-Poly1305.
Parameters and their respective types:
{string|Buffer}
Ciphertext{string|Buffer}
nonce (must be 24 bytes){CryptographyKey}
key{string|Buffer}
assocData
Returns a Promise
that resolves to a Buffer
.
Throws a SodiumError
on decryption failure.
Encrypt a message (and optional associated data) with XChaCha20-Poly1305.
Parameters and their respective types:
{string|Buffer}
Plaintext{string|Buffer}
nonce (must be 24 bytes){CryptographyKey}
key{string|Buffer}
assocData
Returns a Promise
that resolves to a Buffer
.
Returns a CryptographyKey
object containing a key appropriate
for the crypto_aead_xchacha20poly1305_ietf_
API.
const { SodiumPlus } = require('sodium-plus');
let sodium;
(async function () {
if (!sodium) sodium = await SodiumPlus.auto();
let plaintext = 'Your message goes here';
let key = await sodium.crypto_aead_xchacha20poly1305_ietf_keygen();
let nonce = await sodium.randombytes_buf(24);
let ciphertext = await sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(
plaintext,
nonce,
key
);
console.log(ciphertext.toString('hex'));
let decrypted = await sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(
ciphertext,
nonce,
key
);
console.log(decrypted.toString());
})();
Get an authenticator for a message for a given key.
Parameters and their respective types:
{string|Buffer}
message{CryptographyKey}
key
Return a Promise
that resolves to a Buffer
.
Verify an authenticator for a message for a given key.
Parameters and their respective types:
{string|Buffer}
message{CryptographyKey}
key{Buffer}
mac
Return a Promise
that resolves to a boolean
.
Returns a CryptographyKey
object containing a key appropriate
for the crypto_auth
API.
const { SodiumPlus } = require('sodium-plus');
let sodium;
(async function () {
if (!sodium) sodium = await SodiumPlus.auto();
let plaintext = 'Your message goes here';
let key = await sodium.crypto_auth_keygen();
let mac = await sodium.crypto_auth(plaintext, key);
console.log(await sodium.crypto_auth_verify(plaintext, key, mac));
})();
Public-key authenticated encryption.
Parameters and their respective types:
{string|Buffer}
plaintext{Buffer}
nonce (must be 24 bytes){X25519SecretKey}
secret key{X25519PublicKey}
public key
Returns a Promise
that resolves to a Buffer
.
Public-key authenticated encryption.
Parameters and their respective types:
{Buffer}
ciphertext{Buffer}
nonce (must be 24 bytes){X25519SecretKey}
secret key{X25519PublicKey}
public key
Returns a Promise
that resolves to a Buffer
.
Throws a SodiumError
on decryption failure.
Returns a Promise
that resolves to a CryptographyKey
containing a 64-byte
Buffer
. The first 32 bytes are your X25519 secret key, the latter 32 are your
X25519 public key.
Combine two X25519 keys (secret, public) into a keypair object.
Parameters and their respective types:
{X25519SecretKey}
secret key{X25519PublicKey}
public key
Returns a Promise
that resolves to a CryptographyKey
.
Parameters and their respective types:
{CryptographyKey}
(buffer must be 64 bytes long)
Returns a Promise
that resolves to a X25519PublicKey
.
Parameters and their respective types:
{CryptographyKey}
(buffer must be 64 bytes long)
Returns a Promise
that resolves to a X25519SecretKey
.
Derive the public key from a given X25519 secret key.
Parameters and their respective types:
{X25519SecretKey}
Returns a Promise
that resolves to a X25519PublicKey
.
const { SodiumPlus } = require('sodium-plus');
let sodium;
(async function () {
if (!sodium) sodium = await SodiumPlus.auto();
let aliceKeypair = await sodium.crypto_box_keypair();
let aliceSecret = await sodium.crypto_box_secretkey(aliceKeypair);
let alicePublic = await sodium.crypto_box_publickey(aliceKeypair);
let bobKeypair = await sodium.crypto_box_keypair();
let bobSecret = await sodium.crypto_box_secretkey(bobKeypair);
let bobPublic = await sodium.crypto_box_publickey(bobKeypair);
let plaintext = 'Your message goes here';
let nonce = await sodium.randombytes_buf(24);
let ciphertext = await sodium.crypto_box(plaintext, nonce, aliceSecret, bobPublic);
console.log(ciphertext);
let decrypted = await sodium.crypto_box_open(ciphertext, nonce, bobSecret, alicePublic);
console.log(decrypted.toString());
})();
Anonymous public-key encryption. (Message integrity is still assured.)
Parameters and their respective types:
{string|Buffer}
plaintext{X25519PublicKey}
public key
Returns a Promise
that resolves to a Buffer
.
Anonymous public-key decryption. (Message integrity is still assured.)
Parameters and their respective types:
{Buffer}
ciphertext{X25519PublicKey}
public key{X25519SecretKey}
secret key
Returns a Promise
that resolves to a Buffer
.
const { SodiumPlus } = require('sodium-plus');
let sodium;
(async function () {
if (!sodium) sodium = await SodiumPlus.auto();
let aliceKeypair = await sodium.crypto_box_keypair();
let aliceSecret = await sodium.crypto_box_secretkey(aliceKeypair);
let alicePublic = await sodium.crypto_box_publickey(aliceKeypair);
let plaintext = 'Your message goes here';
let ciphertext = await sodium.crypto_box_seal(plaintext, alicePublic);
console.log(ciphertext);
let decrypted = await sodium.crypto_box_seal_open(ciphertext, alicePublic, aliceSecret);
console.log(decrypted.toString());
})();
General-purpose cryptographic hash (powered by BLAKE2).
Parameters and their respective types:
{Buffer}
message{CryptographyKey|null}
key (optional){number}
output length (optional, defaults to 32)
Returns a Promise
that resolves to a Buffer
.
Returns a CryptographyKey
object containing a key appropriate
for the crypto_generichash
API.
Initialize a BLAKE2 hash context for stream hashing.
Parameters and their respective types:
{CryptographyKey|null}
key (optional){number}
output length (optional, defaults to 32)
Returns a Promise
that resolves to... well, that depends on your backend.
- sodium-native returns a
CryptoGenericHashWrap
object. - libsodium-wrappers returns a number (a buffer's memory address)
Update the BLAKE2 hash state with a block of data.
Parameters and their respective types:
{*}
hash state (see crypto_generichash_init()){string|Buffer}
message chunk
Returns a Promise
that resolves to void
. Instead, state
is updated in-place.
Obtain the final BLAKE2 hash output.
Parameters and their respective types:
{*}
hash state (see crypto_generichash_init()){number}
output length (optional, defaults to 32)
Returns a Promise
that resolves to a Buffer
.
const { SodiumPlus } = require('sodium-plus');
let sodium;
(async function () {
if (!sodium) sodium = await SodiumPlus.auto();
let message = 'Any message can go here';
let hashed = await sodium.crypto_generichash(message);
console.log(hashed.toString('hex'));
let key = await sodium.crypto_generichash_keygen();
let hash2 = await sodium.crypto_generichash(message, key, 64);
let state = await sodium.crypto_generichash_init(key, 64);
await sodium.crypto_generichash_update(state, 'Any message ');
await sodium.crypto_generichash_update(state, 'can go here');
let hash3 = await sodium.crypto_generichash_final(state, 64);
if (!await sodium.sodium_memcmp(hash2, hash3)) {
throw new Error('Implementation is broken. You should never see this.');
}
console.log(hash2.toString('hex'));
})();
Derive a subkey from a master key.
Parameters and their respective types:
{number}
output length (typically you want32
){number}
subkey ID{string|Buffer}
context (must be a string/buffer of length 8){CryptographyKey}
master key
Returns a Promise
that resolves to a CryptographyKey
.
Returns a CryptographyKey
object containing a key appropriate
for the crypto_kdf
API.
const { SodiumPlus } = require('sodium-plus');
let sodium;
(async function () {
if (!sodium) sodium = await SodiumPlus.auto();
let masterKey = await sodium.crypto_kdf_keygen();
let context = 'Sodium++';
let subkey1 = await sodium.crypto_kdf_derive_from_key(32, 1, context, masterKey);
let subkey2 = await sodium.crypto_kdf_derive_from_key(32, 2, context, masterKey);
let subkey3 = await sodium.crypto_kdf_derive_from_key(32, 3, context, masterKey);
console.log({
'master-key': masterKey.getBuffer().toString('hex'),
'subkey1': subkey1.getBuffer().toString('hex'),
'subkey2': subkey2.getBuffer().toString('hex'),
'subkey3': subkey3.getBuffer().toString('hex')
});
})();
This is functionally identical to crypto_box_keypair()
.
Returns a Promise
that resolves to a CryptographyKey
with 64 bytes.
Generate an X25519 keypair from a seed. Unlike crypto_kx_seedpair()
, this is
deterministic from your seed.
Parameters and their respective types:
{string|Buffer}
seed
Returns a Promise
that resolves to a CryptographyKey
with 64 bytes.
Perform a key exchange from the client's perspective.
Returns an array of two CryptographyKey objects:
- The first is meant for data sent from the server to the client (incoming decryption).
- The second is meant for data sent from the client to the server (outgoing encryption).
Parameters and their respective types:
{X25519PublicKey}
client public key (yours){X25519SecretKey}
client secret key (yours){X25519PublicKey}
server public key (theirs)
Returns a Promise
that resolves to an array of two CryptographyKey
objects.
Perform a key exchange from the server's perspective.
Returns an array of two CryptographyKey objects:
- The first is meant for data sent from the client to the server (incoming decryption).
- The second is meant for data sent from the server to the client (outgoing encryption).
Parameters and their respective types:
{X25519PublicKey}
server public key (yours){X25519SecretKey}
server secret key (yours){X25519PublicKey}
client public key (theirs)
Returns a Promise
that resolves to an array of two CryptographyKey
objects.
const { SodiumPlus } = require('sodium-plus');
let sodium;
(async function () {
if (!sodium) sodium = await SodiumPlus.auto();
let clientKeypair = await sodium.crypto_box_keypair();
let clientSecret = await sodium.crypto_box_secretkey(clientKeypair);
let clientPublic = await sodium.crypto_box_publickey(clientKeypair);
let serverKeypair = await sodium.crypto_kx_seed_keypair('Your static input goes here');
let serverSecret = await sodium.crypto_box_secretkey(serverKeypair);
let serverPublic = await sodium.crypto_box_publickey(serverKeypair);
let clientIKey, clientOKey, serverIKey, serverOKey;
[clientIKey, clientOKey] = await sodium.crypto_kx_client_session_keys(
clientPublic,
clientSecret,
serverPublic
);
[serverIKey, serverOKey] = await sodium.crypto_kx_server_session_keys(
serverPublic,
serverSecret,
clientPublic
);
console.log({
'client-sees': {
'incoming': clientIKey.getBuffer().toString('hex'),
'outgoing': clientOKey.getBuffer().toString('hex')
},
'server-sees': {
'incoming': serverIKey.getBuffer().toString('hex'),
'outgoing': serverOKey.getBuffer().toString('hex')
}
});
})();
Derive a cryptography key from a password and salt.
Parameters and their respective types:
{number}
output length{string|Buffer}
password{Buffer}
salt (16 bytes){number}
opslimit (recommeded minimum:2
){number}
memlimit (recommended mimimum:67108864
a.k.a. 64MiB){number|null}
algorithm (recommended:this.CRYPTO_PWHASH_ALG_DEFAULT
)
Returns a Promise
that resolves to a CryptographyKey
.
This example is for key derivation. Look below for information about password storage/verification.
const { SodiumPlus } = require('sodium-plus');
let sodium;
(async function () {
if (!sodium) sodium = await SodiumPlus.auto();
let password = 'correct horse battery staple';
let salt = await sodium.randombytes_buf(16);
let key = await sodium.crypto_pwhash(
32,
password,
salt,
sodium.CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE,
sodium.CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE
);
console.log(key.getBuffer().toString('hex'));
})();
Get a password hash (in a safe-for-storage format).
Parameters and their respective types:
{string|Buffer}
password{number}
opslimit (recommeded minimum:2
){number}
memlimit (recommended mimimum:67108864
a.k.a. 64MiB)
Returns a Promise
that resolves to a string
.
Does this password need to be rehashed? (i.e. have the algorithm parameters we want changed since the hash was generated?)
Parameters and their respective types:
{string}
password hash{number}
opslimit (recommeded minimum:2
){number}
memlimit (recommended mimimum:67108864
a.k.a. 64MiB)
Returns a Promise
that resolves to a boolean
.
Verify a password against a known password hash.
{string|Buffer}
password{string}
password hash
Returns a Promise
that resolves to a boolean
.
const { SodiumPlus } = require('sodium-plus');
let sodium;
(async function () {
if (!sodium) sodium = await SodiumPlus.auto();
let password = 'correct horse battery staple';
// Generating a password hash
let pwhash = await sodium.crypto_pwhash_str(
password,
sodium.CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE,
sodium.CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE
);
console.log(pwhash);
// Check that we don't need to rotate hashes
let stale = await sodium.crypto_pwhash_str_needs_rehash(
pwhash,
sodium.CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE,
sodium.CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE
);
if (stale) {
console.warn('Password needs to be rehashed');
}
// Password validation
if (await sodium.crypto_pwhash_str_verify(password, pwhash)) {
console.log("Password valid");
} else {
console.error("Incorrect password");
}
})();
Elliptic Curve Diffie-Hellman key exchange over Curve25519. You probably don't want to ever use this directly.
Parameters and their respective types:
{X25519SecretKey}
your secret key{X25519PublicKey}
their public key
Returns a Promise
that resolves to a CryptographyKey
.
Generate an X25519PublicKey from an X25519SecretKey.
Parameters and their respective types:
{X25519SecretKey}
your secret key
Returns a Promise
that resolves to an X25519PublicKey
.
const { SodiumPlus } = require('sodium-plus');
let sodium;
(async function () {
if (!sodium) sodium = await SodiumPlus.auto();
let aliceKeypair = await sodium.crypto_box_keypair();
let aliceSecret = await sodium.crypto_box_secretkey(aliceKeypair);
let alicePublic = await sodium.crypto_box_publickey(aliceKeypair);
let bobKeypair = await sodium.crypto_box_keypair();
let bobSecret = await sodium.crypto_box_secretkey(bobKeypair);
let bobPublic = await sodium.crypto_scalarmult_base(bobSecret);
let aliceToBob = await sodium.crypto_scalarmult(aliceSecret, bobPublic);
let bobToAlice = await sodium.crypto_scalarmult(bobSecret, alicePublic);
console.log({
'alice-to-bob': aliceToBob.getBuffer().toString('hex'),
'bob-to-alice': bobToAlice.getBuffer().toString('hex')
});
})();
Shared-key authenticated encryption.
Parameters and their respective types:
{string|Buffer}
Plaintext{string|Buffer}
nonce (must be 24 bytes){CryptographyKey}
key
Returns a Promise
that resolves to a Buffer
.
Shared-key authenticated decryption.
Parameters and their respective types:
{string|Buffer}
Ciphertext{string|Buffer}
nonce (must be 24 bytes){CryptographyKey}
key
Returns a Promise
that resolves to a Buffer
.
Throws a SodiumError
on decryption failure.
Returns a CryptographyKey
object containing a key appropriate
for the crypto_secretbox
API.
const { SodiumPlus } = require('sodium-plus');
let sodium;
(async function () {
if (!sodium) sodium = await SodiumPlus.auto();
let plaintext = 'Your message goes here';
let key = await sodium.crypto_secretbox_keygen();
let nonce = await sodium.randombytes_buf(24);
let ciphertext = await sodium.crypto_secretbox(
plaintext,
nonce,
key
);
console.log(ciphertext.toString('hex'));
let decrypted = await sodium.crypto_secretbox_open(
ciphertext,
nonce,
key
);
console.log(decrypted.toString());
})();
Calculate a fast hash for short inputs.
Parameters and their respective types:
{string|Buffer}
input{CryptographyKey}
key
Returns a Promise
that resolves to a Buffer
.
Returns a CryptographyKey
object containing a key appropriate
for the crypto_shorthash
API.
Warning: You probably want
crypto_generichash()
for most use-cases.crypto_shorthash()
does not offer collision resistance.
const { SodiumPlus } = require('sodium-plus');
let sodium;
(async function () {
if (!sodium) sodium = await SodiumPlus.auto();
let key = await sodium.crypto_shorthash_keygen();
let mapped = {};
mapped['foo'] = (await sodium.crypto_shorthash('foo', key)).toString('hex');
mapped['bar'] = (await sodium.crypto_shorthash('bar', key)).toString('hex');
mapped['baz'] = (await sodium.crypto_shorthash('baz', key)).toString('hex');
console.log(mapped);
})();
See also: the detached API below.
Sign a message with Ed25519, returning a signed message (prefixed with the signature).
Parameters and their respective types:
{string|Buffer}
message{Ed25519SecretKey}
secretKey
Returns a Promise
that resolves to a Buffer
.
Verify a signed message with Ed25519, returning the original message if the signature is valid.
Parameters and their respective types:
{string|Buffer}
signedMessage{Ed25519SecretKey}
publicKey
Returns a Promise
that resolves to a Buffer
.
Returns the Ed25519 signature of the message, for the given secret key.
Parameters and their respective types:
{string|Buffer}
message{Ed25519SecretKey}
secretKey
Returns a Promise
that resolves to a Buffer
.
Returns true if the Ed25519 signature is valid for a given message and public key.
Parameters and their respective types:
{string|Buffer}
message{Ed25519PublicKey}
publicKey{Buffer}
signature
Returns a Promise
that resolves to a boolean
.
Returns a Promise
that resolves to a CryptographyKey
containing a 96-byte
Buffer
. The first 64 bytes are your Ed25519 secret key, the latter 32 are your
Ed25519 public key.
Parameters and their respective types:
{CryptographyKey}
(buffer must be 96 bytes long)
Returns a Promise
that resolves to a Ed25519PublicKey
.
Parameters and their respective types:
{CryptographyKey}
(buffer must be 96 bytes long)
Returns a Promise
that resolves to a Ed25519SecretKey
.
Obtain a birationally equivalent X25519 secret key, given an Ed25519 secret key.
Parameters and their respective types:
{Ed25519SecretKey}
Returns a Promise
that resolves to an X25519SecretKey
.
Obtain a birationally equivalent X25519 public key, given an Ed25519 public key.
Parameters and their respective types:
{Ed25519PublicKey}
Returns a Promise
that resolves to an X25519PublicKey
.
const { SodiumPlus } = require('sodium-plus');
let sodium;
(async function () {
if (!sodium) sodium = await SodiumPlus.auto();
let aliceKeypair = await sodium.crypto_sign_keypair();
let aliceSecret = await sodium.crypto_sign_secretkey(aliceKeypair);
let alicePublic = await sodium.crypto_sign_publickey(aliceKeypair);
let message = 'This is something I need to sign publicly.';
// Detached mode:
let signature = await sodium.crypto_sign_detached(message, aliceSecret);
console.log(signature.toString('hex'));
if (await sodium.crypto_sign_verify_detached(message, alicePublic, signature)) {
console.log("Signature is valid.");
} else {
console.error("Invalid signature!");
}
// NaCl (crypto_sign / crypto_sign_open):
let signed = await sodium.crypto_sign(message, aliceSecret);
let opened = await sodium.crypto_sign_open(signed, alicePublic);
console.log(opened.toString());
})();
Obtain a buffer filled with random bytes.
Parameters and their respective types:
{number}
Size of buffer to return
Returns a Promise
that resolves to a Buffer
Generate an integer between 0 and upperBound (non-inclusive).
For example, randombytes_uniform(10) returns an integer between 0 and 9.
Parameters and their respective types:
{number}
Upper bound
Returns a Promise
that resolves to a number
.
const { SodiumPlus } = require('sodium-plus');
let sodium;
(async function () {
if (!sodium) sodium = await SodiumPlus.auto();
let someBuf = await sodium.randombytes_buf(32);
console.log(someBuf.toString('hex'));
let someInt = await sodium.randombytes_uniform(65536);
console.log(someInt);
})();