![Malicious npm Package Typosquats react-login-page to Deploy Keylogger](https://cdn.sanity.io/images/cgdhsj6q/production/007b21d9cf9e03ae0bb3f577d1bd59b9d715645a-1024x1024.webp?w=400&fit=max&auto=format)
Research
Security News
Malicious npm Package Typosquats react-login-page to Deploy Keylogger
Socket researchers unpack a typosquatting package with malicious code that logs keystrokes and exfiltrates sensitive data to a remote server.
noble-hashes
Advanced tools
Readme
Fast, secure & minimal JS implementation of SHA2, SHA3, RIPEMD, BLAKE2/3, HMAC, HKDF, PBKDF2 & Scrypt.
n: 2**22
with 4GB arrays while other implementations crash on 2**21
or even 2**20
, maxmem
security param, onProgress
callbackThe library's initial development was funded by Ethereum Foundation.
noble-crypto — high-security, easily auditable set of contained cryptographic libraries and tools.
Use NPM in node.js / browser, or include single file from GitHub's releases page:
npm install noble-hashes
The library does not have an entry point. It allows you to select specific primitives and drop everything else. If you only want to use sha256, just use the library with rollup or other bundlers. This is done to make your bundles tiny.
const { sha256 } = require('noble-hashes/lib/sha256');
console.log(sha256(new Uint8Array([1, 2, 3])));
// Uint8Array(32) [3, 144, 88, 198, 242, 192, 203, 73, ...]
// you could also pass strings that will be UTF8-encoded to Uint8Array
console.log(sha256('abc'))); // == sha256(new TextEncoder().encode('abc'))
// sha384 is here, because it uses same internals as sha512
const { sha512, sha512_256, sha384 } = require('noble-hashes/lib/sha512');
// prettier-ignore
const {
sha3_224, sha3_256, sha3_384, sha3_512,
keccak_224, keccak_256, keccak_384, keccak_512,
shake128, shake256
} = require('noble-hashes/lib/sha3');
// prettier-ignore
const {
cshake128, cshake256, kmac128, kmac256, k12, m14
} = require('noble-hashes/lib/sha3-addons');
const { ripemd160 } = require('noble-hashes/lib/ripemd160');
const { blake3 } = require('noble-hashes/lib/blake3');
const { blake2b } = require('noble-hashes/lib/blake2b');
const { blake2s } = require('noble-hashes/lib/blake2s');
const { hmac } = require('noble-hashes/lib/hmac');
const { hkdf } = require('noble-hashes/lib/hkdf');
const { pbkdf2, pbkdf2Async } = require('noble-hashes/lib/pbkdf2');
const { scrypt, scryptAsync } = require('noble-hashes/lib/scrypt');
// small utility method that converts bytes to hex
const { bytesToHex as toHex } = require('noble-hashes/lib/utils');
console.log(toHex(sha256('abc')));
// ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
All hash functions:
Uint8Array
.Uint8Array
string
, which is automatically converted to Uint8Array
via utf8 encoding (not hex)function hash(message: Uint8Array | string): Uint8Array;
hash(new Uint8Array([1, 3]));
hash('string') == hash(new TextEncoder().encode('string'));
All hash functions can be constructed via hash.create()
method:
Hash
subclass instance, which has update()
and digest()
methodsdigest()
finalizes the hash and makes it no longer usablehash
.create()
.update(new Uint8Array([1, 3]))
.digest();
Some hash functions can also receive options
object, which can be either passed as a:
blake3('abc', { key: 'd', dkLen: 32 })
blake3.create({ context: 'e', dkLen: 32 })
import { sha256 } from 'noble-hashes/lib/sha256.js';
const h1a = sha256('abc');
const h1b = sha256
.create()
.update(Uint8Array.from([1, 2, 3]))
.digest();
import { sha512 } from 'noble-hashes/lib/sha512.js';
const h2a = sha512('abc');
const h2b = sha512
.create()
.update(Uint8Array.from([1, 2, 3]))
.digest();
// SHA512/256 variant
import { sha512_256 } from 'noble-hashes/lib/sha512.js';
const h3a = sha512_256('abc');
const h3b = sha512_256
.create()
.update(Uint8Array.from([1, 2, 3]))
.digest();
// SHA384
import { sha384 } from 'noble-hashes/lib/sha512.js';
const h4a = sha384('abc');
const h4b = sha384
.create()
.update(Uint8Array.from([1, 2, 3]))
.digest();
See RFC 4634 and the paper on SHA512/256.
import {
sha3_224,
sha3_256,
sha3_384,
sha3_512,
keccak_224,
keccak_256,
keccak_384,
keccak_512,
shake128,
shake256
} from 'noble-hashes/lib/sha3.js';
const h5a = sha3_256('abc');
const h5b = sha3_256
.create()
.update(Uint8Array.from([1, 2, 3]))
.digest();
const h6a = keccak_256('abc');
const h7a = shake128('abc', { dkLen: 512 });
const h7b = shake256('abc', { dkLen: 512 })
See (FIPS PUB 202, Website).
Check out the differences between SHA-3 and Keccak
import {
cshake128, cshake256, kmac128, kmac256, k12, m14
} from 'noble-hashes/lib/sha3-addons.js';
const h7c = cshake128('abc', { personalization: 'def' })
const h7d = cshake256('abc', { personalization: 'def' })
const h7e = kmac128('key', 'message')
const h7f = kmac256('key', 'message')
const h7h = k12('abc');
const h7g = m14('abc')
🦘 K12 and M14 are basically faster versions of Keccak.
See KangarooTwelve Paper, RFC Draft, Website and (NIST SP 800-185)
import { ripemd160 } from 'noble-hashes/lib/ripemd160.js';
// function ripemd160(data: Uint8Array): Uint8Array;
const hash8 = ripemd160('abc');
const hash9 = ripemd160()
.create()
.update(Uint8Array.from([1, 2, 3]))
.digest();
import { blake2b } from 'noble-hashes/lib/blake2b.js';
import { blake2s } from 'noble-hashes/lib/blake2s.js';
const h10a = blake2s('abc');
const b2params = { key: new Uint8Array([1]), personalization: t, salt: t, dkLen: 32 };
const h10b = blake2s('abc', b2params);
const h10c = blake2s
.create(b2params)
.update(Uint8Array.from([1, 2, 3]))
.digest();
import { blake3 } from 'noble-hashes/lib/blake3.js';
// All params are optional
const h11 = blake3('abc', { dkLen: 256, key: 'def', context: 'fji' })
See Website.
import { hmac } from 'noble-hashes/lib/hmac.js';
import { sha256 } from 'noble-hashes/lib/sha256.js';
const mac1 = hmac(sha256, 'key', 'message');
const mac2 = hmac.create(sha256, Uint8Array.from([1, 2, 3])).update(Uint8Array.from([4, 5, 6]).digest();
Matches RFC 2104.
import { hkdf } from 'noble-hashes/lib/kdf.js';
import { sha256 } from 'noble-hashes/lib/sha256.js';
import { randomBytes } from 'noble-hashes/utils.js';
const inputKey = randomBytes(32);
const salt = randomBytes(32);
const info = 'abc';
const dkLen = 32;
const hk1 = hkdf(sha256, inputKey, salt, info, dkLen);
// == same as
import { hkdf_extract, hkdf_expand } from 'noble-hashes/lib/kdf.js';
import { sha256 } from 'noble-hashes/lib/sha256.js';
const prk = hkdf_extract(sha256, inputKey, salt);
const hk2 = hkdf_expand(sha256, prk, info, dkLen);
Matches RFC 5869.
import { pbkdf2, pbkdf2Async } from 'noble-hashes/lib/pbkdf2.js';
import { sha256 } from 'noble-hashes/lib/sha256.js';
const pbkey1 = pbkdf2(sha256, 'password', 'salt', { c: 32, dkLen: 32 });
const pbkey2 = await pbkdf2Async(sha256, 'password', 'salt', { c: 32, dkLen: 32 });
const pbkey3 = await pbkdf2Async(sha256, Uint8Array.from([1, 2, 3]), Uint8Array.from([4, 5, 6]), {
c: 32,
dkLen: 32,
});
Matches RFC 2898.
import { scrypt, scryptAsync } from 'noble-hashes/lib/scrypt.js';
const scr1 = scrypt('password', 'salt', { N: 2 ** 16, r: 8, p: 1, dkLen: 32 });
const scr2 = await scryptAsync('password', 'salt', { N: 2 ** 16, r: 8, p: 1, dkLen: 32 });
const scr3 = await scryptAsync(Uint8Array.from([1, 2, 3]), Uint8Array.from([4, 5, 6]), {
N: 2 ** 22,
r: 8,
p: 1,
dkLen: 32,
onProgress(percentage) {
console.log('progress', percentage);
},
maxmem: 2 ** 32 + 128 * 8 * 1, // N * r * p * 128 + (128*r*p)
});
N, r, p
are work factors. To understand them, see the blog post.dkLen
is the length of output bytes2**10
to 2**22
and {r: 8, p: 1, dkLen: 32}
onProgress
can be used with async version of the function to report progress to a user.Memory usage of scrypt is calculated with the formula N * r * p * 128 + (128 * r * p)
, which means
{N: 2 ** 22, r: 8, p: 1}
will use 4GB + 1KB of memory. To prevent DoS, we limit scrypt to 1GB + 1KB
of RAM used,
which corresponds to {N: 2 ** 20, r: 8, p: 1}
. If you want to use higher values, increase maxmem
using the formula above.
Note: noble supports 2**22
(4GB RAM) which is the highest amount amongst JS libs. Many other implementations don't support it.
We cannot support 2**23
, because there is a limitation in JS engines that makes allocating
arrays bigger than 4GB impossible, but we're looking into other possible solutions.
import { bytesToHex as toHex, randomBytes } from 'noble-hashes/lib/scrypt.js';
console.log(toHex(randomBytes(32)));
bytesToHex
will convert Uint8Array
to a hex stringrandomBytes(bytes)
will produce cryptographically secure random Uint8Array
of length bytes
Noble is production-ready.
The library will be audited by an independent security firm in the next few months.
The library has been fuzzed by Guido Vranken's cryptofuzz. You can run the fuzzer by yourself to check it.
A note on timing attacks: JIT-compiler and Garbage Collector make "constant time" extremely hard to achieve 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.
We consider infrastructure attacks like rogue NPM modules very important; that's why it's crucial to minimize the amount of 3rd-party dependencies & native bindings. If your app uses 500 dependencies, any dep could get hacked and you'll be downloading rootkits with every npm install
. Our goal is to minimize this attack vector.
Benchmarks measured on Apple M1 with macOS 12 using 32-byte inputs.
Note that PBKDF2 and Scrypt are tested with extremely high work factor.
To run benchmarks, execute npm run bench-install
and then npm run bench
SHA256 x 1,131,221 ops/sec @ 884ns/op
SHA384 x 452,284 ops/sec @ 2μs/op
SHA512 x 451,059 ops/sec @ 2μs/op
SHA3-256, keccak256, shake256 x 185,494 ops/sec @ 5μs/op
Kangaroo12 x 300,480 ops/sec @ 3μs/op
Marsupilami14 x 269,614 ops/sec @ 3μs/op
BLAKE2b x 291,375 ops/sec @ 3μs/op
BLAKE2s x 505,561 ops/sec @ 1μs/op
BLAKE3 x 576,036 ops/sec @ 1μs/op
HMAC-SHA256 x 342,583 ops/sec @ 2μs/op
RIPEMD160 noble x 1,191,895 ops/sec @ 839ns/op
HKDF-SHA256 x 115,500 ops/sec @ 8μs/op
PBKDF2-HMAC-SHA256 262144 x 2 ops/sec @ 338ms/op
PBKDF2-HMAC-SHA512 262144 x 0 ops/sec @ 1024ms/op
Scrypt r: 8, p: 1, n: 262144 x 1 ops/sec @ 637ms/op
Compare to native node.js implementation that uses C bindings instead of pure-js code:
SHA256 32B native x 1,164,144 ops/sec @ 859ns/op
SHA384 32B native x 938,086 ops/sec @ 1μs/op
SHA512 32B native x 946,969 ops/sec @ 1μs/op
SHA3 32B native x 879,507 ops/sec @ 1μs/op
keccak, k12, m14 are not implemented
BLAKE2b 32B native x 879,507 ops/sec @ 1μs/op
BLAKE2s 32B native x 977,517 ops/sec @ 1μs/op
BLAKE3 is not implemented
RIPEMD160 32B native x 913,242 ops/sec @ 1μs/op
HMAC-SHA256 32B native x 755,287 ops/sec @ 1μs/op
HKDF-SHA256 32B native x 207,856 ops/sec @ 4μs/op
PBKDF2-HMAC-SHA256 262144 native x 23 ops/sec @ 42ms/op
Scrypt 262144 native x 1 ops/sec @ 564ms/op
Scrypt 262144 scrypt.js x 0 ops/sec @ 1678ms/op
It is possible to make this library 4x+ faster by doing code generation of full loop unrolls. We've decided against it. Reasons:
The current performance is good enough when compared to other projects; SHA256 takes only 900 nanoseconds to run.
npm install
to install build dependencies like TypeScriptnpm run build
to compile TypeScript codenpm run test
will execute all main tests. See our approach to testingnpm run test-dos
will test against DoS; by measuring function complexity. Takes ~20 minutesnpm run test-big
will execute hashing on 4GB inputs,
scrypt with 1024 different N, r, p
combinations, etc. Takes several hours. Using 8-32+ core CPU helps.The MIT License (MIT)
Copyright (c) 2021 Paul Miller (https://paulmillr.com)
See LICENSE file.
FAQs
Unknown package
We found that noble-hashes demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer 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.
Research
Security News
Socket researchers unpack a typosquatting package with malicious code that logs keystrokes and exfiltrates sensitive data to a remote server.
Security News
The JavaScript community has launched the e18e initiative to improve ecosystem performance by cleaning up dependency trees, speeding up critical parts of the ecosystem, and documenting lighter alternatives to established tools.
Product
Socket now supports four distinct alert actions instead of the previous two, and alert triaging allows users to override the actions taken for all individual alerts.