Buckets:
| import { rotl64 } from "@oslojs/binary"; | |
| export class SHA3 { | |
| rate; | |
| outputSize; | |
| state = new BigUint64Array(25); | |
| absorbedBytes = 0; | |
| constructor(rate, outputSize) { | |
| this.rate = rate; | |
| this.outputSize = outputSize; | |
| } | |
| absorb(bytes) { | |
| for (let i = 0; i < bytes.byteLength; i++) { | |
| this.state[Math.floor(this.absorbedBytes / 8)] ^= | |
| BigInt(bytes[i]) << (BigInt(this.absorbedBytes % 8) * 8n); | |
| this.absorbedBytes++; | |
| if (this.absorbedBytes === this.rate) { | |
| keccak(this.state); | |
| this.absorbedBytes = 0; | |
| } | |
| } | |
| } | |
| squeeze() { | |
| this.state[Math.floor(this.absorbedBytes / 8)] ^= | |
| 0x06n << (BigInt(this.absorbedBytes % 8) * 8n); | |
| this.state[Math.floor((this.rate - 1) / 8)] ^= 0x8000000000000000n; | |
| keccak(this.state); | |
| if (this.outputSize <= this.rate) { | |
| return new Uint8Array(this.state.buffer).slice(0, this.outputSize); | |
| } | |
| const keccakCount = Math.ceil(this.outputSize / this.rate); | |
| const z = new Uint8Array(keccakCount * this.rate); | |
| z.set(new Uint8Array(this.state.buffer).slice(0, this.rate)); | |
| for (let i = 1; i < keccakCount; i++) { | |
| keccak(this.state); | |
| z.set(new Uint8Array(this.state.buffer).slice(0, this.rate), i * this.rate); | |
| } | |
| return z.slice(0, this.outputSize); | |
| } | |
| } | |
| export class SHA3XOF { | |
| rate; | |
| outputSize; | |
| state = new BigUint64Array(25); | |
| absorbedBytes = 0; | |
| constructor(rate, outputSize) { | |
| this.rate = rate; | |
| this.outputSize = outputSize; | |
| } | |
| absorb(bytes) { | |
| for (let i = 0; i < bytes.byteLength; i++) { | |
| this.state[Math.floor(this.absorbedBytes / 8)] ^= | |
| BigInt(bytes[i]) << (BigInt(this.absorbedBytes % 8) * 8n); | |
| this.absorbedBytes++; | |
| if (this.absorbedBytes === this.rate) { | |
| keccak(this.state); | |
| this.absorbedBytes = 0; | |
| } | |
| } | |
| } | |
| squeeze() { | |
| this.state[Math.floor(this.absorbedBytes / 8)] ^= | |
| 0x1fn << (BigInt(this.absorbedBytes % 8) * 8n); | |
| this.state[Math.floor((this.rate - 1) / 8)] ^= 0x8000000000000000n; | |
| keccak(this.state); | |
| if (this.outputSize <= this.rate) { | |
| return new Uint8Array(this.state.buffer).slice(0, this.outputSize); | |
| } | |
| const keccakCount = Math.ceil(this.outputSize / this.rate); | |
| const z = new Uint8Array(keccakCount * this.rate); | |
| z.set(new Uint8Array(this.state.buffer).slice(0, this.rate)); | |
| for (let i = 1; i < keccakCount; i++) { | |
| keccak(this.state); | |
| z.set(new Uint8Array(this.state.buffer).slice(0, this.rate), i * this.rate); | |
| } | |
| return z.slice(0, this.outputSize); | |
| } | |
| } | |
| function keccak(a) { | |
| for (let i = 0; i < 24; i++) { | |
| theta(a); | |
| rho(a); | |
| pi(a); | |
| chi(a); | |
| iota(a, i); | |
| } | |
| } | |
| function theta(a) { | |
| const c = new BigUint64Array(5); | |
| for (let x = 0; x < 5; x++) { | |
| c[x] = a[x]; | |
| c[x] ^= a[x + 5]; | |
| c[x] ^= a[x + 10]; | |
| c[x] ^= a[x + 15]; | |
| c[x] ^= a[x + 20]; | |
| } | |
| const d = new BigUint64Array(5); | |
| for (let x = 0; x < 5; x++) { | |
| d[x] = c[(x + 4) % 5] ^ rotl64(c[(x + 1) % 5], 1); | |
| } | |
| for (let x = 0; x < 5; x++) { | |
| for (let y = 0; y < 5; y++) { | |
| a[x + y * 5] ^= d[x]; | |
| } | |
| } | |
| } | |
| function rho(a) { | |
| // Lane (0, 0) stays the same | |
| const shifts = [ | |
| 0, 1, 62, 28, 27, 36, 44, 6, 55, 20, 3, 10, 43, 25, 39, 41, 45, 15, 21, 8, 18, 2, 61, 56, 14 | |
| ]; | |
| for (let i = 0; i < 25; i++) { | |
| a[i] = rotl64(a[i], shifts[i]); | |
| } | |
| } | |
| function pi(a) { | |
| const dests = [ | |
| 0, 10, 20, 5, 15, 16, 1, 11, 21, 6, 7, 17, 2, 12, 22, 23, 8, 18, 3, 13, 14, 24, 9, 19, 4 | |
| ]; | |
| const temp = new BigUint64Array(a); | |
| for (let i = 0; i < 25; i++) { | |
| a[dests[i]] = temp[i]; | |
| } | |
| } | |
| function chi(a) { | |
| const temp = new BigUint64Array(a); | |
| for (let x = 0; x < 5; x++) { | |
| for (let y = 0; y < 5; y++) { | |
| a[x + 5 * y] ^= ~temp[((x + 1) % 5) + 5 * y] & temp[((x + 2) % 5) + 5 * y]; | |
| } | |
| } | |
| } | |
| function iota(a, i) { | |
| a[0] ^= iotaConstants[i]; | |
| } | |
| const iotaConstants = new BigUint64Array([ | |
| 0x0000000000000001n, | |
| 0x0000000000008082n, | |
| 0x800000000000808an, | |
| 0x8000000080008000n, | |
| 0x000000000000808bn, | |
| 0x0000000080000001n, | |
| 0x8000000080008081n, | |
| 0x8000000000008009n, | |
| 0x000000000000008an, | |
| 0x0000000000000088n, | |
| 0x0000000080008009n, | |
| 0x000000008000000an, | |
| 0x000000008000808bn, | |
| 0x800000000000008bn, | |
| 0x8000000000008089n, | |
| 0x8000000000008003n, | |
| 0x8000000000008002n, | |
| 0x8000000000000080n, | |
| 0x000000000000800an, | |
| 0x800000008000000an, | |
| 0x8000000080008081n, | |
| 0x8000000000008080n, | |
| 0x0000000080000001n, | |
| 0x8000000080008008n | |
| ]); | |
Xet Storage Details
- Size:
- 4.96 kB
- Xet hash:
- cf37ab758c48e29b197783e42f252edcc2939d49103a8e6aae141adac6e03aa4
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.