@mybucks.online/core 1.0.1 → 1.0.3
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.
- package/README.md +22 -2
- package/index.js +53 -14
- package/package.json +8 -2
- package/test/index.test.js +45 -3
package/README.md
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
# @mybucks.online/core
|
|
2
2
|
|
|
3
|
-
This is a core part of [mybucks.online](https://mybucks.online) crypto wallet, involving
|
|
3
|
+
This is a core part of [mybucks.online](https://mybucks.online) crypto wallet, involving hash and private key generation, generate and parse transfer-link token.
|
|
4
4
|
|
|
5
5
|
## mybucks.online
|
|
6
6
|
|
|
7
|
-
[Mybucks.online](https://mybucks.online) is a **password-only, self-custodial and browser-based cryptocurrency wallet** built with Javascript. It generates a private key from your password and passcode using an industry-standard, verified **one-way hash function**. Your private key forms your account, allowing you to transfer, receive, and hold your crypto assets
|
|
7
|
+
[Mybucks.online](https://mybucks.online) is a **password-only, self-custodial and browser-based cryptocurrency wallet** built with Javascript. It generates a private key from your password and passcode using an industry-standard, verified **one-way hash function**. Your private key forms your account, allowing you to transfer, receive, and hold your crypto assets instantly.
|
|
8
|
+
|
|
9
|
+
As a hash function, the **scrypt** Key Derivation Function (KDF) increases the computational effort required to crack passwords, effectively delaying **brute-force** attacks and making them impractical.
|
|
10
|
+
|
|
11
|
+
It fully runs on your **browser side** without using any storage or invoking any 3rd-party APIs for key management. It instantly generates your private key from your password input, and whenever you close or refresh, there is no footprint. This absolutely protects your privacy.
|
|
8
12
|
|
|
9
13
|
## Quick start
|
|
10
14
|
|
|
@@ -29,6 +33,21 @@ const privateKey = getEvmPrivateKey(hash);
|
|
|
29
33
|
console.log("Private key: ", privateKey);
|
|
30
34
|
```
|
|
31
35
|
|
|
36
|
+
### 3. Generate and parse (transfer-link's)token
|
|
37
|
+
```javascript
|
|
38
|
+
import { generateToken } from "@mybucks.online/core";
|
|
39
|
+
const token = generateToken(password, passcode, network);
|
|
40
|
+
|
|
41
|
+
console.log("https://app.mybucks.online?wallet=" + token);
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
```javascript
|
|
45
|
+
import { parseToken } from "@mybucks.online/core";
|
|
46
|
+
const [password, passcode, network] = parseToken(token);
|
|
47
|
+
console.log("Account credentials are: ", password, passcode);
|
|
48
|
+
console.log("Network: ", network);
|
|
49
|
+
```
|
|
50
|
+
|
|
32
51
|
## Test
|
|
33
52
|
```bash
|
|
34
53
|
npm run test
|
|
@@ -42,3 +61,4 @@ Find the docs [here](https://docs.mybucks.online).
|
|
|
42
61
|
|
|
43
62
|
- https://github.com/mybucks.online/app
|
|
44
63
|
- https://app.mybucks.online
|
|
64
|
+
- https://app.mybucks.online/?wallet=VWnsSGRGVtb0FjY291bnQ1JgIxMTIzMjQCb3B0aW1pc20=_wNovT
|
package/index.js
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { Buffer } from "buffer";
|
|
2
|
+
import { ethers } from "ethers";
|
|
3
|
+
import scryptJS from "scrypt-js";
|
|
4
|
+
import { nanoid } from "nanoid";
|
|
4
5
|
|
|
6
|
+
const { scrypt } = scryptJS;
|
|
5
7
|
const abi = new ethers.AbiCoder();
|
|
6
8
|
|
|
7
|
-
/**
|
|
8
|
-
* [CRITICAL] DON'T CHANGE FOREVER!!!
|
|
9
|
-
* Reference:
|
|
10
|
-
* https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#scrypt
|
|
11
|
-
*/
|
|
12
9
|
const HASH_OPTIONS = {
|
|
13
10
|
N: 32768, // CPU/memory cost parameter, 2^15
|
|
14
11
|
r: 8, // block size parameter
|
|
@@ -24,7 +21,7 @@ const HASH_OPTIONS = {
|
|
|
24
21
|
* @param {*} cb a callback function designed to receive the progress updates during the scrypt hashing process.
|
|
25
22
|
* @returns hash result as string format
|
|
26
23
|
*/
|
|
27
|
-
async function generateHash(password, passcode, cb = () => {}) {
|
|
24
|
+
export async function generateHash(password, passcode, cb = () => {}) {
|
|
28
25
|
if (!password || !passcode) {
|
|
29
26
|
return "";
|
|
30
27
|
}
|
|
@@ -52,11 +49,53 @@ async function generateHash(password, passcode, cb = () => {}) {
|
|
|
52
49
|
* @param {*} hash
|
|
53
50
|
* @returns private key as string format
|
|
54
51
|
*/
|
|
55
|
-
function getEvmPrivateKey(hash) {
|
|
52
|
+
export function getEvmPrivateKey(hash) {
|
|
56
53
|
return ethers.keccak256(abi.encode(["string"], [hash]));
|
|
57
54
|
}
|
|
58
55
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
56
|
+
const URL_DELIMITER = "\u0002";
|
|
57
|
+
const NETWORKS = [
|
|
58
|
+
"ethereum",
|
|
59
|
+
"polygon",
|
|
60
|
+
"arbitrum",
|
|
61
|
+
"optimism",
|
|
62
|
+
"bsc",
|
|
63
|
+
"avalanche",
|
|
64
|
+
"tron",
|
|
65
|
+
];
|
|
66
|
+
/**
|
|
67
|
+
* This function generates a transfer-link by combining credentials and randomly generated padding.
|
|
68
|
+
* The transfer-link introduces a nice feature that enables the transfer of full ownership of a wallet account.
|
|
69
|
+
* @param {*} password
|
|
70
|
+
* @param {*} passcode
|
|
71
|
+
* @param {*} network ethereum | polygon | arbitrum | optimism | bsc | avalanche | tron
|
|
72
|
+
* @returns A string formatted as a transfer-link token, which can be appended to `https://app.mybucks.online?wallet=`
|
|
73
|
+
*/
|
|
74
|
+
export function generateToken(password, passcode, network) {
|
|
75
|
+
if (!password || !passcode || !network) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
if (!NETWORKS.find((n) => n === network)) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const merged = Buffer.from(
|
|
83
|
+
password + URL_DELIMITER + passcode + URL_DELIMITER + network,
|
|
84
|
+
"utf-8"
|
|
85
|
+
);
|
|
86
|
+
const base64Encoded = merged.toString("base64");
|
|
87
|
+
const padding = nanoid(12);
|
|
88
|
+
return padding.slice(0, 6) + base64Encoded + padding.slice(6);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* This function parses a transfer-link token generated by generateToken().
|
|
93
|
+
* @param {*} token
|
|
94
|
+
* @returns an array of strings, including the password, passcode and network.
|
|
95
|
+
*/
|
|
96
|
+
export function parseToken(token) {
|
|
97
|
+
const payload = token.slice(6, token.length - 6);
|
|
98
|
+
const base64Decoded = Buffer.from(payload, "base64").toString("utf-8");
|
|
99
|
+
const [password, passcode, network] = base64Decoded.split(URL_DELIMITER);
|
|
100
|
+
return [password, passcode, network];
|
|
101
|
+
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mybucks.online/core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Core module for mybucks.online crypto wallet",
|
|
5
5
|
"main": "index.js",
|
|
6
|
+
"type": "module",
|
|
6
7
|
"scripts": {
|
|
7
8
|
"test": "node test/index.test.js"
|
|
8
9
|
},
|
|
@@ -19,7 +20,11 @@
|
|
|
19
20
|
"browser-based",
|
|
20
21
|
"ethereum",
|
|
21
22
|
"tron",
|
|
22
|
-
"
|
|
23
|
+
"scrypt",
|
|
24
|
+
"keccak256",
|
|
25
|
+
"key-generation",
|
|
26
|
+
"open-source",
|
|
27
|
+
"mybucks.online"
|
|
23
28
|
],
|
|
24
29
|
"author": "koko37",
|
|
25
30
|
"license": "MIT",
|
|
@@ -30,6 +35,7 @@
|
|
|
30
35
|
"dependencies": {
|
|
31
36
|
"buffer": "^6.0.3",
|
|
32
37
|
"ethers": "^6.13.5",
|
|
38
|
+
"nanoid": "^5.0.9",
|
|
33
39
|
"scrypt-js": "^3.0.1"
|
|
34
40
|
}
|
|
35
41
|
}
|
package/test/index.test.js
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import { describe, test } from "node:test";
|
|
3
|
+
import {
|
|
4
|
+
generateHash,
|
|
5
|
+
getEvmPrivateKey,
|
|
6
|
+
generateToken,
|
|
7
|
+
parseToken,
|
|
8
|
+
} from "../index.js";
|
|
4
9
|
|
|
5
10
|
const DEMO_PASSWORD = "DemoAccount5&";
|
|
6
11
|
const DEMO_PASSCODE = "112324";
|
|
12
|
+
const DEMO_NETWORK = "optimism";
|
|
7
13
|
const DEMO_HASH =
|
|
8
14
|
"af9a22d75f8f69d33fe8fc294e8f413219d9c75374dec07fda2e4a66868599609887a10e04981e17356d2c07432fc89c11089172fdf91c0015b9a4beef11e447";
|
|
9
15
|
const DEMO_PRIVATE_KEY =
|
|
10
16
|
"0x71743de900c63ed741263a2a4513c1b1829e80bd9f18d5d3a593e651b914cb3b";
|
|
17
|
+
const DEMO_TOKEN =
|
|
18
|
+
"VWnsSGRGVtb0FjY291bnQ1JgIxMTIzMjQCb3B0aW1pc20=_wNovT";
|
|
11
19
|
|
|
12
20
|
describe("generateHash", () => {
|
|
13
21
|
test("should return empty string if password or passcode is blank", async () => {
|
|
@@ -29,3 +37,37 @@ describe("getEvmPrivateKey", () => {
|
|
|
29
37
|
assert.strictEqual(privateKey, DEMO_PRIVATE_KEY);
|
|
30
38
|
});
|
|
31
39
|
});
|
|
40
|
+
|
|
41
|
+
describe("generateToken", () => {
|
|
42
|
+
test("should return null if password, passcode or network is invalid", async () => {
|
|
43
|
+
assert.strictEqual(generateToken("", "123345", "ethereum"), null);
|
|
44
|
+
assert.strictEqual(generateToken("", "123345"), null);
|
|
45
|
+
assert.strictEqual(generateToken("password", "", "ethereum"), null);
|
|
46
|
+
assert.strictEqual(generateToken("password", "123456", ""), null);
|
|
47
|
+
assert.strictEqual(generateToken("password", "123456", "invalid"), null);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe("parseToken", () => {
|
|
52
|
+
test("should return array of password, passcode, and network", () => {
|
|
53
|
+
const [password, passcode, network] = parseToken(DEMO_TOKEN);
|
|
54
|
+
|
|
55
|
+
assert.strictEqual(password, DEMO_PASSWORD);
|
|
56
|
+
assert.strictEqual(passcode, DEMO_PASSCODE);
|
|
57
|
+
assert.strictEqual(network, DEMO_NETWORK);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe("generateToken and parseToken", () => {
|
|
62
|
+
test("should be compatible and return correct result", () => {
|
|
63
|
+
const testPassword = "random^Password9";
|
|
64
|
+
const testPasscode = "909011";
|
|
65
|
+
const testNetwork = "polygon";
|
|
66
|
+
const token = generateToken(testPassword, testPasscode, testNetwork);
|
|
67
|
+
|
|
68
|
+
const [password, passcode, network] = parseToken(token);
|
|
69
|
+
assert.strictEqual(password, testPassword);
|
|
70
|
+
assert.strictEqual(passcode, testPasscode);
|
|
71
|
+
assert.strictEqual(network, testNetwork);
|
|
72
|
+
});
|
|
73
|
+
});
|