1 | import { when, is, identity, has, both } from 'ramda';
|
2 | import isNode from 'detect-node';
|
3 |
|
4 | import blueDefer from './defer';
|
5 | import smartTimeout from './smart-timeout';
|
6 | import { convertToUint8Array, sha1HashSync, sha256HashSync, aesEncryptSync, aesDecryptSync, convertToByteArray, convertToArrayBuffer, pqPrimeFactorization, bytesModPow } from './bin';
|
7 |
|
8 | const convertIfArray = when(is(Array), convertToUint8Array);
|
9 | let webWorker = !isNode;
|
10 | let taskID = 0;
|
11 | const awaiting = {};
|
12 | const webCrypto = isNode ? false
|
13 |
|
14 | : window.crypto.subtle || window.crypto.webkitSubtle
|
15 |
|
16 | || window.msCrypto && window.msCrypto.subtle;
|
17 | const useWebCrypto = webCrypto && !!webCrypto.digest;
|
18 | let useSha1Crypto = useWebCrypto;
|
19 | let useSha256Crypto = useWebCrypto;
|
20 | const finalizeTask = (taskID, result) => {
|
21 | const deferred = awaiting[taskID];
|
22 | if (deferred) {
|
23 |
|
24 | deferred.resolve(result);
|
25 | delete awaiting[taskID];
|
26 | }
|
27 | };
|
28 |
|
29 | const isCryptoTask = both(has('taskID'), has('result'));
|
30 |
|
31 |
|
32 | const workerEnable = !isNode && window.Worker;
|
33 | if (workerEnable) {
|
34 | require('worker-loader!./worker.js');
|
35 | const tmpWorker = new Worker('./bundle/hash.worker.js');
|
36 |
|
37 |
|
38 |
|
39 | tmpWorker.onmessage = e => {
|
40 | if (e.data === 'ready') {
|
41 | console.info('CW ready');
|
42 | } else if (!isCryptoTask(e.data)) {
|
43 | console.info('Not crypto task', e, e.data);
|
44 | return e;
|
45 | } else return webWorker ? finalizeTask(e.data.taskID, e.data.result) : webWorker = tmpWorker;
|
46 | };
|
47 |
|
48 | tmpWorker.onerror = function (error) {
|
49 | console.error('CW error', error, error.stack);
|
50 | webWorker = false;
|
51 | };
|
52 | tmpWorker.postMessage('b');
|
53 | webWorker = tmpWorker;
|
54 | }
|
55 |
|
56 | const performTaskWorker = (task, params, embed) => {
|
57 |
|
58 | const deferred = blueDefer();
|
59 |
|
60 | awaiting[taskID] = deferred;
|
61 |
|
62 | params.task = task;
|
63 | params.taskID = taskID;(embed || webWorker).postMessage(params);
|
64 |
|
65 | taskID++;
|
66 |
|
67 | return deferred.promise;
|
68 | };
|
69 |
|
70 | const sha1Hash = bytes => {
|
71 | if (useSha1Crypto) {
|
72 |
|
73 |
|
74 | const bytesTyped = convertIfArray(bytes);
|
75 |
|
76 | return webCrypto.digest({ name: 'SHA-1' }, bytesTyped).then(digest =>
|
77 |
|
78 | digest, e => {
|
79 | console.error('Crypto digest error', e);
|
80 | useSha1Crypto = false;
|
81 | return sha1HashSync(bytes);
|
82 | });
|
83 | }
|
84 | return smartTimeout.immediate(sha1HashSync, bytes);
|
85 | };
|
86 |
|
87 | const sha256Hash = bytes => {
|
88 | if (useSha256Crypto) {
|
89 | const bytesTyped = convertIfArray(bytes);
|
90 |
|
91 | return webCrypto.digest({ name: 'SHA-256' }, bytesTyped).then(identity
|
92 |
|
93 | , e => {
|
94 | console.error('Crypto digest error', e);
|
95 | useSha256Crypto = false;
|
96 | return sha256HashSync(bytes);
|
97 | });
|
98 | }
|
99 | return smartTimeout.immediate(sha256HashSync, bytes);
|
100 | };
|
101 |
|
102 | const aesEncrypt = (bytes, keyBytes, ivBytes) => smartTimeout.immediate(() => convertToArrayBuffer(aesEncryptSync(bytes, keyBytes, ivBytes)));
|
103 |
|
104 | const aesDecrypt = (encryptedBytes, keyBytes, ivBytes) => smartTimeout.immediate(() => convertToArrayBuffer(aesDecryptSync(encryptedBytes, keyBytes, ivBytes)));
|
105 |
|
106 | const factorize = bytes => {
|
107 | bytes = convertToByteArray(bytes);
|
108 | return webWorker ? performTaskWorker('factorize', { bytes }) : smartTimeout.immediate(pqPrimeFactorization, bytes);
|
109 | };
|
110 |
|
111 | const modPow = (x, y, m) => webWorker ? performTaskWorker('mod-pow', {
|
112 | x,
|
113 | y,
|
114 | m
|
115 | }) : smartTimeout.immediate(bytesModPow, x, y, m);
|
116 |
|
117 | export const CryptoWorker = {
|
118 | sha1Hash,
|
119 | sha256Hash,
|
120 | aesEncrypt,
|
121 | aesDecrypt,
|
122 | factorize,
|
123 | modPow
|
124 | };
|
125 |
|
126 | export default CryptoWorker;
|
127 |
|
\ | No newline at end of file |