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/ringlwe.ts ADDED
@@ -0,0 +1,271 @@
1
+ /**
2
+ * QuarkDash Ring-LWE 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 {ICryptoEncapsulated, ICryptoKeyPair, IKeyExchange} from "./types";
12
+ import {QuarkDashUtils} from "./utils";
13
+
14
+ /**
15
+ * Ring-LWE based key exchange implementation
16
+ */
17
+ export class QuarkDashKeyExchange implements IKeyExchange {
18
+ // Ring-LWE Constants
19
+ private static readonly N = 256;
20
+ private static readonly Q = 7681n;
21
+ private static readonly ROOT = 7n;
22
+ private static readonly INV_N = this.modInverse(BigInt(this.N), this.Q);
23
+
24
+ /**
25
+ * Get small polygon
26
+ * @returns {bigint[]} Small polygon
27
+ * @private
28
+ */
29
+ private static smallPoly(): bigint[] {
30
+ const poly = new Array<bigint>(this.N);
31
+ for (let i=0;i<this.N;i++) {
32
+ const r = Math.random();
33
+ if (r<0.33) poly[i] = -1n;
34
+ else if (r<0.66) poly[i] = 0n;
35
+ else poly[i] = 1n;
36
+ }
37
+ return poly;
38
+ }
39
+
40
+ /**
41
+ * Uniform polygon
42
+ * @returns {bigint[]}
43
+ * @private
44
+ */
45
+ private static uniformPoly(): bigint[] {
46
+ const poly = new Array<bigint>(this.N);
47
+ const bytes = QuarkDashUtils.randomBytes(this.N*2);
48
+ for(let i=0;i<this.N;i++) {
49
+ const val = (bytes[2*i] | (bytes[2*i+1]<<8)) % Number(this.Q);
50
+ poly[i] = BigInt(val);
51
+ }
52
+ return poly;
53
+ }
54
+
55
+ /**
56
+ * NTT Operation
57
+ * @param poly {bigint[]} Polygon
58
+ * @private
59
+ */
60
+ private static ntt(poly: bigint[]): bigint[] {
61
+ const res = [...poly];
62
+ let len = 2;
63
+ while(len <= this.N) {
64
+ const wlen = this.powMod(this.ROOT, BigInt(this.N/len), this.Q);
65
+ for(let i=0;i<this.N;i+=len){
66
+ let w=1n;
67
+ for(let j=0;j<len/2;j++){
68
+ const u=res[i+j];
69
+ const v=(res[i+j+len/2]*w)%this.Q;
70
+ res[i+j]=(u+v)%this.Q;
71
+ res[i+j+len/2]=(u-v+this.Q)%this.Q;
72
+ w=(w*wlen)%this.Q;
73
+ }
74
+ }
75
+ len<<=1;
76
+ }
77
+ return res;
78
+ }
79
+
80
+ /**
81
+ * Inverse NTT
82
+ * @param poly {bigint[]} Polygon
83
+ * @private
84
+ */
85
+ private static invNTT(poly: bigint[]): bigint[] {
86
+ const res = [...poly];
87
+ let len = this.N;
88
+ while(len >= 2){
89
+ const wlen = this.powMod(this.ROOT, BigInt(this.N/len), this.Q);
90
+ for(let i=0;i<this.N;i+=len){
91
+ let w=1n;
92
+ for(let j=0;j<len/2;j++){
93
+ const u=res[i+j];
94
+ const v=res[i+j+len/2];
95
+ res[i+j]=(u+v)%this.Q;
96
+ res[i+j+len/2]=((u-v+this.Q)*w)%this.Q;
97
+ w=(w*wlen)%this.Q;
98
+ }
99
+ }
100
+ len>>=1;
101
+ }
102
+ for(let i=0;i<this.N;i++) res[i]=(res[i]*this.INV_N)%this.Q;
103
+ return res;
104
+ }
105
+
106
+ /**
107
+ * Multiply
108
+ * @param a {bigint[]} Polygon
109
+ * @param b {bigint[]} Polygon
110
+ * @returns {bigint[]} Multiplied polygons
111
+ */
112
+ public static multiply(a: bigint[], b: bigint[]): bigint[] {
113
+ const aNTT = this.ntt(a);
114
+ const bNTT = this.ntt(b);
115
+ const prod = new Array<bigint>(this.N);
116
+ for(let i=0;i<this.N;i++) prod[i]=(aNTT[i]*bNTT[i])%this.Q;
117
+ return this.invNTT(prod);
118
+ }
119
+
120
+ /**
121
+ * Serialize polygon
122
+ * @param poly {bigint[]} Polygon
123
+ * @returns {Uint8Array} Polygon buffer
124
+ * @private
125
+ */
126
+ private static serializePoly(poly: bigint[]): Uint8Array {
127
+ const bytes = new Uint8Array(this.N*2);
128
+ for(let i=0;i<this.N;i++) {
129
+ const val = Number(poly[i]);
130
+ bytes[2*i]=val&0xFF;
131
+ bytes[2*i+1]=(val>>8)&0xFF;
132
+ }
133
+ return bytes;
134
+ }
135
+
136
+ /**
137
+ * Deserialize Polygon
138
+ * @param bytes {Uint8Array} Polygon buffer
139
+ * @returns {bigint[]} Polygon
140
+ * @private
141
+ */
142
+ private static deserializePoly(bytes: Uint8Array): bigint[] {
143
+ const poly = new Array<bigint>(this.N);
144
+ for(let i=0;i<this.N;i++) {
145
+ const val = bytes[2*i] | (bytes[2*i+1]<<8);
146
+ poly[i]=BigInt(val);
147
+ }
148
+ return poly;
149
+ }
150
+
151
+ /**
152
+ * Round to bits
153
+ * @param poly {bigint[]} Polygon
154
+ * @returns {Uint8Array} rounded buffer
155
+ * @private
156
+ */
157
+ private static roundToBits(poly: bigint[]): Uint8Array {
158
+ const result = new Uint8Array(32);
159
+ for(let i=0;i<this.N;i++) {
160
+ const bit = (Number(poly[i]) > Number(this.Q)/2) ? 1 : 0;
161
+ if(bit) result[i>>3] |= (1<<(i&7));
162
+ }
163
+ return result;
164
+ }
165
+
166
+ /**
167
+ * Modular exponentiation
168
+ * @param base {bigint} Base
169
+ * @param exp {bigint} exponential
170
+ * @param mod {bigint} module
171
+ * @returns {bigint} Result of modular exponentiation
172
+ * @private
173
+ */
174
+ private static powMod(base: bigint, exp: bigint, mod: bigint): bigint {
175
+ let result=1n, b=base%mod, e=exp;
176
+ while(e>0n){ if(e&1n) result=(result*b)%mod; b=(b*b)%mod; e>>=1n; }
177
+ return result;
178
+ }
179
+
180
+ /**
181
+ * Modular inverse
182
+ * @param a {bigint}
183
+ * @param m {bigint}
184
+ * @returns {bigint} Inversion result
185
+ * @private
186
+ */
187
+ private static modInverse(a: bigint, m: bigint): bigint {
188
+ let [old_r,r]=[a,m], [old_s,s]=[1n,0n];
189
+ while(r!==0n){ const q=old_r/r; [old_r,r]=[r,old_r-q*r]; [old_s,s]=[s,old_s-q*s]; }
190
+ return (old_s%m+m)%m;
191
+ }
192
+
193
+ /**
194
+ * Generate crypto key pair async
195
+ * @returns {ICryptoKeyPair} Crypto key pair
196
+ * TODO: GPU Calculations
197
+ */
198
+ public async generateKeyPair(): Promise<ICryptoKeyPair> {
199
+ return this.generateKeyPairSync();
200
+ }
201
+
202
+ /**
203
+ * Generate crypto key pair sync
204
+ * @returns {ICryptoKeyPair} Crypto key pair
205
+ */
206
+ public generateKeyPairSync(): ICryptoKeyPair {
207
+ const a = QuarkDashKeyExchange.uniformPoly();
208
+ const s = QuarkDashKeyExchange.smallPoly();
209
+ const e = QuarkDashKeyExchange.smallPoly();
210
+ const as = QuarkDashKeyExchange.multiply(a,s);
211
+ const b = new Array<bigint>(QuarkDashKeyExchange.N);
212
+ for(let i=0; i<QuarkDashKeyExchange.N; i++) b[i] = (as[i]+e[i]) % QuarkDashKeyExchange.Q;
213
+ const pub = QuarkDashUtils.concatBytes(QuarkDashKeyExchange.serializePoly(a), QuarkDashKeyExchange.serializePoly(b));
214
+ const priv = QuarkDashKeyExchange.serializePoly(s);
215
+ return { publicKey: pub, privateKey: priv };
216
+ }
217
+
218
+ /**
219
+ * Encapsulate async
220
+ * @param publicKey {Uint8Array} Public key buffer
221
+ * @returns {Promise<ICryptoEncapsulated>} Encapsulated data
222
+ * TODO: GPU Calculations
223
+ */
224
+ public async encapsulate(publicKey: Uint8Array): Promise<ICryptoEncapsulated> {
225
+ return this.encapsulateSync(publicKey);
226
+ }
227
+
228
+ /**
229
+ * Encapsulate sync
230
+ * @param publicKey {Uint8Array} Public key buffer
231
+ * @returns {ICryptoEncapsulated} Encapsulated data
232
+ */
233
+ public encapsulateSync(publicKey: Uint8Array): ICryptoEncapsulated {
234
+ const aBytes = publicKey.slice(0, QuarkDashKeyExchange.N*2);
235
+ const bBytes = publicKey.slice(QuarkDashKeyExchange.N*2);
236
+ const a = QuarkDashKeyExchange.deserializePoly(aBytes);
237
+ const b = QuarkDashKeyExchange.deserializePoly(bBytes);
238
+ const sp = QuarkDashKeyExchange.smallPoly();
239
+ const ep = QuarkDashKeyExchange.smallPoly();
240
+ const uArr = QuarkDashKeyExchange.multiply(a,sp);
241
+ for(let i=0; i<QuarkDashKeyExchange.N; i++) uArr[i] = (uArr[i]+ep[i]) % QuarkDashKeyExchange.Q;
242
+ const w = QuarkDashKeyExchange.multiply(b,sp);
243
+ const shared = QuarkDashKeyExchange.roundToBits(w);
244
+ const ciphertext = QuarkDashKeyExchange.serializePoly(uArr);
245
+ return { ciphertext, sharedSecret: shared };
246
+ }
247
+
248
+ /**
249
+ * Decapsulate async
250
+ * @param privateKey {Uint8Array} Private key buffer
251
+ * @param ciphertext {Uint8Array} Cipher text buffer
252
+ * @returns {Promise<Uint8Array>} Buffer data
253
+ * TODO: GPU Calculations
254
+ */
255
+ public async decapsulate(privateKey: Uint8Array, ciphertext: Uint8Array): Promise<Uint8Array> {
256
+ return this.decapsulateSync(privateKey, ciphertext);
257
+ }
258
+
259
+ /**
260
+ * Decapsulate sync
261
+ * @param privateKey {Uint8Array} Private key buffer
262
+ * @param ciphertext {Uint8Array} Cipher text buffer
263
+ * @returns {Uint8Array} Buffer data
264
+ */
265
+ public decapsulateSync(privateKey: Uint8Array, ciphertext: Uint8Array): Uint8Array {
266
+ const s = QuarkDashKeyExchange.deserializePoly(privateKey);
267
+ const u = QuarkDashKeyExchange.deserializePoly(ciphertext);
268
+ const w = QuarkDashKeyExchange.multiply(u,s);
269
+ return QuarkDashKeyExchange.roundToBits(w);
270
+ }
271
+ }
package/src/types.ts ADDED
@@ -0,0 +1,75 @@
1
+ /**
2
+ * QuarkDash Crypto Types
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
+ * Crypto methods async interface
12
+ */
13
+ export interface ICryptoMethodAsync {
14
+ encrypt(decryptedData: Uint8Array): Promise<Uint8Array>;
15
+ decrypt(encryptedData: Uint8Array): Promise<Uint8Array>;
16
+ }
17
+
18
+ /**
19
+ * Crypto methods sync interface
20
+ */
21
+ export interface ICryptoMethodSync {
22
+ encryptSync(decryptedData: Uint8Array): Uint8Array;
23
+ decryptSync(encryptedData: Uint8Array): Uint8Array;
24
+ }
25
+
26
+ /**
27
+ * Cipher interface
28
+ */
29
+ export interface ICipher extends ICryptoMethodAsync, ICryptoMethodSync{}
30
+
31
+ /**
32
+ * KDF interface
33
+ */
34
+ export interface IKDF {
35
+ derive(ikm: Uint8Array, salt: Uint8Array, info: Uint8Array, length: number): Promise<Uint8Array>;
36
+ deriveSync(ikm: Uint8Array, salt: Uint8Array, info: Uint8Array, length: number): Uint8Array;
37
+ }
38
+
39
+ /**
40
+ * MAC interface
41
+ */
42
+ export interface IMAC {
43
+ sign(data: Uint8Array, key: Uint8Array): Promise<Uint8Array>;
44
+ verify(data: Uint8Array, key: Uint8Array, tag: Uint8Array): Promise<boolean>;
45
+ signSync(data: Uint8Array, key: Uint8Array): Uint8Array;
46
+ verifySync(data: Uint8Array, key: Uint8Array, tag: Uint8Array): boolean;
47
+ }
48
+
49
+ /**
50
+ * Key exchange interface
51
+ */
52
+ export interface IKeyExchange {
53
+ generateKeyPair(): Promise<ICryptoKeyPair>;
54
+ generateKeyPairSync(): ICryptoKeyPair;
55
+ encapsulate(publicKey: Uint8Array): Promise<ICryptoEncapsulated>;
56
+ encapsulateSync(publicKey: Uint8Array): ICryptoEncapsulated;
57
+ decapsulate(privateKey: Uint8Array, ciphertext: Uint8Array): Promise<Uint8Array>;
58
+ decapsulateSync(privateKey: Uint8Array, ciphertext: Uint8Array): Uint8Array;
59
+ }
60
+
61
+ /**
62
+ * Crypto key pair
63
+ */
64
+ export interface ICryptoKeyPair {
65
+ publicKey : Uint8Array;
66
+ privateKey : Uint8Array;
67
+ }
68
+
69
+ /**
70
+ * Crypto encapsulated
71
+ */
72
+ export interface ICryptoEncapsulated {
73
+ ciphertext: Uint8Array;
74
+ sharedSecret: Uint8Array;
75
+ }
package/src/utils.ts ADDED
@@ -0,0 +1,343 @@
1
+ /**
2
+ * QuarkDash Crypto Utils
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 crypto from "crypto";
11
+
12
+ /**
13
+ * Crypto Utils Class
14
+ */
15
+ export class QuarkDashUtils {
16
+ // Protected Constants
17
+ private static HEXChars : string = '0123456789abcdef';
18
+
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
+ /**
44
+ * Get Shake-256 result async
45
+ * @param data {Uint8Array} Bytes buffer
46
+ * @param len {number} Buffer length
47
+ * @return {Promise<Uint8Array>} Result buffer
48
+ */
49
+ 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;
66
+ }
67
+
68
+ /**
69
+ * Get Shake-256 result sync
70
+ * @param data {Uint8Array} Bytes buffer
71
+ * @param len {number} Buffer length
72
+ * @return {Uint8Array} Result buffer
73
+ */
74
+ 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;
91
+ }
92
+
93
+ /**
94
+ * Concat bytes
95
+ * @param arrays {Uint8Array|null|undefined} Input arrays for concat
96
+ * @returns {Uint8Array} Result buffer
97
+ */
98
+ public static concatBytes(...arrays: (Uint8Array|null|undefined)[]): Uint8Array {
99
+ const valid = arrays.filter(a => a != null) as Uint8Array[];
100
+ const total = valid.reduce((s, a) => s + a.length, 0);
101
+ const res = new Uint8Array(total);
102
+ let pos = 0;
103
+ for (const a of valid) {
104
+ res.set(a, pos);
105
+ pos += a.length;
106
+ }
107
+ return res;
108
+ }
109
+
110
+ /**
111
+ * Coerce Array
112
+ * @param arg {any} Argument
113
+ * @param copy {any} Copy
114
+ * @protected
115
+ */
116
+ public static coerceArray(arg : any, copy ? : any) : any {
117
+ let self = this
118
+
119
+ // ArrayBuffer view
120
+ if (arg.buffer && arg.name === 'Uint8Array') {
121
+ if (copy) {
122
+ if (arg.slice) {
123
+ arg = arg.slice()
124
+ } else {
125
+ arg = Array.prototype.slice.call(arg)
126
+ }
127
+ }
128
+
129
+ return arg
130
+ }
131
+
132
+ // It's an array; check it is a valid representation of a byte
133
+ if (Array.isArray(arg)) {
134
+ if (!self.checkInts(arg)) {
135
+ throw new Error('Array contains invalid value: ' + arg)
136
+ }
137
+
138
+ return new Uint8Array(arg)
139
+ }
140
+
141
+ // Something else, but behaves like an array (maybe a Buffer? Arguments?)
142
+ if (self.checkInt(arg.length) && self.checkInts(arg)) {
143
+ return new Uint8Array(arg)
144
+ }
145
+
146
+ throw new Error('unsupported array-like object')
147
+ }
148
+
149
+ /**
150
+ * Check if value is int
151
+ * @param value {any} Value
152
+ * @returns {boolean}
153
+ * @protected
154
+ */
155
+ public static checkInt(value: any) : boolean {
156
+ return parseInt(value) === value
157
+ }
158
+
159
+ /**
160
+ * Check Ints inside array
161
+ * @param arrayish {any} Array
162
+ * @returns {boolean} Any value is integer and between 0 and 255
163
+ * @protected
164
+ */
165
+ public static checkInts(arrayish : any) : boolean {
166
+ let self = this
167
+ if (!self.checkInt(arrayish.length)) {
168
+ return false
169
+ }
170
+
171
+ for (let i = 0; i < arrayish.length; i++) {
172
+ if (!self.checkInt(arrayish[i]) || arrayish[i] < 0 || arrayish[i] > 255) {
173
+ return false
174
+ }
175
+ }
176
+
177
+ return true
178
+ }
179
+
180
+ /**
181
+ * Get random bytes
182
+ * @param len {number} buffer length
183
+ * @returns {Uint8Array} Random bytes buffer
184
+ */
185
+ public static randomBytes(len: number): Uint8Array {
186
+ return crypto.getRandomValues(new Uint8Array(len));
187
+ }
188
+
189
+ /**
190
+ * Convert raw text to bytes array
191
+ * @param text {string} raw string
192
+ * @returns {any} bytes array
193
+ */
194
+ public static textToBytes(text : string) : any {
195
+ let self = this
196
+ let result = [],
197
+ i = 0
198
+ text = encodeURI(text)
199
+ while (i < text.length) {
200
+ let c = text.charCodeAt(i++)
201
+
202
+ // if it is a % sign, encode the following 2 bytes as a hex value
203
+ if (c === 37) {
204
+ result.push(parseInt(text.substr(i, 2), 16))
205
+ i += 2
206
+
207
+ // otherwise, just the actual byte
208
+ } else {
209
+ result.push(c)
210
+ }
211
+ }
212
+
213
+ return self.coerceArray(result)
214
+ }
215
+
216
+ /**
217
+ * Convert bytes array to raw string
218
+ * @param bytes {number[]|Uint8Array} Bytes array
219
+ * @returns {string} raw string
220
+ */
221
+ public static bytesToText(bytes : number[] | Uint8Array) : string {
222
+ return new TextDecoder().decode(bytes as Uint8Array);
223
+
224
+ let result = [],
225
+ i = 0
226
+
227
+ while (i < bytes.length) {
228
+ let c = bytes[i]
229
+
230
+ if (c < 128) {
231
+ result.push(String.fromCharCode(c))
232
+ i++
233
+ } else if (c > 191 && c < 224) {
234
+ result.push(String.fromCharCode(((c & 0x1f) << 6) | (bytes[i + 1] & 0x3f)))
235
+ i += 2
236
+ } else {
237
+ result.push(
238
+ String.fromCharCode(
239
+ ((c & 0x0f) << 12) | ((bytes[i + 1] & 0x3f) << 6) | (bytes[i + 2] & 0x3f),
240
+ ),
241
+ )
242
+ i += 3
243
+ }
244
+ }
245
+
246
+ return result.join('')
247
+ }
248
+
249
+ /**
250
+ * Convert HEX string to bytes array
251
+ * @param text {string} HEX string
252
+ * @returns {number[]} bytes array
253
+ * @constructor
254
+ */
255
+ public static HEXToBytes(text : string) : number[] {
256
+ let result = []
257
+ for (let i = 0; i < text.length; i += 2) {
258
+ result.push(parseInt(text.substr(i, 2), 16))
259
+ }
260
+
261
+ return result
262
+ }
263
+
264
+ /**
265
+ * Convert bytes array to HEX string
266
+ * @param bytes {number[]|Uint8Array} Bytes array
267
+ * @returns {string} HEX String
268
+ */
269
+ public static bytesToHEX(bytes : number[] | Uint8Array) : string {
270
+ let self = this
271
+ let result = []
272
+ for (let i = 0; i < bytes.length; i++) {
273
+ let v = bytes[i]
274
+ result.push(self.HEXChars[(v & 0xf0) >> 4] + self.HEXChars[v & 0x0f])
275
+ }
276
+ return result.join('')
277
+ }
278
+
279
+ /**
280
+ * Constant time equal
281
+ * @param a {Uint8Array} first buffer
282
+ * @param b {Uint8Array} second buffer
283
+ * @returns {boolean} Equal or not
284
+ */
285
+ public static constantTimeEqual(a: Uint8Array, b: Uint8Array): boolean {
286
+ if (a.length !== b.length) return false;
287
+ let diff = 0;
288
+ for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i];
289
+ return diff === 0;
290
+ }
291
+
292
+ /**
293
+ * Secure zero
294
+ * @param bytes {Uint8Array} bytes buffer
295
+ */
296
+ public static secureZero(bytes: Uint8Array): void {
297
+ for (let i = 0; i < bytes.length; i++) bytes[i] = 0;
298
+ }
299
+
300
+ /**
301
+ * Read U32 from buffer
302
+ * @param arr {Uint8Array} buffer
303
+ * @param off {number} Offset
304
+ * @returns {number} U32
305
+ * @private
306
+ */
307
+ public static readU32(arr:Uint8Array, off:number): number {
308
+ return (arr[off]|(arr[off+1]<<8)|(arr[off+2]<<16)|(arr[off+3]<<24))>>>0;
309
+ }
310
+
311
+ /**
312
+ * Write U32 to buffer
313
+ * @param v {number} U32
314
+ * @param arr {Uint8Array} Target buffer
315
+ * @param off {number} Offset
316
+ * @private
317
+ */
318
+ public static writeU32(v:number, arr:Uint8Array, off:number){
319
+ arr[off]=v&0xFF; arr[off+1]=(v>>8)&0xFF; arr[off+2]=(v>>16)&0xFF; arr[off+3]=(v>>24)&0xFF;
320
+ }
321
+
322
+ /**
323
+ * Read Uint32 Value
324
+ * @param arr {Uint8Array} Bytes buffer
325
+ * @param off {number} Offset
326
+ * @returns {number} Uint32 Value
327
+ */
328
+ public static readUint32(arr: Uint8Array, off: number): number {
329
+ return (arr[off] | (arr[off+1]<<8) | (arr[off+2]<<16) | (arr[off+3]<<24)) >>> 0;
330
+ }
331
+
332
+ /**
333
+ * Read Uint64 Value
334
+ * @param arr {Uint8Array} Bytes buffer
335
+ * @param off {number} offset
336
+ * @returns {bigint} Bigint
337
+ */
338
+ public static readUint64(arr: Uint8Array, off: number): bigint {
339
+ let v = 0n;
340
+ for (let i = 0; i < 8; i++) v |= BigInt(arr[off+i]) << BigInt(i*8);
341
+ return v;
342
+ }
343
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "module": "CommonJS",
5
+ "outDir": "./dist/cjs"
6
+ }
7
+ }