mirror of
https://github.com/Qortal/Qortal-Hub.git
synced 2025-04-23 19:37:52 +00:00
move bcrypt function to webworkers
This commit is contained in:
parent
47c2c6ce16
commit
db754eb121
@ -47,8 +47,8 @@
|
|||||||
"@types/chrome": "^0.0.263",
|
"@types/chrome": "^0.0.263",
|
||||||
"asmcrypto.js": "2.3.2",
|
"asmcrypto.js": "2.3.2",
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.7.7",
|
||||||
"bcryptjs": "2.4.3",
|
|
||||||
"buffer": "6.0.3",
|
"buffer": "6.0.3",
|
||||||
|
"bcryptjs": "2.4.3",
|
||||||
"chokidar": "^3.6.0",
|
"chokidar": "^3.6.0",
|
||||||
"compressorjs": "^1.2.1",
|
"compressorjs": "^1.2.1",
|
||||||
"cordova-plugin-android-permissions": "^1.1.5",
|
"cordova-plugin-android-permissions": "^1.1.5",
|
||||||
|
12
src/deps/bcryptworker.worker.js
Normal file
12
src/deps/bcryptworker.worker.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import bcrypt from 'bcryptjs'
|
||||||
|
|
||||||
|
|
||||||
|
self.onmessage = function (e) {
|
||||||
|
const { hashBase64, salt } = e.data;
|
||||||
|
try {
|
||||||
|
const result = bcrypt.hashSync(hashBase64, salt);
|
||||||
|
self.postMessage({ result });
|
||||||
|
} catch (error) {
|
||||||
|
self.postMessage({ error: error.message });
|
||||||
|
}
|
||||||
|
};
|
71
src/deps/bcryptworkerwasm.worker.js
Normal file
71
src/deps/bcryptworkerwasm.worker.js
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import { bcrypt } from 'hash-wasm';
|
||||||
|
|
||||||
|
self.onmessage = async function (e) {
|
||||||
|
const { hashBase64, salt } = e.data;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Split the salt string
|
||||||
|
const parts = salt.split('$');
|
||||||
|
if (parts.length !== 4) {
|
||||||
|
throw new Error('Invalid salt format');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract the raw salt from the bcrypt salt string
|
||||||
|
const rawSalt = parts[3]; // e.g., "IxVE941tXVUD4cW0TNVm.O"
|
||||||
|
|
||||||
|
// Bcrypt's custom Base64 decoding function
|
||||||
|
function bcryptBase64Decode(base64String) {
|
||||||
|
const base64Code = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||||
|
const inverseBase64Code = {};
|
||||||
|
for (let i = 0; i < base64Code.length; i++) {
|
||||||
|
inverseBase64Code[base64Code[i]] = i;
|
||||||
|
}
|
||||||
|
const bytes = [];
|
||||||
|
let i = 0;
|
||||||
|
while (i < base64String.length) {
|
||||||
|
const c1 = inverseBase64Code[base64String.charAt(i++)];
|
||||||
|
const c2 = inverseBase64Code[base64String.charAt(i++)];
|
||||||
|
bytes.push(((c1 << 2) | (c2 >> 4)) & 0xff);
|
||||||
|
|
||||||
|
if (i >= base64String.length) break;
|
||||||
|
|
||||||
|
const c3 = inverseBase64Code[base64String.charAt(i++)];
|
||||||
|
bytes.push(((c2 << 4) | (c3 >> 2)) & 0xff);
|
||||||
|
|
||||||
|
if (i >= base64String.length) break;
|
||||||
|
|
||||||
|
const c4 = inverseBase64Code[base64String.charAt(i++)];
|
||||||
|
bytes.push(((c3 << 6) | c4) & 0xff);
|
||||||
|
}
|
||||||
|
return new Uint8Array(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode the bcrypt Base64 salt into a Uint8Array
|
||||||
|
const saltArray = bcryptBase64Decode(rawSalt);
|
||||||
|
|
||||||
|
if (saltArray.length !== 16) {
|
||||||
|
throw new Error('Salt must be 16 bytes long for hash-wasm.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract the cost factor
|
||||||
|
const costFactor = parseInt(parts[2], 10);
|
||||||
|
|
||||||
|
// Determine if 'hashBase64' is the password or needs decoding
|
||||||
|
const password = hashBase64; // Adjust if 'hashBase64' is encoded
|
||||||
|
|
||||||
|
// Compute the hash using hash-wasm
|
||||||
|
const result = await bcrypt({
|
||||||
|
password: password,
|
||||||
|
salt: saltArray,
|
||||||
|
costFactor: costFactor,
|
||||||
|
outputType: 'encoded', // Outputs in bcrypt format
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Return the result to the main thread
|
||||||
|
self.postMessage({ result });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error in Web Worker:', error);
|
||||||
|
self.postMessage({ error: error.message });
|
||||||
|
}
|
||||||
|
};
|
@ -1,9 +1,10 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
|
|
||||||
import {bytes_to_base64 as bytesToBase64, Sha512} from 'asmcrypto.js'
|
import {bytes_to_base64 as bytesToBase64, Sha512} from 'asmcrypto.js'
|
||||||
import bcrypt from 'bcryptjs'
|
|
||||||
import utils from '../utils/utils'
|
import utils from '../utils/utils'
|
||||||
import { crypto } from '../constants/decryptWallet'
|
import { crypto as crypto2 } from '../constants/decryptWallet'
|
||||||
|
import BcryptWorker from './bcryptworker.worker.js?worker';
|
||||||
|
|
||||||
const stringtoUTF8Array = (message)=> {
|
const stringtoUTF8Array = (message)=> {
|
||||||
if (typeof message === 'string') {
|
if (typeof message === 'string') {
|
||||||
var s = unescape(encodeURIComponent(message)) // UTF-8
|
var s = unescape(encodeURIComponent(message)) // UTF-8
|
||||||
@ -15,6 +16,29 @@ const stringtoUTF8Array = (message)=> {
|
|||||||
return message
|
return message
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const bcryptInWorker = (hashBase64, salt) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const worker = new BcryptWorker()
|
||||||
|
worker.onmessage = (e) => {
|
||||||
|
const { result, error } = e.data;
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
resolve(result);
|
||||||
|
}
|
||||||
|
worker.terminate();
|
||||||
|
};
|
||||||
|
worker.onerror = (err) => {
|
||||||
|
reject(err.message);
|
||||||
|
worker.terminate();
|
||||||
|
};
|
||||||
|
worker.postMessage({ hashBase64, salt });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const stringToUTF8Array=(message)=> {
|
const stringToUTF8Array=(message)=> {
|
||||||
if (typeof message !== 'string') return message; // Assuming you still want to pass through non-string inputs unchanged
|
if (typeof message !== 'string') return message; // Assuming you still want to pass through non-string inputs unchanged
|
||||||
const encoder = new TextEncoder(); // TextEncoder defaults to UTF-8
|
const encoder = new TextEncoder(); // TextEncoder defaults to UTF-8
|
||||||
@ -23,10 +47,11 @@ const stringToUTF8Array=(message)=> {
|
|||||||
const computekdf = async (req)=> {
|
const computekdf = async (req)=> {
|
||||||
const { salt, key, nonce, staticSalt, staticBcryptSalt } = req
|
const { salt, key, nonce, staticSalt, staticBcryptSalt } = req
|
||||||
const combinedBytes = utils.appendBuffer(new Uint8Array([]), stringToUTF8Array(`${staticSalt}${key}${nonce}`))
|
const combinedBytes = utils.appendBuffer(new Uint8Array([]), stringToUTF8Array(`${staticSalt}${key}${nonce}`))
|
||||||
|
|
||||||
const sha512Hash = new Sha512().process(combinedBytes).finish().result
|
const sha512Hash = new Sha512().process(combinedBytes).finish().result
|
||||||
const sha512HashBase64 = bytesToBase64(sha512Hash)
|
const sha512HashBase64 = bytesToBase64(sha512Hash)
|
||||||
const result = bcrypt.hashSync(sha512HashBase64.substring(0, 72), staticBcryptSalt)
|
|
||||||
|
const result = await bcryptInWorker(sha512HashBase64.substring(0, 72), staticBcryptSalt);
|
||||||
return { key, nonce, result }
|
return { key, nonce, result }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,8 +80,8 @@ export const kdf = async (seed, salt, threads) => {
|
|||||||
key: seed,
|
key: seed,
|
||||||
salt,
|
salt,
|
||||||
nonce,
|
nonce,
|
||||||
staticSalt: crypto.staticSalt,
|
staticSalt: crypto2.staticSalt,
|
||||||
staticBcryptSalt: crypto.staticBcryptSalt
|
staticBcryptSalt: crypto2.staticBcryptSalt
|
||||||
}).then(data => {
|
}).then(data => {
|
||||||
let jsonData
|
let jsonData
|
||||||
try {
|
try {
|
||||||
@ -70,6 +95,6 @@ export const kdf = async (seed, salt, threads) => {
|
|||||||
return data.result
|
return data.result
|
||||||
})
|
})
|
||||||
}))
|
}))
|
||||||
const result = new Sha512().process(stringtoUTF8Array(crypto.staticSalt + seedParts.reduce((a, c) => a + c))).finish().result
|
const result = new Sha512().process(stringtoUTF8Array(crypto2.staticSalt + seedParts.reduce((a, c) => a + c))).finish().result
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
import { defineConfig } from 'vite';
|
import { defineConfig } from 'vite';
|
||||||
import react from '@vitejs/plugin-react';
|
import react from '@vitejs/plugin-react';
|
||||||
// Import path module for resolving file paths
|
// Import path module for resolving file paths
|
||||||
import { resolve } from 'path';
|
|
||||||
import fixReactVirtualized from 'esbuild-plugin-react-virtualized'
|
import fixReactVirtualized from 'esbuild-plugin-react-virtualized'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
@ -11,22 +10,8 @@ export default defineConfig({
|
|||||||
globals: true,
|
globals: true,
|
||||||
setupFiles: ['./src/test/setup.ts']
|
setupFiles: ['./src/test/setup.ts']
|
||||||
},
|
},
|
||||||
|
|
||||||
plugins: [react()],
|
plugins: [react()],
|
||||||
build: {
|
|
||||||
rollupOptions: {
|
|
||||||
// Specify multiple entry points for Rollup
|
|
||||||
input: {
|
|
||||||
index: resolve(__dirname, 'index.html'), // Main entry for your React app
|
|
||||||
background: resolve(__dirname, 'src/background.ts'), // Separate entry for the background script
|
|
||||||
},
|
|
||||||
output: {
|
|
||||||
// Adjust the output settings if necessary
|
|
||||||
entryFileNames: `[name].js`,
|
|
||||||
chunkFileNames: `[name].js`,
|
|
||||||
assetFileNames: `[name].[ext]`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
optimizeDeps: {
|
optimizeDeps: {
|
||||||
esbuildOptions: {
|
esbuildOptions: {
|
||||||
plugins: [fixReactVirtualized],
|
plugins: [fixReactVirtualized],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user