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.
- package/.idea/modules.xml +8 -0
- package/.idea/quarkdash.iml +12 -0
- package/.idea/vcs.xml +6 -0
- package/LICENSE +21 -0
- package/README.md +161 -0
- package/coverage/clover.xml +470 -0
- package/coverage/coverage-final.json +8 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/cipher.ts.html +862 -0
- package/coverage/lcov-report/crypto.ts.html +1000 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +206 -0
- package/coverage/lcov-report/index.ts.html +151 -0
- package/coverage/lcov-report/kdf.ts.html +274 -0
- package/coverage/lcov-report/mac.ts.html +277 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/ringlwe.ts.html +895 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +210 -0
- package/coverage/lcov-report/utils.ts.html +1111 -0
- package/coverage/lcov.info +740 -0
- package/dist/cjs/cipher.js +265 -0
- package/dist/cjs/cipher.js.map +1 -0
- package/dist/cjs/crypto.js +284 -0
- package/dist/cjs/crypto.js.map +1 -0
- package/dist/cjs/index.js +37 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/kdf.js +56 -0
- package/dist/cjs/kdf.js.map +1 -0
- package/dist/cjs/mac.js +55 -0
- package/dist/cjs/mac.js.map +1 -0
- package/dist/cjs/ringlwe.js +267 -0
- package/dist/cjs/ringlwe.js.map +1 -0
- package/dist/cjs/types.js +3 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/cjs/utils.js +320 -0
- package/dist/cjs/utils.js.map +1 -0
- package/dist/esm/cipher.js +259 -0
- package/dist/esm/cipher.js.map +1 -0
- package/dist/esm/crypto.js +280 -0
- package/dist/esm/crypto.js.map +1 -0
- package/dist/esm/index.js +21 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/kdf.js +52 -0
- package/dist/esm/kdf.js.map +1 -0
- package/dist/esm/mac.js +51 -0
- package/dist/esm/mac.js.map +1 -0
- package/dist/esm/ringlwe.js +263 -0
- package/dist/esm/ringlwe.js.map +1 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/utils.js +313 -0
- package/dist/esm/utils.js.map +1 -0
- package/dist/types/cipher.d.ts +153 -0
- package/dist/types/crypto.d.ts +155 -0
- package/dist/types/index.d.ts +16 -0
- package/dist/types/kdf.d.ts +34 -0
- package/dist/types/mac.d.ts +47 -0
- package/dist/types/ringlwe.d.ts +127 -0
- package/dist/types/types.d.ts +69 -0
- package/dist/types/utils.d.ts +132 -0
- package/img/cover.png +0 -0
- package/package.json +63 -0
- package/src/cipher.ts +260 -0
- package/src/crypto.ts +306 -0
- package/src/index.ts +23 -0
- package/src/kdf.ts +64 -0
- package/src/mac.ts +65 -0
- package/src/ringlwe.ts +271 -0
- package/src/types.ts +75 -0
- package/src/utils.ts +343 -0
- package/tsconfig.cjs.json +7 -0
- 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
|
+
}
|