@varnir/signing 0.2.0
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/LICENSE +20 -0
- package/README.md +68 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +93 -0
- package/dist/index.js.map +1 -0
- package/package.json +40 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License (MIT)
|
|
2
|
+
Copyright (c) 2026 Adam Walker
|
|
3
|
+
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# @varnir/signing
|
|
2
|
+
|
|
3
|
+
Key management for Varnir wallets: generate and validate BIP39 recovery
|
|
4
|
+
phrases, derive a secp256k1 key pair from one, and import an already-known
|
|
5
|
+
private key. This package derives and validates key material — it never
|
|
6
|
+
sends a key anywhere. All signing and derivation happen locally, in the
|
|
7
|
+
caller's own process; nothing here talks to a network.
|
|
8
|
+
|
|
9
|
+
## Custody model
|
|
10
|
+
|
|
11
|
+
Everything in this package operates on key material the caller already
|
|
12
|
+
holds in memory. There is no server component, no remote call, and no
|
|
13
|
+
place a private key or recovery phrase is transmitted. A recovery phrase
|
|
14
|
+
generated here, or a private key derived or imported through it, exists
|
|
15
|
+
only for as long as the calling process keeps it — what you do with it
|
|
16
|
+
afterwards (store it, hand it to a signer, discard it) is entirely up to
|
|
17
|
+
the caller. Treat both recovery phrases and private keys as bearer secrets:
|
|
18
|
+
anyone who has one can spend from the wallet it derives.
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install @varnir/signing
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import {
|
|
30
|
+
generateRecoveryPhrase,
|
|
31
|
+
isValidRecoveryPhrase,
|
|
32
|
+
derivePrivateKeyFromPhrase,
|
|
33
|
+
keyPairFromPrivateKeyHex,
|
|
34
|
+
} from '@varnir/signing';
|
|
35
|
+
|
|
36
|
+
const phrase = generateRecoveryPhrase(); // 12-word BIP39 phrase
|
|
37
|
+
isValidRecoveryPhrase(phrase); // true
|
|
38
|
+
|
|
39
|
+
const {privateKeyHex, publicKeyHex} = derivePrivateKeyFromPhrase(phrase);
|
|
40
|
+
|
|
41
|
+
// Or start from an already-known private key instead of a phrase:
|
|
42
|
+
const keyPair = keyPairFromPrivateKeyHex('0x...');
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
- **`generateRecoveryPhrase()`** — a fresh 12-word (128-bit entropy) BIP39
|
|
46
|
+
mnemonic, from the standard English wordlist.
|
|
47
|
+
- **`isValidRecoveryPhrase(phrase)`** / **`normalizeRecoveryPhrase(phrase)`**
|
|
48
|
+
— validate or normalize (trim, lower-case, collapse whitespace) a phrase
|
|
49
|
+
before using it.
|
|
50
|
+
- **`derivePrivateKeyFromPhrase(phrase)`** — BIP32/BIP44 HD derivation
|
|
51
|
+
(`m/44'/1'/0'/0/0`) from the phrase's BIP39 seed, returning a secp256k1
|
|
52
|
+
key pair as `0x`-prefixed hex.
|
|
53
|
+
- **`recoverySeedFromPhrase(phrase)`** — the raw 64-byte BIP39 seed itself,
|
|
54
|
+
for callers (such as `@varnir/chain-client`) that derive other key types
|
|
55
|
+
from the same seed.
|
|
56
|
+
- **`keyPairFromPrivateKeyHex(hex)`** / **`isPrivateKeyHex(value)`** —
|
|
57
|
+
derive the matching public key from an already-known private key, or
|
|
58
|
+
check that a string looks like one, without generating anything new.
|
|
59
|
+
|
|
60
|
+
Built on audited, widely-used primitives: [`@noble/curves`](https://www.npmjs.com/package/@noble/curves)
|
|
61
|
+
for secp256k1, [`@scure/bip32`](https://www.npmjs.com/package/@scure/bip32)
|
|
62
|
+
for HD derivation, and [`bip39`](https://www.npmjs.com/package/bip39) for
|
|
63
|
+
mnemonic generation/validation. Ships as compiled ESM with type
|
|
64
|
+
declarations.
|
|
65
|
+
|
|
66
|
+
## License
|
|
67
|
+
|
|
68
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare const RECOVERY_PHRASE_LENGTH = 12;
|
|
2
|
+
export type KeyPair = {
|
|
3
|
+
privateKeyHex: string;
|
|
4
|
+
publicKeyHex: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function normalizeRecoveryPhrase(phrase: string): string;
|
|
7
|
+
export declare function generateRecoveryPhrase(): string;
|
|
8
|
+
export declare function isValidRecoveryPhrase(phrase: string): boolean;
|
|
9
|
+
export declare function isPrivateKeyHex(value: string): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* The raw 64-byte BIP39 seed for a recovery phrase: `mnemonicToSeedSync` of the
|
|
12
|
+
* normalized phrase, validated first. This is the ONE seed step every key type
|
|
13
|
+
* derives from - the secp256k1 HD key below, and the post-quantum keys derived
|
|
14
|
+
* in `@varnir/chain-client`'s `deriveKeyPairFromPhrase` (which domain-separates
|
|
15
|
+
* by key type on top of this same seed). It is exported so that PQ derivation
|
|
16
|
+
* reuses this exact step rather than duplicating `bip39.mnemonicToSeedSync`.
|
|
17
|
+
*
|
|
18
|
+
* Returned as a plain `Uint8Array` (not a Node `Buffer`) so a consumer without
|
|
19
|
+
* Node builtins - a browser, a Worker - can use it.
|
|
20
|
+
*/
|
|
21
|
+
export declare function recoverySeedFromPhrase(phrase: string): Uint8Array;
|
|
22
|
+
export declare function derivePrivateKeyFromPhrase(phrase: string): KeyPair;
|
|
23
|
+
export declare function keyPairFromPrivateKeyHex(value: string): KeyPair;
|
|
24
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA0BA,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC,MAAM,MAAM,OAAO,GAAG;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAmBF,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAMjE;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAWlE;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAa/D"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// Secure signing tools — key management and transaction signing used by the wallet apps and SDK.
|
|
2
|
+
//
|
|
3
|
+
// BIP39/HD derivation ported from apps/wallet-mobile/src/wallet/keys.ts,
|
|
4
|
+
// where it's already proven to run inside the Expo/React Native runtime
|
|
5
|
+
// (a strictly harder environment than a browser - no Node builtins either
|
|
6
|
+
// way) - not reimplemented, just given a shared home so scanner-web's
|
|
7
|
+
// mini-wallet doesn't duplicate it a third time. wallet-mobile's own copy
|
|
8
|
+
// is untouched; nothing here is wired up to import from this package yet.
|
|
9
|
+
import { secp256k1 } from '@noble/curves/secp256k1';
|
|
10
|
+
import { HDKey } from '@scure/bip32';
|
|
11
|
+
import * as bip39 from 'bip39';
|
|
12
|
+
/**
|
|
13
|
+
* BIP44: purpose 44' / coin type 1' / account 0' / external chain / first address.
|
|
14
|
+
* Coin type 1' is the registered "all testnets" slot; the ledger engine has no
|
|
15
|
+
* registered coin type of its own and this build talks to no chain, so 1' keeps
|
|
16
|
+
* the keys off any production coin's derivation space.
|
|
17
|
+
*/
|
|
18
|
+
const DERIVATION_PATH = "m/44'/1'/0'/0/0";
|
|
19
|
+
/** 128 bits of entropy — a 12 word phrase. */
|
|
20
|
+
const ENTROPY_BITS = 128;
|
|
21
|
+
const WORDLIST = bip39.wordlists.english;
|
|
22
|
+
export const RECOVERY_PHRASE_LENGTH = 12;
|
|
23
|
+
function toPrefixedHex(bytes) {
|
|
24
|
+
let out = '';
|
|
25
|
+
for (const byte of bytes) {
|
|
26
|
+
out += byte.toString(16).padStart(2, '0');
|
|
27
|
+
}
|
|
28
|
+
return `0x${out}`;
|
|
29
|
+
}
|
|
30
|
+
function fromPrefixedHex(value) {
|
|
31
|
+
const body = value.slice(2);
|
|
32
|
+
const bytes = new Uint8Array(body.length / 2);
|
|
33
|
+
for (let i = 0; i < bytes.length; i += 1) {
|
|
34
|
+
bytes[i] = Number.parseInt(body.slice(i * 2, i * 2 + 2), 16);
|
|
35
|
+
}
|
|
36
|
+
return bytes;
|
|
37
|
+
}
|
|
38
|
+
export function normalizeRecoveryPhrase(phrase) {
|
|
39
|
+
return phrase.trim().toLowerCase().split(/\s+/).join(' ');
|
|
40
|
+
}
|
|
41
|
+
export function generateRecoveryPhrase() {
|
|
42
|
+
return bip39.generateMnemonic(ENTROPY_BITS, undefined, WORDLIST);
|
|
43
|
+
}
|
|
44
|
+
export function isValidRecoveryPhrase(phrase) {
|
|
45
|
+
return bip39.validateMnemonic(normalizeRecoveryPhrase(phrase), WORDLIST);
|
|
46
|
+
}
|
|
47
|
+
export function isPrivateKeyHex(value) {
|
|
48
|
+
return /^0x[0-9a-fA-F]{64}$/.test(value.trim());
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The raw 64-byte BIP39 seed for a recovery phrase: `mnemonicToSeedSync` of the
|
|
52
|
+
* normalized phrase, validated first. This is the ONE seed step every key type
|
|
53
|
+
* derives from - the secp256k1 HD key below, and the post-quantum keys derived
|
|
54
|
+
* in `@varnir/chain-client`'s `deriveKeyPairFromPhrase` (which domain-separates
|
|
55
|
+
* by key type on top of this same seed). It is exported so that PQ derivation
|
|
56
|
+
* reuses this exact step rather than duplicating `bip39.mnemonicToSeedSync`.
|
|
57
|
+
*
|
|
58
|
+
* Returned as a plain `Uint8Array` (not a Node `Buffer`) so a consumer without
|
|
59
|
+
* Node builtins - a browser, a Worker - can use it.
|
|
60
|
+
*/
|
|
61
|
+
export function recoverySeedFromPhrase(phrase) {
|
|
62
|
+
const normalized = normalizeRecoveryPhrase(phrase);
|
|
63
|
+
if (!bip39.validateMnemonic(normalized, WORDLIST)) {
|
|
64
|
+
throw new Error('That recovery phrase is not valid.');
|
|
65
|
+
}
|
|
66
|
+
return Uint8Array.from(bip39.mnemonicToSeedSync(normalized));
|
|
67
|
+
}
|
|
68
|
+
export function derivePrivateKeyFromPhrase(phrase) {
|
|
69
|
+
const seed = recoverySeedFromPhrase(phrase);
|
|
70
|
+
const child = HDKey.fromMasterSeed(seed).derive(DERIVATION_PATH);
|
|
71
|
+
if (!child.privateKey || !child.publicKey) {
|
|
72
|
+
throw new Error('Could not derive a key from that recovery phrase.');
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
privateKeyHex: toPrefixedHex(child.privateKey),
|
|
76
|
+
publicKeyHex: toPrefixedHex(child.publicKey),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
export function keyPairFromPrivateKeyHex(value) {
|
|
80
|
+
const trimmed = value.trim();
|
|
81
|
+
if (!isPrivateKeyHex(trimmed)) {
|
|
82
|
+
throw new Error('Enter a 64-character hex key prefixed with 0x.');
|
|
83
|
+
}
|
|
84
|
+
const privateKeyHex = trimmed.toLowerCase();
|
|
85
|
+
try {
|
|
86
|
+
const publicKey = secp256k1.getPublicKey(fromPrefixedHex(privateKeyHex), true);
|
|
87
|
+
return { privateKeyHex, publicKeyHex: toPrefixedHex(publicKey) };
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
throw new Error('That key is not a valid secp256k1 private key.');
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@varnir/signing",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"description": "Secure signing tools — key management and transaction signing used by the wallet apps and SDK.",
|
|
6
|
+
"$comment": "Ships COMPILED output (dist) for the same reason @varnir/chain-client does, and as a precondition of it: chain-client's built dist/index.js imports this package by name, so if this one still resolved to raw .ts, chain-client's build would be unloadable outside a TS-aware bundler - exactly the case shipping dist exists to serve. ESM to match chain-client; src/ has no relative imports, so nothing here needed .js extensions.",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/Varnir/varnir.git",
|
|
10
|
+
"directory": "packages/signing"
|
|
11
|
+
},
|
|
12
|
+
"type": "module",
|
|
13
|
+
"main": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public"
|
|
20
|
+
},
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=20.19.4"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@noble/curves": "^1.9.0",
|
|
26
|
+
"@scure/bip32": "^1.7.0",
|
|
27
|
+
"bip39": "^3.1.0"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"typescript": "^5.7.2",
|
|
31
|
+
"@varnir/tsconfig": "0.1.0"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsc -p tsconfig.json",
|
|
35
|
+
"dev": "tsc -p tsconfig.json --watch --preserveWatchOutput",
|
|
36
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
37
|
+
"lint": "echo \"no lint configured yet\"",
|
|
38
|
+
"clean": "rm -rf dist"
|
|
39
|
+
}
|
|
40
|
+
}
|