quantum-coin-js-sdk 1.0.37 → 1.0.39
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 +20 -0
- package/example/node_modules/.package-lock.json +1 -1
- package/example/package-lock.json +1 -1
- package/index.d.ts +16 -0
- package/index.js +52 -0
- package/package.json +2 -2
- package/tests/scrypt.test.js +128 -0
package/README.md
CHANGED
|
@@ -168,6 +168,7 @@ Example Project: https://github.com/quantumcoinproject/quantum-coin-js-sdk/tree/
|
|
|
168
168
|
* [~publicKeyFromSignature(digest, signature)](#module_quantum-coin-js-sdk..publicKeyFromSignature) ⇒ <code>string</code>
|
|
169
169
|
* [~publicKeyFromPrivateKey(privateKey)](#module_quantum-coin-js-sdk..publicKeyFromPrivateKey) ⇒ <code>string</code>
|
|
170
170
|
* [~addressFromPublicKey(publicKey)](#module_quantum-coin-js-sdk..addressFromPublicKey) ⇒ <code>string</code>
|
|
171
|
+
* [~scryptDeriveKey(secret, salt, N, r, p, dkLen)](#module_quantum-coin-js-sdk..scryptDeriveKey) ⇒ <code>Array.<number></code>
|
|
171
172
|
* [~combinePublicKeySignature(publicKey, signature)](#module_quantum-coin-js-sdk..combinePublicKeySignature) ⇒ <code>string</code>
|
|
172
173
|
* [~packMethodData(abiJSON, methodName, ...args)](#module_quantum-coin-js-sdk..packMethodData) ⇒ <code>PackUnpackResult</code>
|
|
173
174
|
* [~unpackMethodData(abiJSON, methodName, hexData)](#module_quantum-coin-js-sdk..unpackMethodData) ⇒ <code>PackUnpackResult</code>
|
|
@@ -1541,6 +1542,25 @@ The addressFromPublicKey returns the address corresponding to the public key.
|
|
|
1541
1542
|
| --- | --- | --- |
|
|
1542
1543
|
| publicKey | <code>Array.<number></code> | An array of bytes containing the public key. |
|
|
1543
1544
|
|
|
1545
|
+
<a name="module_quantum-coin-js-sdk..scryptDeriveKey"></a>
|
|
1546
|
+
|
|
1547
|
+
### quantum-coin-js-sdk~scryptDeriveKey(secret, salt, N, r, p, dkLen) ⇒ <code>Array.<number></code>
|
|
1548
|
+
The scryptDeriveKey function derives a key from a secret and salt using the scrypt KDF.
|
|
1549
|
+
|
|
1550
|
+
Note: Only the specific scrypt parameter set N=262144, r=8, p=1, dkLen=32 is supported currently. Passing any other values returns null.
|
|
1551
|
+
|
|
1552
|
+
**Kind**: inner method of [<code>quantum-coin-js-sdk</code>](#module_quantum-coin-js-sdk)
|
|
1553
|
+
**Returns**: <code>Array.<number></code> - - Returns the 32-byte derived key as a byte array. Returns null if the operation failed or the parameters are unsupported.
|
|
1554
|
+
|
|
1555
|
+
| Param | Type | Description |
|
|
1556
|
+
| --- | --- | --- |
|
|
1557
|
+
| secret | <code>string</code> | The secret/passphrase to derive the key from. |
|
|
1558
|
+
| salt | <code>Uint8Array</code> \| <code>Array.<number></code> | The salt as a byte array. |
|
|
1559
|
+
| N | <code>number</code> | The scrypt CPU/memory cost parameter. Must be 262144. |
|
|
1560
|
+
| r | <code>number</code> | The scrypt block size parameter. Must be 8. |
|
|
1561
|
+
| p | <code>number</code> | The scrypt parallelization parameter. Must be 1. |
|
|
1562
|
+
| dkLen | <code>number</code> | The derived key length in bytes. Must be 32. |
|
|
1563
|
+
|
|
1544
1564
|
<a name="module_quantum-coin-js-sdk..combinePublicKeySignature"></a>
|
|
1545
1565
|
|
|
1546
1566
|
### quantum-coin-js-sdk~combinePublicKeySignature(publicKey, signature) ⇒ <code>string</code>
|
package/index.d.ts
CHANGED
|
@@ -726,6 +726,22 @@ export function publicKeyFromPrivateKey(privateKey: number[]): string;
|
|
|
726
726
|
* @return {string} - Returns the address corresponding to the public key as a hex string. Returns null if the operation failed.
|
|
727
727
|
*/
|
|
728
728
|
export function addressFromPublicKey(publicKey: number[]): string;
|
|
729
|
+
/**
|
|
730
|
+
* The scryptDeriveKey function derives a key from a secret and salt using the scrypt KDF.
|
|
731
|
+
*
|
|
732
|
+
* Note: Only the specific scrypt parameter set N=262144, r=8, p=1, dkLen=32 is supported
|
|
733
|
+
* currently. Passing any other values returns null.
|
|
734
|
+
*
|
|
735
|
+
* @function scryptDeriveKey
|
|
736
|
+
* @param {string} secret - The secret/passphrase to derive the key from.
|
|
737
|
+
* @param {Uint8Array|number[]} salt - The salt as a byte array.
|
|
738
|
+
* @param {number} N - The scrypt CPU/memory cost parameter. Must be 262144.
|
|
739
|
+
* @param {number} r - The scrypt block size parameter. Must be 8.
|
|
740
|
+
* @param {number} p - The scrypt parallelization parameter. Must be 1.
|
|
741
|
+
* @param {number} dkLen - The derived key length in bytes. Must be 32.
|
|
742
|
+
* @return {number[]} - Returns the 32-byte derived key as a byte array. Returns null if the operation failed or the parameters are unsupported.
|
|
743
|
+
*/
|
|
744
|
+
export function scryptDeriveKey(secret: string, salt: Uint8Array | number[], N: number, r: number, p: number, dkLen: number): number[];
|
|
729
745
|
/**
|
|
730
746
|
* The combinePublicKeySignature combines the public key and signature.
|
|
731
747
|
*
|
package/index.js
CHANGED
|
@@ -62,6 +62,10 @@ const BASE_SEED_BYTES_HYBRIDEDS = 96;
|
|
|
62
62
|
const BASE_SEED_BYTES_HYBRIDEDMLDSASLHDSA5 = 72;
|
|
63
63
|
const BASE_SEED_BYTES_HYBRIDEDMLDSASLHDSA = 64;
|
|
64
64
|
const MIN_PASSPHRASE_LENGTH = 12;
|
|
65
|
+
const SCRYPT_SUPPORTED_N = 262144;
|
|
66
|
+
const SCRYPT_SUPPORTED_R = 8;
|
|
67
|
+
const SCRYPT_SUPPORTED_P = 1;
|
|
68
|
+
const SCRYPT_SUPPORTED_DKLEN = 32;
|
|
65
69
|
const INVALID_KEY_TYPE = -1001;
|
|
66
70
|
const CIRCL_CRYPTO_FAILURE = -1002;
|
|
67
71
|
const EXPECTED_WASM_SHA256 = "17aff465c5879e2ff94d33e8ce9d98d6ad6a70849b3e3cad7cccbcc9728e5a02";
|
|
@@ -2658,6 +2662,53 @@ function addressFromPublicKey(publicKey) {
|
|
|
2658
2662
|
return PublicKeyToAddress(publicKey);
|
|
2659
2663
|
}
|
|
2660
2664
|
|
|
2665
|
+
/**
|
|
2666
|
+
* The scryptDeriveKey function derives a key from a secret and salt using the scrypt KDF.
|
|
2667
|
+
*
|
|
2668
|
+
* Note: Only the specific scrypt parameter set N=262144, r=8, p=1, dkLen=32 is supported
|
|
2669
|
+
* currently. Passing any other values returns null.
|
|
2670
|
+
*
|
|
2671
|
+
* @function scryptDeriveKey
|
|
2672
|
+
* @param {string} secret - The secret/passphrase to derive the key from.
|
|
2673
|
+
* @param {Uint8Array|number[]} salt - The salt as a byte array.
|
|
2674
|
+
* @param {number} N - The scrypt CPU/memory cost parameter. Must be 262144.
|
|
2675
|
+
* @param {number} r - The scrypt block size parameter. Must be 8.
|
|
2676
|
+
* @param {number} p - The scrypt parallelization parameter. Must be 1.
|
|
2677
|
+
* @param {number} dkLen - The derived key length in bytes. Must be 32.
|
|
2678
|
+
* @return {number[]} - Returns the 32-byte derived key as a byte array. Returns null if the operation failed or the parameters are unsupported.
|
|
2679
|
+
*/
|
|
2680
|
+
function scryptDeriveKey(secret, salt, N, r, p, dkLen) {
|
|
2681
|
+
if (isInitialized === false) {
|
|
2682
|
+
return -1000;
|
|
2683
|
+
}
|
|
2684
|
+
|
|
2685
|
+
if (typeof secret !== 'string' && !(secret instanceof String)) {
|
|
2686
|
+
return null;
|
|
2687
|
+
}
|
|
2688
|
+
|
|
2689
|
+
if (isByteArray(salt) === false) {
|
|
2690
|
+
return null;
|
|
2691
|
+
}
|
|
2692
|
+
|
|
2693
|
+
if (typeof N !== 'number' || typeof r !== 'number' || typeof p !== 'number' || typeof dkLen !== 'number') {
|
|
2694
|
+
return null;
|
|
2695
|
+
}
|
|
2696
|
+
|
|
2697
|
+
if (N !== SCRYPT_SUPPORTED_N || r !== SCRYPT_SUPPORTED_R || p !== SCRYPT_SUPPORTED_P || dkLen !== SCRYPT_SUPPORTED_DKLEN) {
|
|
2698
|
+
return null;
|
|
2699
|
+
}
|
|
2700
|
+
|
|
2701
|
+
const saltU8 = salt instanceof Uint8Array ? salt : new Uint8Array(salt);
|
|
2702
|
+
const saltBase64 = bytesToBase64(saltU8);
|
|
2703
|
+
|
|
2704
|
+
const derivedBase64 = Scrypt(secret, saltBase64);
|
|
2705
|
+
if (derivedBase64 == null || (typeof derivedBase64 !== 'string' && !(derivedBase64 instanceof String))) {
|
|
2706
|
+
return null;
|
|
2707
|
+
}
|
|
2708
|
+
|
|
2709
|
+
return Array.from(base64ToBytes(derivedBase64));
|
|
2710
|
+
}
|
|
2711
|
+
|
|
2661
2712
|
/**
|
|
2662
2713
|
* The combinePublicKeySignature combines the public key and signature.
|
|
2663
2714
|
*
|
|
@@ -3162,6 +3213,7 @@ module.exports = {
|
|
|
3162
3213
|
publicKeyFromSignature,
|
|
3163
3214
|
publicKeyFromPrivateKey,
|
|
3164
3215
|
addressFromPublicKey,
|
|
3216
|
+
scryptDeriveKey,
|
|
3165
3217
|
combinePublicKeySignature,
|
|
3166
3218
|
TransactionSigningRequest,
|
|
3167
3219
|
signRawTransaction,
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "quantum-coin-js-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.39",
|
|
4
4
|
"description": "Quantum Coin - Q SDK in JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"test": "node --test tests/non-transactional.preinit.test.js tests/non-transactional.test.js tests/sign-raw-transaction.test.js tests/sign-verify.test.js tests/get-gas-price.test.js tests/transactional.rpc.test.js tests/transactional.relay.test.js",
|
|
7
|
+
"test": "node --test tests/non-transactional.preinit.test.js tests/non-transactional.test.js tests/sign-raw-transaction.test.js tests/sign-verify.test.js tests/scrypt.test.js tests/get-gas-price.test.js tests/transactional.rpc.test.js tests/transactional.relay.test.js",
|
|
8
8
|
"build": "npx -p typescript tsc index.js --declaration --allowJs --emitDeclarationOnly"
|
|
9
9
|
},
|
|
10
10
|
"repository": {
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for scryptDeriveKey(secret, salt, N, r, p, dkLen).
|
|
3
|
+
*
|
|
4
|
+
* Only the fixed scrypt parameter set N=262144, r=8, p=1, dkLen=32 is supported currently,
|
|
5
|
+
* so the derived key is always 32 bytes and any other parameter values return null.
|
|
6
|
+
*/
|
|
7
|
+
const { describe, test, before } = require('node:test');
|
|
8
|
+
const assert = require('node:assert/strict');
|
|
9
|
+
|
|
10
|
+
const qcsdk = require('..');
|
|
11
|
+
|
|
12
|
+
const MAINNET_CHAIN_ID = 123123;
|
|
13
|
+
const READ_RELAY_URL = 'https://sdk.readrelay.quantumcoinapi.com';
|
|
14
|
+
const WRITE_RELAY_URL = 'https://sdk.writerelay.quantumcoinapi.com';
|
|
15
|
+
|
|
16
|
+
const SALT = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
|
|
17
|
+
|
|
18
|
+
// Supported scrypt parameters.
|
|
19
|
+
const N = 262144;
|
|
20
|
+
const R = 8;
|
|
21
|
+
const P = 1;
|
|
22
|
+
const DKLEN = 32;
|
|
23
|
+
|
|
24
|
+
function toBase64(bytes) {
|
|
25
|
+
return Buffer.from(bytes).toString('base64');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// This block intentionally runs before initialize() is called.
|
|
29
|
+
describe('scryptDeriveKey (pre-init)', () => {
|
|
30
|
+
test('returns -1000 before initialize', () => {
|
|
31
|
+
assert.equal(qcsdk.scryptDeriveKey('test-passphrase-123', SALT, N, R, P, DKLEN), -1000);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
describe('scryptDeriveKey', () => {
|
|
36
|
+
before(async () => {
|
|
37
|
+
const cfg = new qcsdk.Config(READ_RELAY_URL, WRITE_RELAY_URL, MAINNET_CHAIN_ID, '', '');
|
|
38
|
+
const initResult = await qcsdk.initialize(cfg);
|
|
39
|
+
assert.equal(initResult, true, 'SDK initialize should succeed');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('derives a 32-byte key for a valid secret and salt', () => {
|
|
43
|
+
const key = qcsdk.scryptDeriveKey('test-passphrase-123', SALT, N, R, P, DKLEN);
|
|
44
|
+
assert.ok(Array.isArray(key), 'result should be a byte array');
|
|
45
|
+
assert.equal(key.length, 32, 'derived key must be 32 bytes');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('is deterministic for the same secret and salt', () => {
|
|
49
|
+
const key1 = qcsdk.scryptDeriveKey('test-passphrase-123', SALT, N, R, P, DKLEN);
|
|
50
|
+
const key2 = qcsdk.scryptDeriveKey('test-passphrase-123', SALT, N, R, P, DKLEN);
|
|
51
|
+
assert.deepEqual(key1, key2, 'same inputs must produce the same key');
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('produces a different key for a different salt', () => {
|
|
55
|
+
const otherSalt = new Uint8Array(SALT);
|
|
56
|
+
otherSalt[0] = (otherSalt[0] + 1) & 0xff;
|
|
57
|
+
const key1 = qcsdk.scryptDeriveKey('test-passphrase-123', SALT, N, R, P, DKLEN);
|
|
58
|
+
const key2 = qcsdk.scryptDeriveKey('test-passphrase-123', otherSalt, N, R, P, DKLEN);
|
|
59
|
+
assert.notDeepEqual(key1, key2, 'different salt must produce a different key');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('produces a different key for a different secret', () => {
|
|
63
|
+
const key1 = qcsdk.scryptDeriveKey('test-passphrase-123', SALT, N, R, P, DKLEN);
|
|
64
|
+
const key2 = qcsdk.scryptDeriveKey('test-passphrase-124', SALT, N, R, P, DKLEN);
|
|
65
|
+
assert.notDeepEqual(key1, key2, 'different secret must produce a different key');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test('accepts a plain number[] salt (equivalent to Uint8Array)', () => {
|
|
69
|
+
const key1 = qcsdk.scryptDeriveKey('test-passphrase-123', SALT, N, R, P, DKLEN);
|
|
70
|
+
const key2 = qcsdk.scryptDeriveKey('test-passphrase-123', Array.from(SALT), N, R, P, DKLEN);
|
|
71
|
+
assert.deepEqual(key1, key2, 'number[] and Uint8Array salt must match');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test('matches known-answer vector', () => {
|
|
75
|
+
const key = qcsdk.scryptDeriveKey('test-passphrase-123', SALT, N, R, P, DKLEN);
|
|
76
|
+
assert.equal(
|
|
77
|
+
toBase64(key),
|
|
78
|
+
'YCJuvOP0hUtJpNfmRp7PMP5Evkr4gXFUXPKl4zaXnHo=',
|
|
79
|
+
'derived key must match the hardcoded vector'
|
|
80
|
+
);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test('returns null for a null secret', () => {
|
|
84
|
+
assert.equal(qcsdk.scryptDeriveKey(null, SALT, N, R, P, DKLEN), null);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test('returns null for a non-string secret', () => {
|
|
88
|
+
assert.equal(qcsdk.scryptDeriveKey(12345, SALT, N, R, P, DKLEN), null);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test('returns null for a null salt', () => {
|
|
92
|
+
assert.equal(qcsdk.scryptDeriveKey('test-passphrase-123', null, N, R, P, DKLEN), null);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test('returns null for a non-array salt', () => {
|
|
96
|
+
assert.equal(qcsdk.scryptDeriveKey('test-passphrase-123', {}, N, R, P, DKLEN), null);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
describe('unsupported parameters return null', () => {
|
|
100
|
+
test('returns null for an unsupported N', () => {
|
|
101
|
+
assert.equal(qcsdk.scryptDeriveKey('test-passphrase-123', SALT, 16384, R, P, DKLEN), null);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test('returns null for an unsupported r', () => {
|
|
105
|
+
assert.equal(qcsdk.scryptDeriveKey('test-passphrase-123', SALT, N, 16, P, DKLEN), null);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
test('returns null for an unsupported p', () => {
|
|
109
|
+
assert.equal(qcsdk.scryptDeriveKey('test-passphrase-123', SALT, N, R, 2, DKLEN), null);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test('returns null for an unsupported dkLen', () => {
|
|
113
|
+
assert.equal(qcsdk.scryptDeriveKey('test-passphrase-123', SALT, N, R, P, 64), null);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test('returns null for a non-number N (null)', () => {
|
|
117
|
+
assert.equal(qcsdk.scryptDeriveKey('test-passphrase-123', SALT, null, R, P, DKLEN), null);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test('returns null for a non-number N (string)', () => {
|
|
121
|
+
assert.equal(qcsdk.scryptDeriveKey('test-passphrase-123', SALT, '262144', R, P, DKLEN), null);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test('returns null when parameters are omitted', () => {
|
|
125
|
+
assert.equal(qcsdk.scryptDeriveKey('test-passphrase-123', SALT), null);
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
});
|