quarkdash 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/coverage/clover.xml +158 -122
- package/coverage/coverage-final.json +4 -3
- package/coverage/lcov-report/cipher.ts.html +1 -1
- package/coverage/lcov-report/crypto.ts.html +1 -1
- package/coverage/lcov-report/index.html +37 -22
- package/coverage/lcov-report/index.ts.html +7 -4
- package/coverage/lcov-report/kdf.ts.html +1 -1
- package/coverage/lcov-report/mac.ts.html +1 -1
- package/coverage/lcov-report/ringlwe.ts.html +3 -3
- package/coverage/lcov-report/shake.ts.html +571 -0
- package/coverage/lcov-report/utils.ts.html +23 -182
- package/coverage/lcov.info +251 -195
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/shake.js +159 -0
- package/dist/cjs/shake.js.map +1 -0
- package/dist/cjs/utils.js +3 -54
- package/dist/cjs/utils.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/shake.js +155 -0
- package/dist/esm/shake.js.map +1 -0
- package/dist/esm/utils.js +3 -54
- package/dist/esm/utils.js.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/shake.d.ts +53 -0
- package/dist/types/utils.d.ts +0 -12
- package/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/shake.ts +163 -0
- package/src/utils.ts +3 -56
package/src/shake.ts
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QuarkDash Crypto SHAKE-256 Implementation
|
|
3
|
+
*
|
|
4
|
+
* @git https://github.com/devsdaddy/quarkdash
|
|
5
|
+
* @version 1.0.0
|
|
6
|
+
* @author Elijah Rastorguev
|
|
7
|
+
* @build 1000
|
|
8
|
+
* @website https://dev.to/devsdaddy
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Shake-256 Hash
|
|
12
|
+
*/
|
|
13
|
+
export class Shake256 {
|
|
14
|
+
/* Shake 256 Constants */
|
|
15
|
+
private static KECCAK_ROUNDS = 24;
|
|
16
|
+
private static RATE_BYTES = 136;
|
|
17
|
+
private static ROTATIONS: number[] = [
|
|
18
|
+
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14,
|
|
19
|
+
27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44
|
|
20
|
+
];
|
|
21
|
+
private static RC: bigint[] = [
|
|
22
|
+
0x0000000000000001n, 0x0000000000008082n, 0x800000000000808an, 0x8000000080008000n,
|
|
23
|
+
0x000000000000808bn, 0x0000000080000001n, 0x8000000080008081n, 0x8000000000008009n,
|
|
24
|
+
0x000000000000008an, 0x0000000000000088n, 0x0000000080008009n, 0x000000008000000an,
|
|
25
|
+
0x000000008000808bn, 0x800000000000008bn, 0x8000000000008089n, 0x8000000000008003n,
|
|
26
|
+
0x8000000000008002n, 0x8000000000000080n, 0x000000000000800an, 0x800000008000000an,
|
|
27
|
+
0x8000000080008081n, 0x8000000000008080n, 0x0000000080000001n, 0x8000000080008008n
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Shake-256 async
|
|
32
|
+
* @param input {Uint8Array} Input buffer
|
|
33
|
+
* @param outputLength {number} Output buffer length
|
|
34
|
+
* @returns {Uint8Array} Output buffer
|
|
35
|
+
*/
|
|
36
|
+
public static async hash(input: Uint8Array, outputLength: number): Promise<Uint8Array> {
|
|
37
|
+
return this.process(input, outputLength);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Shake-256 sync
|
|
42
|
+
* @param input {Uint8Array} Input buffer
|
|
43
|
+
* @param outputLength {number} Output buffer length
|
|
44
|
+
* @returns {Uint8Array} Output buffer
|
|
45
|
+
*/
|
|
46
|
+
public static hashSync(input: Uint8Array, outputLength: number): Uint8Array {
|
|
47
|
+
return this.process(input, outputLength);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Process SHAKE-256
|
|
52
|
+
* @param input {Uint8Array} Input buffer
|
|
53
|
+
* @param outputLength {number} Output length
|
|
54
|
+
* @returns {Uint8Array} Output buffer
|
|
55
|
+
* @private
|
|
56
|
+
*/
|
|
57
|
+
private static process(input: Uint8Array, outputLength: number): Uint8Array {
|
|
58
|
+
const state = new Array(25).fill(0n);
|
|
59
|
+
// Absorb phase
|
|
60
|
+
let offset = 0;
|
|
61
|
+
let blockSize = this.RATE_BYTES;
|
|
62
|
+
while (offset < input.length) {
|
|
63
|
+
const block = input.subarray(offset, Math.min(offset + blockSize, input.length));
|
|
64
|
+
for (let i = 0; i < block.length; i++) {
|
|
65
|
+
const lane = i % 8;
|
|
66
|
+
const bytePos = i - lane;
|
|
67
|
+
const laneIdx = bytePos / 8;
|
|
68
|
+
const shift = BigInt(lane * 8);
|
|
69
|
+
const val = BigInt(block[i]) << shift;
|
|
70
|
+
state[laneIdx] ^= val;
|
|
71
|
+
}
|
|
72
|
+
offset += block.length;
|
|
73
|
+
if (block.length === blockSize || offset >= input.length) {
|
|
74
|
+
// padding
|
|
75
|
+
if (offset >= input.length) {
|
|
76
|
+
const lastByteIdx = block.length;
|
|
77
|
+
const padByte = 0x1F; // domain for SHAKE256
|
|
78
|
+
const laneIdx = Math.floor(lastByteIdx / 8);
|
|
79
|
+
const shift = BigInt((lastByteIdx % 8) * 8);
|
|
80
|
+
state[laneIdx] ^= (BigInt(padByte) << shift);
|
|
81
|
+
// final padding bit
|
|
82
|
+
const finalBytePos = lastByteIdx + 1;
|
|
83
|
+
const finalLane = Math.floor(finalBytePos / 8);
|
|
84
|
+
const finalShift = BigInt((finalBytePos % 8) * 8);
|
|
85
|
+
state[finalLane] ^= (0x80n << finalShift);
|
|
86
|
+
}
|
|
87
|
+
this.keccakF(state);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Squeeze phase
|
|
92
|
+
const result = new Uint8Array(outputLength);
|
|
93
|
+
let outOffset = 0;
|
|
94
|
+
while (outOffset < outputLength) {
|
|
95
|
+
for (let lane = 0; lane < 25 && outOffset < outputLength; lane++) {
|
|
96
|
+
let val = state[lane];
|
|
97
|
+
for (let byte = 0; byte < 8 && outOffset < outputLength; byte++) {
|
|
98
|
+
result[outOffset++] = Number(val & 0xFFn);
|
|
99
|
+
val >>= 8n;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (outOffset < outputLength) {
|
|
103
|
+
this.keccakF(state);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return result;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Keccak Function
|
|
111
|
+
* @param state {bigint[]} State array
|
|
112
|
+
* @private
|
|
113
|
+
*/
|
|
114
|
+
private static keccakF(state: bigint[]): void {
|
|
115
|
+
for (let round = 0; round < this.KECCAK_ROUNDS; round++) {
|
|
116
|
+
// Theta
|
|
117
|
+
const C = new Array(5);
|
|
118
|
+
for (let x = 0; x < 5; x++) {
|
|
119
|
+
C[x] = state[x] ^ state[x+5] ^ state[x+10] ^ state[x+15] ^ state[x+20];
|
|
120
|
+
}
|
|
121
|
+
const D = new Array(5);
|
|
122
|
+
for (let x = 0; x < 5; x++) {
|
|
123
|
+
D[x] = C[(x+4)%5] ^ this.rot(C[(x+1)%5], 1n);
|
|
124
|
+
}
|
|
125
|
+
for (let x = 0; x < 5; x++) {
|
|
126
|
+
for (let y = 0; y < 5; y++) {
|
|
127
|
+
state[x+5*y] ^= D[x];
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Rho and Pi
|
|
132
|
+
let current = state[1];
|
|
133
|
+
for (let i = 0; i < 24; i++) {
|
|
134
|
+
const nextIdx = (2 * ((i + 1) % 5) + 5*Math.floor((i+1)/5)) % 25;
|
|
135
|
+
const temp = state[nextIdx];
|
|
136
|
+
state[nextIdx] = this.rot(current, BigInt(this.ROTATIONS[i]));
|
|
137
|
+
current = temp;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Chi
|
|
141
|
+
for (let y = 0; y < 5; y++) {
|
|
142
|
+
const row = state.slice(y*5, y*5+5);
|
|
143
|
+
for (let x = 0; x < 5; x++) {
|
|
144
|
+
state[y*5 + x] = row[x] ^ ((~row[(x+1)%5]) & row[(x+2)%5]);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Iota
|
|
149
|
+
state[0] ^= this.RC[round];
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Rotate function
|
|
155
|
+
* @param x {number}
|
|
156
|
+
* @param n {number}
|
|
157
|
+
* @private
|
|
158
|
+
*/
|
|
159
|
+
private static rot(x: bigint, n: bigint): bigint {
|
|
160
|
+
const mask = (1n << 64n) - 1n;
|
|
161
|
+
return ((x << n) | (x >> (64n - n))) & mask;
|
|
162
|
+
}
|
|
163
|
+
}
|
package/src/utils.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* @website https://dev.to/devsdaddy
|
|
9
9
|
*/
|
|
10
10
|
import crypto from "crypto";
|
|
11
|
+
import {Shake256} from "./shake";
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Crypto Utils Class
|
|
@@ -16,30 +17,6 @@ export class QuarkDashUtils {
|
|
|
16
17
|
// Protected Constants
|
|
17
18
|
private static HEXChars : string = '0123456789abcdef';
|
|
18
19
|
|
|
19
|
-
/**
|
|
20
|
-
* Run SHA256 async
|
|
21
|
-
* @param data {Uint8Array} Bytes buffer
|
|
22
|
-
* @return {Promise<Uint8Array>} Result
|
|
23
|
-
*/
|
|
24
|
-
public static async sha256(data: Uint8Array): Promise<Uint8Array> {
|
|
25
|
-
const hash = await crypto.subtle.digest('SHA-256', data);
|
|
26
|
-
return new Uint8Array(hash);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Run SHA256 sync
|
|
31
|
-
* @param data {Uint8Array} Bytes buffer
|
|
32
|
-
* @return {Uint8Array} Result
|
|
33
|
-
*/
|
|
34
|
-
public static sha256Sync(data: Uint8Array): Uint8Array {
|
|
35
|
-
if (typeof require !== 'undefined') {
|
|
36
|
-
const crypto = require('crypto');
|
|
37
|
-
const hash = crypto.createHash('sha256').update(data).digest();
|
|
38
|
-
return new Uint8Array(hash);
|
|
39
|
-
}
|
|
40
|
-
throw new Error('Synchronous SHA256 not available in browser');
|
|
41
|
-
}
|
|
42
|
-
|
|
43
20
|
/**
|
|
44
21
|
* Get Shake-256 result async
|
|
45
22
|
* @param data {Uint8Array} Bytes buffer
|
|
@@ -47,22 +24,7 @@ export class QuarkDashUtils {
|
|
|
47
24
|
* @return {Promise<Uint8Array>} Result buffer
|
|
48
25
|
*/
|
|
49
26
|
public static async shake256(data: Uint8Array, len: number): Promise<Uint8Array> {
|
|
50
|
-
|
|
51
|
-
let counter = 0;
|
|
52
|
-
let offset = 0;
|
|
53
|
-
while (offset < len) {
|
|
54
|
-
const cnt = new Uint8Array(4);
|
|
55
|
-
cnt[0] = (counter >> 24) & 0xFF;
|
|
56
|
-
cnt[1] = (counter >> 16) & 0xFF;
|
|
57
|
-
cnt[2] = (counter >> 8) & 0xFF;
|
|
58
|
-
cnt[3] = counter & 0xFF;
|
|
59
|
-
const hash = await this.sha256(this.concatBytes(data, cnt));
|
|
60
|
-
const take = Math.min(hash.length, len - offset);
|
|
61
|
-
result.set(hash.slice(0, take), offset);
|
|
62
|
-
offset += take;
|
|
63
|
-
counter++;
|
|
64
|
-
}
|
|
65
|
-
return result;
|
|
27
|
+
return await Shake256.hash(data, len);
|
|
66
28
|
}
|
|
67
29
|
|
|
68
30
|
/**
|
|
@@ -72,22 +34,7 @@ export class QuarkDashUtils {
|
|
|
72
34
|
* @return {Uint8Array} Result buffer
|
|
73
35
|
*/
|
|
74
36
|
public static shake256Sync(data: Uint8Array, len: number): Uint8Array {
|
|
75
|
-
|
|
76
|
-
let counter = 0;
|
|
77
|
-
let offset = 0;
|
|
78
|
-
while (offset < len) {
|
|
79
|
-
const cnt = new Uint8Array(4);
|
|
80
|
-
cnt[0] = (counter >> 24) & 0xFF;
|
|
81
|
-
cnt[1] = (counter >> 16) & 0xFF;
|
|
82
|
-
cnt[2] = (counter >> 8) & 0xFF;
|
|
83
|
-
cnt[3] = counter & 0xFF;
|
|
84
|
-
const hash = this.sha256Sync(this.concatBytes(data, cnt));
|
|
85
|
-
const take = Math.min(hash.length, len - offset);
|
|
86
|
-
result.set(hash.slice(0, take), offset);
|
|
87
|
-
offset += take;
|
|
88
|
-
counter++;
|
|
89
|
-
}
|
|
90
|
-
return result;
|
|
37
|
+
return Shake256.hashSync(data, len);
|
|
91
38
|
}
|
|
92
39
|
|
|
93
40
|
/**
|