quarkdash 1.0.0

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.
Files changed (75) hide show
  1. package/.idea/modules.xml +8 -0
  2. package/.idea/quarkdash.iml +12 -0
  3. package/.idea/vcs.xml +6 -0
  4. package/LICENSE +21 -0
  5. package/README.md +161 -0
  6. package/coverage/clover.xml +470 -0
  7. package/coverage/coverage-final.json +8 -0
  8. package/coverage/lcov-report/base.css +224 -0
  9. package/coverage/lcov-report/block-navigation.js +87 -0
  10. package/coverage/lcov-report/cipher.ts.html +862 -0
  11. package/coverage/lcov-report/crypto.ts.html +1000 -0
  12. package/coverage/lcov-report/favicon.png +0 -0
  13. package/coverage/lcov-report/index.html +206 -0
  14. package/coverage/lcov-report/index.ts.html +151 -0
  15. package/coverage/lcov-report/kdf.ts.html +274 -0
  16. package/coverage/lcov-report/mac.ts.html +277 -0
  17. package/coverage/lcov-report/prettify.css +1 -0
  18. package/coverage/lcov-report/prettify.js +2 -0
  19. package/coverage/lcov-report/ringlwe.ts.html +895 -0
  20. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  21. package/coverage/lcov-report/sorter.js +210 -0
  22. package/coverage/lcov-report/utils.ts.html +1111 -0
  23. package/coverage/lcov.info +740 -0
  24. package/dist/cjs/cipher.js +265 -0
  25. package/dist/cjs/cipher.js.map +1 -0
  26. package/dist/cjs/crypto.js +284 -0
  27. package/dist/cjs/crypto.js.map +1 -0
  28. package/dist/cjs/index.js +37 -0
  29. package/dist/cjs/index.js.map +1 -0
  30. package/dist/cjs/kdf.js +56 -0
  31. package/dist/cjs/kdf.js.map +1 -0
  32. package/dist/cjs/mac.js +55 -0
  33. package/dist/cjs/mac.js.map +1 -0
  34. package/dist/cjs/ringlwe.js +267 -0
  35. package/dist/cjs/ringlwe.js.map +1 -0
  36. package/dist/cjs/types.js +3 -0
  37. package/dist/cjs/types.js.map +1 -0
  38. package/dist/cjs/utils.js +320 -0
  39. package/dist/cjs/utils.js.map +1 -0
  40. package/dist/esm/cipher.js +259 -0
  41. package/dist/esm/cipher.js.map +1 -0
  42. package/dist/esm/crypto.js +280 -0
  43. package/dist/esm/crypto.js.map +1 -0
  44. package/dist/esm/index.js +21 -0
  45. package/dist/esm/index.js.map +1 -0
  46. package/dist/esm/kdf.js +52 -0
  47. package/dist/esm/kdf.js.map +1 -0
  48. package/dist/esm/mac.js +51 -0
  49. package/dist/esm/mac.js.map +1 -0
  50. package/dist/esm/ringlwe.js +263 -0
  51. package/dist/esm/ringlwe.js.map +1 -0
  52. package/dist/esm/types.js +2 -0
  53. package/dist/esm/types.js.map +1 -0
  54. package/dist/esm/utils.js +313 -0
  55. package/dist/esm/utils.js.map +1 -0
  56. package/dist/types/cipher.d.ts +153 -0
  57. package/dist/types/crypto.d.ts +155 -0
  58. package/dist/types/index.d.ts +16 -0
  59. package/dist/types/kdf.d.ts +34 -0
  60. package/dist/types/mac.d.ts +47 -0
  61. package/dist/types/ringlwe.d.ts +127 -0
  62. package/dist/types/types.d.ts +69 -0
  63. package/dist/types/utils.d.ts +132 -0
  64. package/img/cover.png +0 -0
  65. package/package.json +63 -0
  66. package/src/cipher.ts +260 -0
  67. package/src/crypto.ts +306 -0
  68. package/src/index.ts +23 -0
  69. package/src/kdf.ts +64 -0
  70. package/src/mac.ts +65 -0
  71. package/src/ringlwe.ts +271 -0
  72. package/src/types.ts +75 -0
  73. package/src/utils.ts +343 -0
  74. package/tsconfig.cjs.json +7 -0
  75. package/tsconfig.json +18 -0
package/src/crypto.ts ADDED
@@ -0,0 +1,306 @@
1
+ /**
2
+ * QuarkDash Crypto Algorithm 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
+ /* Import Required Modules */
11
+ import {CipherFactory, CipherType} from "./cipher";
12
+ import {ICipher, ICryptoMethodAsync, ICryptoMethodSync, IKDF, IKeyExchange, IMAC} from "./types";
13
+ import {QuarkDashKDF} from "./kdf";
14
+ import {QuarkDashMAC} from "./mac";
15
+ import {QuarkDashKeyExchange} from "./ringlwe";
16
+ import {QuarkDashUtils} from "./utils";
17
+
18
+ /**
19
+ * Quark Dash parsed encrypted packet
20
+ */
21
+ export interface QDEncryptedPacket {
22
+ metadata: Uint8Array;
23
+ encrypted: Uint8Array;
24
+ mac: Uint8Array;
25
+ }
26
+
27
+ /**
28
+ * QuarkDash options
29
+ */
30
+ export interface QuarkDashOptions {
31
+ cipher: CipherType;
32
+ kdf: IKDF;
33
+ mac: IMAC;
34
+ keyExchange: IKeyExchange;
35
+ maxPacketWindow: number;
36
+ timestampToleranceMs: number;
37
+ }
38
+
39
+ /**
40
+ * Default QuarkDash options
41
+ */
42
+ const DEFAULT_OPTIONS : QuarkDashOptions = {
43
+ cipher: CipherType.ChaCha20,
44
+ kdf: new QuarkDashKDF(),
45
+ mac: new QuarkDashMAC(),
46
+ keyExchange: new QuarkDashKeyExchange(),
47
+ maxPacketWindow: 1000,
48
+ timestampToleranceMs: 300000,
49
+ }
50
+
51
+ /**
52
+ * QuarkDash Crypto Algorithm Implementation
53
+ */
54
+ export class QuarkDash implements ICryptoMethodAsync, ICryptoMethodSync {
55
+ private config: QuarkDashOptions;
56
+ private sessionKey: Uint8Array | null = null;
57
+ private cipher: ICipher | null = null;
58
+ private macKey: Uint8Array | null = null;
59
+ private sendSeq = 0;
60
+ private recvSeq = 0;
61
+ private receivedPackets = new Set<number>();
62
+ private myKeyPair?: { publicKey: Uint8Array; privateKey: Uint8Array };
63
+ private peerPublicKey?: Uint8Array;
64
+
65
+ /**
66
+ * Create QuarkDash Crypto
67
+ * @param config {QuarkDashOptions} Crypto Options
68
+ */
69
+ constructor(config?: Partial<QuarkDashOptions>) {
70
+ this.config = { ...DEFAULT_OPTIONS, ...config };
71
+ }
72
+
73
+ /**
74
+ * Generate key pair async
75
+ * @returns {Promise<Uint8Array>} Key pair buffer
76
+ * TODO: GPU Computing
77
+ */
78
+ public async generateKeyPair(): Promise<Uint8Array> {
79
+ this.myKeyPair = await this.config.keyExchange.generateKeyPair();
80
+ return this.myKeyPair.publicKey;
81
+ }
82
+
83
+ /**
84
+ * Generate key pair sync
85
+ * @returns {Uint8Array} Key pair buffer
86
+ */
87
+ public generateKeyPairSync(): Uint8Array {
88
+ this.myKeyPair = this.config.keyExchange.generateKeyPairSync();
89
+ return this.myKeyPair.publicKey;
90
+ }
91
+
92
+ /**
93
+ * Initialize session async
94
+ * @param peerPublicKey {Uint8Array} Peer public key buffer
95
+ * @param isInitiator {boolean} Is session initiator
96
+ * @returns {Promise<Uint8Array|number>} Returns derived session key or null
97
+ * TODO: GPU Computing
98
+ */
99
+ public async initializeSession(peerPublicKey: Uint8Array, isInitiator: boolean): Promise<Uint8Array | null> {
100
+ this.peerPublicKey = peerPublicKey;
101
+ if (!this.myKeyPair) await this.generateKeyPair();
102
+ if (isInitiator) {
103
+ const { ciphertext, sharedSecret } = await this.config.keyExchange.encapsulate(peerPublicKey);
104
+ await this.deriveSessionKeys(sharedSecret);
105
+ return ciphertext;
106
+ } else {
107
+ return null;
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Initialize session sync
113
+ * @param peerPublicKey {Uint8Array} Peer public key buffer
114
+ * @param isInitiator {boolean} Is session initiator
115
+ * @returns {Uint8Array|number} Returns derived session key or null
116
+ */
117
+ public initializeSessionSync(peerPublicKey: Uint8Array, isInitiator: boolean): Uint8Array | null {
118
+ this.peerPublicKey = peerPublicKey;
119
+ if (!this.myKeyPair) this.generateKeyPairSync();
120
+ if (isInitiator) {
121
+ const { ciphertext, sharedSecret } = this.config.keyExchange.encapsulateSync(peerPublicKey);
122
+ this.deriveSessionKeysSync(sharedSecret);
123
+ return ciphertext;
124
+ } else {
125
+ return null;
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Finalize session async
131
+ * @param ciphertext {Uint8Array} Cipher text buffer
132
+ * TODO: GPU Computing
133
+ */
134
+ public async finalizeSession(ciphertext: Uint8Array): Promise<void> {
135
+ if (!this.myKeyPair || !this.peerPublicKey) throw new Error('Session not initialized');
136
+ const sharedSecret = await this.config.keyExchange.decapsulate(this.myKeyPair.privateKey, ciphertext);
137
+ await this.deriveSessionKeys(sharedSecret);
138
+ }
139
+
140
+ /**
141
+ * Finalize session sync
142
+ * @param ciphertext {Uint8Array} Cipher text buffer
143
+ */
144
+ public finalizeSessionSync(ciphertext: Uint8Array): void {
145
+ if (!this.myKeyPair || !this.peerPublicKey) throw new Error('Session not initialized');
146
+ const sharedSecret = this.config.keyExchange.decapsulateSync(this.myKeyPair.privateKey, ciphertext);
147
+ this.deriveSessionKeysSync(sharedSecret);
148
+ }
149
+
150
+ /**
151
+ * Derive session keys async
152
+ * @param sharedSecret {Uint8Array} Shared secret buffer
153
+ * @private
154
+ * TODO: GPU Computing
155
+ */
156
+ private async deriveSessionKeys(sharedSecret: Uint8Array): Promise<void> {
157
+ const salt = QuarkDashUtils.randomBytes(32);
158
+ const info = QuarkDashUtils.textToBytes('session-key');
159
+ const keyMaterial = await this.config.kdf.derive(sharedSecret, salt, info, 64);
160
+ this.processDeriveSessionKeys(keyMaterial, sharedSecret);
161
+ }
162
+
163
+ /**
164
+ * Derive session keys sync
165
+ * @param sharedSecret {Uint8Array} Shared secret buffer
166
+ * @private
167
+ */
168
+ private deriveSessionKeysSync(sharedSecret: Uint8Array): void {
169
+ const salt = QuarkDashUtils.randomBytes(32);
170
+ const info = QuarkDashUtils.textToBytes('session-key');
171
+ const keyMaterial = this.config.kdf.deriveSync(sharedSecret, salt, info, 64);
172
+ this.processDeriveSessionKeys(keyMaterial, sharedSecret);
173
+ }
174
+
175
+ /**
176
+ * Process derive session keys
177
+ * @param keyMaterial {Uint8Array} Key material buffer
178
+ * @param sharedSecret {Uint8Array} Shared secret buffer
179
+ * @private
180
+ */
181
+ private processDeriveSessionKeys(keyMaterial : Uint8Array, sharedSecret: Uint8Array){
182
+ this.sessionKey = keyMaterial.slice(0, 32);
183
+ this.macKey = keyMaterial.slice(32, 64);
184
+ const nonce = new Uint8Array(12);
185
+ this.cipher = CipherFactory.create(this.config.cipher, this.sessionKey, nonce);
186
+ QuarkDashUtils.secureZero(sharedSecret);
187
+ QuarkDashUtils.secureZero(keyMaterial);
188
+ }
189
+
190
+ /**
191
+ * Encrypt sync
192
+ * @param decryptedData {Uint8Array} Decrypted buffer
193
+ * @returns {Promise<Uint8Array>} Encrypted buffer
194
+ * TODO: GPU Computing
195
+ */
196
+ public async encrypt(decryptedData: Uint8Array): Promise<Uint8Array> {
197
+ if (!this.cipher || !this.macKey) throw new Error('Session not established');
198
+ const metadata = this.buildMetadata();
199
+ const encrypted = await this.cipher.encrypt(decryptedData);
200
+ const mac = await this.config.mac.sign(QuarkDashUtils.concatBytes(metadata, encrypted), this.macKey);
201
+ return QuarkDashUtils.concatBytes(metadata, encrypted, mac);
202
+ }
203
+
204
+ /**
205
+ * Encrypt sync
206
+ * @param decryptedData {Uint8Array} Decrypted buffer
207
+ * @returns {Uint8Array} Encrypted buffer
208
+ */
209
+ public encryptSync(decryptedData: Uint8Array): Uint8Array {
210
+ if (!this.cipher || !this.macKey) throw new Error('Session not established');
211
+ const metadata = this.buildMetadata();
212
+ const encrypted = this.cipher.encryptSync(decryptedData);
213
+ const mac = this.config.mac.signSync(QuarkDashUtils.concatBytes(metadata, encrypted), this.macKey);
214
+ return QuarkDashUtils.concatBytes(metadata, encrypted, mac);
215
+ }
216
+
217
+ /**
218
+ * Decrypt async
219
+ * @param encryptedData {Uint8Array} Encrypted buffer
220
+ * @returns {Promise<Uint8Array>} Decrypted buffer
221
+ * TODO: GPU Computing
222
+ */
223
+ public async decrypt(encryptedData: Uint8Array): Promise<Uint8Array> {
224
+ if (!this.cipher || !this.macKey) throw new Error('Session not established');
225
+ const packet = this.processDecrypt(encryptedData);
226
+ const valid = await this.config.mac.verify(QuarkDashUtils.concatBytes(packet.metadata, packet.encrypted), this.macKey, packet.mac);
227
+ if (!valid) throw new Error('MAC verification failed');
228
+ this.checkMetadata(packet.metadata);
229
+ return await this.cipher.decrypt(packet.encrypted);
230
+ }
231
+
232
+ /**
233
+ * Decrypt sync
234
+ * @param encryptedData {Uint8Array} Encrypted buffer
235
+ * @returns {Uint8Array} Decrypted buffer
236
+ */
237
+ public decryptSync(encryptedData: Uint8Array): Uint8Array {
238
+ if (!this.cipher || !this.macKey) throw new Error('Session not established');
239
+ const packet = this.processDecrypt(encryptedData);
240
+ const valid = this.config.mac.verifySync(QuarkDashUtils.concatBytes(packet.metadata, packet.encrypted), this.macKey, packet.mac);
241
+ if (!valid) throw new Error('MAC verification failed');
242
+ this.checkMetadata(packet.metadata);
243
+ return this.cipher.decryptSync(packet.encrypted);
244
+ }
245
+
246
+ /**
247
+ * Process decrypt
248
+ * @param encryptedData {Uint8Array} encrypted buffer
249
+ * @returns {QDEncryptedPacket} Parsed encrypted packet
250
+ * @private
251
+ */
252
+ private processDecrypt(encryptedData: Uint8Array) : QDEncryptedPacket {
253
+ if (encryptedData.length < 44) throw new Error('Invalid ciphertext');
254
+ return {
255
+ metadata: encryptedData.slice(0, 12),
256
+ encrypted: encryptedData.slice(12, encryptedData.length - 32),
257
+ mac: encryptedData.slice(encryptedData.length - 32)
258
+ }
259
+ }
260
+
261
+ /**
262
+ * Build meta-data
263
+ * @returns {Uint8Array} Meta-data buffer
264
+ * @private
265
+ */
266
+ private buildMetadata(): Uint8Array {
267
+ const metadata = new Uint8Array(12);
268
+ const timestamp = BigInt(Date.now());
269
+ for (let i = 0; i < 8; i++) metadata[i] = Number((timestamp >> BigInt(i*8)) & 0xFFn);
270
+ const seq = this.sendSeq++;
271
+ for (let i = 0; i < 4; i++) metadata[8+i] = (seq >> (i*8)) & 0xFF;
272
+ return metadata;
273
+ }
274
+
275
+ /**
276
+ * Check Meta-Data
277
+ * @param metadata {Uint8Array} Meta-data buffer
278
+ * @private
279
+ */
280
+ private checkMetadata(metadata: Uint8Array): void {
281
+ const timestamp = QuarkDashUtils.readUint64(metadata, 0);
282
+ const now = Date.now();
283
+ if (Math.abs(now - Number(timestamp)) > this.config.timestampToleranceMs) {
284
+ throw new Error('Timestamp out of window');
285
+ }
286
+ const seq = QuarkDashUtils.readUint32(metadata, 8);
287
+ if (this.receivedPackets.has(seq)) throw new Error('Replay detected');
288
+ this.receivedPackets.add(seq);
289
+ if (this.receivedPackets.size > this.config.maxPacketWindow) {
290
+ const oldest = Math.min(...this.receivedPackets);
291
+ this.receivedPackets.delete(oldest);
292
+ }
293
+ }
294
+
295
+ /**
296
+ * Dispose QuarkDash Crypto
297
+ */
298
+ public dispose() : void {
299
+ if (this.sessionKey) QuarkDashUtils.secureZero(this.sessionKey);
300
+ if (this.macKey) QuarkDashUtils.secureZero(this.macKey);
301
+ this.sessionKey = null;
302
+ this.macKey = null;
303
+ this.cipher = null;
304
+ this.receivedPackets.clear();
305
+ }
306
+ }
package/src/index.ts ADDED
@@ -0,0 +1,23 @@
1
+ /**
2
+ * QuarkDash Crypto Library
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
+ /* Export Types and Utils */
11
+ export * from "./types";
12
+ export * from "./utils";
13
+
14
+ /* Export KDF and MAC */
15
+ export * from "./kdf";
16
+ export * from "./mac";
17
+
18
+ /* Export Cipher and Ring-LWE */
19
+ export * from "./cipher";
20
+ export * from "./ringlwe";
21
+
22
+ /* Export Main Algorithm */
23
+ export * from "./crypto";
package/src/kdf.ts ADDED
@@ -0,0 +1,64 @@
1
+ /**
2
+ * QuarkDash Shake256 Based KDF
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
+ /* Import Required Modules */
11
+ import type {IKDF} from "./types";
12
+ import { QuarkDashUtils } from "./utils";
13
+
14
+ /**
15
+ * KDF implementation using Shake-256
16
+ */
17
+ export class QuarkDashKDF implements IKDF {
18
+ /**
19
+ * Derive KDF async
20
+ * @param ikm {Uint8Array} IKM buffer
21
+ * @param salt {Uint8Array} Salt buffer
22
+ * @param info {Uint8Array} Meta buffer
23
+ * @param length {number} Buffer length
24
+ * @returns {Promise<Uint8Array>} Result
25
+ * TODO: GPU Calculations
26
+ */
27
+ public async derive(ikm: Uint8Array, salt: Uint8Array, info: Uint8Array, length: number): Promise<Uint8Array> {
28
+ const prk = await QuarkDashUtils.shake256(QuarkDashUtils.concatBytes(salt, ikm), 64) as Uint8Array;
29
+ const result = new Uint8Array(length);
30
+ let t = new Uint8Array(0) as Uint8Array;
31
+ let i = 1;
32
+ while (result.length < length) {
33
+ const input = QuarkDashUtils.concatBytes(t, info, new Uint8Array([i])) as Uint8Array;
34
+ t = await QuarkDashUtils.shake256(QuarkDashUtils.concatBytes(prk, input), 64);
35
+ const take = Math.min(t.length, length - result.length);
36
+ result.set(t.slice(0, take), result.length);
37
+ i++;
38
+ }
39
+ return result;
40
+ }
41
+
42
+ /**
43
+ * Derive KDF sync
44
+ * @param ikm {Uint8Array} IKM buffer
45
+ * @param salt {Uint8Array} Salt buffer
46
+ * @param info {Uint8Array} Meta buffer
47
+ * @param length {number} Buffer length
48
+ * @returns {Uint8Array} Result
49
+ */
50
+ public deriveSync(ikm: Uint8Array, salt: Uint8Array, info: Uint8Array, length: number): Uint8Array {
51
+ const prk = QuarkDashUtils.shake256Sync(QuarkDashUtils.concatBytes(salt, ikm), 64);
52
+ const result = new Uint8Array(length);
53
+ let t = new Uint8Array(0) as Uint8Array;
54
+ let i = 1;
55
+ while (result.length < length) {
56
+ const input = QuarkDashUtils.concatBytes(t, info, new Uint8Array([i]));
57
+ t = QuarkDashUtils.shake256Sync(QuarkDashUtils.concatBytes(prk, input), 64);
58
+ const take = Math.min(t.length, length - result.length);
59
+ result.set(t.slice(0, take), result.length);
60
+ i++;
61
+ }
62
+ return result;
63
+ }
64
+ }
package/src/mac.ts ADDED
@@ -0,0 +1,65 @@
1
+ /**
2
+ * QuarkDash Shake256 Based MAC
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
+ /* Import Required Modules */
11
+ import {IMAC} from "./types";
12
+ import {QuarkDashUtils} from "./utils";
13
+
14
+ /**
15
+ * MAC implementation using Shake-256
16
+ */
17
+ export class QuarkDashMAC implements IMAC {
18
+ /**
19
+ * Sign data async
20
+ * @param data {Uint8Array} Data buffer
21
+ * @param key {Uint8Array} Key buffer
22
+ * @returns {Promise<Uint8Array>} Signed result buffer
23
+ * TODO: GPU Calculations
24
+ */
25
+ public async sign(data: Uint8Array, key: Uint8Array): Promise<Uint8Array> {
26
+ const full = QuarkDashUtils.concatBytes(key, data);
27
+ return await QuarkDashUtils.shake256(full, 32);
28
+ }
29
+
30
+ /**
31
+ * Verify async
32
+ * @param data {Uint8Array} data buffer
33
+ * @param key {Uint8Array} key buffer
34
+ * @param tag {Uint8Array} tag buffer
35
+ * @returns {Promise<boolean>} Is verified?
36
+ * TODO: GPU Calculations
37
+ */
38
+ public async verify(data: Uint8Array, key: Uint8Array, tag: Uint8Array): Promise<boolean> {
39
+ const expected = await this.sign(data, key);
40
+ return QuarkDashUtils.constantTimeEqual(expected, tag);
41
+ }
42
+
43
+ /**
44
+ * Sign data sync
45
+ * @param data {Uint8Array} Data buffer
46
+ * @param key {Uint8Array} Key buffer
47
+ * @returns {Uint8Array} Signed result buffer
48
+ */
49
+ public signSync(data: Uint8Array, key: Uint8Array): Uint8Array {
50
+ const full = QuarkDashUtils.concatBytes(key, data);
51
+ return QuarkDashUtils.shake256Sync(full, 32);
52
+ }
53
+
54
+ /**
55
+ * Verify sync
56
+ * @param data {Uint8Array} data buffer
57
+ * @param key {Uint8Array} key buffer
58
+ * @param tag {Uint8Array} tag buffer
59
+ * @returns {Promise<boolean>} Is verified?
60
+ */
61
+ public verifySync(data: Uint8Array, key: Uint8Array, tag: Uint8Array): boolean {
62
+ const expected = this.signSync(data, key);
63
+ return QuarkDashUtils.constantTimeEqual(expected, tag);
64
+ }
65
+ }