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.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion"
|
||||||
implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion"
|
implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion"
|
||||||
implementation project(':capacitor-android')
|
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"
|
testImplementation "junit:junit:$junitVersion"
|
||||||
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
||||||
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
||||||
|
@ -1,5 +1,15 @@
|
|||||||
package com.github.Qortal.qortalMobile;
|
package com.github.Qortal.qortalMobile;
|
||||||
|
|
||||||
import com.getcapacitor.BridgeActivity;
|
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",
|
"name": "qortal-go",
|
||||||
"version": "0.3.1",
|
"version": "0.3.2",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "qortal-go",
|
"name": "qortal-go",
|
||||||
"version": "0.3.1",
|
"version": "0.3.2",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@capacitor/android": "^6.1.2",
|
"@capacitor/android": "^6.1.2",
|
||||||
"@capacitor/app": "^6.0.1",
|
"@capacitor/app": "^6.0.1",
|
||||||
|
@ -23,7 +23,7 @@ import { set } from "lodash";
|
|||||||
import { cleanUrl, isUsingLocal } from "../background";
|
import { cleanUrl, isUsingLocal } from "../background";
|
||||||
|
|
||||||
export const manifestData = {
|
export const manifestData = {
|
||||||
version: '0.3.2'
|
version: '0.3.2.1'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const NotAuthenticated = ({
|
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 {bytes_to_base64 as bytesToBase64, Sha512} from 'asmcrypto.js'
|
||||||
import bcrypt from 'bcryptjs'
|
import bcrypt from 'bcryptjs'
|
||||||
import utils from '../utils/utils'
|
import utils from '../utils/utils'
|
||||||
|
// import NativeBcrypt from '../utils/nativebcrypt'
|
||||||
|
import BcryptWorker from './bcryptworker.worker.js?worker';
|
||||||
import { crypto } from '../constants/decryptWallet'
|
import { crypto } from '../constants/decryptWallet'
|
||||||
|
|
||||||
|
|
||||||
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 +19,27 @@ 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 +48,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 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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