mirror of
https://github.com/Qortal/qortal-mobile.git
synced 2025-04-24 20:07:52 +00:00
move bcrypt operations to webworkers
This commit is contained in:
parent
9ef74d7a42
commit
8679911c65
@ -36,6 +36,9 @@ dependencies {
|
||||
implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion"
|
||||
implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion"
|
||||
implementation project(':capacitor-android')
|
||||
implementation "org.mindrot:jbcrypt:0.4"
|
||||
implementation "at.favre.lib:bcrypt:0.10.2"
|
||||
implementation 'com.password4j:password4j:1.8.2'
|
||||
testImplementation "junit:junit:$junitVersion"
|
||||
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
||||
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
||||
|
@ -1,5 +1,15 @@
|
||||
package com.github.Qortal.qortalMobile;
|
||||
|
||||
import com.getcapacitor.BridgeActivity;
|
||||
import com.github.Qortal.qortalMobile.NativeBcrypt;
|
||||
import android.os.Bundle;
|
||||
|
||||
public class MainActivity extends BridgeActivity {}
|
||||
public class MainActivity extends BridgeActivity {
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
registerPlugin(NativeBcrypt.class);
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,62 @@
|
||||
package com.github.Qortal.qortalMobile;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import android.os.Process;
|
||||
import com.getcapacitor.Plugin;
|
||||
import com.getcapacitor.PluginCall;
|
||||
import com.getcapacitor.JSObject;
|
||||
import com.getcapacitor.PluginMethod;
|
||||
import com.getcapacitor.annotation.CapacitorPlugin;
|
||||
import org.mindrot.jbcrypt.BCrypt;
|
||||
|
||||
@CapacitorPlugin(name = "NativeBcrypt")
|
||||
public class NativeBcrypt extends Plugin {
|
||||
// Use a fixed thread pool with the number of CPU cores
|
||||
private final ExecutorService executor = Executors.newFixedThreadPool(
|
||||
Runtime.getRuntime().availableProcessors(),
|
||||
new ThreadFactory() {
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread thread = new Thread(r);
|
||||
thread.setPriority(Thread.MAX_PRIORITY); // Set thread priority to high
|
||||
return thread;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@PluginMethod
|
||||
public void hashPassword(PluginCall call) {
|
||||
String password = call.getString("password");
|
||||
String salt = call.getString("salt");
|
||||
|
||||
if (password == null || salt == null) {
|
||||
call.reject("Password or salt is missing");
|
||||
return;
|
||||
}
|
||||
|
||||
executor.execute(() -> {
|
||||
try {
|
||||
// Perform bcrypt hashing
|
||||
String hash = BCrypt.hashpw(password, salt);
|
||||
|
||||
// Prepare the result
|
||||
JSObject result = new JSObject();
|
||||
result.put("hash", hash);
|
||||
|
||||
// Resolve the call on the main thread
|
||||
getActivity().runOnUiThread(() -> call.resolve(result));
|
||||
} catch (Exception e) {
|
||||
// Reject the call on the main thread in case of an error
|
||||
getActivity().runOnUiThread(() -> call.reject("Hashing failed: " + e.getMessage()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleOnDestroy() {
|
||||
super.handleOnDestroy();
|
||||
executor.shutdown(); // Shutdown the executor to release resources
|
||||
}
|
||||
}
|
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "qortal-go",
|
||||
"version": "0.3.1",
|
||||
"version": "0.3.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "qortal-go",
|
||||
"version": "0.3.1",
|
||||
"version": "0.3.2",
|
||||
"dependencies": {
|
||||
"@capacitor/android": "^6.1.2",
|
||||
"@capacitor/app": "^6.0.1",
|
||||
|
@ -23,7 +23,7 @@ import { set } from "lodash";
|
||||
import { cleanUrl, isUsingLocal } from "../background";
|
||||
|
||||
export const manifestData = {
|
||||
version: '0.3.2'
|
||||
version: '0.3.2.1'
|
||||
}
|
||||
|
||||
export const NotAuthenticated = ({
|
||||
|
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 });
|
||||
}
|
||||
};
|
@ -3,7 +3,11 @@
|
||||
import {bytes_to_base64 as bytesToBase64, Sha512} from 'asmcrypto.js'
|
||||
import bcrypt from 'bcryptjs'
|
||||
import utils from '../utils/utils'
|
||||
// import NativeBcrypt from '../utils/nativebcrypt'
|
||||
import BcryptWorker from './bcryptworker.worker.js?worker';
|
||||
import { crypto } from '../constants/decryptWallet'
|
||||
|
||||
|
||||
const stringtoUTF8Array = (message)=> {
|
||||
if (typeof message === 'string') {
|
||||
var s = unescape(encodeURIComponent(message)) // UTF-8
|
||||
@ -15,6 +19,27 @@ const stringtoUTF8Array = (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)=> {
|
||||
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
|
||||
@ -23,10 +48,11 @@ const stringToUTF8Array=(message)=> {
|
||||
const computekdf = async (req)=> {
|
||||
const { salt, key, nonce, staticSalt, staticBcryptSalt } = req
|
||||
const combinedBytes = utils.appendBuffer(new Uint8Array([]), stringToUTF8Array(`${staticSalt}${key}${nonce}`))
|
||||
|
||||
const sha512Hash = new Sha512().process(combinedBytes).finish().result
|
||||
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 }
|
||||
}
|
||||
|
||||
|
9
src/utils/nativebcrypt.ts
Normal file
9
src/utils/nativebcrypt.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { registerPlugin } from '@capacitor/core';
|
||||
|
||||
export interface NativeBcryptPlugin {
|
||||
hashPassword(options: { password: string; salt: string }): Promise<{ hash: string }>;
|
||||
}
|
||||
|
||||
const NativeBcrypt = registerPlugin<NativeBcryptPlugin>('NativeBcrypt');
|
||||
|
||||
export default NativeBcrypt;
|
Loading…
x
Reference in New Issue
Block a user