
Security News
How Enterprise Security Is Adapting to AI-Accelerated Threats
Socket CTO Ahmad Nassri discusses why supply chain attacks now target developer machines and what AI means for the future of enterprise security.
@hackbg/miscreant-esm
Advanced tools
(ESM port) Misuse resistant symmetric encryption library providing AES-SIV (RFC 5297), AES-PMAC-SIV, and STREAM constructions
The best crypto you've never heard of, brought to you by Phil Rogaway
JavaScript-compatible TypeScript implementation of Miscreant: Advanced symmetric encryption library which provides the AES-SIV (RFC 5297), AES-PMAC-SIV, and STREAM constructions. These algorithms are easy-to-use (or rather, hard-to-misuse) and support encryption of individual messages or message streams.
AES-SIV provides nonce-reuse misuse-resistance (NRMR): accidentally reusing a nonce with this construction is not a security catastrophe, unlike it is with more popular AES encryption modes like AES-GCM. With AES-SIV, the worst outcome of reusing a nonce is an attacker can see you've sent the same plaintext twice, as opposed to almost all other AES modes where it can facilitate chosen ciphertext attacks and/or full plaintext recovery.
Have questions? Want to suggest a feature or change?
Though this library is written by cryptographic professionals, it has not undergone a thorough security audit, and cryptographic professionals are still humans that make mistakes.
USE AT YOUR OWN RISK
Via npm:
npm install miscreant
Via Yarn:
yarn install miscreant
Import Miscreant into your project with:
import * as miscreant from "miscreant";
Import Miscreant into your project with the following:
import * as miscreant from "miscreant";
The Authenticated Encryption with Associated Data API, or AEAD API, is the recommended API for encrypting and
decrypting data with Miscreant. It accepts a nonce, optional associated data (i.e. data you'd like to authenticate
along with the encrypted message), and a message to encrypt.
When decrypting, the same nonce and associated data must be supplied as were passed at the time of encryption. If anything is amiss, e.g. if the ciphertext has been tampered with, the cipher will detect it and throw an error.
The miscreant.AEAD.importKey() method creates a new instance of an AES-SIV AEAD encryptor/decryptor.
miscreant.AEAD.importKey(keyData, algorithm[, provider = new miscreant.WebCryptoProvider()])
"AES-SIV": CMAC-based construction described in RFC 5297. Slower but
standardized and more common."AES-PMAC-SIV": PMAC-based construction. Supports potentially faster
implementations, but is non-standard and only available in Miscreant libraries.The miscreant.AEAD.importKey() method returns a Promise that, when fulfilled, returns an AEAD encryptor/decryptor.
import * as miscreant from "miscreant";
let keyData = new Uint32Array(32);
// Assuming window.crypto.getRandomValues is available
window.crypto.getRandomValues(keyData);
let key = await miscreant.AEAD.importKey(keyData, "AES-PMAC-SIV");
seal()The seal() method encrypts a message along with an optional associated data value which will be authenticated along with the message.
key.seal(plaintext, nonce[, associatedData = ""])
The seal() method returns a Promise that, when fulfilled, returns a Uint8Array containing the resulting ciphertext.
import * as miscreant from "miscreant";
let keyData = new Uint8Array(32);
// Assuming window.crypto.getRandomValues is available
window.crypto.getRandomValues(keyData);
let key = await miscreant.SIV.importKey(keyData, "AES-PMAC-SIV");
// Encrypt plaintext
let plaintext = new Uint8Array([2,3,5,7,11,13,17,19,23,29]);
let nonce = new Uint8Array(16);
window.crypto.getRandomValues(nonce);
let ciphertext = await key.seal(plaintext, nonce);
open()The open() method decrypts a message which has been encrypted using AES-SIV or AES-PMAC-SIV.
key.open(ciphertext, nonce[, associatedData = ""])
The open() method returns a Promise that, when fulfilled, returns a Uint8Array containing the decrypted plaintext.
If the message has been tampered with or is otherwise corrupted, the promise will be rejected with an IntegrityError.
import * as miscreant from "miscreant";
let keyData = new Uint8Array(32);
// Assuming window.crypto.getRandomValues is available
window.crypto.getRandomValues(keyData);
let key = await miscreant.SIV.importKey(keyData, "AES-PMAC-SIV");
// Encrypt plaintext
let plaintext = new Uint8Array([2,3,5,7,11,13,17,19,23,29]);
let nonce = new Uint8Array(16);
window.crypto.getRandomValues(nonce);
let ciphertext = await key.seal(plaintext, nonce);
// Decrypt ciphertext
var decrypted = await key.open(ciphertext, nonce);
Miscreant implements an interface that permits incremental processing of encrypted data based on the STREAM construction, which is provably secure against a wide range of attacks including truncation and reordering attacks.
The API is provided in the form of miscreant.StreamEncryptor and miscreant.StreamDecryptor classes, which each take
a per-STREAM key and nonce, and from there operate a message-at-a-time on input plaintext/ciphertext along with
optional per-message associated data (i.e. data you'd like to authenticate along with the encrypted message).
The miscreant.StreamEncryptor.importKey() method creates a new instance of a STREAM encryptor, capable of encrypting a stream of authenticated messages and ensuring their integrity, ordering, and termination.
miscreant.StreamEncryptor.importKey(keyData, nonceData, algorithm[, provider = new miscreant.WebCryptoProvider()])
"AES-SIV": CMAC-based construction described in RFC 5297. Slower but standardized and more common."AES-PMAC-SIV": PMAC-based construction. Supports potentially faster implementations, but is non-standard and
only available in Miscreant libraries.The miscreant.StreamEncryptor.importKey() method returns a Promise that, when fulfilled, returns a StreamEncryptor object.
import * as miscreant from "miscreant";
let keyData = new Uint32Array(32);
let nonceData = new Uint8Array(8);
// Assuming window.crypto.getRandomValues is available
window.crypto.getRandomValues(keyData);
window.crypto.getRandomValues(nonceData);
let encryptor = await miscreant.StreamEncryptor.importKey(keyData, nonceData, "AES-PMAC-SIV");
seal()The seal() method of miscreant.StreamEncryptor encrypts a message, and also takes an optional associated data
value which will be authenticated along with the message (but not encrypted).
Note that unlike the AEAD API, STREAM encodes the position of the message into the message stream, so the order
in which seal() is called is significant.
encryptor.seal(plaintext, [lastBlock = false[, associatedData = ""]])
The seal() method returns a Promise that, when fulfilled, returns a Uint8Array containing the resulting ciphertext.
import * as miscreant from "miscreant";
let keyData = new Uint32Array(32);
let nonceData = new Uint8Array(8);
// Assuming window.crypto.getRandomValues is available
window.crypto.getRandomValues(keyData);
window.crypto.getRandomValues(nonceData);
let encryptor = await miscreant.StreamEncryptor.importKey(keyData, nonceData, "AES-PMAC-SIV");
// Encrypt plaintext
let msg1 = new Uint8Array([1,2]);
let msg2 = new Uint8Array([3,4,5]);
let msg3 = new Uint8Array([6,7,8,9]);
let ciphertext1 = await encryptor.seal(msg1);
let ciphertext2 = await encryptor.seal(msg2);
let ciphertext3 = await encryptor.seal(msg3, true);
miscreant.StreamDecryptor.importKey()The miscreant.StreamDecryptor.importKey() method creates a new instance of a STREAM decryptor, capable of decrypting a previously encrypted stream of authenticated messages and ensuring their integrity, ordering, and termination.
miscreant.StreamDecryptor.importKey(keyData, nonceData, algorithm[, provider = new miscreant.WebCryptoProvider()])
"AES-SIV": CMAC-based construction described in RFC 5297. Slower but standardized and more common."AES-PMAC-SIV": PMAC-based construction. Supports potentially faster implementations, but is non-standard and
only available in Miscreant libraries.The miscreant.StreamDecryptor.importKey() method returns a Promise that, when fulfilled, returns a StreamDecryptor object.
import * as miscreant from "miscreant";
let keyData = new Uint32Array(32);
let nonceData = new Uint8Array(8);
// Assuming window.crypto.getRandomValues is available
window.crypto.getRandomValues(keyData);
window.crypto.getRandomValues(nonceData);
let decryptor = await miscreant.StreamDecryptor.importKey(keyData, nonceData, "AES-PMAC-SIV");
open()The open() method decrypts a stream of messages which has been encrypted using AES-SIV or AES-PMAC-SIV.
decryptor.open(ciphertext, [lastBlock = false[, associatedData = ""]])
The open() method returns a Promise that, when fulfilled, returns a Uint8Array containing the decrypted plaintext.
If the message has been tampered with or is otherwise corrupted, the promise will be rejected with an IntegrityError.
import * as miscreant from "miscreant";
let keyData = new Uint32Array(32);
let nonceData = new Uint8Array(8);
// Assuming window.crypto.getRandomValues is available
window.crypto.getRandomValues(keyData);
window.crypto.getRandomValues(nonceData);
let encryptor = await miscreant.StreamEncryptor.importKey(keyData, nonceData, "AES-PMAC-SIV");
// Encrypt plaintext
let msg1 = new Uint8Array([1,2]);
let msg2 = new Uint8Array([3,4,5]);
let msg3 = new Uint8Array([6,7,8,9]);
let ciphertext1 = await encryptor.seal(msg1);
let ciphertext2 = await encryptor.seal(msg2);
let ciphertext3 = await encryptor.seal(msg3, true);
// Decrypt ciphertext
let decryptor = await miscreant.StreamDecryptor.importKey(keyData, nonceData, "AES-PMAC-SIV");
var decrypted1 = await key.open(ciphertext1);
var decrypted2 = await key.open(ciphertext2);
var decrypted3 = await key.open(ciphertext3, true);
The SIV API is a power-user API that allows you to make full use of the multiple header feature the SIV construction provides.
The miscreant.SIV.importKey() method creates a new instance of an AES-SIV encryptor/decryptor.
miscreant.SIV.importKey(keyData, algorithm[, provider = new miscreant.WebCryptoProvider()])
"AES-SIV": CMAC-based construction described in RFC 5297. Slower but standardized and more common."AES-PMAC-SIV": PMAC-based construction. Supports potentially faster implementations, but is non-standard and
only available in Miscreant libraries.The miscreant.SIV.importKey() method returns a Promise that, when fulfilled, returns a SIV encryptor/decryptor.
import * as miscreant from "miscreant";
let keyData = new Uint32Array(32);
// Assuming window.crypto.getRandomValues is available
window.crypto.getRandomValues(keyData);
let key = await miscreant.SIV.importKey(keyData, "AES-PMAC-SIV");
The seal() method encrypts a message along with a set of message headers known as associated data.
key.seal(associatedData, plaintext)
The seal() method returns a Promise that, when fulfilled, returns a Uint8Array containing the resulting ciphertext.
import * as miscreant from "miscreant";
let keyData = new Uint8Array(32);
// Assuming window.crypto.getRandomValues is available
window.crypto.getRandomValues(keyData);
let key = await miscreant.SIV.importKey(keyData, "AES-PMAC-SIV");
// Encrypt plaintext
let plaintext = new Uint8Array([2,3,5,7,11,13,17,19,23,29]);
let nonce = new Uint8Array(16);
window.crypto.getRandomValues(nonce);
let ciphertext = await key.seal(plaintext, [nonce]);
The open() method decrypts a message which has been encrypted using AES-SIV or AES-PMAC-SIV.
key.open(associatedData, ciphertext)
The open() method returns a Promise that, when fulfilled, returns a Uint8Array containing the decrypted plaintext.
If the message has been tampered with or is otherwise corrupted, the promise will be rejected with an IntegrityError.
import * as miscreant from "miscreant";
let keyData = new Uint8Array(32);
// Assuming window.crypto.getRandomValues is available
window.crypto.getRandomValues(keyData);
let key = await SIV.importKey(keyData, "AES-PMAC-SIV");
// Encrypt plaintext
let plaintext = new Uint8Array([2,3,5,7,11,13,17,19,23,29]);
let nonce = new Uint8Array(16);
window.crypto.getRandomValues(nonce);
let ciphertext = await key.seal(plaintext, [nonce]);
// Decrypt ciphertext
var decrypted = await key.open(ciphertext, [nonce]);
We abide by the Contributor Covenant and ask that you do as well.
For more information, please see CODE_OF_CONDUCT.md.
Bug reports and pull requests are welcome on GitHub at https://github.com/miscreant/miscreant
Copyright (c) 2017-2019 The Miscreant Developers.
Software AES implementation derived from the Go standard library: Copyright (c) 2012 The Go Authors. All rights reserved.
See LICENSE.txt for further details.
FAQs
(ESM port) Misuse resistant symmetric encryption library providing AES-SIV (RFC 5297), AES-PMAC-SIV, and STREAM constructions
We found that @hackbg/miscreant-esm demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 6 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Socket CTO Ahmad Nassri discusses why supply chain attacks now target developer machines and what AI means for the future of enterprise security.

Security News
Learn the essential steps every developer should take to stay secure on npm and reduce exposure to supply chain attacks.

Security News
Experts push back on new claims about AI-driven ransomware, warning that hype and sponsored research are distorting how the threat is understood.