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/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
- const result = new Uint8Array(len);
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
- const result = new Uint8Array(len);
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
  /**