• Stars
    star
    140
  • Rank 253,422 (Top 6 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created 11 months ago
  • Updated 30 days ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Auditable & minimal JS implementation of Salsa20, ChaCha and AES

noble-ciphers

Auditable & minimal JS implementation of Salsa20, ChaCha and AES.

  • πŸ”’ Auditable
  • πŸ”» Tree-shaking-friendly: use only what's necessary, other code won't be included
  • 🏎 Ultra-fast, hand-optimized for caveats of JS engines
  • πŸ” Unique tests ensure correctness: property-based, cross-library and Wycheproof vectors
  • πŸ’Ό AES: ECB, CBC, CTR, GCM, SIV (nonce misuse-resistant)
  • πŸ’ƒ Salsa20, ChaCha, XSalsa20, XChaCha, Poly1305, ChaCha8, ChaCha12
  • πŸ₯ˆ Two AES implementations: choose between friendly webcrypto wrapper and pure JS one
  • πŸͺΆ 21KB for everything, 10KB for ChaCha build

For discussions, questions and support, visit GitHub Discussions section of the repository.

This library belongs to noble cryptography

noble cryptography β€” high-security, easily auditable set of contained cryptographic libraries and tools.

Usage

npm install @noble/ciphers

We support all major platforms and runtimes. For Deno, ensure to use npm specifier. For React Native, you may need a polyfill for getRandomValues. A standalone file noble-ciphers.js is also available.

// import * from '@noble/ciphers'; // Error: use sub-imports, to ensure small app size
import { xchacha20poly1305 } from '@noble/ciphers/chacha';
// import { xchacha20poly1305 } from 'npm:@noble/[email protected]/chacha'; // Deno

Examples

Encrypt with XChaCha20-Poly1305

import { xchacha20poly1305 } from '@noble/ciphers/chacha';
import { utf8ToBytes } from '@noble/ciphers/utils';
import { randomBytes } from '@noble/ciphers/webcrypto';
const key = randomBytes(32);
const nonce = randomBytes(24);
const chacha = xchacha20poly1305(key, nonce);
const data = utf8ToBytes('hello, noble');
const ciphertext = chacha.encrypt(data);
const data_ = chacha.decrypt(ciphertext); // utils.bytesToUtf8(data_) === data

Encrypt with AES-256-GCM

import { gcm } from '@noble/ciphers/aes';
import { utf8ToBytes } from '@noble/ciphers/utils';
import { randomBytes } from '@noble/ciphers/webcrypto';
const key = randomBytes(32);
const nonce = randomBytes(24);
const aes = gcm(key, nonce);
const data = utf8ToBytes('hello, noble');
const ciphertext = aes.encrypt(data);
const data_ = aes.decrypt(ciphertext); // utils.bytesToUtf8(data_) === data

Use existing key instead of a new one

const key = new Uint8Array([
  169,  88, 160, 139, 168,  29, 147, 196,
   14,  88, 237,  76, 243, 177, 109, 140,
  195, 140,  80,  10, 216, 134, 215,  71,
  191,  48,  20, 104, 189,  37,  38,  55
]);
const nonce = new Uint8Array([
  180,  90,  27, 63, 160, 191, 150,
   33,  67, 212, 86,  71, 144,   6,
  200, 102, 218, 32,  23, 147,   8,
   41, 147,  11
]);
// or, hex:
import { hexToBytes } from '@noble/ciphers/utils';
const key2 = hexToBytes('4b7f89bac90a1086fef73f5da2cbe93b2fae9dfbf7678ae1f3e75fd118ddf999');
const nonce2 = hexToBytes('9610467513de0bbd7c4cc2c3c64069f1802086fbd3232b13');

Encrypt without nonce

import { xchacha20poly1305 } from '@noble/ciphers/chacha';
import { managedNonce } from '@noble/ciphers/webcrypto'
import { hexToBytes, utf8ToBytes } from '@noble/ciphers/utils';
const key = hexToBytes('fa686bfdffd3758f6377abbc23bf3d9bdc1a0dda4a6e7f8dbdd579fa1ff6d7e1');
const chacha = managedNonce(xchacha20poly1305)(key); // manages nonces for you
const data = utf8ToBytes('hello, noble');
const ciphertext = chacha.encrypt(data);
const data_ = chacha.decrypt(ciphertext);

Use same array for input and output

import { chacha20poly1305 } from '@noble/ciphers/chacha';
import { utf8ToBytes } from '@noble/ciphers/utils';
import { randomBytes } from '@noble/ciphers/webcrypto';

const key = randomBytes(32);
const nonce = randomBytes(12);
const buf = new Uint8Array(12 + 16);
const _data = utf8ToBytes('hello, noble');
buf.set(_data, 0); // first 12 bytes
const _12b = buf.subarray(0, 12);

const chacha = chacha20poly1305(key, nonce);
chacha.encrypt(_12b, buf);
chacha.decrypt(buf, _12b); // _12b now same as _data

All imports

import { gcm, siv } from '@noble/ciphers/aes';
import { xsalsa20poly1305 } from '@noble/ciphers/salsa';
import { chacha20poly1305, xchacha20poly1305 } from '@noble/ciphers/chacha';

// Unauthenticated encryption: make sure to use HMAC or similar
import { ctr, cbc, ecb } from '@noble/ciphers/aes';
import { salsa20, xsalsa20 } from '@noble/ciphers/salsa';
import { chacha20, xchacha20, chacha8, chacha12 } from '@noble/ciphers/chacha';

// Utilities
import { bytesToHex, hexToBytes, bytesToUtf8, utf8ToBytes } from '@noble/ciphers/utils';
import { managedNonce, randomBytes } from '@noble/ciphers/webcrypto';

Implementations

Salsa

import { xsalsa20poly1305 } from '@noble/ciphers/salsa';
import { secretbox } from '@noble/ciphers/salsa'; // == xsalsa20poly1305
import { salsa20, xsalsa20 } from '@noble/ciphers/salsa';

Salsa20 stream cipher was released in 2005. Salsa's goal was to implement AES replacement that does not rely on S-Boxes, which are hard to implement in a constant-time manner. Salsa20 is usually faster than AES, a big deal on slow, budget mobile phones.

XSalsa20, extended-nonce variant was released in 2008. It switched nonces from 96-bit to 192-bit, and became safe to be picked at random.

Nacl / Libsodium popularized term "secretbox", a simple black-box authenticated encryption. Secretbox is just xsalsa20-poly1305. We provide the alias and corresponding seal / open methods. We don't provide "box" or "sealedbox".

Check out PDF and wiki.

ChaCha

import { chacha20poly1305, xchacha20poly1305 } from '@noble/ciphers/chacha';
import { chacha20, xchacha20, chacha8, chacha12 } from '@noble/ciphers/chacha';

ChaCha20 stream cipher was released in 2008. ChaCha aims to increase the diffusion per round, but had slightly less cryptanalysis. It was standardized in RFC 8439 and is now used in TLS 1.3.

XChaCha20 extended-nonce variant is also provided. Similar to XSalsa, it's safe to use with randomly-generated nonces.

Check out PDF and wiki.

AES

import { gcm, siv, ctr, cbc, ecb } from '@noble/ciphers/aes';
import { randomBytes } from '@noble/ciphers/webcrypto';
const plaintext = new Uint8Array(32).fill(16);
const key = randomBytes(32); // 24 for AES-192, 16 for AES-128
for (let cipher of [gcm, siv]) {
  const stream = cipher(key, randomBytes(12));
  const ciphertext_ = stream.encrypt(plaintext);
  const plaintext_ = stream.decrypt(ciphertext_);
}
for (const cipher of [ctr, cbc]) {
  const stream = cipher(key, randomBytes(16));
  const ciphertext_ = stream.encrypt(plaintext);
  const plaintext_ = stream.decrypt(ciphertext_);
}
for (const cipher of [ecb]) {
  const stream = cipher(key);
  const ciphertext_ = stream.encrypt(plaintext);
  const plaintext_ = stream.decrypt(ciphertext_);
}

AES is a variant of Rijndael block cipher, standardized by NIST in 2001. We provide the fastest available pure JS implementation.

We support AES-128, AES-192 and AES-256: the mode is selected dynamically, based on key length (16, 24, 32).

AES-GCM-SIV nonce-misuse-resistant mode is also provided. It's recommended to use it, to prevent catastrophic consequences of nonce reuse. Our implementation of SIV has the same speed as GCM: there is no performance hit.

Check out AES internals and block modes.

Webcrypto AES

import { gcm, ctr, cbc, randomBytes } from '@noble/ciphers/webcrypto';
const plaintext = new Uint8Array(32).fill(16);
const key = randomBytes(32);
for (const cipher of [gcm]) {
  const stream = cipher(key, randomBytes(12));
  const ciphertext_ = await stream.encrypt(plaintext);
  const plaintext_ = await stream.decrypt(ciphertext_);
}
for (const cipher of [ctr, cbc]) {
  const stream = cipher(key, randomBytes(16));
  const ciphertext_ = await stream.encrypt(plaintext);
  const plaintext_ = await stream.decrypt(ciphertext_);
}

We also have a separate wrapper over WebCrypto built-in.

It's the same as using crypto.subtle, but with massively simplified API.

Unlike pure js version, it's asynchronous.

Poly1305, GHash, Polyval

import { poly1305 } from '@noble/ciphers/_poly1305';
import { ghash, polyval } from '@noble/ciphers/_polyval';

We expose polynomial-evaluation MACs: Poly1305, AES-GCM's GHash and AES-SIV's Polyval.

Poly1305 (PDF, wiki) is a fast and parallel secret-key message-authentication code suitable for a wide variety of applications. It was standardized in RFC 8439 and is now used in TLS 1.3.

Polynomial MACs are not perfect for every situation: they lack Random Key Robustness: the MAC can be forged, and can't be used in PAKE schemes. See invisible salamanders attack. To combat invisible salamanders, hash(key) can be included in ciphertext, however, this would violate ciphertext indistinguishability: an attacker would know which key was used - so HKDF(key, i) could be used instead.

FF1

Format-preserving encryption algorithm (FPE-FF1) specified in NIST Special Publication 800-38G. See more info.

Managed nonces

import { managedNonce } from '@noble/ciphers/webcrypto';
import { gcm, siv, ctr, cbc, ecb } from '@noble/ciphers/aes';
import { xsalsa20poly1305 } from '@noble/ciphers/salsa';
import { chacha20poly1305, xchacha20poly1305 } from '@noble/ciphers/chacha';

const wgcm = managedNonce(gcm);
const wsiv = managedNonce(siv);
const wcbc = managedNonce(cbc);
const wctr = managedNonce(ctr);
const wsalsapoly = managedNonce(xsalsa20poly1305);
const wchacha = managedNonce(chacha20poly1305);
const wxchacha = managedNonce(xchacha20poly1305);

// Now:
const encrypted = wgcm(key).encrypt(data); // no nonces

We provide API that manages nonce internally instead of exposing them to library's user.

For encrypt, a nonceBytes-length buffer is fetched from CSPRNG and prenended to encrypted ciphertext.

For decrypt, first nonceBytes of ciphertext are treated as nonce.

Guidance

Which cipher should I pick?

XChaCha20-Poly1305 is the safest bet these days. AES-GCM-SIV is the second safest. AES-GCM is the third.

How to encrypt properly

  • Use unpredictable key with enough entropy
    • Random key must be using cryptographically secure random number generator (CSPRNG), not Math.random etc.
    • Non-random key generated from KDF is fine
    • Re-using key is fine, but be aware of rules for cryptographic key wear-out and encryption limits
  • Use new nonce every time and don't repeat it
    • chacha and salsa20 are fine for sequential counters that never repeat: 01, 02...
    • xchacha and xsalsa20 should be used for random nonces instead
  • Prefer authenticated encryption (AEAD)
    • HMAC+ChaCha / HMAC+AES / chacha20poly1305 / aes-gcm is good
    • chacha20 without poly1305 or hmac / aes-ctr / aes-cbc is bad
    • Flipping bits or ciphertext substitution won't be detected in unauthenticated ciphers
  • Don't re-use keys between different protocols
    • For example, using secp256k1 key in AES is bad
    • Use hkdf or, at least, a hash function to create sub-key instead

Nonces

Most ciphers need a key and a nonce (aka initialization vector / IV) to encrypt a data:

ciphertext = encrypt(plaintext, key, nonce)

Repeating (key, nonce) pair with different plaintexts would allow an attacker to decrypt it:

ciphertext_a = encrypt(plaintext_a, key, nonce)
ciphertext_b = encrypt(plaintext_b, key, nonce)
stream_diff = xor(ciphertext_a, ciphertext_b)   # Break encryption

So, you can't repeat nonces. One way of doing so is using counters:

for i in 0..:
    ciphertext[i] = encrypt(plaintexts[i], key, i)

Another is generating random nonce every time:

for i in 0..:
    rand_nonces[i] = random()
    ciphertext[i] = encrypt(plaintexts[i], key, rand_nonces[i])

Counters are OK, but it's not always possible to store current counter value: e.g. in decentralized, unsyncable systems.

Randomness is OK, but there's a catch: ChaCha20 and AES-GCM use 96-bit / 12-byte nonces, which implies higher chance of collision. In the example above, random() can collide and produce repeating nonce.

To safely use random nonces, utilize XSalsa20 or XChaCha: they increased nonce length to 192-bit, minimizing a chance of collision. AES-SIV is also fine. In situations where you can't use eXtended-nonce algorithms, key rotation is advised. hkdf would work great for this case.

Encryption limits

A "protected message" would mean a probability of 2**-50 that a passive attacker successfully distinguishes the ciphertext outputs of the AEAD scheme from the outputs of a random function. See draft-irtf-cfrg-aead-limits for details.

  • Max message size:
    • AES-GCM: ~68GB, 2**36-256
    • Salsa, ChaCha, XSalsa, XChaCha: ~256GB, 2**38-64
  • Max amount of protected messages, under same key:
    • AES-GCM: 2**32.5
    • Salsa, ChaCha: 2**46, but only integrity is affected, not confidentiality
    • XSalsa, XChaCha: 2**72
  • Max amount of protected messages, across all keys:
    • AES-GCM: 2**69/B where B is max blocks encrypted by a key. Meaning 2**59 for 1KB, 2**49 for 1MB, 2**39 for 1GB
    • Salsa, ChaCha, XSalsa, XChaCha: 2**100
AES internals and block modes

cipher = encrypt(block, key). Data is split into 128-bit blocks. Encrypted in 10/12/14 rounds (128/192/256bit). Every round does:

  1. S-box, table substitution
  2. Shift rows, cyclic shift left of all rows of data array
  3. Mix columns, multiplying every column by fixed polynomial
  4. Add round key, round_key xor i-th column of array

For non-deterministic (not ECB) schemes, initialization vector (IV) is mixed to block/key; and each new round either depends on previous block's key, or on some counter.

  • ECB β€” simple deterministic replacement. Dangerous: always map x to y. See AES Penguin
  • CBC β€” key is previous round’s block. Hard to use: need proper padding, also needs MAC
  • CTR β€” counter, allows to create streaming cipher. Requires good IV. Parallelizable. OK, but no MAC
  • GCM β€” modern CTR, parallel, with MAC
  • SIV β€” synthetic initialization vector, nonce-misuse-resistant. Guarantees that, when a nonce is repeated, the only security loss is that identical plaintexts will produce identical ciphertexts.
  • XTS β€” used in hard drives. Similar to ECB (deterministic), but has [i][j] tweak arguments corresponding to sector i and 16-byte block (part of sector) j. Not authenticated!

GCM / SIV are not ideal:

  • Conservative key wear-out is 2**32 (4B) msgs
  • MAC can be forged: see Poly1305 section above. Same for SIV

Security

The library has not been independently audited yet.

It is tested against property-based, cross-library and Wycheproof vectors, and has fuzzing by Guido Vranken's cryptofuzz.

If you see anything unusual: investigate and report.

Constant-timeness

JIT-compiler and Garbage Collector make "constant time" extremely hard to achieve timing attack resistance in a scripting language. Which means any other JS library can't have constant-timeness. Even statically typed Rust, a language without GC, makes it harder to achieve constant-time for some cases. If your goal is absolute security, don't use any JS lib β€” including bindings to native ones. Use low-level libraries & languages. Nonetheless we're targetting algorithmic constant time.

Supply chain security

  • Commits are signed with PGP keys, to prevent forgery. Make sure to verify commit signatures.
  • Releases are transparent and built on GitHub CI. Make sure to verify provenance logs
  • Rare releasing is followed to ensure less re-audit need for end-users
  • Dependencies are minimized and locked-down:
    • If your app has 500 dependencies, any dep could get hacked and you'll be downloading malware with every install. We make sure to use as few dependencies as possible
    • We prevent automatic dependency updates by locking-down version ranges. Every update is checked with npm-diff
  • Dev Dependencies are only used if you want to contribute to the repo. They are disabled for end-users:
    • scure-base, micro-bmark and micro-should are developed by the same author and follow identical security practices
    • prettier (linter), fast-check (property-based testing) and typescript are used for code quality, vector generation and ts compilation. The packages are big, which makes it hard to audit their source code thoroughly and fully

Randomness

We're deferring to built-in crypto.getRandomValues which is considered cryptographically secure (CSPRNG).

In the past, browsers had bugs that made it weak: it may happen again. Implementing a userspace CSPRNG to get resilient to the weakness is even worse: there is no reliable userspace source of quality entropy.

Speed

To summarize, noble is the fastest JS implementation of Salsa, ChaCha and AES.

You can gain additional speed-up and avoid memory allocations by passing output uint8array into encrypt / decrypt methods.

Benchmark results on Apple M2 with node v20:

encrypt (64B)
β”œβ”€xsalsa20poly1305 x 485,672 ops/sec @ 2ΞΌs/op
β”œβ”€chacha20poly1305 x 466,200 ops/sec @ 2ΞΌs/op
β”œβ”€xchacha20poly1305 x 312,500 ops/sec @ 3ΞΌs/op
β”œβ”€aes-256-gcm x 151,057 ops/sec @ 6ΞΌs/op
└─aes-256-gcm-siv x 124,984 ops/sec @ 8ΞΌs/op
encrypt (1KB)
β”œβ”€xsalsa20poly1305 x 146,477 ops/sec @ 6ΞΌs/op
β”œβ”€chacha20poly1305 x 145,518 ops/sec @ 6ΞΌs/op
β”œβ”€xchacha20poly1305 x 126,119 ops/sec @ 7ΞΌs/op
β”œβ”€aes-256-gcm x 43,207 ops/sec @ 23ΞΌs/op
└─aes-256-gcm-siv x 39,363 ops/sec @ 25ΞΌs/op
encrypt (8KB)
β”œβ”€xsalsa20poly1305 x 23,773 ops/sec @ 42ΞΌs/op
β”œβ”€chacha20poly1305 x 24,134 ops/sec @ 41ΞΌs/op
β”œβ”€xchacha20poly1305 x 23,520 ops/sec @ 42ΞΌs/op
β”œβ”€aes-256-gcm x 8,420 ops/sec @ 118ΞΌs/op
└─aes-256-gcm-siv x 8,126 ops/sec @ 123ΞΌs/op
encrypt (1MB)
β”œβ”€xsalsa20poly1305 x 195 ops/sec @ 5ms/op
β”œβ”€chacha20poly1305 x 199 ops/sec @ 5ms/op
β”œβ”€xchacha20poly1305 x 198 ops/sec @ 5ms/op
β”œβ”€aes-256-gcm x 76 ops/sec @ 13ms/op
└─aes-256-gcm-siv x 78 ops/sec @ 12ms/op

Unauthenticated encryption:

encrypt (64B)
β”œβ”€salsa x 1,287,001 ops/sec @ 777ns/op
β”œβ”€chacha x 1,555,209 ops/sec @ 643ns/op
β”œβ”€xsalsa x 938,086 ops/sec @ 1ΞΌs/op
└─xchacha x 920,810 ops/sec @ 1ΞΌs/op
encrypt (1KB)
β”œβ”€salsa x 353,107 ops/sec @ 2ΞΌs/op
β”œβ”€chacha x 377,216 ops/sec @ 2ΞΌs/op
β”œβ”€xsalsa x 331,674 ops/sec @ 3ΞΌs/op
└─xchacha x 336,247 ops/sec @ 2ΞΌs/op
encrypt (8KB)
β”œβ”€salsa x 57,084 ops/sec @ 17ΞΌs/op
β”œβ”€chacha x 59,520 ops/sec @ 16ΞΌs/op
β”œβ”€xsalsa x 57,097 ops/sec @ 17ΞΌs/op
└─xchacha x 58,278 ops/sec @ 17ΞΌs/op
encrypt (1MB)
β”œβ”€salsa x 479 ops/sec @ 2ms/op
β”œβ”€chacha x 491 ops/sec @ 2ms/op
β”œβ”€xsalsa x 483 ops/sec @ 2ms/op
└─xchacha x 492 ops/sec @ 2ms/op

AES
encrypt (64B)
β”œβ”€ctr-256 x 689,179 ops/sec @ 1ΞΌs/op
β”œβ”€cbc-256 x 639,795 ops/sec @ 1ΞΌs/op
└─ecb-256 x 668,449 ops/sec @ 1ΞΌs/op
encrypt (1KB)
β”œβ”€ctr-256 x 93,668 ops/sec @ 10ΞΌs/op
β”œβ”€cbc-256 x 94,428 ops/sec @ 10ΞΌs/op
└─ecb-256 x 151,699 ops/sec @ 6ΞΌs/op
encrypt (8KB)
β”œβ”€ctr-256 x 13,342 ops/sec @ 74ΞΌs/op
β”œβ”€cbc-256 x 13,664 ops/sec @ 73ΞΌs/op
└─ecb-256 x 22,426 ops/sec @ 44ΞΌs/op
encrypt (1MB)
β”œβ”€ctr-256 x 106 ops/sec @ 9ms/op
β”œβ”€cbc-256 x 109 ops/sec @ 9ms/op
└─ecb-256 x 179 ops/sec @ 5ms/op

Compare to other implementations:

xsalsa20poly1305 (encrypt, 1MB)
β”œβ”€tweetnacl x 108 ops/sec @ 9ms/op
└─noble x 190 ops/sec @ 5ms/op

chacha20poly1305 (encrypt, 1MB)
β”œβ”€node x 1,360 ops/sec @ 735ΞΌs/op
β”œβ”€stablelib x 117 ops/sec @ 8ms/op
└─noble x 193 ops/sec @ 5ms/op

chacha (encrypt, 1MB)
β”œβ”€node x 2,035 ops/sec @ 491ΞΌs/op
β”œβ”€stablelib x 206 ops/sec @ 4ms/op
└─noble x 474 ops/sec @ 2ms/op

ctr-256 (encrypt, 1MB)
β”œβ”€node x 3,530 ops/sec @ 283ΞΌs/op
β”œβ”€stablelib x 70 ops/sec @ 14ms/op
β”œβ”€aesjs x 31 ops/sec @ 32ms/op
β”œβ”€noble-webcrypto x 4,589 ops/sec @ 217ΞΌs/op
└─noble x 107 ops/sec @ 9ms/op

cbc-256 (encrypt, 1MB)
β”œβ”€node x 993 ops/sec @ 1ms/op
β”œβ”€stablelib x 63 ops/sec @ 15ms/op
β”œβ”€aesjs x 29 ops/sec @ 34ms/op
β”œβ”€noble-webcrypto x 1,087 ops/sec @ 919ΞΌs/op
└─noble x 110 ops/sec @ 9ms/op

gcm-256 (encrypt, 1MB)
β”œβ”€node x 3,196 ops/sec @ 312ΞΌs/op
β”œβ”€stablelib x 27 ops/sec @ 36ms/op
β”œβ”€noble-webcrypto x 4,059 ops/sec @ 246ΞΌs/op
└─noble x 74 ops/sec @ 13ms/op

Upgrading

Upgrade from micro-aes-gcm package is simple:

// prepare
const key = Uint8Array.from([
  64, 196, 127, 247, 172, 2, 34, 159, 6, 241, 30,
  174, 183, 229, 41, 114, 253, 122, 119, 168, 177,
  243, 155, 236, 164, 159, 98, 72, 162, 243, 224, 195,
]);
const message = 'Hello world';

// previous
import * as aes from 'micro-aes-gcm';
const ciphertext = await aes.encrypt(key, aes.utils.utf8ToBytes(message));
const plaintext = await aes.decrypt(key, ciphertext);
console.log(aes.utils.bytesToUtf8(plaintext) === message);

// became =>

import { gcm } from '@noble/ciphers/aes';
import { bytesToUtf8, utf8ToBytes } from '@noble/ciphers/utils';
import { managedNonce } from '@noble/ciphers/webcrypto';
const aes = managedNonce(gcm)(key);
const ciphertext = aes.encrypt(utf8ToBytes(message));
const plaintext = aes.decrypt(key, ciphertext);
console.log(bytesToUtf8(plaintext) === message);

Contributing & testing

  1. Clone the repository
  2. npm install to install build dependencies like TypeScript
  3. npm run build to compile TypeScript code
  4. npm run test will execute all main tests

Resources

Check out paulmillr.com/noble for useful resources, articles, documentation and demos related to the library.

License

The MIT License (MIT)

Copyright (c) 2023 Paul Miller (https://paulmillr.com) Copyright (c) 2016 Thomas Pornin [email protected]

See LICENSE file.

More Repositories

1

chokidar

Minimal and efficient cross-platform file watching library
JavaScript
10,550
star
2

es6-shim

ECMAScript 6 compatibility shims for legacy JS engines
JavaScript
3,119
star
3

encrypted-dns

DNS over HTTPS config profiles for iOS & macOS
2,885
star
4

dotfiles

Colourful & robust configuration files and utilities for Mac, Linux & BSD
Shell
1,182
star
5

exoskeleton

Faster and leaner Backbone for your HTML5 apps
JavaScript
882
star
6

noble-secp256k1

Fastest 4KB JS implementation of secp256k1 signatures and ECDH
JavaScript
695
star
7

noble-curves

Audited & minimal JS implementation of elliptic curve cryptography.
TypeScript
588
star
8

noble-hashes

Audited & minimal JS implementation of hash functions, MACs and KDFs.
JavaScript
468
star
9

console-polyfill

Browser console methods polyfill.
JavaScript
433
star
10

noble-ed25519

Fastest 4KB JS implementation of ed25519 signatures
JavaScript
388
star
11

readdirp

Recursive version of fs.readdir with streaming api.
JavaScript
376
star
12

top-github-users

GitHub top-1000 generation script
CoffeeScript
262
star
13

ostio

Your open-source talks place.
JavaScript
248
star
14

noble-bls12-381

DEPRECATED. Use noble-curves instead. Fastest JS implementation of BLS12-381.
TypeScript
197
star
15

code-style-guides

Idiomatic, widely-used code style guides for various programming languages.
163
star
16

micro-eth-signer

Minimal library for Ethereum transactions, addresses and smart contracts.
JavaScript
148
star
17

scaffolt

Dead-simple JSON-based scaffolder.
JavaScript
127
star
18

scure-btc-signer

Audited & minimal library for creating, signing & decoding Bitcoin transactions.
JavaScript
118
star
19

scure-bip39

Secure, audited & minimal implementation of BIP39 mnemonic phrases
TypeScript
108
star
20

async-each

No-bullshit, ultra-simple, 40-lines-of-code async parallel forEach / map function for JavaScript.
JavaScript
105
star
21

qr

Minimal node.js & browser QR Code Pattern reader and generator
JavaScript
96
star
22

scure-base

Secure, audited & 0-deps implementation of bech32, base64, base32, base16 & base58
JavaScript
91
star
23

ostio-api

Your open-source talks place. Rails backend.
Ruby
71
star
24

tx-tor-broadcaster

CLI utility that broadcasts BTC, ETH, SOL, ZEC & XMR transactions through TOR using public block explorers
JavaScript
65
star
25

micro-web3

Typesafe Web3 with minimum deps: call eth contracts directly from JS. Batteries included
TypeScript
59
star
26

scure-starknet

Audited & minimal JS implementation of Starknet cryptography.
JavaScript
59
star
27

native-notifier

Use native system notifications in node.js without third-party libraries
JavaScript
56
star
28

scure-bip32

Secure, audited & minimal implementation of BIP32 hierarchical deterministic (HD) wallets.
TypeScript
50
star
29

chieftain

New generation imageboard. Built with Python / Django.
Python
50
star
30

micro-sol-signer

Create, sign & decode Solana transactions with minimum deps
JavaScript
46
star
31

loggy

Colorful stdstream dead-simple logger for node.js.
JavaScript
42
star
32

Array.prototype.find

Simple ES6 Array.prototype.find polyfill for older environments.
JavaScript
37
star
33

noble-post-quantum

Auditable & minimal JS implementation of public-key post-quantum cryptography
TypeScript
37
star
34

micro-otp

One Time Password generation via RFC 6238
JavaScript
33
star
35

pushserve

Dead-simple pushState-enabled command-line http server.
JavaScript
32
star
36

LiveScript.tmbundle

A TextMate, Chocolat and Sublime Text bundle for LiveScript
Python
30
star
37

micro-packed

Define complex binary structures using composable primitives
TypeScript
29
star
38

jage

age-encryption.org tool implementation in JavaScript
TypeScript
29
star
39

read-components

Read bower and component(1) components
JavaScript
28
star
40

mnp

My new passport
JavaScript
28
star
41

ed25519-keygen

Generate ed25519 keys for SSH, PGP (GPG), TOR, IPNS and SLIP-0010 hdkey
TypeScript
27
star
42

micro-bmark

Benchmark your node.js projects with nanosecond resolution.
JavaScript
27
star
43

Array.prototype.findIndex

Simple ES6 Array.prototype.findIndex polyfill for older environments.
JavaScript
26
star
44

github-pull-req-stats

Stats from GitHub repos about accepted / closed pull requests.
JavaScript
24
star
45

micro-aes-gcm

0-dep wrapper around webcrypto AES-GCM. Has optional RFC 8452 SIV implementation.
JavaScript
24
star
46

steg

Simple and secure steganography
TypeScript
21
star
47

micro-ordinals

Minimal JS library for ordinals and inscriptions on top of scure-btc-signer
JavaScript
21
star
48

nip44

NIP44 spec and implementations of encrypted messages for nostr
Go
20
star
49

papers

Papers i've read and / or wanted to save
17
star
50

noble-ripemd160

Noble RIPEMD160. High-security, easily auditable, 0-dep, 1-file hash function
TypeScript
17
star
51

tag-shell

Use ES6 template tags for your node.js shell commands.
JavaScript
16
star
52

micro-password-generator

Utilities for password generation and estimation with support for iOS keychain
TypeScript
16
star
53

micro-should

Simplest zero-dependency testing framework, a drop-in replacement for Mocha.
JavaScript
16
star
54

micro-promisify

Convert callback-based JS function into promise. Simple, 10LOC, no deps.
JavaScript
16
star
55

bls12-381-keygen

BLS12-381 Key Generation compatible with EIP-2333.
TypeScript
15
star
56

micro-base58

Fast and beautiful base58 encoder without dependencies.
TypeScript
15
star
57

lastfm-tools

Last.FM data reclaimer (backuper, helper and analyzer).
Ruby
14
star
58

micro-ed25519-hdkey

Minimal implementation of SLIP-0010 hierarchical deterministic (HD) wallets
JavaScript
14
star
59

fetch-streaming

Simple XMLHTTPRequest-based `fetch` implementation for streaming content.
JavaScript
13
star
60

unicode-categories

ECMAscript unicode categories. Useful for lexing.
12
star
61

micro-ftch

Tiny optimized `fetch()`-like node.js and browser method with binary/JSON, CORS, redirects & SSL pinning
JavaScript
10
star
62

noble.py

Noble cryptographic libraries in Python. High-security, easily auditable, 0-dep pubkey, scalarmult & EDDSA.
Python
9
star
63

argumentum

No-bullshit option parser for node.js.
JavaScript
8
star
64

micro-es7-shim

No-bullshit super-simple es7 collections shim for Array#includes, Object.values, Object.entries
JavaScript
7
star
65

quickly-copy-file

Quickly copy file from one path to another. No bullshit, ultra-simple, async and just one dep.
JavaScript
6
star
66

microtemplates

John Resig's micro-templates aka underscore templates. No-bullshit and small
JavaScript
6
star
67

micro-ff1

Format-preserving encryption algorithm (FPE-FF1) specified in NIST Special Publication 800-38G.
TypeScript
5
star
68

popular-user-agents

Regularly updated list of popular user agents aka browser versions
JavaScript
5
star
69

eth-vectors

Comprehensive official vectors for ETH
JavaScript
5
star
70

roy.tmbundle

Roy TextMate, Chocolat & Sublime Text 2 bundle
5
star
71

backup

Backup of all my projects in a single signed file
JavaScript
4
star
72

paulmillr

4
star
73

jsbt

Build tools for js projects. Includes tsconfigs, templates and CI workflows
JavaScript
4
star
74

qr-code-vectors

QR Code test vectors
Python
3
star
75

aesscr

Use AES-256-GCM + Scrypt to encrypt files.
JavaScript
3
star
76

universal-path

Cross-platform universal node.js `path` module replacement that works better with Windows
JavaScript
2
star
77

fcache

fs.readFile cache for node.js build systems & watchers
JavaScript
2
star
78

rn-bigint

Java
1
star
79

packed

https://github.com/paulmillr/micro-packed
1
star
80

paulmillr.github.io

JavaScript
1
star