Upload via GUI (7543 Dateien)

This commit is contained in:
2026-10-22 06:59:59 +00:00
parent a57786fe54
commit 03f4fa6fbc
50 changed files with 4175 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2022 Paul Miller (https://paulmillr.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+521
View File
@@ -0,0 +1,521 @@
# noble-hashes
Audited & minimal JS implementation of hash functions, MACs and KDFs.
- 🔒 [**Audited**](#security) by an independent security firm
- 🔻 Tree-shakeable: unused code is excluded from your builds
- 🏎 Fast: hand-optimized for caveats of JS engines
- 🔍 Reliable: chained / sliding window / DoS tests and fuzzing ensure correctness
- 🔁 No unrolled loops: makes it easier to verify and reduces source code size up to 5x
- 🦘 Includes SHA, RIPEMD, BLAKE, HMAC, HKDF, PBKDF, Scrypt, Argon2 & KangarooTwelve
- 🪶 48KB for everything, 4.8KB (2.36KB gzipped) for single-hash build
Take a glance at [GitHub Discussions](https://github.com/paulmillr/noble-hashes/discussions) for questions and support.
The library's initial development was funded by [Ethereum Foundation](https://ethereum.org/).
### This library belongs to _noble_ cryptography
> **noble cryptography** — high-security, easily auditable set of contained cryptographic libraries and tools.
- Zero or minimal dependencies
- Highly readable TypeScript / JS code
- PGP-signed releases and transparent NPM builds
- All libraries:
[ciphers](https://github.com/paulmillr/noble-ciphers),
[curves](https://github.com/paulmillr/noble-curves),
[hashes](https://github.com/paulmillr/noble-hashes),
[post-quantum](https://github.com/paulmillr/noble-post-quantum),
4kb [secp256k1](https://github.com/paulmillr/noble-secp256k1) /
[ed25519](https://github.com/paulmillr/noble-ed25519)
- [Check out homepage](https://paulmillr.com/noble/)
for reading resources, documentation and apps built with noble
## Usage
> `npm install @noble/hashes`
> `deno add jsr:@noble/hashes`
> `deno doc jsr:@noble/hashes` # command-line documentation
We support all major platforms and runtimes.
For React Native, you may need a [polyfill for getRandomValues](https://github.com/LinusU/react-native-get-random-values).
A standalone file [noble-hashes.js](https://github.com/paulmillr/noble-hashes/releases) is also available.
```js
// import * from '@noble/hashes'; // Error: use sub-imports, to ensure small app size
import { sha256 } from '@noble/hashes/sha2.js'; // ESM & Common.js
sha256(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])); // returns Uint8Array
// Available modules
import { sha256, sha384, sha512, sha224, sha512_224, sha512_256 } from '@noble/hashes/sha2.js';
import { sha3_256, sha3_512, keccak_256, keccak_512, shake128, shake256 } from '@noble/hashes/sha3.js';
import { cshake256, turboshake256, kmac256, tuplehash256, k12, m14, keccakprg } from '@noble/hashes/sha3-addons.js';
import { blake3 } from '@noble/hashes/blake3.js';
import { blake2b, blake2s } from '@noble/hashes/blake2.js';
import { blake256, blake512 } from '@noble/hashes/blake1.js';
import { sha1, md5, ripemd160 } from '@noble/hashes/legacy.js';
import { hmac } from '@noble/hashes/hmac.js';
import { hkdf } from '@noble/hashes/hkdf.js';
import { pbkdf2, pbkdf2Async } from '@noble/hashes/pbkdf2.js';
import { scrypt, scryptAsync } from '@noble/hashes/scrypt.js';
import { argon2d, argon2i, argon2id } from '@noble/hashes/argon2.js';
import * as utils from '@noble/hashes/utils'; // bytesToHex, bytesToUtf8, concatBytes...
```
- [sha2: sha256, sha384, sha512](#sha2-sha256-sha384-sha512-and-others)
- [sha3: FIPS, SHAKE, Keccak](#sha3-fips-shake-keccak)
- [sha3-addons: cSHAKE, KMAC, K12, M14, TurboSHAKE](#sha3-addons-cshake-kmac-k12-m14-turboshake)
- [blake, blake2, blake3](#blake-blake2-blake3) | [legacy: sha1, md5, ripemd160](#legacy-sha1-md5-ripemd160)
- MACs: [hmac](#hmac) | [sha3-addons kmac](#sha3-addons-cshake-kmac-k12-m14-turboshake) | [blake3 key mode](#blake2b-blake2s-blake3)
- KDFs: [hkdf](#hkdf) | [pbkdf2](#pbkdf2) | [scrypt](#scrypt) | [argon2](#argon2)
- [utils](#utils)
- [Security](#security) | [Speed](#speed) | [Contributing & testing](#contributing--testing) | [License](#license)
### Implementations
Hash functions:
- `sha256()`: receive & return `Uint8Array`
- `sha256.create().update(a).update(b).digest()`: support partial updates
- `blake3.create({ context: 'e', dkLen: 32 })`: sometimes have options
- support little-endian architecture; also experimentally big-endian
- can hash up to 4GB per chunk, with any amount of chunks
#### sha2: sha256, sha384, sha512 and others
```typescript
import { sha224, sha256, sha384, sha512, sha512_224, sha512_256 } from '@noble/hashes/sha2.js';
const res = sha256(Uint8Array.from([0xbc])); // basic
for (let hash of [sha256, sha384, sha512, sha224, sha512_224, sha512_256]) {
const arr = Uint8Array.from([0x10, 0x20, 0x30]);
const a = hash(arr);
const b = hash.create().update(arr).digest();
}
```
See [RFC 4634](https://datatracker.ietf.org/doc/html/rfc4634) and
[the paper on truncated SHA512/256](https://eprint.iacr.org/2010/548.pdf).
#### sha3: FIPS, SHAKE, Keccak
```typescript
import {
keccak_224, keccak_256, keccak_384, keccak_512,
sha3_224, sha3_256, sha3_384, sha3_512,
shake128, shake256,
} from '@noble/hashes/sha3.js';
for (let hash of [
sha3_224, sha3_256, sha3_384, sha3_512,
keccak_224, keccak_256, keccak_384, keccak_512,
]) {
const arr = Uint8Array.from([0x10, 0x20, 0x30]);
const a = hash(arr);
const b = hash.create().update(arr).digest();
}
const shka = shake128(Uint8Array.from([0x10]), { dkLen: 512 });
const shkb = shake256(Uint8Array.from([0x30]), { dkLen: 512 });
```
See [FIPS-202](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf),
[Website](https://keccak.team/keccak.html).
Check out [the differences between SHA-3 and Keccak](https://crypto.stackexchange.com/questions/15727/what-are-the-key-differences-between-the-draft-sha-3-standard-and-the-keccak-sub)
#### sha3-addons: cSHAKE, KMAC, K12, M14, TurboSHAKE
```typescript
import {
cshake128, cshake256,
k12,
keccakprg,
kmac128, kmac256,
m14,
parallelhash256,
tuplehash256,
turboshake128, turboshake256
} from '@noble/hashes/sha3-addons.js';
const data = Uint8Array.from([0x10, 0x20, 0x30]);
const ec1 = cshake128(data, { personalization: 'def' });
const ec2 = cshake256(data, { personalization: 'def' });
const et1 = turboshake128(data);
const et2 = turboshake256(data, { D: 0x05 });
// tuplehash(['ab', 'c']) !== tuplehash(['a', 'bc']) !== tuplehash([data])
const et3 = tuplehash256([utf8ToBytes('ab'), utf8ToBytes('c')]);
// Not parallel in JS (similar to blake3 / k12), added for compat
const ep1 = parallelhash256(data, { blockLen: 8 });
const kk = Uint8Array.from([0xca]);
const ek10 = kmac128(kk, data);
const ek11 = kmac256(kk, data);
const ek12 = k12(data);
const ek13 = m14(data);
// pseudo-random generator, first argument is capacity. XKCP recommends 254 bits capacity for 128-bit security strength.
// * with a capacity of 254 bits.
const p = keccakprg(254);
p.feed('test');
const rand1b = p.fetch(1);
```
- Full [NIST SP 800-185](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf):
cSHAKE, KMAC, TupleHash, ParallelHash + XOF variants
- [Reduced-round Keccak](https://datatracker.ietf.org/doc/draft-irtf-cfrg-kangarootwelve/):
- 🦘 K12 aka KangarooTwelve
- M14 aka MarsupilamiFourteen
- TurboSHAKE
- [KeccakPRG](https://keccak.team/files/CSF-0.1.pdf): Pseudo-random generator based on Keccak
#### blake, blake2, blake3
```typescript
import { blake224, blake256, blake384, blake512 } from '@noble/hashes/blake1.js';
import { blake2b, blake2s } from '@noble/hashes/blake2.js';
import { blake3 } from '@noble/hashes/blake3.js';
for (let hash of [
blake224, blake256, blake384, blake512,
blake2b, blake2s, blake3
]) {
const arr = Uint8Array.from([0x10, 0x20, 0x30]);
const a = hash(arr);
const b = hash.create().update(arr).digest();
}
// blake2 advanced usage
const ab = Uint8Array.from([0x01]);
blake2s(ab);
blake2s(ab, { key: new Uint8Array(32) });
blake2s(ab, { personalization: 'pers1234' });
blake2s(ab, { salt: 'salt1234' });
blake2b(ab);
blake2b(ab, { key: new Uint8Array(64) });
blake2b(ab, { personalization: 'pers1234pers1234' });
blake2b(ab, { salt: 'salt1234salt1234' });
// blake3 advanced usage
blake3(ab);
blake3(ab, { dkLen: 256 });
blake3(ab, { key: new Uint8Array(32) });
blake3(ab, { context: 'application-name' });
```
- Blake1 is legacy hash, one of SHA3 proposals. It is rarely used anywhere. See [pdf](https://www.aumasson.jp/blake/blake.pdf).
- Blake2 is popular fast hash. blake2b focuses on 64-bit platforms while blake2s is for 8-bit to 32-bit ones. See [RFC 7693](https://datatracker.ietf.org/doc/html/rfc7693), [Website](https://www.blake2.net)
- Blake3 is faster, reduced-round blake2. See [Website & specs](https://blake3.io)
#### legacy: sha1, md5, ripemd160
SHA1 (RFC 3174), MD5 (RFC 1321) and RIPEMD160 (RFC 2286) legacy, weak hash functions.
Don't use them in a new protocol. What "weak" means:
- Collisions can be made with 2^18 effort in MD5, 2^60 in SHA1, 2^80 in RIPEMD160.
- No practical pre-image attacks (only theoretical, 2^123.4)
- HMAC seems kinda ok: https://datatracker.ietf.org/doc/html/rfc6151
```typescript
import { md5, ripemd160, sha1 } from '@noble/hashes/legacy.js';
for (let hash of [md5, ripemd160, sha1]) {
const arr = Uint8Array.from([0x10, 0x20, 0x30]);
const a = hash(arr);
const b = hash.create().update(arr).digest();
}
```
#### hmac
```typescript
import { hmac } from '@noble/hashes/hmac.js';
import { sha256 } from '@noble/hashes/sha2.js';
const key = new Uint8Array(32).fill(1);
const msg = new Uint8Array(32).fill(2);
const mac1 = hmac(sha256, key, msg);
const mac2 = hmac.create(sha256, key).update(msg).digest();
```
Matches [RFC 2104](https://datatracker.ietf.org/doc/html/rfc2104).
#### hkdf
```typescript
import { hkdf } from '@noble/hashes/hkdf.js';
import { randomBytes } from '@noble/hashes/utils.js';
import { sha256 } from '@noble/hashes/sha2.js';
const inputKey = randomBytes(32);
const salt = randomBytes(32);
const info = 'application-key';
const hk1 = hkdf(sha256, inputKey, salt, info, 32);
// == same as
import { extract, expand } from '@noble/hashes/hkdf.js';
import { sha256 } from '@noble/hashes/sha2.js';
const prk = extract(sha256, inputKey, salt);
const hk2 = expand(sha256, prk, info, 32);
```
Matches [RFC 5869](https://datatracker.ietf.org/doc/html/rfc5869).
#### pbkdf2
```typescript
import { pbkdf2, pbkdf2Async } from '@noble/hashes/pbkdf2.js';
import { sha256 } from '@noble/hashes/sha2.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](https://datatracker.ietf.org/doc/html/rfc2898).
#### scrypt
```typescript
import { scrypt, scryptAsync } from '@noble/hashes/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 ** 17,
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)
});
```
Conforms to [RFC 7914](https://datatracker.ietf.org/doc/html/rfc7914),
[Website](https://www.tarsnap.com/scrypt.html)
- `N, r, p` are work factors. To understand them, see [the blog post](https://blog.filippo.io/the-scrypt-parameters/).
`r: 8, p: 1` are common. JS doesn't support parallelization, making increasing p meaningless.
- `dkLen` is the length of output bytes e.g. `32` or `64`
- `onProgress` can be used with async version of the function to report progress to a user.
- `maxmem` prevents DoS and is limited to `1GB + 1KB` (`2**30 + 2**10`), but can be adjusted using formula: `N * r * p * 128 + (128 * r * p)`
Time it takes to derive Scrypt key under different values of N (2\*\*N) on Apple M4 (mobile phones can be 1x-4x slower):
| N pow | Time | RAM |
| ----- | ---- | ----- |
| 16 | 0.1s | 64MB |
| 17 | 0.2s | 128MB |
| 18 | 0.4s | 256MB |
| 19 | 0.8s | 512MB |
| 20 | 1.5s | 1GB |
| 21 | 3.1s | 2GB |
| 22 | 6.2s | 4GB |
| 23 | 13s | 8GB |
| 24 | 27s | 16GB |
> [!NOTE]
> We support N larger than `2**20` where available, however,
> not all JS engines support >= 2GB ArrayBuffer-s.
> When using such N, you'll need to manually adjust `maxmem`, using formula above.
> Other JS implementations don't support large N-s.
#### argon2
```ts
import { argon2d, argon2i, argon2id } from '@noble/hashes/argon2.js';
const arg1 = argon2id('password', 'saltsalt', { t: 2, m: 65536, p: 1, maxmem: 2 ** 32 - 1 });
```
Argon2 [RFC 9106](https://datatracker.ietf.org/doc/html/rfc9106) implementation.
> [!WARNING]
> Argon2 can't be fast in JS, because there is no fast Uint64Array.
> It is suggested to use [Scrypt](#scrypt) instead.
> Being 5x slower than native code means brute-forcing attackers have bigger advantage.
#### utils
```typescript
import { bytesToHex as toHex, randomBytes } from '@noble/hashes/utils';
console.log(toHex(randomBytes(32)));
```
- `bytesToHex` will convert `Uint8Array` to a hex string
- `randomBytes(bytes)` will produce cryptographically secure random `Uint8Array` of length `bytes`
## Security
The library has been independently audited:
- at version 1.0.0, in Jan 2022, by [Cure53](https://cure53.de)
- PDFs: [website](https://cure53.de/pentest-report_hashing-libs.pdf), [in-repo](./audit/2022-01-05-cure53-audit-nbl2.pdf)
- [Changes since audit](https://github.com/paulmillr/noble-hashes/compare/1.0.0..main).
- Scope: everything, besides `blake3`, `sha3-addons`, `sha1` and `argon2`, which have not been audited
- The audit has been funded by [Ethereum Foundation](https://ethereum.org/en/) with help of [Nomic Labs](https://nomiclabs.io)
It is tested against property-based, cross-library and Wycheproof vectors,
and is being fuzzed in [the separate repo](https://github.com/paulmillr/fuzzing).
If you see anything unusual: investigate and report.
### Constant-timeness
We're targetting algorithmic constant time. _JIT-compiler_ and _Garbage Collector_ make "constant time"
extremely hard to achieve [timing attack](https://en.wikipedia.org/wiki/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](https://www.chosenplaintext.ca/open-source/rust-timing-shield/security)
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.
### Memory dumping
The library shares state buffers between hash
function calls. The buffers are zeroed-out after each call. However, if an attacker
can read application memory, you are doomed in any case:
- At some point, input will be a string and strings are immutable in JS:
there is no way to overwrite them with zeros. For example: deriving
key from `scrypt(password, salt)` where password and salt are strings
- Input from a file will stay in file buffers
- Input / output will be re-used multiple times in application which means it could stay in memory
- `await anything()` will always write all internal variables (including numbers)
to memory. With async functions / Promises there are no guarantees when the code
chunk would be executed. Which means attacker can have plenty of time to read data from memory
- There is no way to guarantee anything about zeroing sensitive data without
complex tests-suite which will dump process memory and verify that there is
no sensitive data left. For JS it means testing all browsers (incl. mobile),
which is complex. And of course it will be useless without using the same
test-suite in the actual application that consumes the library
### 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](https://docs.npmjs.com/generating-provenance-statements) logs
- Use GitHub CLI to verify single-file builds:
`gh attestation verify --owner paulmillr noble-hashes.js`
- **Rare releasing** is followed to ensure less re-audit need for end-users
- **Dependencies** are minimized and locked-down: any dependency could get hacked and users will be downloading malware with every install.
- We make sure to use as few dependencies as possible
- Automatic dep updates are prevented by locking-down version ranges; diffs are checked with `npm-diff`
- **Dev Dependencies** are disabled for end-users; they are only used to develop / build the source code
For this package, there are 0 dependencies; and a few dev dependencies:
- micro-bmark, micro-should and jsbt are used for benchmarking / testing / build tooling and developed by the same author
- prettier, fast-check and typescript are used for code quality / test generation / ts compilation. It's hard to audit their source code thoroughly and fully because of their size
### Randomness
We're deferring to built-in
[crypto.getRandomValues](https://developer.mozilla.org/en-US/docs/Web/API/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.
### Quantum computers
Cryptographically relevant quantum computer, if built, will allow to
utilize Grover's algorithm to break hashes in 2^n/2 operations, instead of 2^n.
This means SHA256 should be replaced with SHA512, SHA3-256 with SHA3-512, SHAKE128 with SHAKE256 etc.
Australian ASD prohibits SHA256 and similar hashes [after 2030](https://www.cyber.gov.au/resources-business-and-government/essential-cyber-security/ism/cyber-security-guidelines/guidelines-cryptography).
## Speed
```sh
npm run bench:install && npm run bench
```
Benchmarks measured on Apple M4.
```
# 32B
sha256 x 1,968,503 ops/sec @ 508ns/op
sha512 x 740,740 ops/sec @ 1μs/op
sha3_256 x 287,686 ops/sec @ 3μs/op
sha3_512 x 288,267 ops/sec @ 3μs/op
k12 x 476,190 ops/sec @ 2μs/op
m14 x 423,190 ops/sec @ 2μs/op
blake2b x 464,252 ops/sec @ 2μs/op
blake2s x 766,871 ops/sec @ 1μs/op
blake3 x 879,507 ops/sec @ 1μs/op
# 1MB
sha256 x 331 ops/sec @ 3ms/op
sha512 x 129 ops/sec @ 7ms/op
sha3_256 x 38 ops/sec @ 25ms/op
sha3_512 x 20 ops/sec @ 47ms/op
k12 x 88 ops/sec @ 11ms/op
m14 x 62 ops/sec @ 15ms/op
blake2b x 69 ops/sec @ 14ms/op
blake2s x 57 ops/sec @ 17ms/op
blake3 x 72 ops/sec @ 13ms/op
# MAC
hmac(sha256) x 599,880 ops/sec @ 1μs/op
hmac(sha512) x 197,122 ops/sec @ 5μs/op
kmac256 x 87,981 ops/sec @ 11μs/op
blake3(key) x 796,812 ops/sec @ 1μs/op
# KDF
hkdf(sha256) x 259,942 ops/sec @ 3μs/op
blake3(context) x 424,808 ops/sec @ 2μs/op
pbkdf2(sha256, c: 2 ** 18) x 5 ops/sec @ 197ms/op
pbkdf2(sha512, c: 2 ** 18) x 1 ops/sec @ 630ms/op
scrypt(n: 2 ** 18, r: 8, p: 1) x 2 ops/sec @ 400ms/op
argon2id(t: 1, m: 256MB) 2881ms
```
Compare to native node.js implementation that uses C bindings instead of pure-js code:
```
# native (node) 32B
sha256 x 2,267,573 ops/sec
sha512 x 983,284 ops/sec
sha3_256 x 1,522,070 ops/sec
blake2b x 1,512,859 ops/sec
blake2s x 1,821,493 ops/sec
hmac(sha256) x 1,085,776 ops/sec
hkdf(sha256) x 312,109 ops/sec
# native (node) KDF
pbkdf2(sha256, c: 2 ** 18) x 5 ops/sec @ 197ms/op
pbkdf2(sha512, c: 2 ** 18) x 1 ops/sec @ 630ms/op
scrypt(n: 2 ** 18, r: 8, p: 1) x 2 ops/sec @ 378ms/op
```
It is possible to [make this library 4x+ faster](./benchmark/README.md) by
_doing code generation of full loop unrolls_. We've decided against it. Reasons:
- the library must be auditable, with minimum amount of code, and zero dependencies
- most method invocations with the lib are going to be something like hashing 32b to 64kb of data
- hashing big inputs is 10x faster with low-level languages, which means you should probably pick 'em instead
The current performance is good enough when compared to other projects; SHA256 takes only 900 nanoseconds to run.
## Contributing & testing
`test/misc` directory contains implementations of loop unrolling and md5.
- `npm install && npm run build && npm test` will build the code and run tests.
- `npm run lint` / `npm run format` will run linter / fix linter issues.
- `npm run bench` will run benchmarks, which may need their deps first (`npm run bench:install`)
- `npm run build:release` will build single file
- There is **additional** 20-min DoS test `npm run test:dos` and 2-hour "big" multicore test `npm run test:big`.
See [our approach to testing](./test/README.md)
Additional resources:
- NTT hashes are outside of scope of the library. You can view some of them in different repos:
- [Pedersen in micro-zk-proofs](https://github.com/paulmillr/micro-zk-proofs/blob/1ed5ce1253583b2e540eef7f3477fb52bf5344ff/src/pedersen.ts)
- [Poseidon in noble-curves](https://github.com/paulmillr/noble-curves/blob/3d124dd3ecec8b6634cc0b2ba1c183aded5304f9/src/abstract/poseidon.ts)
- Check out [guidelines](https://github.com/paulmillr/guidelines) for coding practices
- See [paulmillr.com/noble](https://paulmillr.com/noble/) for useful resources, articles, documentation and demos
related to the library.
## License
The MIT License (MIT)
Copyright (c) 2022 Paul Miller [(https://paulmillr.com)](https://paulmillr.com)
See LICENSE file.
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"hmac.js","sourceRoot":"","sources":["src/hmac.ts"],"names":[],"mappings":"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"}
+1
View File
@@ -0,0 +1 @@
//# sourceMappingURL=index.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":""}
+33
View File
@@ -0,0 +1,33 @@
"use strict";
/**
* Audited & minimal JS implementation of hash functions, MACs and KDFs. Check out individual modules.
* @module
* @example
```js
import {
sha256, sha384, sha512, sha224, sha512_224, sha512_256
} from '@noble/hashes/sha2';
import {
sha3_224, sha3_256, sha3_384, sha3_512,
keccak_224, keccak_256, keccak_384, keccak_512,
shake128, shake256
} from '@noble/hashes/sha3';
import {
cshake128, cshake256,
turboshake128, turboshake256,
kmac128, kmac256,
tuplehash256, parallelhash256,
k12, m14, keccakprg
} from '@noble/hashes/sha3-addons';
import { blake3 } from '@noble/hashes/blake3';
import { blake2b, blake2s } from '@noble/hashes/blake2';
import { hmac } from '@noble/hashes/hmac';
import { hkdf } from '@noble/hashes/hkdf';
import { pbkdf2, pbkdf2Async } from '@noble/hashes/pbkdf2';
import { scrypt, scryptAsync } from '@noble/hashes/scrypt';
import { md5, ripemd160, sha1 } from '@noble/hashes/legacy';
import * as utils from '@noble/hashes/utils';
```
*/
throw new Error('root module cannot be imported: import submodules instead. Check out README');
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC"}
+71
View File
@@ -0,0 +1,71 @@
/**
SHA1 (RFC 3174), MD5 (RFC 1321) and RIPEMD160 (RFC 2286) legacy, weak hash functions.
Don't use them in a new protocol. What "weak" means:
- Collisions can be made with 2^18 effort in MD5, 2^60 in SHA1, 2^80 in RIPEMD160.
- No practical pre-image attacks (only theoretical, 2^123.4)
- HMAC seems kinda ok: https://datatracker.ietf.org/doc/html/rfc6151
* @module
*/
import { HashMD } from './_md.ts';
import { type CHash } from './utils.ts';
/** SHA1 legacy hash class. */
export declare class SHA1 extends HashMD<SHA1> {
private A;
private B;
private C;
private D;
private E;
constructor();
protected get(): [number, number, number, number, number];
protected set(A: number, B: number, C: number, D: number, E: number): void;
protected process(view: DataView, offset: number): void;
protected roundClean(): void;
destroy(): void;
}
/** SHA1 (RFC 3174) legacy hash function. It was cryptographically broken. */
export declare const sha1: CHash;
/** MD5 legacy hash class. */
export declare class MD5 extends HashMD<MD5> {
private A;
private B;
private C;
private D;
constructor();
protected get(): [number, number, number, number];
protected set(A: number, B: number, C: number, D: number): void;
protected process(view: DataView, offset: number): void;
protected roundClean(): void;
destroy(): void;
}
/**
* MD5 (RFC 1321) legacy hash function. It was cryptographically broken.
* MD5 architecture is similar to SHA1, with some differences:
* - Reduced output length: 16 bytes (128 bit) instead of 20
* - 64 rounds, instead of 80
* - Little-endian: could be faster, but will require more code
* - Non-linear index selection: huge speed-up for unroll
* - Per round constants: more memory accesses, additional speed-up for unroll
*/
export declare const md5: CHash;
export declare class RIPEMD160 extends HashMD<RIPEMD160> {
private h0;
private h1;
private h2;
private h3;
private h4;
constructor();
protected get(): [number, number, number, number, number];
protected set(h0: number, h1: number, h2: number, h3: number, h4: number): void;
protected process(view: DataView, offset: number): void;
protected roundClean(): void;
destroy(): void;
}
/**
* RIPEMD-160 - a legacy hash function from 1990s.
* * https://homes.esat.kuleuven.be/~bosselae/ripemd160.html
* * https://homes.esat.kuleuven.be/~bosselae/ripemd160/pdf/AB-9601/AB-9601.pdf
*/
export declare const ripemd160: CHash;
//# sourceMappingURL=legacy.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"legacy.d.ts","sourceRoot":"","sources":["src/legacy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAO,MAAM,EAAO,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,KAAK,KAAK,EAA6B,MAAM,YAAY,CAAC;AAUnE,8BAA8B;AAC9B,qBAAa,IAAK,SAAQ,MAAM,CAAC,IAAI,CAAC;IACpC,OAAO,CAAC,CAAC,CAAkB;IAC3B,OAAO,CAAC,CAAC,CAAkB;IAC3B,OAAO,CAAC,CAAC,CAAkB;IAC3B,OAAO,CAAC,CAAC,CAAkB;IAC3B,OAAO,CAAC,CAAC,CAAkB;;IAK3B,SAAS,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;IAIzD,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI;IAO1E,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAoCvD,SAAS,CAAC,UAAU,IAAI,IAAI;IAG5B,OAAO,IAAI,IAAI;CAIhB;AAED,6EAA6E;AAC7E,eAAO,MAAM,IAAI,EAAE,KAAsD,CAAC;AAa1E,6BAA6B;AAC7B,qBAAa,GAAI,SAAQ,MAAM,CAAC,GAAG,CAAC;IAClC,OAAO,CAAC,CAAC,CAAiB;IAC1B,OAAO,CAAC,CAAC,CAAiB;IAC1B,OAAO,CAAC,CAAC,CAAiB;IAC1B,OAAO,CAAC,CAAC,CAAiB;;IAK1B,SAAS,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;IAIjD,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI;IAM/D,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAoCvD,SAAS,CAAC,UAAU,IAAI,IAAI;IAG5B,OAAO,IAAI,IAAI;CAIhB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,GAAG,EAAE,KAAqD,CAAC;AA6CxE,qBAAa,SAAU,SAAQ,MAAM,CAAC,SAAS,CAAC;IAC9C,OAAO,CAAC,EAAE,CAAkB;IAC5B,OAAO,CAAC,EAAE,CAAkB;IAC5B,OAAO,CAAC,EAAE,CAAkB;IAC5B,OAAO,CAAC,EAAE,CAAkB;IAC5B,OAAO,CAAC,EAAE,CAAkB;;IAK5B,SAAS,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;IAIzD,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI;IAO/E,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAmCvD,SAAS,CAAC,UAAU,IAAI,IAAI;IAG5B,OAAO,IAAI,IAAI;CAKhB;AAED;;;;GAIG;AACH,eAAO,MAAM,SAAS,EAAE,KAA2D,CAAC"}
+287
View File
@@ -0,0 +1,287 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ripemd160 = exports.RIPEMD160 = exports.md5 = exports.MD5 = exports.sha1 = exports.SHA1 = void 0;
/**
SHA1 (RFC 3174), MD5 (RFC 1321) and RIPEMD160 (RFC 2286) legacy, weak hash functions.
Don't use them in a new protocol. What "weak" means:
- Collisions can be made with 2^18 effort in MD5, 2^60 in SHA1, 2^80 in RIPEMD160.
- No practical pre-image attacks (only theoretical, 2^123.4)
- HMAC seems kinda ok: https://datatracker.ietf.org/doc/html/rfc6151
* @module
*/
const _md_ts_1 = require("./_md.js");
const utils_ts_1 = require("./utils.js");
/** Initial SHA1 state */
const SHA1_IV = /* @__PURE__ */ Uint32Array.from([
0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0,
]);
// Reusable temporary buffer
const SHA1_W = /* @__PURE__ */ new Uint32Array(80);
/** SHA1 legacy hash class. */
class SHA1 extends _md_ts_1.HashMD {
constructor() {
super(64, 20, 8, false);
this.A = SHA1_IV[0] | 0;
this.B = SHA1_IV[1] | 0;
this.C = SHA1_IV[2] | 0;
this.D = SHA1_IV[3] | 0;
this.E = SHA1_IV[4] | 0;
}
get() {
const { A, B, C, D, E } = this;
return [A, B, C, D, E];
}
set(A, B, C, D, E) {
this.A = A | 0;
this.B = B | 0;
this.C = C | 0;
this.D = D | 0;
this.E = E | 0;
}
process(view, offset) {
for (let i = 0; i < 16; i++, offset += 4)
SHA1_W[i] = view.getUint32(offset, false);
for (let i = 16; i < 80; i++)
SHA1_W[i] = (0, utils_ts_1.rotl)(SHA1_W[i - 3] ^ SHA1_W[i - 8] ^ SHA1_W[i - 14] ^ SHA1_W[i - 16], 1);
// Compression function main loop, 80 rounds
let { A, B, C, D, E } = this;
for (let i = 0; i < 80; i++) {
let F, K;
if (i < 20) {
F = (0, _md_ts_1.Chi)(B, C, D);
K = 0x5a827999;
}
else if (i < 40) {
F = B ^ C ^ D;
K = 0x6ed9eba1;
}
else if (i < 60) {
F = (0, _md_ts_1.Maj)(B, C, D);
K = 0x8f1bbcdc;
}
else {
F = B ^ C ^ D;
K = 0xca62c1d6;
}
const T = ((0, utils_ts_1.rotl)(A, 5) + F + E + K + SHA1_W[i]) | 0;
E = D;
D = C;
C = (0, utils_ts_1.rotl)(B, 30);
B = A;
A = T;
}
// Add the compressed chunk to the current hash value
A = (A + this.A) | 0;
B = (B + this.B) | 0;
C = (C + this.C) | 0;
D = (D + this.D) | 0;
E = (E + this.E) | 0;
this.set(A, B, C, D, E);
}
roundClean() {
(0, utils_ts_1.clean)(SHA1_W);
}
destroy() {
this.set(0, 0, 0, 0, 0);
(0, utils_ts_1.clean)(this.buffer);
}
}
exports.SHA1 = SHA1;
/** SHA1 (RFC 3174) legacy hash function. It was cryptographically broken. */
exports.sha1 = (0, utils_ts_1.createHasher)(() => new SHA1());
/** Per-round constants */
const p32 = /* @__PURE__ */ Math.pow(2, 32);
const K = /* @__PURE__ */ Array.from({ length: 64 }, (_, i) => Math.floor(p32 * Math.abs(Math.sin(i + 1))));
/** md5 initial state: same as sha1, but 4 u32 instead of 5. */
const MD5_IV = /* @__PURE__ */ SHA1_IV.slice(0, 4);
// Reusable temporary buffer
const MD5_W = /* @__PURE__ */ new Uint32Array(16);
/** MD5 legacy hash class. */
class MD5 extends _md_ts_1.HashMD {
constructor() {
super(64, 16, 8, true);
this.A = MD5_IV[0] | 0;
this.B = MD5_IV[1] | 0;
this.C = MD5_IV[2] | 0;
this.D = MD5_IV[3] | 0;
}
get() {
const { A, B, C, D } = this;
return [A, B, C, D];
}
set(A, B, C, D) {
this.A = A | 0;
this.B = B | 0;
this.C = C | 0;
this.D = D | 0;
}
process(view, offset) {
for (let i = 0; i < 16; i++, offset += 4)
MD5_W[i] = view.getUint32(offset, true);
// Compression function main loop, 64 rounds
let { A, B, C, D } = this;
for (let i = 0; i < 64; i++) {
let F, g, s;
if (i < 16) {
F = (0, _md_ts_1.Chi)(B, C, D);
g = i;
s = [7, 12, 17, 22];
}
else if (i < 32) {
F = (0, _md_ts_1.Chi)(D, B, C);
g = (5 * i + 1) % 16;
s = [5, 9, 14, 20];
}
else if (i < 48) {
F = B ^ C ^ D;
g = (3 * i + 5) % 16;
s = [4, 11, 16, 23];
}
else {
F = C ^ (B | ~D);
g = (7 * i) % 16;
s = [6, 10, 15, 21];
}
F = F + A + K[i] + MD5_W[g];
A = D;
D = C;
C = B;
B = B + (0, utils_ts_1.rotl)(F, s[i % 4]);
}
// Add the compressed chunk to the current hash value
A = (A + this.A) | 0;
B = (B + this.B) | 0;
C = (C + this.C) | 0;
D = (D + this.D) | 0;
this.set(A, B, C, D);
}
roundClean() {
(0, utils_ts_1.clean)(MD5_W);
}
destroy() {
this.set(0, 0, 0, 0);
(0, utils_ts_1.clean)(this.buffer);
}
}
exports.MD5 = MD5;
/**
* MD5 (RFC 1321) legacy hash function. It was cryptographically broken.
* MD5 architecture is similar to SHA1, with some differences:
* - Reduced output length: 16 bytes (128 bit) instead of 20
* - 64 rounds, instead of 80
* - Little-endian: could be faster, but will require more code
* - Non-linear index selection: huge speed-up for unroll
* - Per round constants: more memory accesses, additional speed-up for unroll
*/
exports.md5 = (0, utils_ts_1.createHasher)(() => new MD5());
// RIPEMD-160
const Rho160 = /* @__PURE__ */ Uint8Array.from([
7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
]);
const Id160 = /* @__PURE__ */ (() => Uint8Array.from(new Array(16).fill(0).map((_, i) => i)))();
const Pi160 = /* @__PURE__ */ (() => Id160.map((i) => (9 * i + 5) % 16))();
const idxLR = /* @__PURE__ */ (() => {
const L = [Id160];
const R = [Pi160];
const res = [L, R];
for (let i = 0; i < 4; i++)
for (let j of res)
j.push(j[i].map((k) => Rho160[k]));
return res;
})();
const idxL = /* @__PURE__ */ (() => idxLR[0])();
const idxR = /* @__PURE__ */ (() => idxLR[1])();
// const [idxL, idxR] = idxLR;
const shifts160 = /* @__PURE__ */ [
[11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8],
[12, 13, 11, 15, 6, 9, 9, 7, 12, 15, 11, 13, 7, 8, 7, 7],
[13, 15, 14, 11, 7, 7, 6, 8, 13, 14, 13, 12, 5, 5, 6, 9],
[14, 11, 12, 14, 8, 6, 5, 5, 15, 12, 15, 14, 9, 9, 8, 6],
[15, 12, 13, 13, 9, 5, 8, 6, 14, 11, 12, 11, 8, 6, 5, 5],
].map((i) => Uint8Array.from(i));
const shiftsL160 = /* @__PURE__ */ idxL.map((idx, i) => idx.map((j) => shifts160[i][j]));
const shiftsR160 = /* @__PURE__ */ idxR.map((idx, i) => idx.map((j) => shifts160[i][j]));
const Kl160 = /* @__PURE__ */ Uint32Array.from([
0x00000000, 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xa953fd4e,
]);
const Kr160 = /* @__PURE__ */ Uint32Array.from([
0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9, 0x00000000,
]);
// It's called f() in spec.
function ripemd_f(group, x, y, z) {
if (group === 0)
return x ^ y ^ z;
if (group === 1)
return (x & y) | (~x & z);
if (group === 2)
return (x | ~y) ^ z;
if (group === 3)
return (x & z) | (y & ~z);
return x ^ (y | ~z);
}
// Reusable temporary buffer
const BUF_160 = /* @__PURE__ */ new Uint32Array(16);
class RIPEMD160 extends _md_ts_1.HashMD {
constructor() {
super(64, 20, 8, true);
this.h0 = 0x67452301 | 0;
this.h1 = 0xefcdab89 | 0;
this.h2 = 0x98badcfe | 0;
this.h3 = 0x10325476 | 0;
this.h4 = 0xc3d2e1f0 | 0;
}
get() {
const { h0, h1, h2, h3, h4 } = this;
return [h0, h1, h2, h3, h4];
}
set(h0, h1, h2, h3, h4) {
this.h0 = h0 | 0;
this.h1 = h1 | 0;
this.h2 = h2 | 0;
this.h3 = h3 | 0;
this.h4 = h4 | 0;
}
process(view, offset) {
for (let i = 0; i < 16; i++, offset += 4)
BUF_160[i] = view.getUint32(offset, true);
// prettier-ignore
let al = this.h0 | 0, ar = al, bl = this.h1 | 0, br = bl, cl = this.h2 | 0, cr = cl, dl = this.h3 | 0, dr = dl, el = this.h4 | 0, er = el;
// Instead of iterating 0 to 80, we split it into 5 groups
// And use the groups in constants, functions, etc. Much simpler
for (let group = 0; group < 5; group++) {
const rGroup = 4 - group;
const hbl = Kl160[group], hbr = Kr160[group]; // prettier-ignore
const rl = idxL[group], rr = idxR[group]; // prettier-ignore
const sl = shiftsL160[group], sr = shiftsR160[group]; // prettier-ignore
for (let i = 0; i < 16; i++) {
const tl = ((0, utils_ts_1.rotl)(al + ripemd_f(group, bl, cl, dl) + BUF_160[rl[i]] + hbl, sl[i]) + el) | 0;
al = el, el = dl, dl = (0, utils_ts_1.rotl)(cl, 10) | 0, cl = bl, bl = tl; // prettier-ignore
}
// 2 loops are 10% faster
for (let i = 0; i < 16; i++) {
const tr = ((0, utils_ts_1.rotl)(ar + ripemd_f(rGroup, br, cr, dr) + BUF_160[rr[i]] + hbr, sr[i]) + er) | 0;
ar = er, er = dr, dr = (0, utils_ts_1.rotl)(cr, 10) | 0, cr = br, br = tr; // prettier-ignore
}
}
// Add the compressed chunk to the current hash value
this.set((this.h1 + cl + dr) | 0, (this.h2 + dl + er) | 0, (this.h3 + el + ar) | 0, (this.h4 + al + br) | 0, (this.h0 + bl + cr) | 0);
}
roundClean() {
(0, utils_ts_1.clean)(BUF_160);
}
destroy() {
this.destroyed = true;
(0, utils_ts_1.clean)(this.buffer);
this.set(0, 0, 0, 0, 0);
}
}
exports.RIPEMD160 = RIPEMD160;
/**
* RIPEMD-160 - a legacy hash function from 1990s.
* * https://homes.esat.kuleuven.be/~bosselae/ripemd160.html
* * https://homes.esat.kuleuven.be/~bosselae/ripemd160/pdf/AB-9601/AB-9601.pdf
*/
exports.ripemd160 = (0, utils_ts_1.createHasher)(() => new RIPEMD160());
//# sourceMappingURL=legacy.js.map
+1
View File
File diff suppressed because one or more lines are too long
+266
View File
@@ -0,0 +1,266 @@
{
"name": "@noble/hashes",
"version": "1.8.0",
"description": "Audited & minimal 0-dependency JS implementation of SHA, RIPEMD, BLAKE, HMAC, HKDF, PBKDF & Scrypt",
"files": [
"/*.js",
"/*.js.map",
"/*.d.ts",
"/*.d.ts.map",
"esm",
"src/*.ts"
],
"scripts": {
"bench": "node benchmark/noble.js",
"bench:compare": "MBENCH_DIMS='algorithm,buffer,library' node benchmark/hashes.js",
"bench:compare-hkdf": "MBENCH_DIMS='algorithm,length,library' node benchmark/hkdf.js",
"bench:compare-scrypt": "MBENCH_DIMS='iters,library' MBENCH_FILTER='async' node benchmark/scrypt.js",
"bench:install": "cd benchmark; npm install; npm install .. --install-links",
"build": "npm run build:clean; tsc && tsc -p tsconfig.cjs.json",
"build:clean": "rm -f *.{js,d.ts,js.map,d.ts.map} esm/*.{js,js.map,d.ts.map}",
"build:release": "npx jsbt esbuild test/build",
"lint": "prettier --check 'src/**/*.{js,ts}' 'test/**/*.{js,ts}'",
"format": "prettier --write 'src/**/*.{js,ts}' 'test/**/*.{js,ts}'",
"test": "node --import ./test/esm-register.js test/index.js",
"test:bun": "bun test/index.js",
"test:deno": "deno --allow-env --allow-read --import-map=./test/import_map.json test/index.js",
"test:dos": "node --import ./test/esm-register.js test/slow-dos.test.js",
"test:big": "node --import ./test/esm-register.js test/slow-big.test.js",
"test:kdf": "node --import ./test/esm-register.js test/slow-kdf.test.js"
},
"author": "Paul Miller (https://paulmillr.com)",
"homepage": "https://paulmillr.com/noble/",
"repository": {
"type": "git",
"url": "git+https://github.com/paulmillr/noble-hashes.git"
},
"license": "MIT",
"devDependencies": {
"@paulmillr/jsbt": "0.3.3",
"fast-check": "3.0.0",
"micro-bmark": "0.4.1",
"micro-should": "0.5.2",
"prettier": "3.5.3",
"typescript": "5.8.3"
},
"engines": {
"node": "^14.21.3 || >=16"
},
"exports": {
".": {
"import": "./esm/index.js",
"require": "./index.js"
},
"./crypto": {
"node": {
"import": "./esm/cryptoNode.js",
"default": "./cryptoNode.js"
},
"import": "./esm/crypto.js",
"default": "./crypto.js"
},
"./_assert": {
"import": "./esm/_assert.js",
"require": "./_assert.js"
},
"./_md": {
"import": "./esm/_md.js",
"require": "./_md.js"
},
"./argon2": {
"import": "./esm/argon2.js",
"require": "./argon2.js"
},
"./blake1": {
"import": "./esm/blake1.js",
"require": "./blake1.js"
},
"./blake2": {
"import": "./esm/blake2.js",
"require": "./blake2.js"
},
"./blake2b": {
"import": "./esm/blake2b.js",
"require": "./blake2b.js"
},
"./blake2s": {
"import": "./esm/blake2s.js",
"require": "./blake2s.js"
},
"./blake3": {
"import": "./esm/blake3.js",
"require": "./blake3.js"
},
"./eskdf": {
"import": "./esm/eskdf.js",
"require": "./eskdf.js"
},
"./hkdf": {
"import": "./esm/hkdf.js",
"require": "./hkdf.js"
},
"./hmac": {
"import": "./esm/hmac.js",
"require": "./hmac.js"
},
"./legacy": {
"import": "./esm/legacy.js",
"require": "./legacy.js"
},
"./pbkdf2": {
"import": "./esm/pbkdf2.js",
"require": "./pbkdf2.js"
},
"./ripemd160": {
"import": "./esm/ripemd160.js",
"require": "./ripemd160.js"
},
"./scrypt": {
"import": "./esm/scrypt.js",
"require": "./scrypt.js"
},
"./sha1": {
"import": "./esm/sha1.js",
"require": "./sha1.js"
},
"./sha2": {
"import": "./esm/sha2.js",
"require": "./sha2.js"
},
"./sha3-addons": {
"import": "./esm/sha3-addons.js",
"require": "./sha3-addons.js"
},
"./sha3": {
"import": "./esm/sha3.js",
"require": "./sha3.js"
},
"./sha256": {
"import": "./esm/sha256.js",
"require": "./sha256.js"
},
"./sha512": {
"import": "./esm/sha512.js",
"require": "./sha512.js"
},
"./utils": {
"import": "./esm/utils.js",
"require": "./utils.js"
},
"./_assert.js": {
"import": "./esm/_assert.js",
"require": "./_assert.js"
},
"./_md.js": {
"import": "./esm/_md.js",
"require": "./_md.js"
},
"./argon2.js": {
"import": "./esm/argon2.js",
"require": "./argon2.js"
},
"./blake1.js": {
"import": "./esm/blake1.js",
"require": "./blake1.js"
},
"./blake2.js": {
"import": "./esm/blake2.js",
"require": "./blake2.js"
},
"./blake2b.js": {
"import": "./esm/blake2b.js",
"require": "./blake2b.js"
},
"./blake2s.js": {
"import": "./esm/blake2s.js",
"require": "./blake2s.js"
},
"./blake3.js": {
"import": "./esm/blake3.js",
"require": "./blake3.js"
},
"./eskdf.js": {
"import": "./esm/eskdf.js",
"require": "./eskdf.js"
},
"./hkdf.js": {
"import": "./esm/hkdf.js",
"require": "./hkdf.js"
},
"./hmac.js": {
"import": "./esm/hmac.js",
"require": "./hmac.js"
},
"./legacy.js": {
"import": "./esm/legacy.js",
"require": "./legacy.js"
},
"./pbkdf2.js": {
"import": "./esm/pbkdf2.js",
"require": "./pbkdf2.js"
},
"./ripemd160.js": {
"import": "./esm/ripemd160.js",
"require": "./ripemd160.js"
},
"./scrypt.js": {
"import": "./esm/scrypt.js",
"require": "./scrypt.js"
},
"./sha1.js": {
"import": "./esm/sha1.js",
"require": "./sha1.js"
},
"./sha2.js": {
"import": "./esm/sha2.js",
"require": "./sha2.js"
},
"./sha3-addons.js": {
"import": "./esm/sha3-addons.js",
"require": "./sha3-addons.js"
},
"./sha3.js": {
"import": "./esm/sha3.js",
"require": "./sha3.js"
},
"./sha256.js": {
"import": "./esm/sha256.js",
"require": "./sha256.js"
},
"./sha512.js": {
"import": "./esm/sha512.js",
"require": "./sha512.js"
},
"./utils.js": {
"import": "./esm/utils.js",
"require": "./utils.js"
}
},
"sideEffects": false,
"browser": {
"node:crypto": false,
"./crypto": "./crypto.js"
},
"keywords": [
"sha",
"sha2",
"sha3",
"sha256",
"sha512",
"keccak",
"kangarootwelve",
"ripemd160",
"blake2",
"blake3",
"hmac",
"hkdf",
"pbkdf2",
"scrypt",
"kdf",
"hash",
"cryptography",
"security",
"noble"
],
"funding": "https://paulmillr.com/funding/"
}
+23
View File
@@ -0,0 +1,23 @@
import { type CHash, type KDFInput } from './utils.ts';
export type Pbkdf2Opt = {
c: number;
dkLen?: number;
asyncTick?: number;
};
/**
* PBKDF2-HMAC: RFC 2898 key derivation function
* @param hash - hash function that would be used e.g. sha256
* @param password - password from which a derived key is generated
* @param salt - cryptographic salt
* @param opts - {c, dkLen} where c is work factor and dkLen is output message size
* @example
* const key = pbkdf2(sha256, 'password', 'salt', { dkLen: 32, c: Math.pow(2, 18) });
*/
export declare function pbkdf2(hash: CHash, password: KDFInput, salt: KDFInput, opts: Pbkdf2Opt): Uint8Array;
/**
* PBKDF2-HMAC: RFC 2898 key derivation function. Async version.
* @example
* await pbkdf2Async(sha256, 'password', 'salt', { dkLen: 32, c: 500_000 });
*/
export declare function pbkdf2Async(hash: CHash, password: KDFInput, salt: KDFInput, opts: Pbkdf2Opt): Promise<Uint8Array>;
//# sourceMappingURL=pbkdf2.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"pbkdf2.d.ts","sourceRoot":"","sources":["src/pbkdf2.ts"],"names":[],"mappings":"AAMA,OAAO,EAGL,KAAK,KAAK,EACV,KAAK,QAAQ,EACd,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,SAAS,GAAG;IACtB,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAkCF;;;;;;;;GAQG;AACH,wBAAgB,MAAM,CACpB,IAAI,EAAE,KAAK,EACX,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,SAAS,GACd,UAAU,CAsBZ;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,KAAK,EACX,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,SAAS,GACd,OAAO,CAAC,UAAU,CAAC,CAsBrB"}
+101
View File
@@ -0,0 +1,101 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.pbkdf2 = pbkdf2;
exports.pbkdf2Async = pbkdf2Async;
/**
* PBKDF (RFC 2898). Can be used to create a key from password and salt.
* @module
*/
const hmac_ts_1 = require("./hmac.js");
// prettier-ignore
const utils_ts_1 = require("./utils.js");
// Common prologue and epilogue for sync/async functions
function pbkdf2Init(hash, _password, _salt, _opts) {
(0, utils_ts_1.ahash)(hash);
const opts = (0, utils_ts_1.checkOpts)({ dkLen: 32, asyncTick: 10 }, _opts);
const { c, dkLen, asyncTick } = opts;
(0, utils_ts_1.anumber)(c);
(0, utils_ts_1.anumber)(dkLen);
(0, utils_ts_1.anumber)(asyncTick);
if (c < 1)
throw new Error('iterations (c) should be >= 1');
const password = (0, utils_ts_1.kdfInputToBytes)(_password);
const salt = (0, utils_ts_1.kdfInputToBytes)(_salt);
// DK = PBKDF2(PRF, Password, Salt, c, dkLen);
const DK = new Uint8Array(dkLen);
// U1 = PRF(Password, Salt + INT_32_BE(i))
const PRF = hmac_ts_1.hmac.create(hash, password);
const PRFSalt = PRF._cloneInto().update(salt);
return { c, dkLen, asyncTick, DK, PRF, PRFSalt };
}
function pbkdf2Output(PRF, PRFSalt, DK, prfW, u) {
PRF.destroy();
PRFSalt.destroy();
if (prfW)
prfW.destroy();
(0, utils_ts_1.clean)(u);
return DK;
}
/**
* PBKDF2-HMAC: RFC 2898 key derivation function
* @param hash - hash function that would be used e.g. sha256
* @param password - password from which a derived key is generated
* @param salt - cryptographic salt
* @param opts - {c, dkLen} where c is work factor and dkLen is output message size
* @example
* const key = pbkdf2(sha256, 'password', 'salt', { dkLen: 32, c: Math.pow(2, 18) });
*/
function pbkdf2(hash, password, salt, opts) {
const { c, dkLen, DK, PRF, PRFSalt } = pbkdf2Init(hash, password, salt, opts);
let prfW; // Working copy
const arr = new Uint8Array(4);
const view = (0, utils_ts_1.createView)(arr);
const u = new Uint8Array(PRF.outputLen);
// DK = T1 + T2 + ⋯ + Tdklen/hlen
for (let ti = 1, pos = 0; pos < dkLen; ti++, pos += PRF.outputLen) {
// Ti = F(Password, Salt, c, i)
const Ti = DK.subarray(pos, pos + PRF.outputLen);
view.setInt32(0, ti, false);
// F(Password, Salt, c, i) = U1 ^ U2 ^ ⋯ ^ Uc
// U1 = PRF(Password, Salt + INT_32_BE(i))
(prfW = PRFSalt._cloneInto(prfW)).update(arr).digestInto(u);
Ti.set(u.subarray(0, Ti.length));
for (let ui = 1; ui < c; ui++) {
// Uc = PRF(Password, Uc−1)
PRF._cloneInto(prfW).update(u).digestInto(u);
for (let i = 0; i < Ti.length; i++)
Ti[i] ^= u[i];
}
}
return pbkdf2Output(PRF, PRFSalt, DK, prfW, u);
}
/**
* PBKDF2-HMAC: RFC 2898 key derivation function. Async version.
* @example
* await pbkdf2Async(sha256, 'password', 'salt', { dkLen: 32, c: 500_000 });
*/
async function pbkdf2Async(hash, password, salt, opts) {
const { c, dkLen, asyncTick, DK, PRF, PRFSalt } = pbkdf2Init(hash, password, salt, opts);
let prfW; // Working copy
const arr = new Uint8Array(4);
const view = (0, utils_ts_1.createView)(arr);
const u = new Uint8Array(PRF.outputLen);
// DK = T1 + T2 + ⋯ + Tdklen/hlen
for (let ti = 1, pos = 0; pos < dkLen; ti++, pos += PRF.outputLen) {
// Ti = F(Password, Salt, c, i)
const Ti = DK.subarray(pos, pos + PRF.outputLen);
view.setInt32(0, ti, false);
// F(Password, Salt, c, i) = U1 ^ U2 ^ ⋯ ^ Uc
// U1 = PRF(Password, Salt + INT_32_BE(i))
(prfW = PRFSalt._cloneInto(prfW)).update(arr).digestInto(u);
Ti.set(u.subarray(0, Ti.length));
await (0, utils_ts_1.asyncLoop)(c - 1, asyncTick, () => {
// Uc = PRF(Password, Uc−1)
PRF._cloneInto(prfW).update(u).digestInto(u);
for (let i = 0; i < Ti.length; i++)
Ti[i] ^= u[i];
});
}
return pbkdf2Output(PRF, PRFSalt, DK, prfW, u);
}
//# sourceMappingURL=pbkdf2.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"pbkdf2.js","sourceRoot":"","sources":["src/pbkdf2.ts"],"names":[],"mappings":"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"}
+13
View File
@@ -0,0 +1,13 @@
/**
* RIPEMD-160 legacy hash function.
* https://homes.esat.kuleuven.be/~bosselae/ripemd160.html
* https://homes.esat.kuleuven.be/~bosselae/ripemd160/pdf/AB-9601/AB-9601.pdf
* @module
* @deprecated
*/
import { RIPEMD160 as RIPEMD160n, ripemd160 as ripemd160n } from './legacy.ts';
/** @deprecated Use import from `noble/hashes/legacy` module */
export declare const RIPEMD160: typeof RIPEMD160n;
/** @deprecated Use import from `noble/hashes/legacy` module */
export declare const ripemd160: typeof ripemd160n;
//# sourceMappingURL=ripemd160.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"ripemd160.d.ts","sourceRoot":"","sources":["src/ripemd160.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,SAAS,IAAI,UAAU,EAAE,SAAS,IAAI,UAAU,EAAE,MAAM,aAAa,CAAC;AAC/E,+DAA+D;AAC/D,eAAO,MAAM,SAAS,EAAE,OAAO,UAAuB,CAAC;AACvD,+DAA+D;AAC/D,eAAO,MAAM,SAAS,EAAE,OAAO,UAAuB,CAAC"}
+16
View File
@@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ripemd160 = exports.RIPEMD160 = void 0;
/**
* RIPEMD-160 legacy hash function.
* https://homes.esat.kuleuven.be/~bosselae/ripemd160.html
* https://homes.esat.kuleuven.be/~bosselae/ripemd160/pdf/AB-9601/AB-9601.pdf
* @module
* @deprecated
*/
const legacy_ts_1 = require("./legacy.js");
/** @deprecated Use import from `noble/hashes/legacy` module */
exports.RIPEMD160 = legacy_ts_1.RIPEMD160;
/** @deprecated Use import from `noble/hashes/legacy` module */
exports.ripemd160 = legacy_ts_1.ripemd160;
//# sourceMappingURL=ripemd160.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"ripemd160.js","sourceRoot":"","sources":["src/ripemd160.ts"],"names":[],"mappings":";;;AAAA;;;;;;GAMG;AACH,2CAA+E;AAC/E,+DAA+D;AAClD,QAAA,SAAS,GAAsB,qBAAU,CAAC;AACvD,+DAA+D;AAClD,QAAA,SAAS,GAAsB,qBAAU,CAAC"}
+34
View File
@@ -0,0 +1,34 @@
import { type KDFInput } from './utils.ts';
export type ScryptOpts = {
N: number;
r: number;
p: number;
dkLen?: number;
asyncTick?: number;
maxmem?: number;
onProgress?: (progress: number) => void;
};
/**
* Scrypt KDF from RFC 7914.
* @param password - pass
* @param salt - salt
* @param opts - parameters
* - `N` is cpu/mem work factor (power of 2 e.g. 2**18)
* - `r` is block size (8 is common), fine-tunes sequential memory read size and performance
* - `p` is parallelization factor (1 is common)
* - `dkLen` is output key length in bytes e.g. 32.
* - `asyncTick` - (default: 10) max time in ms for which async function can block execution
* - `maxmem` - (default: `1024 ** 3 + 1024` aka 1GB+1KB). A limit that the app could use for scrypt
* - `onProgress` - callback function that would be executed for progress report
* @returns Derived key
* @example
* scrypt('password', 'salt', { N: 2**18, r: 8, p: 1, dkLen: 32 });
*/
export declare function scrypt(password: KDFInput, salt: KDFInput, opts: ScryptOpts): Uint8Array;
/**
* Scrypt KDF from RFC 7914. Async version.
* @example
* await scryptAsync('password', 'salt', { N: 2**18, r: 8, p: 1, dkLen: 32 });
*/
export declare function scryptAsync(password: KDFInput, salt: KDFInput, opts: ScryptOpts): Promise<Uint8Array>;
//# sourceMappingURL=scrypt.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"scrypt.d.ts","sourceRoot":"","sources":["src/scrypt.ts"],"names":[],"mappings":"AAOA,OAAO,EAGL,KAAK,QAAQ,EAGd,MAAM,YAAY,CAAC;AAuEpB,MAAM,MAAM,UAAU,GAAG;IACvB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC,CAAC;AAoFF;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,GAAG,UAAU,CA0BvF;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,UAAU,CAAC,CA2BrB"}
+232
View File
@@ -0,0 +1,232 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.scrypt = scrypt;
exports.scryptAsync = scryptAsync;
/**
* RFC 7914 Scrypt KDF. Can be used to create a key from password and salt.
* @module
*/
const pbkdf2_ts_1 = require("./pbkdf2.js");
const sha2_ts_1 = require("./sha2.js");
// prettier-ignore
const utils_ts_1 = require("./utils.js");
// The main Scrypt loop: uses Salsa extensively.
// Six versions of the function were tried, this is the fastest one.
// prettier-ignore
function XorAndSalsa(prev, pi, input, ii, out, oi) {
// Based on https://cr.yp.to/salsa20.html
// Xor blocks
let y00 = prev[pi++] ^ input[ii++], y01 = prev[pi++] ^ input[ii++];
let y02 = prev[pi++] ^ input[ii++], y03 = prev[pi++] ^ input[ii++];
let y04 = prev[pi++] ^ input[ii++], y05 = prev[pi++] ^ input[ii++];
let y06 = prev[pi++] ^ input[ii++], y07 = prev[pi++] ^ input[ii++];
let y08 = prev[pi++] ^ input[ii++], y09 = prev[pi++] ^ input[ii++];
let y10 = prev[pi++] ^ input[ii++], y11 = prev[pi++] ^ input[ii++];
let y12 = prev[pi++] ^ input[ii++], y13 = prev[pi++] ^ input[ii++];
let y14 = prev[pi++] ^ input[ii++], y15 = prev[pi++] ^ input[ii++];
// Save state to temporary variables (salsa)
let x00 = y00, x01 = y01, x02 = y02, x03 = y03, x04 = y04, x05 = y05, x06 = y06, x07 = y07, x08 = y08, x09 = y09, x10 = y10, x11 = y11, x12 = y12, x13 = y13, x14 = y14, x15 = y15;
// Main loop (salsa)
for (let i = 0; i < 8; i += 2) {
x04 ^= (0, utils_ts_1.rotl)(x00 + x12 | 0, 7);
x08 ^= (0, utils_ts_1.rotl)(x04 + x00 | 0, 9);
x12 ^= (0, utils_ts_1.rotl)(x08 + x04 | 0, 13);
x00 ^= (0, utils_ts_1.rotl)(x12 + x08 | 0, 18);
x09 ^= (0, utils_ts_1.rotl)(x05 + x01 | 0, 7);
x13 ^= (0, utils_ts_1.rotl)(x09 + x05 | 0, 9);
x01 ^= (0, utils_ts_1.rotl)(x13 + x09 | 0, 13);
x05 ^= (0, utils_ts_1.rotl)(x01 + x13 | 0, 18);
x14 ^= (0, utils_ts_1.rotl)(x10 + x06 | 0, 7);
x02 ^= (0, utils_ts_1.rotl)(x14 + x10 | 0, 9);
x06 ^= (0, utils_ts_1.rotl)(x02 + x14 | 0, 13);
x10 ^= (0, utils_ts_1.rotl)(x06 + x02 | 0, 18);
x03 ^= (0, utils_ts_1.rotl)(x15 + x11 | 0, 7);
x07 ^= (0, utils_ts_1.rotl)(x03 + x15 | 0, 9);
x11 ^= (0, utils_ts_1.rotl)(x07 + x03 | 0, 13);
x15 ^= (0, utils_ts_1.rotl)(x11 + x07 | 0, 18);
x01 ^= (0, utils_ts_1.rotl)(x00 + x03 | 0, 7);
x02 ^= (0, utils_ts_1.rotl)(x01 + x00 | 0, 9);
x03 ^= (0, utils_ts_1.rotl)(x02 + x01 | 0, 13);
x00 ^= (0, utils_ts_1.rotl)(x03 + x02 | 0, 18);
x06 ^= (0, utils_ts_1.rotl)(x05 + x04 | 0, 7);
x07 ^= (0, utils_ts_1.rotl)(x06 + x05 | 0, 9);
x04 ^= (0, utils_ts_1.rotl)(x07 + x06 | 0, 13);
x05 ^= (0, utils_ts_1.rotl)(x04 + x07 | 0, 18);
x11 ^= (0, utils_ts_1.rotl)(x10 + x09 | 0, 7);
x08 ^= (0, utils_ts_1.rotl)(x11 + x10 | 0, 9);
x09 ^= (0, utils_ts_1.rotl)(x08 + x11 | 0, 13);
x10 ^= (0, utils_ts_1.rotl)(x09 + x08 | 0, 18);
x12 ^= (0, utils_ts_1.rotl)(x15 + x14 | 0, 7);
x13 ^= (0, utils_ts_1.rotl)(x12 + x15 | 0, 9);
x14 ^= (0, utils_ts_1.rotl)(x13 + x12 | 0, 13);
x15 ^= (0, utils_ts_1.rotl)(x14 + x13 | 0, 18);
}
// Write output (salsa)
out[oi++] = (y00 + x00) | 0;
out[oi++] = (y01 + x01) | 0;
out[oi++] = (y02 + x02) | 0;
out[oi++] = (y03 + x03) | 0;
out[oi++] = (y04 + x04) | 0;
out[oi++] = (y05 + x05) | 0;
out[oi++] = (y06 + x06) | 0;
out[oi++] = (y07 + x07) | 0;
out[oi++] = (y08 + x08) | 0;
out[oi++] = (y09 + x09) | 0;
out[oi++] = (y10 + x10) | 0;
out[oi++] = (y11 + x11) | 0;
out[oi++] = (y12 + x12) | 0;
out[oi++] = (y13 + x13) | 0;
out[oi++] = (y14 + x14) | 0;
out[oi++] = (y15 + x15) | 0;
}
function BlockMix(input, ii, out, oi, r) {
// The block B is r 128-byte chunks (which is equivalent of 2r 64-byte chunks)
let head = oi + 0;
let tail = oi + 16 * r;
for (let i = 0; i < 16; i++)
out[tail + i] = input[ii + (2 * r - 1) * 16 + i]; // X ← B[2r−1]
for (let i = 0; i < r; i++, head += 16, ii += 16) {
// We write odd & even Yi at same time. Even: 0bXXXXX0 Odd: 0bXXXXX1
XorAndSalsa(out, tail, input, ii, out, head); // head[i] = Salsa(blockIn[2*i] ^ tail[i-1])
if (i > 0)
tail += 16; // First iteration overwrites tmp value in tail
XorAndSalsa(out, head, input, (ii += 16), out, tail); // tail[i] = Salsa(blockIn[2*i+1] ^ head[i])
}
}
// Common prologue and epilogue for sync/async functions
function scryptInit(password, salt, _opts) {
// Maxmem - 1GB+1KB by default
const opts = (0, utils_ts_1.checkOpts)({
dkLen: 32,
asyncTick: 10,
maxmem: 1024 ** 3 + 1024,
}, _opts);
const { N, r, p, dkLen, asyncTick, maxmem, onProgress } = opts;
(0, utils_ts_1.anumber)(N);
(0, utils_ts_1.anumber)(r);
(0, utils_ts_1.anumber)(p);
(0, utils_ts_1.anumber)(dkLen);
(0, utils_ts_1.anumber)(asyncTick);
(0, utils_ts_1.anumber)(maxmem);
if (onProgress !== undefined && typeof onProgress !== 'function')
throw new Error('progressCb should be function');
const blockSize = 128 * r;
const blockSize32 = blockSize / 4;
// Max N is 2^32 (Integrify is 32-bit). Real limit is 2^22: JS engines Uint8Array limit is 4GB in 2024.
// Spec check `N >= 2^(blockSize / 8)` is not done for compat with popular libs,
// which used incorrect r: 1, p: 8. Also, the check seems to be a spec error:
// https://www.rfc-editor.org/errata_search.php?rfc=7914
const pow32 = Math.pow(2, 32);
if (N <= 1 || (N & (N - 1)) !== 0 || N > pow32) {
throw new Error('Scrypt: N must be larger than 1, a power of 2, and less than 2^32');
}
if (p < 0 || p > ((pow32 - 1) * 32) / blockSize) {
throw new Error('Scrypt: p must be a positive integer less than or equal to ((2^32 - 1) * 32) / (128 * r)');
}
if (dkLen < 0 || dkLen > (pow32 - 1) * 32) {
throw new Error('Scrypt: dkLen should be positive integer less than or equal to (2^32 - 1) * 32');
}
const memUsed = blockSize * (N + p);
if (memUsed > maxmem) {
throw new Error('Scrypt: memused is bigger than maxMem. Expected 128 * r * (N + p) > maxmem of ' + maxmem);
}
// [B0...Bp−1] ← PBKDF2HMAC-SHA256(Passphrase, Salt, 1, blockSize*ParallelizationFactor)
// Since it has only one iteration there is no reason to use async variant
const B = (0, pbkdf2_ts_1.pbkdf2)(sha2_ts_1.sha256, password, salt, { c: 1, dkLen: blockSize * p });
const B32 = (0, utils_ts_1.u32)(B);
// Re-used between parallel iterations. Array(iterations) of B
const V = (0, utils_ts_1.u32)(new Uint8Array(blockSize * N));
const tmp = (0, utils_ts_1.u32)(new Uint8Array(blockSize));
let blockMixCb = () => { };
if (onProgress) {
const totalBlockMix = 2 * N * p;
// Invoke callback if progress changes from 10.01 to 10.02
// Allows to draw smooth progress bar on up to 8K screen
const callbackPer = Math.max(Math.floor(totalBlockMix / 10000), 1);
let blockMixCnt = 0;
blockMixCb = () => {
blockMixCnt++;
if (onProgress && (!(blockMixCnt % callbackPer) || blockMixCnt === totalBlockMix))
onProgress(blockMixCnt / totalBlockMix);
};
}
return { N, r, p, dkLen, blockSize32, V, B32, B, tmp, blockMixCb, asyncTick };
}
function scryptOutput(password, dkLen, B, V, tmp) {
const res = (0, pbkdf2_ts_1.pbkdf2)(sha2_ts_1.sha256, password, B, { c: 1, dkLen });
(0, utils_ts_1.clean)(B, V, tmp);
return res;
}
/**
* Scrypt KDF from RFC 7914.
* @param password - pass
* @param salt - salt
* @param opts - parameters
* - `N` is cpu/mem work factor (power of 2 e.g. 2**18)
* - `r` is block size (8 is common), fine-tunes sequential memory read size and performance
* - `p` is parallelization factor (1 is common)
* - `dkLen` is output key length in bytes e.g. 32.
* - `asyncTick` - (default: 10) max time in ms for which async function can block execution
* - `maxmem` - (default: `1024 ** 3 + 1024` aka 1GB+1KB). A limit that the app could use for scrypt
* - `onProgress` - callback function that would be executed for progress report
* @returns Derived key
* @example
* scrypt('password', 'salt', { N: 2**18, r: 8, p: 1, dkLen: 32 });
*/
function scrypt(password, salt, opts) {
const { N, r, p, dkLen, blockSize32, V, B32, B, tmp, blockMixCb } = scryptInit(password, salt, opts);
(0, utils_ts_1.swap32IfBE)(B32);
for (let pi = 0; pi < p; pi++) {
const Pi = blockSize32 * pi;
for (let i = 0; i < blockSize32; i++)
V[i] = B32[Pi + i]; // V[0] = B[i]
for (let i = 0, pos = 0; i < N - 1; i++) {
BlockMix(V, pos, V, (pos += blockSize32), r); // V[i] = BlockMix(V[i-1]);
blockMixCb();
}
BlockMix(V, (N - 1) * blockSize32, B32, Pi, r); // Process last element
blockMixCb();
for (let i = 0; i < N; i++) {
// First u32 of the last 64-byte block (u32 is LE)
const j = B32[Pi + blockSize32 - 16] % N; // j = Integrify(X) % iterations
for (let k = 0; k < blockSize32; k++)
tmp[k] = B32[Pi + k] ^ V[j * blockSize32 + k]; // tmp = B ^ V[j]
BlockMix(tmp, 0, B32, Pi, r); // B = BlockMix(B ^ V[j])
blockMixCb();
}
}
(0, utils_ts_1.swap32IfBE)(B32);
return scryptOutput(password, dkLen, B, V, tmp);
}
/**
* Scrypt KDF from RFC 7914. Async version.
* @example
* await scryptAsync('password', 'salt', { N: 2**18, r: 8, p: 1, dkLen: 32 });
*/
async function scryptAsync(password, salt, opts) {
const { N, r, p, dkLen, blockSize32, V, B32, B, tmp, blockMixCb, asyncTick } = scryptInit(password, salt, opts);
(0, utils_ts_1.swap32IfBE)(B32);
for (let pi = 0; pi < p; pi++) {
const Pi = blockSize32 * pi;
for (let i = 0; i < blockSize32; i++)
V[i] = B32[Pi + i]; // V[0] = B[i]
let pos = 0;
await (0, utils_ts_1.asyncLoop)(N - 1, asyncTick, () => {
BlockMix(V, pos, V, (pos += blockSize32), r); // V[i] = BlockMix(V[i-1]);
blockMixCb();
});
BlockMix(V, (N - 1) * blockSize32, B32, Pi, r); // Process last element
blockMixCb();
await (0, utils_ts_1.asyncLoop)(N, asyncTick, () => {
// First u32 of the last 64-byte block (u32 is LE)
const j = B32[Pi + blockSize32 - 16] % N; // j = Integrify(X) % iterations
for (let k = 0; k < blockSize32; k++)
tmp[k] = B32[Pi + k] ^ V[j * blockSize32 + k]; // tmp = B ^ V[j]
BlockMix(tmp, 0, B32, Pi, r); // B = BlockMix(B ^ V[j])
blockMixCb();
});
}
(0, utils_ts_1.swap32IfBE)(B32);
return scryptOutput(password, dkLen, B, V, tmp);
}
//# sourceMappingURL=scrypt.js.map
+1
View File
File diff suppressed because one or more lines are too long
+11
View File
@@ -0,0 +1,11 @@
/**
* SHA1 (RFC 3174) legacy hash function.
* @module
* @deprecated
*/
import { SHA1 as SHA1n, sha1 as sha1n } from './legacy.ts';
/** @deprecated Use import from `noble/hashes/legacy` module */
export declare const SHA1: typeof SHA1n;
/** @deprecated Use import from `noble/hashes/legacy` module */
export declare const sha1: typeof sha1n;
//# sourceMappingURL=sha1.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"sha1.d.ts","sourceRoot":"","sources":["src/sha1.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,IAAI,IAAI,KAAK,EAAE,IAAI,IAAI,KAAK,EAAE,MAAM,aAAa,CAAC;AAC3D,+DAA+D;AAC/D,eAAO,MAAM,IAAI,EAAE,OAAO,KAAa,CAAC;AACxC,+DAA+D;AAC/D,eAAO,MAAM,IAAI,EAAE,OAAO,KAAa,CAAC"}
+14
View File
@@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.sha1 = exports.SHA1 = void 0;
/**
* SHA1 (RFC 3174) legacy hash function.
* @module
* @deprecated
*/
const legacy_ts_1 = require("./legacy.js");
/** @deprecated Use import from `noble/hashes/legacy` module */
exports.SHA1 = legacy_ts_1.SHA1;
/** @deprecated Use import from `noble/hashes/legacy` module */
exports.sha1 = legacy_ts_1.sha1;
//# sourceMappingURL=sha1.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"sha1.js","sourceRoot":"","sources":["src/sha1.ts"],"names":[],"mappings":";;;AAAA;;;;GAIG;AACH,2CAA2D;AAC3D,+DAA+D;AAClD,QAAA,IAAI,GAAiB,gBAAK,CAAC;AACxC,+DAA+D;AAClD,QAAA,IAAI,GAAiB,gBAAK,CAAC"}
+159
View File
@@ -0,0 +1,159 @@
/**
* SHA2 hash function. A.k.a. sha256, sha384, sha512, sha512_224, sha512_256.
* SHA256 is the fastest hash implementable in JS, even faster than Blake3.
* Check out [RFC 4634](https://datatracker.ietf.org/doc/html/rfc4634) and
* [FIPS 180-4](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf).
* @module
*/
import { HashMD } from './_md.ts';
import { type CHash } from './utils.ts';
export declare class SHA256 extends HashMD<SHA256> {
protected A: number;
protected B: number;
protected C: number;
protected D: number;
protected E: number;
protected F: number;
protected G: number;
protected H: number;
constructor(outputLen?: number);
protected get(): [number, number, number, number, number, number, number, number];
protected set(A: number, B: number, C: number, D: number, E: number, F: number, G: number, H: number): void;
protected process(view: DataView, offset: number): void;
protected roundClean(): void;
destroy(): void;
}
export declare class SHA224 extends SHA256 {
protected A: number;
protected B: number;
protected C: number;
protected D: number;
protected E: number;
protected F: number;
protected G: number;
protected H: number;
constructor();
}
export declare class SHA512 extends HashMD<SHA512> {
protected Ah: number;
protected Al: number;
protected Bh: number;
protected Bl: number;
protected Ch: number;
protected Cl: number;
protected Dh: number;
protected Dl: number;
protected Eh: number;
protected El: number;
protected Fh: number;
protected Fl: number;
protected Gh: number;
protected Gl: number;
protected Hh: number;
protected Hl: number;
constructor(outputLen?: number);
protected get(): [
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number
];
protected set(Ah: number, Al: number, Bh: number, Bl: number, Ch: number, Cl: number, Dh: number, Dl: number, Eh: number, El: number, Fh: number, Fl: number, Gh: number, Gl: number, Hh: number, Hl: number): void;
protected process(view: DataView, offset: number): void;
protected roundClean(): void;
destroy(): void;
}
export declare class SHA384 extends SHA512 {
protected Ah: number;
protected Al: number;
protected Bh: number;
protected Bl: number;
protected Ch: number;
protected Cl: number;
protected Dh: number;
protected Dl: number;
protected Eh: number;
protected El: number;
protected Fh: number;
protected Fl: number;
protected Gh: number;
protected Gl: number;
protected Hh: number;
protected Hl: number;
constructor();
}
export declare class SHA512_224 extends SHA512 {
protected Ah: number;
protected Al: number;
protected Bh: number;
protected Bl: number;
protected Ch: number;
protected Cl: number;
protected Dh: number;
protected Dl: number;
protected Eh: number;
protected El: number;
protected Fh: number;
protected Fl: number;
protected Gh: number;
protected Gl: number;
protected Hh: number;
protected Hl: number;
constructor();
}
export declare class SHA512_256 extends SHA512 {
protected Ah: number;
protected Al: number;
protected Bh: number;
protected Bl: number;
protected Ch: number;
protected Cl: number;
protected Dh: number;
protected Dl: number;
protected Eh: number;
protected El: number;
protected Fh: number;
protected Fl: number;
protected Gh: number;
protected Gl: number;
protected Hh: number;
protected Hl: number;
constructor();
}
/**
* SHA2-256 hash function from RFC 4634.
*
* It is the fastest JS hash, even faster than Blake3.
* To break sha256 using birthday attack, attackers need to try 2^128 hashes.
* BTC network is doing 2^70 hashes/sec (2^95 hashes/year) as per 2025.
*/
export declare const sha256: CHash;
/** SHA2-224 hash function from RFC 4634 */
export declare const sha224: CHash;
/** SHA2-512 hash function from RFC 4634. */
export declare const sha512: CHash;
/** SHA2-384 hash function from RFC 4634. */
export declare const sha384: CHash;
/**
* SHA2-512/256 "truncated" hash function, with improved resistance to length extension attacks.
* See the paper on [truncated SHA512](https://eprint.iacr.org/2010/548.pdf).
*/
export declare const sha512_256: CHash;
/**
* SHA2-512/224 "truncated" hash function, with improved resistance to length extension attacks.
* See the paper on [truncated SHA512](https://eprint.iacr.org/2010/548.pdf).
*/
export declare const sha512_224: CHash;
//# sourceMappingURL=sha2.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"sha2.d.ts","sourceRoot":"","sources":["src/sha2.ts"],"names":[],"mappings":"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"}
+384
View File
@@ -0,0 +1,384 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.sha512_224 = exports.sha512_256 = exports.sha384 = exports.sha512 = exports.sha224 = exports.sha256 = exports.SHA512_256 = exports.SHA512_224 = exports.SHA384 = exports.SHA512 = exports.SHA224 = exports.SHA256 = void 0;
/**
* SHA2 hash function. A.k.a. sha256, sha384, sha512, sha512_224, sha512_256.
* SHA256 is the fastest hash implementable in JS, even faster than Blake3.
* Check out [RFC 4634](https://datatracker.ietf.org/doc/html/rfc4634) and
* [FIPS 180-4](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf).
* @module
*/
const _md_ts_1 = require("./_md.js");
const u64 = require("./_u64.js");
const utils_ts_1 = require("./utils.js");
/**
* Round constants:
* First 32 bits of fractional parts of the cube roots of the first 64 primes 2..311)
*/
// prettier-ignore
const SHA256_K = /* @__PURE__ */ Uint32Array.from([
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
]);
/** Reusable temporary buffer. "W" comes straight from spec. */
const SHA256_W = /* @__PURE__ */ new Uint32Array(64);
class SHA256 extends _md_ts_1.HashMD {
constructor(outputLen = 32) {
super(64, outputLen, 8, false);
// We cannot use array here since array allows indexing by variable
// which means optimizer/compiler cannot use registers.
this.A = _md_ts_1.SHA256_IV[0] | 0;
this.B = _md_ts_1.SHA256_IV[1] | 0;
this.C = _md_ts_1.SHA256_IV[2] | 0;
this.D = _md_ts_1.SHA256_IV[3] | 0;
this.E = _md_ts_1.SHA256_IV[4] | 0;
this.F = _md_ts_1.SHA256_IV[5] | 0;
this.G = _md_ts_1.SHA256_IV[6] | 0;
this.H = _md_ts_1.SHA256_IV[7] | 0;
}
get() {
const { A, B, C, D, E, F, G, H } = this;
return [A, B, C, D, E, F, G, H];
}
// prettier-ignore
set(A, B, C, D, E, F, G, H) {
this.A = A | 0;
this.B = B | 0;
this.C = C | 0;
this.D = D | 0;
this.E = E | 0;
this.F = F | 0;
this.G = G | 0;
this.H = H | 0;
}
process(view, offset) {
// Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array
for (let i = 0; i < 16; i++, offset += 4)
SHA256_W[i] = view.getUint32(offset, false);
for (let i = 16; i < 64; i++) {
const W15 = SHA256_W[i - 15];
const W2 = SHA256_W[i - 2];
const s0 = (0, utils_ts_1.rotr)(W15, 7) ^ (0, utils_ts_1.rotr)(W15, 18) ^ (W15 >>> 3);
const s1 = (0, utils_ts_1.rotr)(W2, 17) ^ (0, utils_ts_1.rotr)(W2, 19) ^ (W2 >>> 10);
SHA256_W[i] = (s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16]) | 0;
}
// Compression function main loop, 64 rounds
let { A, B, C, D, E, F, G, H } = this;
for (let i = 0; i < 64; i++) {
const sigma1 = (0, utils_ts_1.rotr)(E, 6) ^ (0, utils_ts_1.rotr)(E, 11) ^ (0, utils_ts_1.rotr)(E, 25);
const T1 = (H + sigma1 + (0, _md_ts_1.Chi)(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0;
const sigma0 = (0, utils_ts_1.rotr)(A, 2) ^ (0, utils_ts_1.rotr)(A, 13) ^ (0, utils_ts_1.rotr)(A, 22);
const T2 = (sigma0 + (0, _md_ts_1.Maj)(A, B, C)) | 0;
H = G;
G = F;
F = E;
E = (D + T1) | 0;
D = C;
C = B;
B = A;
A = (T1 + T2) | 0;
}
// Add the compressed chunk to the current hash value
A = (A + this.A) | 0;
B = (B + this.B) | 0;
C = (C + this.C) | 0;
D = (D + this.D) | 0;
E = (E + this.E) | 0;
F = (F + this.F) | 0;
G = (G + this.G) | 0;
H = (H + this.H) | 0;
this.set(A, B, C, D, E, F, G, H);
}
roundClean() {
(0, utils_ts_1.clean)(SHA256_W);
}
destroy() {
this.set(0, 0, 0, 0, 0, 0, 0, 0);
(0, utils_ts_1.clean)(this.buffer);
}
}
exports.SHA256 = SHA256;
class SHA224 extends SHA256 {
constructor() {
super(28);
this.A = _md_ts_1.SHA224_IV[0] | 0;
this.B = _md_ts_1.SHA224_IV[1] | 0;
this.C = _md_ts_1.SHA224_IV[2] | 0;
this.D = _md_ts_1.SHA224_IV[3] | 0;
this.E = _md_ts_1.SHA224_IV[4] | 0;
this.F = _md_ts_1.SHA224_IV[5] | 0;
this.G = _md_ts_1.SHA224_IV[6] | 0;
this.H = _md_ts_1.SHA224_IV[7] | 0;
}
}
exports.SHA224 = SHA224;
// SHA2-512 is slower than sha256 in js because u64 operations are slow.
// Round contants
// First 32 bits of the fractional parts of the cube roots of the first 80 primes 2..409
// prettier-ignore
const K512 = /* @__PURE__ */ (() => u64.split([
'0x428a2f98d728ae22', '0x7137449123ef65cd', '0xb5c0fbcfec4d3b2f', '0xe9b5dba58189dbbc',
'0x3956c25bf348b538', '0x59f111f1b605d019', '0x923f82a4af194f9b', '0xab1c5ed5da6d8118',
'0xd807aa98a3030242', '0x12835b0145706fbe', '0x243185be4ee4b28c', '0x550c7dc3d5ffb4e2',
'0x72be5d74f27b896f', '0x80deb1fe3b1696b1', '0x9bdc06a725c71235', '0xc19bf174cf692694',
'0xe49b69c19ef14ad2', '0xefbe4786384f25e3', '0x0fc19dc68b8cd5b5', '0x240ca1cc77ac9c65',
'0x2de92c6f592b0275', '0x4a7484aa6ea6e483', '0x5cb0a9dcbd41fbd4', '0x76f988da831153b5',
'0x983e5152ee66dfab', '0xa831c66d2db43210', '0xb00327c898fb213f', '0xbf597fc7beef0ee4',
'0xc6e00bf33da88fc2', '0xd5a79147930aa725', '0x06ca6351e003826f', '0x142929670a0e6e70',
'0x27b70a8546d22ffc', '0x2e1b21385c26c926', '0x4d2c6dfc5ac42aed', '0x53380d139d95b3df',
'0x650a73548baf63de', '0x766a0abb3c77b2a8', '0x81c2c92e47edaee6', '0x92722c851482353b',
'0xa2bfe8a14cf10364', '0xa81a664bbc423001', '0xc24b8b70d0f89791', '0xc76c51a30654be30',
'0xd192e819d6ef5218', '0xd69906245565a910', '0xf40e35855771202a', '0x106aa07032bbd1b8',
'0x19a4c116b8d2d0c8', '0x1e376c085141ab53', '0x2748774cdf8eeb99', '0x34b0bcb5e19b48a8',
'0x391c0cb3c5c95a63', '0x4ed8aa4ae3418acb', '0x5b9cca4f7763e373', '0x682e6ff3d6b2b8a3',
'0x748f82ee5defb2fc', '0x78a5636f43172f60', '0x84c87814a1f0ab72', '0x8cc702081a6439ec',
'0x90befffa23631e28', '0xa4506cebde82bde9', '0xbef9a3f7b2c67915', '0xc67178f2e372532b',
'0xca273eceea26619c', '0xd186b8c721c0c207', '0xeada7dd6cde0eb1e', '0xf57d4f7fee6ed178',
'0x06f067aa72176fba', '0x0a637dc5a2c898a6', '0x113f9804bef90dae', '0x1b710b35131c471b',
'0x28db77f523047d84', '0x32caab7b40c72493', '0x3c9ebe0a15c9bebc', '0x431d67c49c100d4c',
'0x4cc5d4becb3e42b6', '0x597f299cfc657e2a', '0x5fcb6fab3ad6faec', '0x6c44198c4a475817'
].map(n => BigInt(n))))();
const SHA512_Kh = /* @__PURE__ */ (() => K512[0])();
const SHA512_Kl = /* @__PURE__ */ (() => K512[1])();
// Reusable temporary buffers
const SHA512_W_H = /* @__PURE__ */ new Uint32Array(80);
const SHA512_W_L = /* @__PURE__ */ new Uint32Array(80);
class SHA512 extends _md_ts_1.HashMD {
constructor(outputLen = 64) {
super(128, outputLen, 16, false);
// We cannot use array here since array allows indexing by variable
// which means optimizer/compiler cannot use registers.
// h -- high 32 bits, l -- low 32 bits
this.Ah = _md_ts_1.SHA512_IV[0] | 0;
this.Al = _md_ts_1.SHA512_IV[1] | 0;
this.Bh = _md_ts_1.SHA512_IV[2] | 0;
this.Bl = _md_ts_1.SHA512_IV[3] | 0;
this.Ch = _md_ts_1.SHA512_IV[4] | 0;
this.Cl = _md_ts_1.SHA512_IV[5] | 0;
this.Dh = _md_ts_1.SHA512_IV[6] | 0;
this.Dl = _md_ts_1.SHA512_IV[7] | 0;
this.Eh = _md_ts_1.SHA512_IV[8] | 0;
this.El = _md_ts_1.SHA512_IV[9] | 0;
this.Fh = _md_ts_1.SHA512_IV[10] | 0;
this.Fl = _md_ts_1.SHA512_IV[11] | 0;
this.Gh = _md_ts_1.SHA512_IV[12] | 0;
this.Gl = _md_ts_1.SHA512_IV[13] | 0;
this.Hh = _md_ts_1.SHA512_IV[14] | 0;
this.Hl = _md_ts_1.SHA512_IV[15] | 0;
}
// prettier-ignore
get() {
const { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this;
return [Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl];
}
// prettier-ignore
set(Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl) {
this.Ah = Ah | 0;
this.Al = Al | 0;
this.Bh = Bh | 0;
this.Bl = Bl | 0;
this.Ch = Ch | 0;
this.Cl = Cl | 0;
this.Dh = Dh | 0;
this.Dl = Dl | 0;
this.Eh = Eh | 0;
this.El = El | 0;
this.Fh = Fh | 0;
this.Fl = Fl | 0;
this.Gh = Gh | 0;
this.Gl = Gl | 0;
this.Hh = Hh | 0;
this.Hl = Hl | 0;
}
process(view, offset) {
// Extend the first 16 words into the remaining 64 words w[16..79] of the message schedule array
for (let i = 0; i < 16; i++, offset += 4) {
SHA512_W_H[i] = view.getUint32(offset);
SHA512_W_L[i] = view.getUint32((offset += 4));
}
for (let i = 16; i < 80; i++) {
// s0 := (w[i-15] rightrotate 1) xor (w[i-15] rightrotate 8) xor (w[i-15] rightshift 7)
const W15h = SHA512_W_H[i - 15] | 0;
const W15l = SHA512_W_L[i - 15] | 0;
const s0h = u64.rotrSH(W15h, W15l, 1) ^ u64.rotrSH(W15h, W15l, 8) ^ u64.shrSH(W15h, W15l, 7);
const s0l = u64.rotrSL(W15h, W15l, 1) ^ u64.rotrSL(W15h, W15l, 8) ^ u64.shrSL(W15h, W15l, 7);
// s1 := (w[i-2] rightrotate 19) xor (w[i-2] rightrotate 61) xor (w[i-2] rightshift 6)
const W2h = SHA512_W_H[i - 2] | 0;
const W2l = SHA512_W_L[i - 2] | 0;
const s1h = u64.rotrSH(W2h, W2l, 19) ^ u64.rotrBH(W2h, W2l, 61) ^ u64.shrSH(W2h, W2l, 6);
const s1l = u64.rotrSL(W2h, W2l, 19) ^ u64.rotrBL(W2h, W2l, 61) ^ u64.shrSL(W2h, W2l, 6);
// SHA256_W[i] = s0 + s1 + SHA256_W[i - 7] + SHA256_W[i - 16];
const SUMl = u64.add4L(s0l, s1l, SHA512_W_L[i - 7], SHA512_W_L[i - 16]);
const SUMh = u64.add4H(SUMl, s0h, s1h, SHA512_W_H[i - 7], SHA512_W_H[i - 16]);
SHA512_W_H[i] = SUMh | 0;
SHA512_W_L[i] = SUMl | 0;
}
let { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this;
// Compression function main loop, 80 rounds
for (let i = 0; i < 80; i++) {
// S1 := (e rightrotate 14) xor (e rightrotate 18) xor (e rightrotate 41)
const sigma1h = u64.rotrSH(Eh, El, 14) ^ u64.rotrSH(Eh, El, 18) ^ u64.rotrBH(Eh, El, 41);
const sigma1l = u64.rotrSL(Eh, El, 14) ^ u64.rotrSL(Eh, El, 18) ^ u64.rotrBL(Eh, El, 41);
//const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0;
const CHIh = (Eh & Fh) ^ (~Eh & Gh);
const CHIl = (El & Fl) ^ (~El & Gl);
// T1 = H + sigma1 + Chi(E, F, G) + SHA512_K[i] + SHA512_W[i]
// prettier-ignore
const T1ll = u64.add5L(Hl, sigma1l, CHIl, SHA512_Kl[i], SHA512_W_L[i]);
const T1h = u64.add5H(T1ll, Hh, sigma1h, CHIh, SHA512_Kh[i], SHA512_W_H[i]);
const T1l = T1ll | 0;
// S0 := (a rightrotate 28) xor (a rightrotate 34) xor (a rightrotate 39)
const sigma0h = u64.rotrSH(Ah, Al, 28) ^ u64.rotrBH(Ah, Al, 34) ^ u64.rotrBH(Ah, Al, 39);
const sigma0l = u64.rotrSL(Ah, Al, 28) ^ u64.rotrBL(Ah, Al, 34) ^ u64.rotrBL(Ah, Al, 39);
const MAJh = (Ah & Bh) ^ (Ah & Ch) ^ (Bh & Ch);
const MAJl = (Al & Bl) ^ (Al & Cl) ^ (Bl & Cl);
Hh = Gh | 0;
Hl = Gl | 0;
Gh = Fh | 0;
Gl = Fl | 0;
Fh = Eh | 0;
Fl = El | 0;
({ h: Eh, l: El } = u64.add(Dh | 0, Dl | 0, T1h | 0, T1l | 0));
Dh = Ch | 0;
Dl = Cl | 0;
Ch = Bh | 0;
Cl = Bl | 0;
Bh = Ah | 0;
Bl = Al | 0;
const All = u64.add3L(T1l, sigma0l, MAJl);
Ah = u64.add3H(All, T1h, sigma0h, MAJh);
Al = All | 0;
}
// Add the compressed chunk to the current hash value
({ h: Ah, l: Al } = u64.add(this.Ah | 0, this.Al | 0, Ah | 0, Al | 0));
({ h: Bh, l: Bl } = u64.add(this.Bh | 0, this.Bl | 0, Bh | 0, Bl | 0));
({ h: Ch, l: Cl } = u64.add(this.Ch | 0, this.Cl | 0, Ch | 0, Cl | 0));
({ h: Dh, l: Dl } = u64.add(this.Dh | 0, this.Dl | 0, Dh | 0, Dl | 0));
({ h: Eh, l: El } = u64.add(this.Eh | 0, this.El | 0, Eh | 0, El | 0));
({ h: Fh, l: Fl } = u64.add(this.Fh | 0, this.Fl | 0, Fh | 0, Fl | 0));
({ h: Gh, l: Gl } = u64.add(this.Gh | 0, this.Gl | 0, Gh | 0, Gl | 0));
({ h: Hh, l: Hl } = u64.add(this.Hh | 0, this.Hl | 0, Hh | 0, Hl | 0));
this.set(Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl);
}
roundClean() {
(0, utils_ts_1.clean)(SHA512_W_H, SHA512_W_L);
}
destroy() {
(0, utils_ts_1.clean)(this.buffer);
this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
}
exports.SHA512 = SHA512;
class SHA384 extends SHA512 {
constructor() {
super(48);
this.Ah = _md_ts_1.SHA384_IV[0] | 0;
this.Al = _md_ts_1.SHA384_IV[1] | 0;
this.Bh = _md_ts_1.SHA384_IV[2] | 0;
this.Bl = _md_ts_1.SHA384_IV[3] | 0;
this.Ch = _md_ts_1.SHA384_IV[4] | 0;
this.Cl = _md_ts_1.SHA384_IV[5] | 0;
this.Dh = _md_ts_1.SHA384_IV[6] | 0;
this.Dl = _md_ts_1.SHA384_IV[7] | 0;
this.Eh = _md_ts_1.SHA384_IV[8] | 0;
this.El = _md_ts_1.SHA384_IV[9] | 0;
this.Fh = _md_ts_1.SHA384_IV[10] | 0;
this.Fl = _md_ts_1.SHA384_IV[11] | 0;
this.Gh = _md_ts_1.SHA384_IV[12] | 0;
this.Gl = _md_ts_1.SHA384_IV[13] | 0;
this.Hh = _md_ts_1.SHA384_IV[14] | 0;
this.Hl = _md_ts_1.SHA384_IV[15] | 0;
}
}
exports.SHA384 = SHA384;
/**
* Truncated SHA512/256 and SHA512/224.
* SHA512_IV is XORed with 0xa5a5a5a5a5a5a5a5, then used as "intermediary" IV of SHA512/t.
* Then t hashes string to produce result IV.
* See `test/misc/sha2-gen-iv.js`.
*/
/** SHA512/224 IV */
const T224_IV = /* @__PURE__ */ Uint32Array.from([
0x8c3d37c8, 0x19544da2, 0x73e19966, 0x89dcd4d6, 0x1dfab7ae, 0x32ff9c82, 0x679dd514, 0x582f9fcf,
0x0f6d2b69, 0x7bd44da8, 0x77e36f73, 0x04c48942, 0x3f9d85a8, 0x6a1d36c8, 0x1112e6ad, 0x91d692a1,
]);
/** SHA512/256 IV */
const T256_IV = /* @__PURE__ */ Uint32Array.from([
0x22312194, 0xfc2bf72c, 0x9f555fa3, 0xc84c64c2, 0x2393b86b, 0x6f53b151, 0x96387719, 0x5940eabd,
0x96283ee2, 0xa88effe3, 0xbe5e1e25, 0x53863992, 0x2b0199fc, 0x2c85b8aa, 0x0eb72ddc, 0x81c52ca2,
]);
class SHA512_224 extends SHA512 {
constructor() {
super(28);
this.Ah = T224_IV[0] | 0;
this.Al = T224_IV[1] | 0;
this.Bh = T224_IV[2] | 0;
this.Bl = T224_IV[3] | 0;
this.Ch = T224_IV[4] | 0;
this.Cl = T224_IV[5] | 0;
this.Dh = T224_IV[6] | 0;
this.Dl = T224_IV[7] | 0;
this.Eh = T224_IV[8] | 0;
this.El = T224_IV[9] | 0;
this.Fh = T224_IV[10] | 0;
this.Fl = T224_IV[11] | 0;
this.Gh = T224_IV[12] | 0;
this.Gl = T224_IV[13] | 0;
this.Hh = T224_IV[14] | 0;
this.Hl = T224_IV[15] | 0;
}
}
exports.SHA512_224 = SHA512_224;
class SHA512_256 extends SHA512 {
constructor() {
super(32);
this.Ah = T256_IV[0] | 0;
this.Al = T256_IV[1] | 0;
this.Bh = T256_IV[2] | 0;
this.Bl = T256_IV[3] | 0;
this.Ch = T256_IV[4] | 0;
this.Cl = T256_IV[5] | 0;
this.Dh = T256_IV[6] | 0;
this.Dl = T256_IV[7] | 0;
this.Eh = T256_IV[8] | 0;
this.El = T256_IV[9] | 0;
this.Fh = T256_IV[10] | 0;
this.Fl = T256_IV[11] | 0;
this.Gh = T256_IV[12] | 0;
this.Gl = T256_IV[13] | 0;
this.Hh = T256_IV[14] | 0;
this.Hl = T256_IV[15] | 0;
}
}
exports.SHA512_256 = SHA512_256;
/**
* SHA2-256 hash function from RFC 4634.
*
* It is the fastest JS hash, even faster than Blake3.
* To break sha256 using birthday attack, attackers need to try 2^128 hashes.
* BTC network is doing 2^70 hashes/sec (2^95 hashes/year) as per 2025.
*/
exports.sha256 = (0, utils_ts_1.createHasher)(() => new SHA256());
/** SHA2-224 hash function from RFC 4634 */
exports.sha224 = (0, utils_ts_1.createHasher)(() => new SHA224());
/** SHA2-512 hash function from RFC 4634. */
exports.sha512 = (0, utils_ts_1.createHasher)(() => new SHA512());
/** SHA2-384 hash function from RFC 4634. */
exports.sha384 = (0, utils_ts_1.createHasher)(() => new SHA384());
/**
* SHA2-512/256 "truncated" hash function, with improved resistance to length extension attacks.
* See the paper on [truncated SHA512](https://eprint.iacr.org/2010/548.pdf).
*/
exports.sha512_256 = (0, utils_ts_1.createHasher)(() => new SHA512_256());
/**
* SHA2-512/224 "truncated" hash function, with improved resistance to length extension attacks.
* See the paper on [truncated SHA512](https://eprint.iacr.org/2010/548.pdf).
*/
exports.sha512_224 = (0, utils_ts_1.createHasher)(() => new SHA512_224());
//# sourceMappingURL=sha2.js.map
+1
View File
File diff suppressed because one or more lines are too long
+20
View File
@@ -0,0 +1,20 @@
/**
* SHA2-256 a.k.a. sha256. In JS, it is the fastest hash, even faster than Blake3.
*
* To break sha256 using birthday attack, attackers need to try 2^128 hashes.
* BTC network is doing 2^70 hashes/sec (2^95 hashes/year) as per 2025.
*
* Check out [FIPS 180-4](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf).
* @module
* @deprecated
*/
import { SHA224 as SHA224n, sha224 as sha224n, SHA256 as SHA256n, sha256 as sha256n } from './sha2.ts';
/** @deprecated Use import from `noble/hashes/sha2` module */
export declare const SHA256: typeof SHA256n;
/** @deprecated Use import from `noble/hashes/sha2` module */
export declare const sha256: typeof sha256n;
/** @deprecated Use import from `noble/hashes/sha2` module */
export declare const SHA224: typeof SHA224n;
/** @deprecated Use import from `noble/hashes/sha2` module */
export declare const sha224: typeof sha224n;
//# sourceMappingURL=sha256.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"sha256.d.ts","sourceRoot":"","sources":["src/sha256.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EACL,MAAM,IAAI,OAAO,EACjB,MAAM,IAAI,OAAO,EACjB,MAAM,IAAI,OAAO,EACjB,MAAM,IAAI,OAAO,EAClB,MAAM,WAAW,CAAC;AACnB,6DAA6D;AAC7D,eAAO,MAAM,MAAM,EAAE,OAAO,OAAiB,CAAC;AAC9C,6DAA6D;AAC7D,eAAO,MAAM,MAAM,EAAE,OAAO,OAAiB,CAAC;AAC9C,6DAA6D;AAC7D,eAAO,MAAM,MAAM,EAAE,OAAO,OAAiB,CAAC;AAC9C,6DAA6D;AAC7D,eAAO,MAAM,MAAM,EAAE,OAAO,OAAiB,CAAC"}
+23
View File
@@ -0,0 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.sha224 = exports.SHA224 = exports.sha256 = exports.SHA256 = void 0;
/**
* SHA2-256 a.k.a. sha256. In JS, it is the fastest hash, even faster than Blake3.
*
* To break sha256 using birthday attack, attackers need to try 2^128 hashes.
* BTC network is doing 2^70 hashes/sec (2^95 hashes/year) as per 2025.
*
* Check out [FIPS 180-4](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf).
* @module
* @deprecated
*/
const sha2_ts_1 = require("./sha2.js");
/** @deprecated Use import from `noble/hashes/sha2` module */
exports.SHA256 = sha2_ts_1.SHA256;
/** @deprecated Use import from `noble/hashes/sha2` module */
exports.sha256 = sha2_ts_1.sha256;
/** @deprecated Use import from `noble/hashes/sha2` module */
exports.SHA224 = sha2_ts_1.SHA224;
/** @deprecated Use import from `noble/hashes/sha2` module */
exports.sha224 = sha2_ts_1.sha224;
//# sourceMappingURL=sha256.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"sha256.js","sourceRoot":"","sources":["src/sha256.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;GASG;AACH,uCAKmB;AACnB,6DAA6D;AAChD,QAAA,MAAM,GAAmB,gBAAO,CAAC;AAC9C,6DAA6D;AAChD,QAAA,MAAM,GAAmB,gBAAO,CAAC;AAC9C,6DAA6D;AAChD,QAAA,MAAM,GAAmB,gBAAO,CAAC;AAC9C,6DAA6D;AAChD,QAAA,MAAM,GAAmB,gBAAO,CAAC"}
+142
View File
@@ -0,0 +1,142 @@
/**
* SHA3 (keccak) addons.
*
* * Full [NIST SP 800-185](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf):
* cSHAKE, KMAC, TupleHash, ParallelHash + XOF variants
* * Reduced-round Keccak [(draft)](https://datatracker.ietf.org/doc/draft-irtf-cfrg-kangarootwelve/):
* * 🦘 K12 aka KangarooTwelve
* * M14 aka MarsupilamiFourteen
* * TurboSHAKE
* * KeccakPRG: Pseudo-random generator based on Keccak [(pdf)](https://keccak.team/files/CSF-0.1.pdf)
* @module
*/
import { Keccak, type ShakeOpts } from './sha3.ts';
import { type CHashO, type CHashXO, Hash, type HashXOF, type Input } from './utils.ts';
export type cShakeOpts = ShakeOpts & {
personalization?: Input;
NISTfn?: Input;
};
export type ICShake = {
(msg: Input, opts?: cShakeOpts): Uint8Array;
outputLen: number;
blockLen: number;
create(opts: cShakeOpts): HashXOF<Keccak>;
};
export type ITupleHash = {
(messages: Input[], opts?: cShakeOpts): Uint8Array;
create(opts?: cShakeOpts): TupleHash;
};
export type IParHash = {
(message: Input, opts?: ParallelOpts): Uint8Array;
create(opts?: ParallelOpts): ParallelHash;
};
export declare const cshake128: ICShake;
export declare const cshake256: ICShake;
export declare class KMAC extends Keccak implements HashXOF<KMAC> {
constructor(blockLen: number, outputLen: number, enableXOF: boolean, key: Input, opts?: cShakeOpts);
protected finish(): void;
_cloneInto(to?: KMAC): KMAC;
clone(): KMAC;
}
export declare const kmac128: {
(key: Input, message: Input, opts?: cShakeOpts): Uint8Array;
create(key: Input, opts?: cShakeOpts): KMAC;
};
export declare const kmac256: {
(key: Input, message: Input, opts?: cShakeOpts): Uint8Array;
create(key: Input, opts?: cShakeOpts): KMAC;
};
export declare const kmac128xof: {
(key: Input, message: Input, opts?: cShakeOpts): Uint8Array;
create(key: Input, opts?: cShakeOpts): KMAC;
};
export declare const kmac256xof: {
(key: Input, message: Input, opts?: cShakeOpts): Uint8Array;
create(key: Input, opts?: cShakeOpts): KMAC;
};
export declare class TupleHash extends Keccak implements HashXOF<TupleHash> {
constructor(blockLen: number, outputLen: number, enableXOF: boolean, opts?: cShakeOpts);
protected finish(): void;
_cloneInto(to?: TupleHash): TupleHash;
clone(): TupleHash;
}
/** 128-bit TupleHASH. */
export declare const tuplehash128: ITupleHash;
/** 256-bit TupleHASH. */
export declare const tuplehash256: ITupleHash;
/** 128-bit TupleHASH XOF. */
export declare const tuplehash128xof: ITupleHash;
/** 256-bit TupleHASH XOF. */
export declare const tuplehash256xof: ITupleHash;
type ParallelOpts = cShakeOpts & {
blockLen?: number;
};
export declare class ParallelHash extends Keccak implements HashXOF<ParallelHash> {
private leafHash?;
protected leafCons: () => Hash<Keccak>;
private chunkPos;
private chunksDone;
private chunkLen;
constructor(blockLen: number, outputLen: number, leafCons: () => Hash<Keccak>, enableXOF: boolean, opts?: ParallelOpts);
protected finish(): void;
_cloneInto(to?: ParallelHash): ParallelHash;
destroy(): void;
clone(): ParallelHash;
}
/** 128-bit ParallelHash. In JS, it is not parallel. */
export declare const parallelhash128: IParHash;
/** 256-bit ParallelHash. In JS, it is not parallel. */
export declare const parallelhash256: IParHash;
/** 128-bit ParallelHash XOF. In JS, it is not parallel. */
export declare const parallelhash128xof: IParHash;
/** 256-bit ParallelHash. In JS, it is not parallel. */
export declare const parallelhash256xof: IParHash;
export type TurboshakeOpts = ShakeOpts & {
D?: number;
};
/** TurboSHAKE 128-bit: reduced 12-round keccak. */
export declare const turboshake128: CHashXO;
/** TurboSHAKE 256-bit: reduced 12-round keccak. */
export declare const turboshake256: CHashXO;
export type KangarooOpts = {
dkLen?: number;
personalization?: Input;
};
export declare class KangarooTwelve extends Keccak implements HashXOF<KangarooTwelve> {
readonly chunkLen = 8192;
private leafHash?;
protected leafLen: number;
private personalization;
private chunkPos;
private chunksDone;
constructor(blockLen: number, leafLen: number, outputLen: number, rounds: number, opts: KangarooOpts);
update(data: Input): this;
protected finish(): void;
destroy(): void;
_cloneInto(to?: KangarooTwelve): KangarooTwelve;
clone(): KangarooTwelve;
}
/** KangarooTwelve: reduced 12-round keccak. */
export declare const k12: CHashO;
/** MarsupilamiFourteen: reduced 14-round keccak. */
export declare const m14: CHashO;
/**
* More at https://github.com/XKCP/XKCP/tree/master/lib/high/Keccak/PRG.
*/
export declare class KeccakPRG extends Keccak {
protected rate: number;
constructor(capacity: number);
keccak(): void;
update(data: Input): this;
feed(data: Input): this;
protected finish(): void;
digestInto(_out: Uint8Array): Uint8Array;
fetch(bytes: number): Uint8Array;
forget(): void;
_cloneInto(to?: KeccakPRG): KeccakPRG;
clone(): KeccakPRG;
}
/** KeccakPRG: Pseudo-random generator based on Keccak. https://keccak.team/files/CSF-0.1.pdf */
export declare const keccakprg: (capacity?: number) => KeccakPRG;
export {};
//# sourceMappingURL=sha3-addons.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"sha3-addons.d.ts","sourceRoot":"","sources":["src/sha3-addons.ts"],"names":[],"mappings":"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"}
+402
View File
@@ -0,0 +1,402 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.keccakprg = exports.KeccakPRG = exports.m14 = exports.k12 = exports.KangarooTwelve = exports.turboshake256 = exports.turboshake128 = exports.parallelhash256xof = exports.parallelhash128xof = exports.parallelhash256 = exports.parallelhash128 = exports.ParallelHash = exports.tuplehash256xof = exports.tuplehash128xof = exports.tuplehash256 = exports.tuplehash128 = exports.TupleHash = exports.kmac256xof = exports.kmac128xof = exports.kmac256 = exports.kmac128 = exports.KMAC = exports.cshake256 = exports.cshake128 = void 0;
/**
* SHA3 (keccak) addons.
*
* * Full [NIST SP 800-185](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf):
* cSHAKE, KMAC, TupleHash, ParallelHash + XOF variants
* * Reduced-round Keccak [(draft)](https://datatracker.ietf.org/doc/draft-irtf-cfrg-kangarootwelve/):
* * 🦘 K12 aka KangarooTwelve
* * M14 aka MarsupilamiFourteen
* * TurboSHAKE
* * KeccakPRG: Pseudo-random generator based on Keccak [(pdf)](https://keccak.team/files/CSF-0.1.pdf)
* @module
*/
const sha3_ts_1 = require("./sha3.js");
const utils_ts_1 = require("./utils.js");
// cSHAKE && KMAC (NIST SP800-185)
const _8n = BigInt(8);
const _ffn = BigInt(0xff);
// NOTE: it is safe to use bigints here, since they used only for length encoding (not actual data).
// We use bigints in sha256 for lengths too.
function leftEncode(n) {
n = BigInt(n);
const res = [Number(n & _ffn)];
n >>= _8n;
for (; n > 0; n >>= _8n)
res.unshift(Number(n & _ffn));
res.unshift(res.length);
return new Uint8Array(res);
}
function rightEncode(n) {
n = BigInt(n);
const res = [Number(n & _ffn)];
n >>= _8n;
for (; n > 0; n >>= _8n)
res.unshift(Number(n & _ffn));
res.push(res.length);
return new Uint8Array(res);
}
function chooseLen(opts, outputLen) {
return opts.dkLen === undefined ? outputLen : opts.dkLen;
}
const abytesOrZero = (buf) => {
if (buf === undefined)
return Uint8Array.of();
return (0, utils_ts_1.toBytes)(buf);
};
// NOTE: second modulo is necessary since we don't need to add padding if current element takes whole block
const getPadding = (len, block) => new Uint8Array((block - (len % block)) % block);
// Personalization
function cshakePers(hash, opts = {}) {
if (!opts || (!opts.personalization && !opts.NISTfn))
return hash;
// Encode and pad inplace to avoid unneccesary memory copies/slices (so we don't need to zero them later)
// bytepad(encode_string(N) || encode_string(S), 168)
const blockLenBytes = leftEncode(hash.blockLen);
const fn = abytesOrZero(opts.NISTfn);
const fnLen = leftEncode(_8n * BigInt(fn.length)); // length in bits
const pers = abytesOrZero(opts.personalization);
const persLen = leftEncode(_8n * BigInt(pers.length)); // length in bits
if (!fn.length && !pers.length)
return hash;
hash.suffix = 0x04;
hash.update(blockLenBytes).update(fnLen).update(fn).update(persLen).update(pers);
let totalLen = blockLenBytes.length + fnLen.length + fn.length + persLen.length + pers.length;
hash.update(getPadding(totalLen, hash.blockLen));
return hash;
}
const gencShake = (suffix, blockLen, outputLen) => (0, utils_ts_1.createXOFer)((opts = {}) => cshakePers(new sha3_ts_1.Keccak(blockLen, suffix, chooseLen(opts, outputLen), true), opts));
exports.cshake128 = (() => gencShake(0x1f, 168, 128 / 8))();
exports.cshake256 = (() => gencShake(0x1f, 136, 256 / 8))();
class KMAC extends sha3_ts_1.Keccak {
constructor(blockLen, outputLen, enableXOF, key, opts = {}) {
super(blockLen, 0x1f, outputLen, enableXOF);
cshakePers(this, { NISTfn: 'KMAC', personalization: opts.personalization });
key = (0, utils_ts_1.toBytes)(key);
(0, utils_ts_1.abytes)(key);
// 1. newX = bytepad(encode_string(K), 168) || X || right_encode(L).
const blockLenBytes = leftEncode(this.blockLen);
const keyLen = leftEncode(_8n * BigInt(key.length));
this.update(blockLenBytes).update(keyLen).update(key);
const totalLen = blockLenBytes.length + keyLen.length + key.length;
this.update(getPadding(totalLen, this.blockLen));
}
finish() {
if (!this.finished)
this.update(rightEncode(this.enableXOF ? 0 : _8n * BigInt(this.outputLen))); // outputLen in bits
super.finish();
}
_cloneInto(to) {
// Create new instance without calling constructor since key already in state and we don't know it.
// Force "to" to be instance of KMAC instead of Sha3.
if (!to) {
to = Object.create(Object.getPrototypeOf(this), {});
to.state = this.state.slice();
to.blockLen = this.blockLen;
to.state32 = (0, utils_ts_1.u32)(to.state);
}
return super._cloneInto(to);
}
clone() {
return this._cloneInto();
}
}
exports.KMAC = KMAC;
function genKmac(blockLen, outputLen, xof = false) {
const kmac = (key, message, opts) => kmac.create(key, opts).update(message).digest();
kmac.create = (key, opts = {}) => new KMAC(blockLen, chooseLen(opts, outputLen), xof, key, opts);
return kmac;
}
exports.kmac128 = (() => genKmac(168, 128 / 8))();
exports.kmac256 = (() => genKmac(136, 256 / 8))();
exports.kmac128xof = (() => genKmac(168, 128 / 8, true))();
exports.kmac256xof = (() => genKmac(136, 256 / 8, true))();
// TupleHash
// Usage: tuple(['ab', 'cd']) != tuple(['a', 'bcd'])
class TupleHash extends sha3_ts_1.Keccak {
constructor(blockLen, outputLen, enableXOF, opts = {}) {
super(blockLen, 0x1f, outputLen, enableXOF);
cshakePers(this, { NISTfn: 'TupleHash', personalization: opts.personalization });
// Change update after cshake processed
this.update = (data) => {
data = (0, utils_ts_1.toBytes)(data);
(0, utils_ts_1.abytes)(data);
super.update(leftEncode(_8n * BigInt(data.length)));
super.update(data);
return this;
};
}
finish() {
if (!this.finished)
super.update(rightEncode(this.enableXOF ? 0 : _8n * BigInt(this.outputLen))); // outputLen in bits
super.finish();
}
_cloneInto(to) {
to || (to = new TupleHash(this.blockLen, this.outputLen, this.enableXOF));
return super._cloneInto(to);
}
clone() {
return this._cloneInto();
}
}
exports.TupleHash = TupleHash;
function genTuple(blockLen, outputLen, xof = false) {
const tuple = (messages, opts) => {
const h = tuple.create(opts);
for (const msg of messages)
h.update(msg);
return h.digest();
};
tuple.create = (opts = {}) => new TupleHash(blockLen, chooseLen(opts, outputLen), xof, opts);
return tuple;
}
/** 128-bit TupleHASH. */
exports.tuplehash128 = (() => genTuple(168, 128 / 8))();
/** 256-bit TupleHASH. */
exports.tuplehash256 = (() => genTuple(136, 256 / 8))();
/** 128-bit TupleHASH XOF. */
exports.tuplehash128xof = (() => genTuple(168, 128 / 8, true))();
/** 256-bit TupleHASH XOF. */
exports.tuplehash256xof = (() => genTuple(136, 256 / 8, true))();
class ParallelHash extends sha3_ts_1.Keccak {
constructor(blockLen, outputLen, leafCons, enableXOF, opts = {}) {
super(blockLen, 0x1f, outputLen, enableXOF);
this.chunkPos = 0; // Position of current block in chunk
this.chunksDone = 0; // How many chunks we already have
cshakePers(this, { NISTfn: 'ParallelHash', personalization: opts.personalization });
this.leafCons = leafCons;
let { blockLen: B } = opts;
B || (B = 8);
(0, utils_ts_1.anumber)(B);
this.chunkLen = B;
super.update(leftEncode(B));
// Change update after cshake processed
this.update = (data) => {
data = (0, utils_ts_1.toBytes)(data);
(0, utils_ts_1.abytes)(data);
const { chunkLen, leafCons } = this;
for (let pos = 0, len = data.length; pos < len;) {
if (this.chunkPos == chunkLen || !this.leafHash) {
if (this.leafHash) {
super.update(this.leafHash.digest());
this.chunksDone++;
}
this.leafHash = leafCons();
this.chunkPos = 0;
}
const take = Math.min(chunkLen - this.chunkPos, len - pos);
this.leafHash.update(data.subarray(pos, pos + take));
this.chunkPos += take;
pos += take;
}
return this;
};
}
finish() {
if (this.finished)
return;
if (this.leafHash) {
super.update(this.leafHash.digest());
this.chunksDone++;
}
super.update(rightEncode(this.chunksDone));
super.update(rightEncode(this.enableXOF ? 0 : _8n * BigInt(this.outputLen))); // outputLen in bits
super.finish();
}
_cloneInto(to) {
to || (to = new ParallelHash(this.blockLen, this.outputLen, this.leafCons, this.enableXOF));
if (this.leafHash)
to.leafHash = this.leafHash._cloneInto(to.leafHash);
to.chunkPos = this.chunkPos;
to.chunkLen = this.chunkLen;
to.chunksDone = this.chunksDone;
return super._cloneInto(to);
}
destroy() {
super.destroy.call(this);
if (this.leafHash)
this.leafHash.destroy();
}
clone() {
return this._cloneInto();
}
}
exports.ParallelHash = ParallelHash;
function genPrl(blockLen, outputLen, leaf, xof = false) {
const parallel = (message, opts) => parallel.create(opts).update(message).digest();
parallel.create = (opts = {}) => new ParallelHash(blockLen, chooseLen(opts, outputLen), () => leaf.create({ dkLen: 2 * outputLen }), xof, opts);
return parallel;
}
/** 128-bit ParallelHash. In JS, it is not parallel. */
exports.parallelhash128 = (() => genPrl(168, 128 / 8, exports.cshake128))();
/** 256-bit ParallelHash. In JS, it is not parallel. */
exports.parallelhash256 = (() => genPrl(136, 256 / 8, exports.cshake256))();
/** 128-bit ParallelHash XOF. In JS, it is not parallel. */
exports.parallelhash128xof = (() => genPrl(168, 128 / 8, exports.cshake128, true))();
/** 256-bit ParallelHash. In JS, it is not parallel. */
exports.parallelhash256xof = (() => genPrl(136, 256 / 8, exports.cshake256, true))();
const genTurboshake = (blockLen, outputLen) => (0, utils_ts_1.createXOFer)((opts = {}) => {
const D = opts.D === undefined ? 0x1f : opts.D;
// Section 2.1 of https://datatracker.ietf.org/doc/draft-irtf-cfrg-kangarootwelve/
if (!Number.isSafeInteger(D) || D < 0x01 || D > 0x7f)
throw new Error('invalid domain separation byte must be 0x01..0x7f, got: ' + D);
return new sha3_ts_1.Keccak(blockLen, D, opts.dkLen === undefined ? outputLen : opts.dkLen, true, 12);
});
/** TurboSHAKE 128-bit: reduced 12-round keccak. */
exports.turboshake128 = genTurboshake(168, 256 / 8);
/** TurboSHAKE 256-bit: reduced 12-round keccak. */
exports.turboshake256 = genTurboshake(136, 512 / 8);
// Kangaroo
// Same as NIST rightEncode, but returns [0] for zero string
function rightEncodeK12(n) {
n = BigInt(n);
const res = [];
for (; n > 0; n >>= _8n)
res.unshift(Number(n & _ffn));
res.push(res.length);
return Uint8Array.from(res);
}
const EMPTY_BUFFER = /* @__PURE__ */ Uint8Array.of();
class KangarooTwelve extends sha3_ts_1.Keccak {
constructor(blockLen, leafLen, outputLen, rounds, opts) {
super(blockLen, 0x07, outputLen, true, rounds);
this.chunkLen = 8192;
this.chunkPos = 0; // Position of current block in chunk
this.chunksDone = 0; // How many chunks we already have
this.leafLen = leafLen;
this.personalization = abytesOrZero(opts.personalization);
}
update(data) {
data = (0, utils_ts_1.toBytes)(data);
(0, utils_ts_1.abytes)(data);
const { chunkLen, blockLen, leafLen, rounds } = this;
for (let pos = 0, len = data.length; pos < len;) {
if (this.chunkPos == chunkLen) {
if (this.leafHash)
super.update(this.leafHash.digest());
else {
this.suffix = 0x06; // Its safe to change suffix here since its used only in digest()
super.update(Uint8Array.from([3, 0, 0, 0, 0, 0, 0, 0]));
}
this.leafHash = new sha3_ts_1.Keccak(blockLen, 0x0b, leafLen, false, rounds);
this.chunksDone++;
this.chunkPos = 0;
}
const take = Math.min(chunkLen - this.chunkPos, len - pos);
const chunk = data.subarray(pos, pos + take);
if (this.leafHash)
this.leafHash.update(chunk);
else
super.update(chunk);
this.chunkPos += take;
pos += take;
}
return this;
}
finish() {
if (this.finished)
return;
const { personalization } = this;
this.update(personalization).update(rightEncodeK12(personalization.length));
// Leaf hash
if (this.leafHash) {
super.update(this.leafHash.digest());
super.update(rightEncodeK12(this.chunksDone));
super.update(Uint8Array.from([0xff, 0xff]));
}
super.finish.call(this);
}
destroy() {
super.destroy.call(this);
if (this.leafHash)
this.leafHash.destroy();
// We cannot zero personalization buffer since it is user provided and we don't want to mutate user input
this.personalization = EMPTY_BUFFER;
}
_cloneInto(to) {
const { blockLen, leafLen, leafHash, outputLen, rounds } = this;
to || (to = new KangarooTwelve(blockLen, leafLen, outputLen, rounds, {}));
super._cloneInto(to);
if (leafHash)
to.leafHash = leafHash._cloneInto(to.leafHash);
to.personalization.set(this.personalization);
to.leafLen = this.leafLen;
to.chunkPos = this.chunkPos;
to.chunksDone = this.chunksDone;
return to;
}
clone() {
return this._cloneInto();
}
}
exports.KangarooTwelve = KangarooTwelve;
/** KangarooTwelve: reduced 12-round keccak. */
exports.k12 = (() => (0, utils_ts_1.createOptHasher)((opts = {}) => new KangarooTwelve(168, 32, chooseLen(opts, 32), 12, opts)))();
/** MarsupilamiFourteen: reduced 14-round keccak. */
exports.m14 = (() => (0, utils_ts_1.createOptHasher)((opts = {}) => new KangarooTwelve(136, 64, chooseLen(opts, 64), 14, opts)))();
/**
* More at https://github.com/XKCP/XKCP/tree/master/lib/high/Keccak/PRG.
*/
class KeccakPRG extends sha3_ts_1.Keccak {
constructor(capacity) {
(0, utils_ts_1.anumber)(capacity);
// Rho should be full bytes
if (capacity < 0 || capacity > 1600 - 10 || (1600 - capacity - 2) % 8)
throw new Error('invalid capacity');
// blockLen = rho in bytes
super((1600 - capacity - 2) / 8, 0, 0, true);
this.rate = 1600 - capacity;
this.posOut = Math.floor((this.rate + 7) / 8);
}
keccak() {
// Duplex padding
this.state[this.pos] ^= 0x01;
this.state[this.blockLen] ^= 0x02; // Rho is full bytes
super.keccak();
this.pos = 0;
this.posOut = 0;
}
update(data) {
super.update(data);
this.posOut = this.blockLen;
return this;
}
feed(data) {
return this.update(data);
}
finish() { }
digestInto(_out) {
throw new Error('digest is not allowed, use .fetch instead');
}
fetch(bytes) {
return this.xof(bytes);
}
// Ensure irreversibility (even if state leaked previous outputs cannot be computed)
forget() {
if (this.rate < 1600 / 2 + 1)
throw new Error('rate is too low to use .forget()');
this.keccak();
for (let i = 0; i < this.blockLen; i++)
this.state[i] = 0;
this.pos = this.blockLen;
this.keccak();
this.posOut = this.blockLen;
}
_cloneInto(to) {
const { rate } = this;
to || (to = new KeccakPRG(1600 - rate));
super._cloneInto(to);
to.rate = rate;
return to;
}
clone() {
return this._cloneInto();
}
}
exports.KeccakPRG = KeccakPRG;
/** KeccakPRG: Pseudo-random generator based on Keccak. https://keccak.team/files/CSF-0.1.pdf */
const keccakprg = (capacity = 254) => new KeccakPRG(capacity);
exports.keccakprg = keccakprg;
//# sourceMappingURL=sha3-addons.js.map
File diff suppressed because one or more lines are too long
+53
View File
@@ -0,0 +1,53 @@
import { Hash, type CHash, type CHashXO, type HashXOF, type Input } from './utils.ts';
/** `keccakf1600` internal function, additionally allows to adjust round count. */
export declare function keccakP(s: Uint32Array, rounds?: number): void;
/** Keccak sponge function. */
export declare class Keccak extends Hash<Keccak> implements HashXOF<Keccak> {
protected state: Uint8Array;
protected pos: number;
protected posOut: number;
protected finished: boolean;
protected state32: Uint32Array;
protected destroyed: boolean;
blockLen: number;
suffix: number;
outputLen: number;
protected enableXOF: boolean;
protected rounds: number;
constructor(blockLen: number, suffix: number, outputLen: number, enableXOF?: boolean, rounds?: number);
clone(): Keccak;
protected keccak(): void;
update(data: Input): this;
protected finish(): void;
protected writeInto(out: Uint8Array): Uint8Array;
xofInto(out: Uint8Array): Uint8Array;
xof(bytes: number): Uint8Array;
digestInto(out: Uint8Array): Uint8Array;
digest(): Uint8Array;
destroy(): void;
_cloneInto(to?: Keccak): Keccak;
}
/** SHA3-224 hash function. */
export declare const sha3_224: CHash;
/** SHA3-256 hash function. Different from keccak-256. */
export declare const sha3_256: CHash;
/** SHA3-384 hash function. */
export declare const sha3_384: CHash;
/** SHA3-512 hash function. */
export declare const sha3_512: CHash;
/** keccak-224 hash function. */
export declare const keccak_224: CHash;
/** keccak-256 hash function. Different from SHA3-256. */
export declare const keccak_256: CHash;
/** keccak-384 hash function. */
export declare const keccak_384: CHash;
/** keccak-512 hash function. */
export declare const keccak_512: CHash;
export type ShakeOpts = {
dkLen?: number;
};
/** SHAKE128 XOF with 128-bit security. */
export declare const shake128: CHashXO;
/** SHAKE256 XOF with 256-bit security. */
export declare const shake256: CHashXO;
//# sourceMappingURL=sha3.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"sha3.d.ts","sourceRoot":"","sources":["src/sha3.ts"],"names":[],"mappings":"AAaA,OAAO,EAE6B,IAAI,EAGtC,KAAK,KAAK,EAAE,KAAK,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,KAAK,EACnD,MAAM,YAAY,CAAC;AAoCpB,kFAAkF;AAClF,wBAAgB,OAAO,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,GAAE,MAAW,GAAG,IAAI,CAyCjE;AAED,8BAA8B;AAC9B,qBAAa,MAAO,SAAQ,IAAI,CAAC,MAAM,CAAE,YAAW,OAAO,CAAC,MAAM,CAAC;IACjE,SAAS,CAAC,KAAK,EAAE,UAAU,CAAC;IAC5B,SAAS,CAAC,GAAG,SAAK;IAClB,SAAS,CAAC,MAAM,SAAK;IACrB,SAAS,CAAC,QAAQ,UAAS;IAC3B,SAAS,CAAC,OAAO,EAAE,WAAW,CAAC;IAC/B,SAAS,CAAC,SAAS,UAAS;IAErB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,SAAS,UAAS;IAC5B,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;gBAIvB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,SAAS,UAAQ,EACjB,MAAM,GAAE,MAAW;IAiBrB,KAAK,IAAI,MAAM;IAGf,SAAS,CAAC,MAAM,IAAI,IAAI;IAOxB,MAAM,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI;IAazB,SAAS,CAAC,MAAM,IAAI,IAAI;IAUxB,SAAS,CAAC,SAAS,CAAC,GAAG,EAAE,UAAU,GAAG,UAAU;IAehD,OAAO,CAAC,GAAG,EAAE,UAAU,GAAG,UAAU;IAKpC,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU;IAI9B,UAAU,CAAC,GAAG,EAAE,UAAU,GAAG,UAAU;IAOvC,MAAM,IAAI,UAAU;IAGpB,OAAO,IAAI,IAAI;IAIf,UAAU,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM;CAehC;AAKD,8BAA8B;AAC9B,eAAO,MAAM,QAAQ,EAAE,KAAyD,CAAC;AACjF,yDAAyD;AACzD,eAAO,MAAM,QAAQ,EAAE,KAAyD,CAAC;AACjF,8BAA8B;AAC9B,eAAO,MAAM,QAAQ,EAAE,KAAyD,CAAC;AACjF,8BAA8B;AAC9B,eAAO,MAAM,QAAQ,EAAE,KAAwD,CAAC;AAEhF,gCAAgC;AAChC,eAAO,MAAM,UAAU,EAAE,KAAyD,CAAC;AACnF,yDAAyD;AACzD,eAAO,MAAM,UAAU,EAAE,KAAyD,CAAC;AACnF,gCAAgC;AAChC,eAAO,MAAM,UAAU,EAAE,KAAyD,CAAC;AACnF,gCAAgC;AAChC,eAAO,MAAM,UAAU,EAAE,KAAwD,CAAC;AAElF,MAAM,MAAM,SAAS,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAQ3C,0CAA0C;AAC1C,eAAO,MAAM,QAAQ,EAAE,OAAgE,CAAC;AACxF,0CAA0C;AAC1C,eAAO,MAAM,QAAQ,EAAE,OAAgE,CAAC"}
+239
View File
@@ -0,0 +1,239 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.shake256 = exports.shake128 = exports.keccak_512 = exports.keccak_384 = exports.keccak_256 = exports.keccak_224 = exports.sha3_512 = exports.sha3_384 = exports.sha3_256 = exports.sha3_224 = exports.Keccak = void 0;
exports.keccakP = keccakP;
/**
* SHA3 (keccak) hash function, based on a new "Sponge function" design.
* Different from older hashes, the internal state is bigger than output size.
*
* Check out [FIPS-202](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf),
* [Website](https://keccak.team/keccak.html),
* [the differences between SHA-3 and Keccak](https://crypto.stackexchange.com/questions/15727/what-are-the-key-differences-between-the-draft-sha-3-standard-and-the-keccak-sub).
*
* Check out `sha3-addons` module for cSHAKE, k12, and others.
* @module
*/
const _u64_ts_1 = require("./_u64.js");
// prettier-ignore
const utils_ts_1 = require("./utils.js");
// No __PURE__ annotations in sha3 header:
// EVERYTHING is in fact used on every export.
// Various per round constants calculations
const _0n = BigInt(0);
const _1n = BigInt(1);
const _2n = BigInt(2);
const _7n = BigInt(7);
const _256n = BigInt(256);
const _0x71n = BigInt(0x71);
const SHA3_PI = [];
const SHA3_ROTL = [];
const _SHA3_IOTA = [];
for (let round = 0, R = _1n, x = 1, y = 0; round < 24; round++) {
// Pi
[x, y] = [y, (2 * x + 3 * y) % 5];
SHA3_PI.push(2 * (5 * y + x));
// Rotational
SHA3_ROTL.push((((round + 1) * (round + 2)) / 2) % 64);
// Iota
let t = _0n;
for (let j = 0; j < 7; j++) {
R = ((R << _1n) ^ ((R >> _7n) * _0x71n)) % _256n;
if (R & _2n)
t ^= _1n << ((_1n << /* @__PURE__ */ BigInt(j)) - _1n);
}
_SHA3_IOTA.push(t);
}
const IOTAS = (0, _u64_ts_1.split)(_SHA3_IOTA, true);
const SHA3_IOTA_H = IOTAS[0];
const SHA3_IOTA_L = IOTAS[1];
// Left rotation (without 0, 32, 64)
const rotlH = (h, l, s) => (s > 32 ? (0, _u64_ts_1.rotlBH)(h, l, s) : (0, _u64_ts_1.rotlSH)(h, l, s));
const rotlL = (h, l, s) => (s > 32 ? (0, _u64_ts_1.rotlBL)(h, l, s) : (0, _u64_ts_1.rotlSL)(h, l, s));
/** `keccakf1600` internal function, additionally allows to adjust round count. */
function keccakP(s, rounds = 24) {
const B = new Uint32Array(5 * 2);
// NOTE: all indices are x2 since we store state as u32 instead of u64 (bigints to slow in js)
for (let round = 24 - rounds; round < 24; round++) {
// Theta θ
for (let x = 0; x < 10; x++)
B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40];
for (let x = 0; x < 10; x += 2) {
const idx1 = (x + 8) % 10;
const idx0 = (x + 2) % 10;
const B0 = B[idx0];
const B1 = B[idx0 + 1];
const Th = rotlH(B0, B1, 1) ^ B[idx1];
const Tl = rotlL(B0, B1, 1) ^ B[idx1 + 1];
for (let y = 0; y < 50; y += 10) {
s[x + y] ^= Th;
s[x + y + 1] ^= Tl;
}
}
// Rho (ρ) and Pi (π)
let curH = s[2];
let curL = s[3];
for (let t = 0; t < 24; t++) {
const shift = SHA3_ROTL[t];
const Th = rotlH(curH, curL, shift);
const Tl = rotlL(curH, curL, shift);
const PI = SHA3_PI[t];
curH = s[PI];
curL = s[PI + 1];
s[PI] = Th;
s[PI + 1] = Tl;
}
// Chi (χ)
for (let y = 0; y < 50; y += 10) {
for (let x = 0; x < 10; x++)
B[x] = s[y + x];
for (let x = 0; x < 10; x++)
s[y + x] ^= ~B[(x + 2) % 10] & B[(x + 4) % 10];
}
// Iota (ι)
s[0] ^= SHA3_IOTA_H[round];
s[1] ^= SHA3_IOTA_L[round];
}
(0, utils_ts_1.clean)(B);
}
/** Keccak sponge function. */
class Keccak extends utils_ts_1.Hash {
// NOTE: we accept arguments in bytes instead of bits here.
constructor(blockLen, suffix, outputLen, enableXOF = false, rounds = 24) {
super();
this.pos = 0;
this.posOut = 0;
this.finished = false;
this.destroyed = false;
this.enableXOF = false;
this.blockLen = blockLen;
this.suffix = suffix;
this.outputLen = outputLen;
this.enableXOF = enableXOF;
this.rounds = rounds;
// Can be passed from user as dkLen
(0, utils_ts_1.anumber)(outputLen);
// 1600 = 5x5 matrix of 64bit. 1600 bits === 200 bytes
// 0 < blockLen < 200
if (!(0 < blockLen && blockLen < 200))
throw new Error('only keccak-f1600 function is supported');
this.state = new Uint8Array(200);
this.state32 = (0, utils_ts_1.u32)(this.state);
}
clone() {
return this._cloneInto();
}
keccak() {
(0, utils_ts_1.swap32IfBE)(this.state32);
keccakP(this.state32, this.rounds);
(0, utils_ts_1.swap32IfBE)(this.state32);
this.posOut = 0;
this.pos = 0;
}
update(data) {
(0, utils_ts_1.aexists)(this);
data = (0, utils_ts_1.toBytes)(data);
(0, utils_ts_1.abytes)(data);
const { blockLen, state } = this;
const len = data.length;
for (let pos = 0; pos < len;) {
const take = Math.min(blockLen - this.pos, len - pos);
for (let i = 0; i < take; i++)
state[this.pos++] ^= data[pos++];
if (this.pos === blockLen)
this.keccak();
}
return this;
}
finish() {
if (this.finished)
return;
this.finished = true;
const { state, suffix, pos, blockLen } = this;
// Do the padding
state[pos] ^= suffix;
if ((suffix & 0x80) !== 0 && pos === blockLen - 1)
this.keccak();
state[blockLen - 1] ^= 0x80;
this.keccak();
}
writeInto(out) {
(0, utils_ts_1.aexists)(this, false);
(0, utils_ts_1.abytes)(out);
this.finish();
const bufferOut = this.state;
const { blockLen } = this;
for (let pos = 0, len = out.length; pos < len;) {
if (this.posOut >= blockLen)
this.keccak();
const take = Math.min(blockLen - this.posOut, len - pos);
out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos);
this.posOut += take;
pos += take;
}
return out;
}
xofInto(out) {
// Sha3/Keccak usage with XOF is probably mistake, only SHAKE instances can do XOF
if (!this.enableXOF)
throw new Error('XOF is not possible for this instance');
return this.writeInto(out);
}
xof(bytes) {
(0, utils_ts_1.anumber)(bytes);
return this.xofInto(new Uint8Array(bytes));
}
digestInto(out) {
(0, utils_ts_1.aoutput)(out, this);
if (this.finished)
throw new Error('digest() was already called');
this.writeInto(out);
this.destroy();
return out;
}
digest() {
return this.digestInto(new Uint8Array(this.outputLen));
}
destroy() {
this.destroyed = true;
(0, utils_ts_1.clean)(this.state);
}
_cloneInto(to) {
const { blockLen, suffix, outputLen, rounds, enableXOF } = this;
to || (to = new Keccak(blockLen, suffix, outputLen, enableXOF, rounds));
to.state32.set(this.state32);
to.pos = this.pos;
to.posOut = this.posOut;
to.finished = this.finished;
to.rounds = rounds;
// Suffix can change in cSHAKE
to.suffix = suffix;
to.outputLen = outputLen;
to.enableXOF = enableXOF;
to.destroyed = this.destroyed;
return to;
}
}
exports.Keccak = Keccak;
const gen = (suffix, blockLen, outputLen) => (0, utils_ts_1.createHasher)(() => new Keccak(blockLen, suffix, outputLen));
/** SHA3-224 hash function. */
exports.sha3_224 = (() => gen(0x06, 144, 224 / 8))();
/** SHA3-256 hash function. Different from keccak-256. */
exports.sha3_256 = (() => gen(0x06, 136, 256 / 8))();
/** SHA3-384 hash function. */
exports.sha3_384 = (() => gen(0x06, 104, 384 / 8))();
/** SHA3-512 hash function. */
exports.sha3_512 = (() => gen(0x06, 72, 512 / 8))();
/** keccak-224 hash function. */
exports.keccak_224 = (() => gen(0x01, 144, 224 / 8))();
/** keccak-256 hash function. Different from SHA3-256. */
exports.keccak_256 = (() => gen(0x01, 136, 256 / 8))();
/** keccak-384 hash function. */
exports.keccak_384 = (() => gen(0x01, 104, 384 / 8))();
/** keccak-512 hash function. */
exports.keccak_512 = (() => gen(0x01, 72, 512 / 8))();
const genShake = (suffix, blockLen, outputLen) => (0, utils_ts_1.createXOFer)((opts = {}) => new Keccak(blockLen, suffix, opts.dkLen === undefined ? outputLen : opts.dkLen, true));
/** SHAKE128 XOF with 128-bit security. */
exports.shake128 = (() => genShake(0x1f, 168, 128 / 8))();
/** SHAKE256 XOF with 256-bit security. */
exports.shake256 = (() => genShake(0x1f, 136, 256 / 8))();
//# sourceMappingURL=sha3.js.map
+1
View File
File diff suppressed because one or more lines are too long
+26
View File
@@ -0,0 +1,26 @@
/**
* SHA2-512 a.k.a. sha512 and sha384. It is slower than sha256 in js because u64 operations are slow.
*
* Check out [RFC 4634](https://datatracker.ietf.org/doc/html/rfc4634) and
* [the paper on truncated SHA512/256](https://eprint.iacr.org/2010/548.pdf).
* @module
* @deprecated
*/
import { SHA384 as SHA384n, sha384 as sha384n, sha512_224 as sha512_224n, SHA512_224 as SHA512_224n, sha512_256 as sha512_256n, SHA512_256 as SHA512_256n, SHA512 as SHA512n, sha512 as sha512n } from './sha2.ts';
/** @deprecated Use import from `noble/hashes/sha2` module */
export declare const SHA512: typeof SHA512n;
/** @deprecated Use import from `noble/hashes/sha2` module */
export declare const sha512: typeof sha512n;
/** @deprecated Use import from `noble/hashes/sha2` module */
export declare const SHA384: typeof SHA384n;
/** @deprecated Use import from `noble/hashes/sha2` module */
export declare const sha384: typeof sha384n;
/** @deprecated Use import from `noble/hashes/sha2` module */
export declare const SHA512_224: typeof SHA512_224n;
/** @deprecated Use import from `noble/hashes/sha2` module */
export declare const sha512_224: typeof sha512_224n;
/** @deprecated Use import from `noble/hashes/sha2` module */
export declare const SHA512_256: typeof SHA512_256n;
/** @deprecated Use import from `noble/hashes/sha2` module */
export declare const sha512_256: typeof sha512_256n;
//# sourceMappingURL=sha512.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"sha512.d.ts","sourceRoot":"","sources":["src/sha512.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,MAAM,IAAI,OAAO,EACjB,MAAM,IAAI,OAAO,EACjB,UAAU,IAAI,WAAW,EACzB,UAAU,IAAI,WAAW,EACzB,UAAU,IAAI,WAAW,EACzB,UAAU,IAAI,WAAW,EACzB,MAAM,IAAI,OAAO,EACjB,MAAM,IAAI,OAAO,EAClB,MAAM,WAAW,CAAC;AACnB,6DAA6D;AAC7D,eAAO,MAAM,MAAM,EAAE,OAAO,OAAiB,CAAC;AAC9C,6DAA6D;AAC7D,eAAO,MAAM,MAAM,EAAE,OAAO,OAAiB,CAAC;AAC9C,6DAA6D;AAC7D,eAAO,MAAM,MAAM,EAAE,OAAO,OAAiB,CAAC;AAC9C,6DAA6D;AAC7D,eAAO,MAAM,MAAM,EAAE,OAAO,OAAiB,CAAC;AAC9C,6DAA6D;AAC7D,eAAO,MAAM,UAAU,EAAE,OAAO,WAAyB,CAAC;AAC1D,6DAA6D;AAC7D,eAAO,MAAM,UAAU,EAAE,OAAO,WAAyB,CAAC;AAC1D,6DAA6D;AAC7D,eAAO,MAAM,UAAU,EAAE,OAAO,WAAyB,CAAC;AAC1D,6DAA6D;AAC7D,eAAO,MAAM,UAAU,EAAE,OAAO,WAAyB,CAAC"}
+29
View File
@@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.sha512_256 = exports.SHA512_256 = exports.sha512_224 = exports.SHA512_224 = exports.sha384 = exports.SHA384 = exports.sha512 = exports.SHA512 = void 0;
/**
* SHA2-512 a.k.a. sha512 and sha384. It is slower than sha256 in js because u64 operations are slow.
*
* Check out [RFC 4634](https://datatracker.ietf.org/doc/html/rfc4634) and
* [the paper on truncated SHA512/256](https://eprint.iacr.org/2010/548.pdf).
* @module
* @deprecated
*/
const sha2_ts_1 = require("./sha2.js");
/** @deprecated Use import from `noble/hashes/sha2` module */
exports.SHA512 = sha2_ts_1.SHA512;
/** @deprecated Use import from `noble/hashes/sha2` module */
exports.sha512 = sha2_ts_1.sha512;
/** @deprecated Use import from `noble/hashes/sha2` module */
exports.SHA384 = sha2_ts_1.SHA384;
/** @deprecated Use import from `noble/hashes/sha2` module */
exports.sha384 = sha2_ts_1.sha384;
/** @deprecated Use import from `noble/hashes/sha2` module */
exports.SHA512_224 = sha2_ts_1.SHA512_224;
/** @deprecated Use import from `noble/hashes/sha2` module */
exports.sha512_224 = sha2_ts_1.sha512_224;
/** @deprecated Use import from `noble/hashes/sha2` module */
exports.SHA512_256 = sha2_ts_1.SHA512_256;
/** @deprecated Use import from `noble/hashes/sha2` module */
exports.sha512_256 = sha2_ts_1.sha512_256;
//# sourceMappingURL=sha512.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"sha512.js","sourceRoot":"","sources":["src/sha512.ts"],"names":[],"mappings":";;;AAAA;;;;;;;GAOG;AACH,uCASmB;AACnB,6DAA6D;AAChD,QAAA,MAAM,GAAmB,gBAAO,CAAC;AAC9C,6DAA6D;AAChD,QAAA,MAAM,GAAmB,gBAAO,CAAC;AAC9C,6DAA6D;AAChD,QAAA,MAAM,GAAmB,gBAAO,CAAC;AAC9C,6DAA6D;AAChD,QAAA,MAAM,GAAmB,gBAAO,CAAC;AAC9C,6DAA6D;AAChD,QAAA,UAAU,GAAuB,oBAAW,CAAC;AAC1D,6DAA6D;AAChD,QAAA,UAAU,GAAuB,oBAAW,CAAC;AAC1D,6DAA6D;AAChD,QAAA,UAAU,GAAuB,oBAAW,CAAC;AAC1D,6DAA6D;AAChD,QAAA,UAAU,GAAuB,oBAAW,CAAC"}
+497
View File
@@ -0,0 +1,497 @@
/**
* Argon2 KDF from RFC 9106. Can be used to create a key from password and salt.
* We suggest to use Scrypt. JS Argon is 2-10x slower than native code because of 64-bitness:
* * argon uses uint64, but JS doesn't have fast uint64array
* * uint64 multiplication is 1/3 of time
* * `P` function would be very nice with u64, because most of value will be in registers,
* hovewer with u32 it will require 32 registers, which is too much.
* * JS arrays do slow bound checks, so reading from `A2_BUF` slows it down
* @module
*/
import { add3H, add3L, rotr32H, rotr32L, rotrBH, rotrBL, rotrSH, rotrSL } from './_u64.ts';
import { blake2b } from './blake2.ts';
import { abytes, clean, kdfInputToBytes, nextTick, u32, u8, type KDFInput } from './utils.ts';
const AT = { Argond2d: 0, Argon2i: 1, Argon2id: 2 } as const;
type Types = (typeof AT)[keyof typeof AT];
const ARGON2_SYNC_POINTS = 4;
const abytesOrZero = (buf?: KDFInput) => {
if (buf === undefined) return Uint8Array.of();
return kdfInputToBytes(buf);
};
// u32 * u32 = u64
function mul(a: number, b: number) {
const aL = a & 0xffff;
const aH = a >>> 16;
const bL = b & 0xffff;
const bH = b >>> 16;
const ll = Math.imul(aL, bL);
const hl = Math.imul(aH, bL);
const lh = Math.imul(aL, bH);
const hh = Math.imul(aH, bH);
const carry = (ll >>> 16) + (hl & 0xffff) + lh;
const high = (hh + (hl >>> 16) + (carry >>> 16)) | 0;
const low = (carry << 16) | (ll & 0xffff);
return { h: high, l: low };
}
function mul2(a: number, b: number) {
// 2 * a * b (via shifts)
const { h, l } = mul(a, b);
return { h: ((h << 1) | (l >>> 31)) & 0xffff_ffff, l: (l << 1) & 0xffff_ffff };
}
// BlaMka permutation for Argon2
// A + B + (2 * u32(A) * u32(B))
function blamka(Ah: number, Al: number, Bh: number, Bl: number) {
const { h: Ch, l: Cl } = mul2(Al, Bl);
// A + B + (2 * A * B)
const Rll = add3L(Al, Bl, Cl);
return { h: add3H(Rll, Ah, Bh, Ch), l: Rll | 0 };
}
// Temporary block buffer
const A2_BUF = new Uint32Array(256); // 1024 bytes (matrix 16x16)
function G(a: number, b: number, c: number, d: number) {
let Al = A2_BUF[2*a], Ah = A2_BUF[2*a + 1]; // prettier-ignore
let Bl = A2_BUF[2*b], Bh = A2_BUF[2*b + 1]; // prettier-ignore
let Cl = A2_BUF[2*c], Ch = A2_BUF[2*c + 1]; // prettier-ignore
let Dl = A2_BUF[2*d], Dh = A2_BUF[2*d + 1]; // prettier-ignore
({ h: Ah, l: Al } = blamka(Ah, Al, Bh, Bl));
({ Dh, Dl } = { Dh: Dh ^ Ah, Dl: Dl ^ Al });
({ Dh, Dl } = { Dh: rotr32H(Dh, Dl), Dl: rotr32L(Dh, Dl) });
({ h: Ch, l: Cl } = blamka(Ch, Cl, Dh, Dl));
({ Bh, Bl } = { Bh: Bh ^ Ch, Bl: Bl ^ Cl });
({ Bh, Bl } = { Bh: rotrSH(Bh, Bl, 24), Bl: rotrSL(Bh, Bl, 24) });
({ h: Ah, l: Al } = blamka(Ah, Al, Bh, Bl));
({ Dh, Dl } = { Dh: Dh ^ Ah, Dl: Dl ^ Al });
({ Dh, Dl } = { Dh: rotrSH(Dh, Dl, 16), Dl: rotrSL(Dh, Dl, 16) });
({ h: Ch, l: Cl } = blamka(Ch, Cl, Dh, Dl));
({ Bh, Bl } = { Bh: Bh ^ Ch, Bl: Bl ^ Cl });
({ Bh, Bl } = { Bh: rotrBH(Bh, Bl, 63), Bl: rotrBL(Bh, Bl, 63) });
(A2_BUF[2 * a] = Al), (A2_BUF[2 * a + 1] = Ah);
(A2_BUF[2 * b] = Bl), (A2_BUF[2 * b + 1] = Bh);
(A2_BUF[2 * c] = Cl), (A2_BUF[2 * c + 1] = Ch);
(A2_BUF[2 * d] = Dl), (A2_BUF[2 * d + 1] = Dh);
}
// prettier-ignore
function P(
v00: number, v01: number, v02: number, v03: number, v04: number, v05: number, v06: number, v07: number,
v08: number, v09: number, v10: number, v11: number, v12: number, v13: number, v14: number, v15: number,
) {
G(v00, v04, v08, v12);
G(v01, v05, v09, v13);
G(v02, v06, v10, v14);
G(v03, v07, v11, v15);
G(v00, v05, v10, v15);
G(v01, v06, v11, v12);
G(v02, v07, v08, v13);
G(v03, v04, v09, v14);
}
function block(x: Uint32Array, xPos: number, yPos: number, outPos: number, needXor: boolean) {
for (let i = 0; i < 256; i++) A2_BUF[i] = x[xPos + i] ^ x[yPos + i];
// columns (8)
for (let i = 0; i < 128; i += 16) {
// prettier-ignore
P(
i, i + 1, i + 2, i + 3, i + 4, i + 5, i + 6, i + 7,
i + 8, i + 9, i + 10, i + 11, i + 12, i + 13, i + 14, i + 15
);
}
// rows (8)
for (let i = 0; i < 16; i += 2) {
// prettier-ignore
P(
i, i + 1, i + 16, i + 17, i + 32, i + 33, i + 48, i + 49,
i + 64, i + 65, i + 80, i + 81, i + 96, i + 97, i + 112, i + 113
);
}
if (needXor) for (let i = 0; i < 256; i++) x[outPos + i] ^= A2_BUF[i] ^ x[xPos + i] ^ x[yPos + i];
else for (let i = 0; i < 256; i++) x[outPos + i] = A2_BUF[i] ^ x[xPos + i] ^ x[yPos + i];
clean(A2_BUF);
}
// Variable-Length Hash Function H'
function Hp(A: Uint32Array, dkLen: number) {
const A8 = u8(A);
const T = new Uint32Array(1);
const T8 = u8(T);
T[0] = dkLen;
// Fast path
if (dkLen <= 64) return blake2b.create({ dkLen }).update(T8).update(A8).digest();
const out = new Uint8Array(dkLen);
let V = blake2b.create({}).update(T8).update(A8).digest();
let pos = 0;
// First block
out.set(V.subarray(0, 32));
pos += 32;
// Rest blocks
for (; dkLen - pos > 64; pos += 32) {
const Vh = blake2b.create({}).update(V);
Vh.digestInto(V);
Vh.destroy();
out.set(V.subarray(0, 32), pos);
}
// Last block
out.set(blake2b(V, { dkLen: dkLen - pos }), pos);
clean(V, T);
return u32(out);
}
// Used only inside process block!
function indexAlpha(
r: number,
s: number,
laneLen: number,
segmentLen: number,
index: number,
randL: number,
sameLane: boolean = false
) {
// This is ugly, but close enough to reference implementation.
let area: number;
if (r === 0) {
if (s === 0) area = index - 1;
else if (sameLane) area = s * segmentLen + index - 1;
else area = s * segmentLen + (index == 0 ? -1 : 0);
} else if (sameLane) area = laneLen - segmentLen + index - 1;
else area = laneLen - segmentLen + (index == 0 ? -1 : 0);
const startPos = r !== 0 && s !== ARGON2_SYNC_POINTS - 1 ? (s + 1) * segmentLen : 0;
const rel = area - 1 - mul(area, mul(randL, randL).h).h;
return (startPos + rel) % laneLen;
}
/**
* Argon2 options.
* * t: time cost, m: mem cost in kb, p: parallelization.
* * key: optional key. personalization: arbitrary extra data.
* * dkLen: desired number of output bytes.
*/
export type ArgonOpts = {
t: number; // Time cost, iterations count
m: number; // Memory cost (in KB)
p: number; // Parallelization parameter
version?: number; // Default: 0x13 (19)
key?: KDFInput; // Optional key
personalization?: KDFInput; // Optional arbitrary extra data
dkLen?: number; // Desired number of returned bytes
asyncTick?: number; // Maximum time in ms for which async function can block execution
maxmem?: number;
onProgress?: (progress: number) => void;
};
const maxUint32 = Math.pow(2, 32);
function isU32(num: number) {
return Number.isSafeInteger(num) && num >= 0 && num < maxUint32;
}
function argon2Opts(opts: ArgonOpts) {
const merged: any = {
version: 0x13,
dkLen: 32,
maxmem: maxUint32 - 1,
asyncTick: 10,
};
for (let [k, v] of Object.entries(opts)) if (v != null) merged[k] = v;
const { dkLen, p, m, t, version, onProgress } = merged;
if (!isU32(dkLen) || dkLen < 4) throw new Error('dkLen should be at least 4 bytes');
if (!isU32(p) || p < 1 || p >= Math.pow(2, 24)) throw new Error('p should be 1 <= p < 2^24');
if (!isU32(m)) throw new Error('m should be 0 <= m < 2^32');
if (!isU32(t) || t < 1) throw new Error('t (iterations) should be 1 <= t < 2^32');
if (onProgress !== undefined && typeof onProgress !== 'function')
throw new Error('progressCb should be function');
/*
Memory size m MUST be an integer number of kibibytes from 8*p to 2^(32)-1. The actual number of blocks is m', which is m rounded down to the nearest multiple of 4*p.
*/
if (!isU32(m) || m < 8 * p) throw new Error('memory should be at least 8*p bytes');
if (version !== 0x10 && version !== 0x13) throw new Error('unknown version=' + version);
return merged;
}
function argon2Init(password: KDFInput, salt: KDFInput, type: Types, opts: ArgonOpts) {
password = kdfInputToBytes(password);
salt = kdfInputToBytes(salt);
abytes(password);
abytes(salt);
if (!isU32(password.length)) throw new Error('password should be less than 4 GB');
if (!isU32(salt.length) || salt.length < 8)
throw new Error('salt should be at least 8 bytes and less than 4 GB');
if (!Object.values(AT).includes(type)) throw new Error('invalid type');
let { p, dkLen, m, t, version, key, personalization, maxmem, onProgress, asyncTick } =
argon2Opts(opts);
// Validation
key = abytesOrZero(key);
personalization = abytesOrZero(personalization);
// H_0 = H^(64)(LE32(p) || LE32(T) || LE32(m) || LE32(t) ||
// LE32(v) || LE32(y) || LE32(length(P)) || P ||
// LE32(length(S)) || S || LE32(length(K)) || K ||
// LE32(length(X)) || X)
const h = blake2b.create({});
const BUF = new Uint32Array(1);
const BUF8 = u8(BUF);
for (let item of [p, dkLen, m, t, version, type]) {
BUF[0] = item;
h.update(BUF8);
}
for (let i of [password, salt, key, personalization]) {
BUF[0] = i.length; // BUF is u32 array, this is valid
h.update(BUF8).update(i);
}
const H0 = new Uint32Array(18);
const H0_8 = u8(H0);
h.digestInto(H0_8);
// 256 u32 = 1024 (BLOCK_SIZE), fills A2_BUF on processing
// Params
const lanes = p;
// m' = 4 * p * floor (m / 4p)
const mP = 4 * p * Math.floor(m / (ARGON2_SYNC_POINTS * p));
//q = m' / p columns
const laneLen = Math.floor(mP / p);
const segmentLen = Math.floor(laneLen / ARGON2_SYNC_POINTS);
const memUsed = mP * 256;
if (!isU32(maxmem) || memUsed > maxmem)
throw new Error(
'mem should be less than 2**32, got: maxmem=' + maxmem + ', memused=' + memUsed
);
const B = new Uint32Array(memUsed);
// Fill first blocks
for (let l = 0; l < p; l++) {
const i = 256 * laneLen * l;
// B[i][0] = H'^(1024)(H_0 || LE32(0) || LE32(i))
H0[17] = l;
H0[16] = 0;
B.set(Hp(H0, 1024), i);
// B[i][1] = H'^(1024)(H_0 || LE32(1) || LE32(i))
H0[16] = 1;
B.set(Hp(H0, 1024), i + 256);
}
let perBlock = () => {};
if (onProgress) {
const totalBlock = t * ARGON2_SYNC_POINTS * p * segmentLen;
// Invoke callback if progress changes from 10.01 to 10.02
// Allows to draw smooth progress bar on up to 8K screen
const callbackPer = Math.max(Math.floor(totalBlock / 10000), 1);
let blockCnt = 0;
perBlock = () => {
blockCnt++;
if (onProgress && (!(blockCnt % callbackPer) || blockCnt === totalBlock))
onProgress(blockCnt / totalBlock);
};
}
clean(BUF, H0);
return { type, mP, p, t, version, B, laneLen, lanes, segmentLen, dkLen, perBlock, asyncTick };
}
function argon2Output(B: Uint32Array, p: number, laneLen: number, dkLen: number) {
const B_final = new Uint32Array(256);
for (let l = 0; l < p; l++)
for (let j = 0; j < 256; j++) B_final[j] ^= B[256 * (laneLen * l + laneLen - 1) + j];
const res = u8(Hp(B_final, dkLen));
clean(B_final);
return res;
}
function processBlock(
B: Uint32Array,
address: Uint32Array,
l: number,
r: number,
s: number,
index: number,
laneLen: number,
segmentLen: number,
lanes: number,
offset: number,
prev: number,
dataIndependent: boolean,
needXor: boolean
) {
if (offset % laneLen) prev = offset - 1;
let randL, randH;
if (dataIndependent) {
let i128 = index % 128;
if (i128 === 0) {
address[256 + 12]++;
block(address, 256, 2 * 256, 0, false);
block(address, 0, 2 * 256, 0, false);
}
randL = address[2 * i128];
randH = address[2 * i128 + 1];
} else {
const T = 256 * prev;
randL = B[T];
randH = B[T + 1];
}
// address block
const refLane = r === 0 && s === 0 ? l : randH % lanes;
const refPos = indexAlpha(r, s, laneLen, segmentLen, index, randL, refLane == l);
const refBlock = laneLen * refLane + refPos;
// B[i][j] = G(B[i][j-1], B[l][z])
block(B, 256 * prev, 256 * refBlock, offset * 256, needXor);
}
function argon2(type: Types, password: KDFInput, salt: KDFInput, opts: ArgonOpts) {
const { mP, p, t, version, B, laneLen, lanes, segmentLen, dkLen, perBlock } = argon2Init(
password,
salt,
type,
opts
);
// Pre-loop setup
// [address, input, zero_block] format so we can pass single U32 to block function
const address = new Uint32Array(3 * 256);
address[256 + 6] = mP;
address[256 + 8] = t;
address[256 + 10] = type;
for (let r = 0; r < t; r++) {
const needXor = r !== 0 && version === 0x13;
address[256 + 0] = r;
for (let s = 0; s < ARGON2_SYNC_POINTS; s++) {
address[256 + 4] = s;
const dataIndependent = type == AT.Argon2i || (type == AT.Argon2id && r === 0 && s < 2);
for (let l = 0; l < p; l++) {
address[256 + 2] = l;
address[256 + 12] = 0;
let startPos = 0;
if (r === 0 && s === 0) {
startPos = 2;
if (dataIndependent) {
address[256 + 12]++;
block(address, 256, 2 * 256, 0, false);
block(address, 0, 2 * 256, 0, false);
}
}
// current block postion
let offset = l * laneLen + s * segmentLen + startPos;
// previous block position
let prev = offset % laneLen ? offset - 1 : offset + laneLen - 1;
for (let index = startPos; index < segmentLen; index++, offset++, prev++) {
perBlock();
processBlock(
B,
address,
l,
r,
s,
index,
laneLen,
segmentLen,
lanes,
offset,
prev,
dataIndependent,
needXor
);
}
}
}
}
clean(address);
return argon2Output(B, p, laneLen, dkLen);
}
/** argon2d GPU-resistant version. */
export const argon2d = (password: KDFInput, salt: KDFInput, opts: ArgonOpts): Uint8Array =>
argon2(AT.Argond2d, password, salt, opts);
/** argon2i side-channel-resistant version. */
export const argon2i = (password: KDFInput, salt: KDFInput, opts: ArgonOpts): Uint8Array =>
argon2(AT.Argon2i, password, salt, opts);
/** argon2id, combining i+d, the most popular version from RFC 9106 */
export const argon2id = (password: KDFInput, salt: KDFInput, opts: ArgonOpts): Uint8Array =>
argon2(AT.Argon2id, password, salt, opts);
async function argon2Async(type: Types, password: KDFInput, salt: KDFInput, opts: ArgonOpts) {
const { mP, p, t, version, B, laneLen, lanes, segmentLen, dkLen, perBlock, asyncTick } =
argon2Init(password, salt, type, opts);
// Pre-loop setup
// [address, input, zero_block] format so we can pass single U32 to block function
const address = new Uint32Array(3 * 256);
address[256 + 6] = mP;
address[256 + 8] = t;
address[256 + 10] = type;
let ts = Date.now();
for (let r = 0; r < t; r++) {
const needXor = r !== 0 && version === 0x13;
address[256 + 0] = r;
for (let s = 0; s < ARGON2_SYNC_POINTS; s++) {
address[256 + 4] = s;
const dataIndependent = type == AT.Argon2i || (type == AT.Argon2id && r === 0 && s < 2);
for (let l = 0; l < p; l++) {
address[256 + 2] = l;
address[256 + 12] = 0;
let startPos = 0;
if (r === 0 && s === 0) {
startPos = 2;
if (dataIndependent) {
address[256 + 12]++;
block(address, 256, 2 * 256, 0, false);
block(address, 0, 2 * 256, 0, false);
}
}
// current block postion
let offset = l * laneLen + s * segmentLen + startPos;
// previous block position
let prev = offset % laneLen ? offset - 1 : offset + laneLen - 1;
for (let index = startPos; index < segmentLen; index++, offset++, prev++) {
perBlock();
processBlock(
B,
address,
l,
r,
s,
index,
laneLen,
segmentLen,
lanes,
offset,
prev,
dataIndependent,
needXor
);
// Date.now() is not monotonic, so in case if clock goes backwards we return return control too
const diff = Date.now() - ts;
if (!(diff >= 0 && diff < asyncTick)) {
await nextTick();
ts += diff;
}
}
}
}
}
clean(address);
return argon2Output(B, p, laneLen, dkLen);
}
/** argon2d async GPU-resistant version. */
export const argon2dAsync = (
password: KDFInput,
salt: KDFInput,
opts: ArgonOpts
): Promise<Uint8Array> => argon2Async(AT.Argond2d, password, salt, opts);
/** argon2i async side-channel-resistant version. */
export const argon2iAsync = (
password: KDFInput,
salt: KDFInput,
opts: ArgonOpts
): Promise<Uint8Array> => argon2Async(AT.Argon2i, password, salt, opts);
/** argon2id async, combining i+d, the most popular version from RFC 9106 */
export const argon2idAsync = (
password: KDFInput,
salt: KDFInput,
opts: ArgonOpts
): Promise<Uint8Array> => argon2Async(AT.Argon2id, password, salt, opts);
+534
View File
@@ -0,0 +1,534 @@
/**
* Blake1 legacy hash function, one of SHA3 proposals.
* Rarely used. Check out blake2 or blake3 instead.
* https://www.aumasson.jp/blake/blake.pdf
*
* In the best case, there are 0 allocations.
*
* Differences from blake2:
*
* - BE instead of LE
* - Paddings, similar to MD5, RIPEMD, SHA1, SHA2, but:
* - length flag is located before actual length
* - padding block is compressed differently (no lengths)
* Instead of msg[sigma[k]], we have `msg[sigma[k]] ^ constants[sigma[k-1]]`
* (-1 for g1, g2 without -1)
* - Salt is XOR-ed into constants instead of state
* - Salt is XOR-ed with output in `compress`
* - Additional rows (+64 bytes) in SIGMA for new rounds
* - Different round count:
* - 14 / 10 rounds in blake256 / blake2s
* - 16 / 12 rounds in blake512 / blake2b
* - blake512: G1b: rotr 24 -> 25, G2b: rotr 63 -> 11
* @module
*/
import { BSIGMA, G1s, G2s } from './_blake.ts';
import { setBigUint64, SHA224_IV, SHA256_IV, SHA384_IV, SHA512_IV } from './_md.ts';
import * as u64 from './_u64.ts';
// prettier-ignore
import {
abytes, aexists, aoutput,
clean, createOptHasher,
createView, Hash, toBytes,
type CHashO, type Input,
} from './utils.ts';
/** Blake1 options. Basically just "salt" */
export type BlakeOpts = {
salt?: Uint8Array;
};
// Empty zero-filled salt
const EMPTY_SALT = /* @__PURE__ */ new Uint32Array(8);
abstract class BLAKE1<T extends BLAKE1<T>> extends Hash<T> {
protected finished = false;
protected length = 0;
protected pos = 0;
protected destroyed = false;
// For partial updates less than block size
protected buffer: Uint8Array;
protected view: DataView;
protected salt: Uint32Array;
abstract compress(view: DataView, offset: number, withLength?: boolean): void;
protected abstract get(): number[];
protected abstract set(...args: number[]): void;
readonly blockLen: number;
readonly outputLen: number;
private lengthFlag: number;
private counterLen: number;
protected constants: Uint32Array;
constructor(
blockLen: number,
outputLen: number,
lengthFlag: number,
counterLen: number,
saltLen: number,
constants: Uint32Array,
opts: BlakeOpts = {}
) {
super();
const { salt } = opts;
this.blockLen = blockLen;
this.outputLen = outputLen;
this.lengthFlag = lengthFlag;
this.counterLen = counterLen;
this.buffer = new Uint8Array(blockLen);
this.view = createView(this.buffer);
if (salt) {
let slt = salt;
slt = toBytes(slt);
abytes(slt);
if (slt.length !== 4 * saltLen) throw new Error('wrong salt length');
const salt32 = (this.salt = new Uint32Array(saltLen));
const sv = createView(slt);
this.constants = constants.slice();
for (let i = 0, offset = 0; i < salt32.length; i++, offset += 4) {
salt32[i] = sv.getUint32(offset, false);
this.constants[i] ^= salt32[i];
}
} else {
this.salt = EMPTY_SALT;
this.constants = constants;
}
}
update(data: Input): this {
aexists(this);
data = toBytes(data);
abytes(data);
// From _md, but update length before each compress
const { view, buffer, blockLen } = this;
const len = data.length;
let dataView;
for (let pos = 0; pos < len; ) {
const take = Math.min(blockLen - this.pos, len - pos);
// Fast path: we have at least one block in input, cast it to view and process
if (take === blockLen) {
if (!dataView) dataView = createView(data);
for (; blockLen <= len - pos; pos += blockLen) {
this.length += blockLen;
this.compress(dataView, pos);
}
continue;
}
buffer.set(data.subarray(pos, pos + take), this.pos);
this.pos += take;
pos += take;
if (this.pos === blockLen) {
this.length += blockLen;
this.compress(view, 0, true);
this.pos = 0;
}
}
return this;
}
destroy(): void {
this.destroyed = true;
if (this.salt !== EMPTY_SALT) {
clean(this.salt, this.constants);
}
}
_cloneInto(to?: T): T {
to ||= new (this.constructor as any)() as T;
to.set(...this.get());
const { buffer, length, finished, destroyed, constants, salt, pos } = this;
to.buffer.set(buffer);
to.constants = constants.slice();
to.destroyed = destroyed;
to.finished = finished;
to.length = length;
to.pos = pos;
to.salt = salt.slice();
return to;
}
clone(): T {
return this._cloneInto();
}
digestInto(out: Uint8Array): void {
aexists(this);
aoutput(out, this);
this.finished = true;
// Padding
const { buffer, blockLen, counterLen, lengthFlag, view } = this;
clean(buffer.subarray(this.pos)); // clean buf
const counter = BigInt((this.length + this.pos) * 8);
const counterPos = blockLen - counterLen - 1;
buffer[this.pos] |= 0b1000_0000; // End block flag
this.length += this.pos; // add unwritten length
// Not enough in buffer for length: write what we have.
if (this.pos > counterPos) {
this.compress(view, 0);
clean(buffer);
this.pos = 0;
}
// Difference with md: here we have lengthFlag!
buffer[counterPos] |= lengthFlag; // Length flag
// We always set 8 byte length flag. Because length will overflow significantly sooner.
setBigUint64(view, blockLen - 8, counter, false);
this.compress(view, 0, this.pos !== 0); // don't add length if length is not empty block?
// Write output
clean(buffer);
const v = createView(out);
const state = this.get();
for (let i = 0; i < this.outputLen / 4; ++i) v.setUint32(i * 4, state[i]);
}
digest(): Uint8Array {
const { buffer, outputLen } = this;
this.digestInto(buffer);
const res = buffer.slice(0, outputLen);
this.destroy();
return res;
}
}
// Constants
const B64C = /* @__PURE__ */ Uint32Array.from([
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
0x9216d5d9, 0x8979fb1b, 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69,
]);
// first half of C512
const B32C = B64C.slice(0, 16);
const B256_IV = SHA256_IV.slice();
const B224_IV = SHA224_IV.slice();
const B384_IV = SHA384_IV.slice();
const B512_IV = SHA512_IV.slice();
function generateTBL256() {
const TBL = [];
for (let i = 0, j = 0; i < 14; i++, j += 16) {
for (let offset = 1; offset < 16; offset += 2) {
TBL.push(B32C[BSIGMA[j + offset]]);
TBL.push(B32C[BSIGMA[j + offset - 1]]);
}
}
return new Uint32Array(TBL);
}
const TBL256 = /* @__PURE__ */ generateTBL256(); // C256[SIGMA[X]] precompute
// Reusable temporary buffer
const BLAKE256_W = /* @__PURE__ */ new Uint32Array(16);
class Blake1_32 extends BLAKE1<Blake1_32> {
private v0: number;
private v1: number;
private v2: number;
private v3: number;
private v4: number;
private v5: number;
private v6: number;
private v7: number;
constructor(outputLen: number, IV: Uint32Array, lengthFlag: number, opts: BlakeOpts = {}) {
super(64, outputLen, lengthFlag, 8, 4, B32C, opts);
this.v0 = IV[0] | 0;
this.v1 = IV[1] | 0;
this.v2 = IV[2] | 0;
this.v3 = IV[3] | 0;
this.v4 = IV[4] | 0;
this.v5 = IV[5] | 0;
this.v6 = IV[6] | 0;
this.v7 = IV[7] | 0;
}
protected get(): [number, number, number, number, number, number, number, number] {
const { v0, v1, v2, v3, v4, v5, v6, v7 } = this;
return [v0, v1, v2, v3, v4, v5, v6, v7];
}
// prettier-ignore
protected set(
v0: number, v1: number, v2: number, v3: number, v4: number, v5: number, v6: number, v7: number
): void {
this.v0 = v0 | 0;
this.v1 = v1 | 0;
this.v2 = v2 | 0;
this.v3 = v3 | 0;
this.v4 = v4 | 0;
this.v5 = v5 | 0;
this.v6 = v6 | 0;
this.v7 = v7 | 0;
}
destroy(): void {
super.destroy();
this.set(0, 0, 0, 0, 0, 0, 0, 0);
}
compress(view: DataView, offset: number, withLength = true): void {
for (let i = 0; i < 16; i++, offset += 4) BLAKE256_W[i] = view.getUint32(offset, false);
// NOTE: we cannot re-use compress from blake2s, since there is additional xor over u256[SIGMA[e]]
let v00 = this.v0 | 0;
let v01 = this.v1 | 0;
let v02 = this.v2 | 0;
let v03 = this.v3 | 0;
let v04 = this.v4 | 0;
let v05 = this.v5 | 0;
let v06 = this.v6 | 0;
let v07 = this.v7 | 0;
let v08 = this.constants[0] | 0;
let v09 = this.constants[1] | 0;
let v10 = this.constants[2] | 0;
let v11 = this.constants[3] | 0;
const { h, l } = u64.fromBig(BigInt(withLength ? this.length * 8 : 0));
let v12 = (this.constants[4] ^ l) >>> 0;
let v13 = (this.constants[5] ^ l) >>> 0;
let v14 = (this.constants[6] ^ h) >>> 0;
let v15 = (this.constants[7] ^ h) >>> 0;
// prettier-ignore
for (let i = 0, k = 0, j = 0; i < 14; i++) {
({ a: v00, b: v04, c: v08, d: v12 } = G1s(v00, v04, v08, v12, BLAKE256_W[BSIGMA[k++]] ^ TBL256[j++]));
({ a: v00, b: v04, c: v08, d: v12 } = G2s(v00, v04, v08, v12, BLAKE256_W[BSIGMA[k++]] ^ TBL256[j++]));
({ a: v01, b: v05, c: v09, d: v13 } = G1s(v01, v05, v09, v13, BLAKE256_W[BSIGMA[k++]] ^ TBL256[j++]));
({ a: v01, b: v05, c: v09, d: v13 } = G2s(v01, v05, v09, v13, BLAKE256_W[BSIGMA[k++]] ^ TBL256[j++]));
({ a: v02, b: v06, c: v10, d: v14 } = G1s(v02, v06, v10, v14, BLAKE256_W[BSIGMA[k++]] ^ TBL256[j++]));
({ a: v02, b: v06, c: v10, d: v14 } = G2s(v02, v06, v10, v14, BLAKE256_W[BSIGMA[k++]] ^ TBL256[j++]));
({ a: v03, b: v07, c: v11, d: v15 } = G1s(v03, v07, v11, v15, BLAKE256_W[BSIGMA[k++]] ^ TBL256[j++]));
({ a: v03, b: v07, c: v11, d: v15 } = G2s(v03, v07, v11, v15, BLAKE256_W[BSIGMA[k++]] ^ TBL256[j++]));
({ a: v00, b: v05, c: v10, d: v15 } = G1s(v00, v05, v10, v15, BLAKE256_W[BSIGMA[k++]] ^ TBL256[j++]));
({ a: v00, b: v05, c: v10, d: v15 } = G2s(v00, v05, v10, v15, BLAKE256_W[BSIGMA[k++]] ^ TBL256[j++]));
({ a: v01, b: v06, c: v11, d: v12 } = G1s(v01, v06, v11, v12, BLAKE256_W[BSIGMA[k++]] ^ TBL256[j++]));
({ a: v01, b: v06, c: v11, d: v12 } = G2s(v01, v06, v11, v12, BLAKE256_W[BSIGMA[k++]] ^ TBL256[j++]));
({ a: v02, b: v07, c: v08, d: v13 } = G1s(v02, v07, v08, v13, BLAKE256_W[BSIGMA[k++]] ^ TBL256[j++]));
({ a: v02, b: v07, c: v08, d: v13 } = G2s(v02, v07, v08, v13, BLAKE256_W[BSIGMA[k++]] ^ TBL256[j++]));
({ a: v03, b: v04, c: v09, d: v14 } = G1s(v03, v04, v09, v14, BLAKE256_W[BSIGMA[k++]] ^ TBL256[j++]));
({ a: v03, b: v04, c: v09, d: v14 } = G2s(v03, v04, v09, v14, BLAKE256_W[BSIGMA[k++]] ^ TBL256[j++]));
}
this.v0 = (this.v0 ^ v00 ^ v08 ^ this.salt[0]) >>> 0;
this.v1 = (this.v1 ^ v01 ^ v09 ^ this.salt[1]) >>> 0;
this.v2 = (this.v2 ^ v02 ^ v10 ^ this.salt[2]) >>> 0;
this.v3 = (this.v3 ^ v03 ^ v11 ^ this.salt[3]) >>> 0;
this.v4 = (this.v4 ^ v04 ^ v12 ^ this.salt[0]) >>> 0;
this.v5 = (this.v5 ^ v05 ^ v13 ^ this.salt[1]) >>> 0;
this.v6 = (this.v6 ^ v06 ^ v14 ^ this.salt[2]) >>> 0;
this.v7 = (this.v7 ^ v07 ^ v15 ^ this.salt[3]) >>> 0;
clean(BLAKE256_W);
}
}
const BBUF = /* @__PURE__ */ new Uint32Array(32);
const BLAKE512_W = /* @__PURE__ */ new Uint32Array(32);
function generateTBL512() {
const TBL = [];
for (let r = 0, k = 0; r < 16; r++, k += 16) {
for (let offset = 1; offset < 16; offset += 2) {
TBL.push(B64C[BSIGMA[k + offset] * 2 + 0]);
TBL.push(B64C[BSIGMA[k + offset] * 2 + 1]);
TBL.push(B64C[BSIGMA[k + offset - 1] * 2 + 0]);
TBL.push(B64C[BSIGMA[k + offset - 1] * 2 + 1]);
}
}
return new Uint32Array(TBL);
}
const TBL512 = /* @__PURE__ */ generateTBL512(); // C512[SIGMA[X]] precompute
// Mixing function G splitted in two halfs
function G1b(a: number, b: number, c: number, d: number, msg: Uint32Array, k: number) {
const Xpos = 2 * BSIGMA[k];
const Xl = msg[Xpos + 1] ^ TBL512[k * 2 + 1], Xh = msg[Xpos] ^ TBL512[k * 2]; // prettier-ignore
let Al = BBUF[2 * a + 1], Ah = BBUF[2 * a]; // prettier-ignore
let Bl = BBUF[2 * b + 1], Bh = BBUF[2 * b]; // prettier-ignore
let Cl = BBUF[2 * c + 1], Ch = BBUF[2 * c]; // prettier-ignore
let Dl = BBUF[2 * d + 1], Dh = BBUF[2 * d]; // prettier-ignore
// v[a] = (v[a] + v[b] + x) | 0;
let ll = u64.add3L(Al, Bl, Xl);
Ah = u64.add3H(ll, Ah, Bh, Xh) >>> 0;
Al = (ll | 0) >>> 0;
// v[d] = rotr(v[d] ^ v[a], 32)
({ Dh, Dl } = { Dh: Dh ^ Ah, Dl: Dl ^ Al });
({ Dh, Dl } = { Dh: u64.rotr32H(Dh, Dl), Dl: u64.rotr32L(Dh, Dl) });
// v[c] = (v[c] + v[d]) | 0;
({ h: Ch, l: Cl } = u64.add(Ch, Cl, Dh, Dl));
// v[b] = rotr(v[b] ^ v[c], 25)
({ Bh, Bl } = { Bh: Bh ^ Ch, Bl: Bl ^ Cl });
({ Bh, Bl } = { Bh: u64.rotrSH(Bh, Bl, 25), Bl: u64.rotrSL(Bh, Bl, 25) });
(BBUF[2 * a + 1] = Al), (BBUF[2 * a] = Ah);
(BBUF[2 * b + 1] = Bl), (BBUF[2 * b] = Bh);
(BBUF[2 * c + 1] = Cl), (BBUF[2 * c] = Ch);
(BBUF[2 * d + 1] = Dl), (BBUF[2 * d] = Dh);
}
function G2b(a: number, b: number, c: number, d: number, msg: Uint32Array, k: number) {
const Xpos = 2 * BSIGMA[k];
const Xl = msg[Xpos + 1] ^ TBL512[k * 2 + 1], Xh = msg[Xpos] ^ TBL512[k * 2]; // prettier-ignore
let Al = BBUF[2 * a + 1], Ah = BBUF[2 * a]; // prettier-ignore
let Bl = BBUF[2 * b + 1], Bh = BBUF[2 * b]; // prettier-ignore
let Cl = BBUF[2 * c + 1], Ch = BBUF[2 * c]; // prettier-ignore
let Dl = BBUF[2 * d + 1], Dh = BBUF[2 * d]; // prettier-ignore
// v[a] = (v[a] + v[b] + x) | 0;
let ll = u64.add3L(Al, Bl, Xl);
Ah = u64.add3H(ll, Ah, Bh, Xh);
Al = ll | 0;
// v[d] = rotr(v[d] ^ v[a], 16)
({ Dh, Dl } = { Dh: Dh ^ Ah, Dl: Dl ^ Al });
({ Dh, Dl } = { Dh: u64.rotrSH(Dh, Dl, 16), Dl: u64.rotrSL(Dh, Dl, 16) });
// v[c] = (v[c] + v[d]) | 0;
({ h: Ch, l: Cl } = u64.add(Ch, Cl, Dh, Dl));
// v[b] = rotr(v[b] ^ v[c], 11)
({ Bh, Bl } = { Bh: Bh ^ Ch, Bl: Bl ^ Cl });
({ Bh, Bl } = { Bh: u64.rotrSH(Bh, Bl, 11), Bl: u64.rotrSL(Bh, Bl, 11) });
(BBUF[2 * a + 1] = Al), (BBUF[2 * a] = Ah);
(BBUF[2 * b + 1] = Bl), (BBUF[2 * b] = Bh);
(BBUF[2 * c + 1] = Cl), (BBUF[2 * c] = Ch);
(BBUF[2 * d + 1] = Dl), (BBUF[2 * d] = Dh);
}
class Blake1_64 extends BLAKE1<Blake1_64> {
private v0l: number;
private v0h: number;
private v1l: number;
private v1h: number;
private v2l: number;
private v2h: number;
private v3l: number;
private v3h: number;
private v4l: number;
private v4h: number;
private v5l: number;
private v5h: number;
private v6l: number;
private v6h: number;
private v7l: number;
private v7h: number;
constructor(outputLen: number, IV: Uint32Array, lengthFlag: number, opts: BlakeOpts = {}) {
super(128, outputLen, lengthFlag, 16, 8, B64C, opts);
this.v0l = IV[0] | 0;
this.v0h = IV[1] | 0;
this.v1l = IV[2] | 0;
this.v1h = IV[3] | 0;
this.v2l = IV[4] | 0;
this.v2h = IV[5] | 0;
this.v3l = IV[6] | 0;
this.v3h = IV[7] | 0;
this.v4l = IV[8] | 0;
this.v4h = IV[9] | 0;
this.v5l = IV[10] | 0;
this.v5h = IV[11] | 0;
this.v6l = IV[12] | 0;
this.v6h = IV[13] | 0;
this.v7l = IV[14] | 0;
this.v7h = IV[15] | 0;
}
// prettier-ignore
protected get(): [
number, number, number, number, number, number, number, number,
number, number, number, number, number, number, number, number
] {
let { v0l, v0h, v1l, v1h, v2l, v2h, v3l, v3h, v4l, v4h, v5l, v5h, v6l, v6h, v7l, v7h } = this;
return [v0l, v0h, v1l, v1h, v2l, v2h, v3l, v3h, v4l, v4h, v5l, v5h, v6l, v6h, v7l, v7h];
}
// prettier-ignore
protected set(
v0l: number, v0h: number, v1l: number, v1h: number,
v2l: number, v2h: number, v3l: number, v3h: number,
v4l: number, v4h: number, v5l: number, v5h: number,
v6l: number, v6h: number, v7l: number, v7h: number
): void {
this.v0l = v0l | 0;
this.v0h = v0h | 0;
this.v1l = v1l | 0;
this.v1h = v1h | 0;
this.v2l = v2l | 0;
this.v2h = v2h | 0;
this.v3l = v3l | 0;
this.v3h = v3h | 0;
this.v4l = v4l | 0;
this.v4h = v4h | 0;
this.v5l = v5l | 0;
this.v5h = v5h | 0;
this.v6l = v6l | 0;
this.v6h = v6h | 0;
this.v7l = v7l | 0;
this.v7h = v7h | 0;
}
destroy(): void {
super.destroy();
this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
compress(view: DataView, offset: number, withLength = true): void {
for (let i = 0; i < 32; i++, offset += 4) BLAKE512_W[i] = view.getUint32(offset, false);
this.get().forEach((v, i) => (BBUF[i] = v)); // First half from state.
BBUF.set(this.constants.subarray(0, 16), 16);
if (withLength) {
const { h, l } = u64.fromBig(BigInt(this.length * 8));
BBUF[24] = (BBUF[24] ^ h) >>> 0;
BBUF[25] = (BBUF[25] ^ l) >>> 0;
BBUF[26] = (BBUF[26] ^ h) >>> 0;
BBUF[27] = (BBUF[27] ^ l) >>> 0;
}
for (let i = 0, k = 0; i < 16; i++) {
G1b(0, 4, 8, 12, BLAKE512_W, k++);
G2b(0, 4, 8, 12, BLAKE512_W, k++);
G1b(1, 5, 9, 13, BLAKE512_W, k++);
G2b(1, 5, 9, 13, BLAKE512_W, k++);
G1b(2, 6, 10, 14, BLAKE512_W, k++);
G2b(2, 6, 10, 14, BLAKE512_W, k++);
G1b(3, 7, 11, 15, BLAKE512_W, k++);
G2b(3, 7, 11, 15, BLAKE512_W, k++);
G1b(0, 5, 10, 15, BLAKE512_W, k++);
G2b(0, 5, 10, 15, BLAKE512_W, k++);
G1b(1, 6, 11, 12, BLAKE512_W, k++);
G2b(1, 6, 11, 12, BLAKE512_W, k++);
G1b(2, 7, 8, 13, BLAKE512_W, k++);
G2b(2, 7, 8, 13, BLAKE512_W, k++);
G1b(3, 4, 9, 14, BLAKE512_W, k++);
G2b(3, 4, 9, 14, BLAKE512_W, k++);
}
this.v0l ^= BBUF[0] ^ BBUF[16] ^ this.salt[0];
this.v0h ^= BBUF[1] ^ BBUF[17] ^ this.salt[1];
this.v1l ^= BBUF[2] ^ BBUF[18] ^ this.salt[2];
this.v1h ^= BBUF[3] ^ BBUF[19] ^ this.salt[3];
this.v2l ^= BBUF[4] ^ BBUF[20] ^ this.salt[4];
this.v2h ^= BBUF[5] ^ BBUF[21] ^ this.salt[5];
this.v3l ^= BBUF[6] ^ BBUF[22] ^ this.salt[6];
this.v3h ^= BBUF[7] ^ BBUF[23] ^ this.salt[7];
this.v4l ^= BBUF[8] ^ BBUF[24] ^ this.salt[0];
this.v4h ^= BBUF[9] ^ BBUF[25] ^ this.salt[1];
this.v5l ^= BBUF[10] ^ BBUF[26] ^ this.salt[2];
this.v5h ^= BBUF[11] ^ BBUF[27] ^ this.salt[3];
this.v6l ^= BBUF[12] ^ BBUF[28] ^ this.salt[4];
this.v6h ^= BBUF[13] ^ BBUF[29] ^ this.salt[5];
this.v7l ^= BBUF[14] ^ BBUF[30] ^ this.salt[6];
this.v7h ^= BBUF[15] ^ BBUF[31] ^ this.salt[7];
clean(BBUF, BLAKE512_W);
}
}
export class BLAKE224 extends Blake1_32 {
constructor(opts: BlakeOpts = {}) {
super(28, B224_IV, 0b0000_0000, opts);
}
}
export class BLAKE256 extends Blake1_32 {
constructor(opts: BlakeOpts = {}) {
super(32, B256_IV, 0b0000_0001, opts);
}
}
export class BLAKE384 extends Blake1_64 {
constructor(opts: BlakeOpts = {}) {
super(48, B384_IV, 0b0000_0000, opts);
}
}
export class BLAKE512 extends Blake1_64 {
constructor(opts: BlakeOpts = {}) {
super(64, B512_IV, 0b0000_0001, opts);
}
}
/** blake1-224 hash function */
export const blake224: CHashO = /* @__PURE__ */ createOptHasher<BLAKE224, BlakeOpts>(
(opts) => new BLAKE224(opts)
);
/** blake1-256 hash function */
export const blake256: CHashO = /* @__PURE__ */ createOptHasher<BLAKE256, BlakeOpts>(
(opts) => new BLAKE256(opts)
);
/** blake1-384 hash function */
export const blake384: CHashO = /* @__PURE__ */ createOptHasher<BLAKE512, BlakeOpts>(
(opts) => new BLAKE384(opts)
);
/** blake1-512 hash function */
export const blake512: CHashO = /* @__PURE__ */ createOptHasher<BLAKE512, BlakeOpts>(
(opts) => new BLAKE512(opts)
);