@shroud-fi/core 0.1.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 +21 -0
- package/README.md +54 -0
- package/dist/cjs/compute-key.d.ts +24 -0
- package/dist/cjs/compute-key.d.ts.map +1 -0
- package/dist/cjs/compute-key.js +72 -0
- package/dist/cjs/compute-key.js.map +1 -0
- package/dist/cjs/constants.d.ts +20 -0
- package/dist/cjs/constants.d.ts.map +1 -0
- package/dist/cjs/constants.js +23 -0
- package/dist/cjs/constants.js.map +1 -0
- package/dist/cjs/errors.d.ts +35 -0
- package/dist/cjs/errors.d.ts.map +1 -0
- package/dist/cjs/errors.js +48 -0
- package/dist/cjs/errors.js.map +1 -0
- package/dist/cjs/identity.d.ts +20 -0
- package/dist/cjs/identity.d.ts.map +1 -0
- package/dist/cjs/identity.js +38 -0
- package/dist/cjs/identity.js.map +1 -0
- package/dist/cjs/index.d.ts +12 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +36 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/keys.d.ts +17 -0
- package/dist/cjs/keys.d.ts.map +1 -0
- package/dist/cjs/keys.js +51 -0
- package/dist/cjs/keys.js.map +1 -0
- package/dist/cjs/meta-address.d.ts +26 -0
- package/dist/cjs/meta-address.d.ts.map +1 -0
- package/dist/cjs/meta-address.js +86 -0
- package/dist/cjs/meta-address.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/stealth.d.ts +22 -0
- package/dist/cjs/stealth.d.ts.map +1 -0
- package/dist/cjs/stealth.js +100 -0
- package/dist/cjs/stealth.js.map +1 -0
- package/dist/cjs/types.d.ts +46 -0
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/cjs/types.js +9 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/cjs/view-tag.d.ts +29 -0
- package/dist/cjs/view-tag.d.ts.map +1 -0
- package/dist/cjs/view-tag.js +62 -0
- package/dist/cjs/view-tag.js.map +1 -0
- package/dist/esm/compute-key.d.ts +24 -0
- package/dist/esm/compute-key.d.ts.map +1 -0
- package/dist/esm/compute-key.js +69 -0
- package/dist/esm/compute-key.js.map +1 -0
- package/dist/esm/constants.d.ts +20 -0
- package/dist/esm/constants.d.ts.map +1 -0
- package/dist/esm/constants.js +20 -0
- package/dist/esm/constants.js.map +1 -0
- package/dist/esm/errors.d.ts +35 -0
- package/dist/esm/errors.d.ts.map +1 -0
- package/dist/esm/errors.js +41 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/identity.d.ts +20 -0
- package/dist/esm/identity.d.ts.map +1 -0
- package/dist/esm/identity.js +35 -0
- package/dist/esm/identity.js.map +1 -0
- package/dist/esm/index.d.ts +12 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +17 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/keys.d.ts +17 -0
- package/dist/esm/keys.d.ts.map +1 -0
- package/dist/esm/keys.js +48 -0
- package/dist/esm/keys.js.map +1 -0
- package/dist/esm/meta-address.d.ts +26 -0
- package/dist/esm/meta-address.d.ts.map +1 -0
- package/dist/esm/meta-address.js +82 -0
- package/dist/esm/meta-address.js.map +1 -0
- package/dist/esm/stealth.d.ts +22 -0
- package/dist/esm/stealth.d.ts.map +1 -0
- package/dist/esm/stealth.js +97 -0
- package/dist/esm/stealth.js.map +1 -0
- package/dist/esm/types.d.ts +46 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +8 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/view-tag.d.ts +29 -0
- package/dist/esm/view-tag.d.ts.map +1 -0
- package/dist/esm/view-tag.js +58 -0
- package/dist/esm/view-tag.js.map +1 -0
- package/dist/tsconfig.cjs.tsbuildinfo +1 -0
- package/dist/tsconfig.esm.tsbuildinfo +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +63 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ShroudFi contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# @shroud-fi/core
|
|
2
|
+
|
|
3
|
+
> secp256k1 stealth-address identity layer for the ShroudFi privacy SDK.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@shroud-fi/core)
|
|
6
|
+
[](./LICENSE)
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm i @shroud-fi/core viem
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## What it does
|
|
13
|
+
|
|
14
|
+
`@shroud-fi/core` is the identity foundation every other ShroudFi package builds on.
|
|
15
|
+
|
|
16
|
+
- **Deterministic identity** — derives an agent's stealth meta-address (`(spendPub, scanPub)`) from a single 32-byte master seed.
|
|
17
|
+
- **EIP-5564 / 6538 primitives** — canonical Base-network encoding of stealth meta-addresses (`st:base:0x…`), plus the secp256k1 ops used to derive one-time payment addresses.
|
|
18
|
+
- **Constant-time + audited** — built on `@noble/curves` (Cure53-audited) and `@noble/hashes`. Zero new cryptographic surface.
|
|
19
|
+
|
|
20
|
+
The same master seed yields the same meta-address whether you're using the SDK, the MCP server, or the REST API — so an agent's privacy identity is portable across runtimes.
|
|
21
|
+
|
|
22
|
+
## Quick start
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import { deriveAgentIdentity, encodeMetaAddress } from '@shroud-fi/core';
|
|
26
|
+
|
|
27
|
+
const identity = deriveAgentIdentity('0x' + 'a'.repeat(64) /* master seed */);
|
|
28
|
+
|
|
29
|
+
console.log(identity.metaAddressEncoded);
|
|
30
|
+
// → st:base:0x024fa9bb…
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Exports
|
|
34
|
+
|
|
35
|
+
| Symbol | Purpose |
|
|
36
|
+
|---|---|
|
|
37
|
+
| `deriveAgentIdentity(seed)` | Domain-separated identity derivation from a master seed. |
|
|
38
|
+
| `encodeMetaAddress(id)` | Encode spend + scan public keys into the canonical `st:base:0x…` wire format. |
|
|
39
|
+
| `decodeMetaAddress(s)` | Parse `st:base:0x…` into spend + scan pubkeys. |
|
|
40
|
+
| `AgentIdentity` | `{ spendPub, scanPub, metaAddressEncoded, deriveSpendingKey, deriveScanningKey }` |
|
|
41
|
+
|
|
42
|
+
Full API reference: [shroudfi.live/sdk#core](https://shroudfi.live/sdk#core)
|
|
43
|
+
|
|
44
|
+
## Privacy invariants
|
|
45
|
+
|
|
46
|
+
- The **spending key never leaves agent runtime.** No serialization, no logging, no transmission.
|
|
47
|
+
- The **scanning key is separable** — you can delegate it to a scanning service, but never log it alongside identity.
|
|
48
|
+
- **No plaintext keys in error objects.** All `core` errors are structured + key-free.
|
|
49
|
+
|
|
50
|
+
## License
|
|
51
|
+
|
|
52
|
+
MIT — see [LICENSE](./LICENSE).
|
|
53
|
+
|
|
54
|
+
Part of the [ShroudFi](https://shroudfi.live) privacy SDK for AI agents on Base.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stealth Key Computation (Recipient Side)
|
|
3
|
+
*
|
|
4
|
+
* Given the scanning private key, spending private key, and the
|
|
5
|
+
* ephemeral public key from an announcement, derive the stealth
|
|
6
|
+
* private key that controls the stealth address.
|
|
7
|
+
*
|
|
8
|
+
* 1. ECDH: sharedSecret = scanningPrivKey * ephemeralPubKey
|
|
9
|
+
* 2. Hash: hashedSecret = keccak256(compress(sharedSecret))
|
|
10
|
+
* 3. Stealth private key: p_stealth = (spendingPrivKey + hashedSecret) mod n
|
|
11
|
+
*/
|
|
12
|
+
import type { ScanningKey, SpendingKey } from './types.js';
|
|
13
|
+
/**
|
|
14
|
+
* Compute the stealth private key for a detected payment.
|
|
15
|
+
*
|
|
16
|
+
* @param scanningKey - Recipient's scanning private key
|
|
17
|
+
* @param spendingKey - Recipient's spending private key
|
|
18
|
+
* @param ephemeralPubKey - Ephemeral public key from the announcement (33 bytes compressed)
|
|
19
|
+
* @returns 32-byte stealth private key
|
|
20
|
+
* @throws InvalidKeyError if ephemeral public key is invalid
|
|
21
|
+
* @throws StealthAddressError if the derived stealth key is invalid
|
|
22
|
+
*/
|
|
23
|
+
export declare function computeStealthKey(scanningKey: ScanningKey, spendingKey: SpendingKey, ephemeralPubKey: Uint8Array): Uint8Array;
|
|
24
|
+
//# sourceMappingURL=compute-key.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compute-key.d.ts","sourceRoot":"","sources":["../../src/compute-key.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG3D;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,WAAW,EACxB,eAAe,EAAE,UAAU,GAC1B,UAAU,CA6BZ"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Stealth Key Computation (Recipient Side)
|
|
4
|
+
*
|
|
5
|
+
* Given the scanning private key, spending private key, and the
|
|
6
|
+
* ephemeral public key from an announcement, derive the stealth
|
|
7
|
+
* private key that controls the stealth address.
|
|
8
|
+
*
|
|
9
|
+
* 1. ECDH: sharedSecret = scanningPrivKey * ephemeralPubKey
|
|
10
|
+
* 2. Hash: hashedSecret = keccak256(compress(sharedSecret))
|
|
11
|
+
* 3. Stealth private key: p_stealth = (spendingPrivKey + hashedSecret) mod n
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.computeStealthKey = computeStealthKey;
|
|
15
|
+
const secp256k1_1 = require("@noble/curves/secp256k1");
|
|
16
|
+
const sha3_1 = require("@noble/hashes/sha3");
|
|
17
|
+
const errors_js_1 = require("./errors.js");
|
|
18
|
+
/**
|
|
19
|
+
* Compute the stealth private key for a detected payment.
|
|
20
|
+
*
|
|
21
|
+
* @param scanningKey - Recipient's scanning private key
|
|
22
|
+
* @param spendingKey - Recipient's spending private key
|
|
23
|
+
* @param ephemeralPubKey - Ephemeral public key from the announcement (33 bytes compressed)
|
|
24
|
+
* @returns 32-byte stealth private key
|
|
25
|
+
* @throws InvalidKeyError if ephemeral public key is invalid
|
|
26
|
+
* @throws StealthAddressError if the derived stealth key is invalid
|
|
27
|
+
*/
|
|
28
|
+
function computeStealthKey(scanningKey, spendingKey, ephemeralPubKey) {
|
|
29
|
+
// Validate ephemeral public key
|
|
30
|
+
let ephemeralPoint;
|
|
31
|
+
try {
|
|
32
|
+
ephemeralPoint = secp256k1_1.secp256k1.ProjectivePoint.fromHex(ephemeralPubKey);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
throw new errors_js_1.InvalidKeyError('Invalid ephemeral public key');
|
|
36
|
+
}
|
|
37
|
+
// Step 1: ECDH shared secret S = scanningPriv * P_ephemeral
|
|
38
|
+
const scanScalar = bytesToBigInt(scanningKey.bytes);
|
|
39
|
+
const sharedSecretPoint = ephemeralPoint.multiply(scanScalar);
|
|
40
|
+
// Step 2: Hash the compressed shared secret
|
|
41
|
+
const sharedSecretCompressed = sharedSecretPoint.toRawBytes(true); // 33 bytes
|
|
42
|
+
const hashedSecret = (0, sha3_1.keccak_256)(sharedSecretCompressed); // 32 bytes
|
|
43
|
+
// Step 3: Stealth private key = (spendingPriv + hashedSecret) mod n
|
|
44
|
+
const n = secp256k1_1.secp256k1.CURVE.n;
|
|
45
|
+
const spendScalar = bytesToBigInt(spendingKey.bytes);
|
|
46
|
+
const hashedScalar = bytesToBigInt(hashedSecret) % n;
|
|
47
|
+
const stealthScalar = (spendScalar + hashedScalar) % n;
|
|
48
|
+
if (stealthScalar === 0n) {
|
|
49
|
+
throw new errors_js_1.StealthAddressError('Derived stealth key is zero');
|
|
50
|
+
}
|
|
51
|
+
// Convert BigInt back to 32-byte Uint8Array (big-endian)
|
|
52
|
+
return bigIntToBytes(stealthScalar, 32);
|
|
53
|
+
}
|
|
54
|
+
/** Convert a Uint8Array to a BigInt (big-endian). */
|
|
55
|
+
function bytesToBigInt(bytes) {
|
|
56
|
+
let result = 0n;
|
|
57
|
+
for (const byte of bytes) {
|
|
58
|
+
result = (result << 8n) | BigInt(byte);
|
|
59
|
+
}
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
/** Convert a BigInt to a fixed-length Uint8Array (big-endian). */
|
|
63
|
+
function bigIntToBytes(value, length) {
|
|
64
|
+
const result = new Uint8Array(length);
|
|
65
|
+
let remaining = value;
|
|
66
|
+
for (let i = length - 1; i >= 0; i--) {
|
|
67
|
+
result[i] = Number(remaining & 0xffn);
|
|
68
|
+
remaining >>= 8n;
|
|
69
|
+
}
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=compute-key.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compute-key.js","sourceRoot":"","sources":["../../src/compute-key.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;AAiBH,8CAiCC;AAhDD,uDAAoD;AACpD,6CAAgD;AAEhD,2CAAmE;AAEnE;;;;;;;;;GASG;AACH,SAAgB,iBAAiB,CAC/B,WAAwB,EACxB,WAAwB,EACxB,eAA2B;IAE3B,gCAAgC;IAChC,IAAI,cAA8D,CAAC;IACnE,IAAI,CAAC;QACH,cAAc,GAAG,qBAAS,CAAC,eAAe,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IACtE,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,2BAAe,CAAC,8BAA8B,CAAC,CAAC;IAC5D,CAAC;IAED,6DAA6D;IAC7D,MAAM,UAAU,GAAG,aAAa,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,iBAAiB,GAAG,cAAc,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAE9D,4CAA4C;IAC5C,MAAM,sBAAsB,GAAG,iBAAiB,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW;IAC9E,MAAM,YAAY,GAAG,IAAA,iBAAU,EAAC,sBAAsB,CAAC,CAAC,CAAC,WAAW;IAEpE,oEAAoE;IACpE,MAAM,CAAC,GAAG,qBAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5B,MAAM,WAAW,GAAG,aAAa,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IACrD,MAAM,YAAY,GAAG,aAAa,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IACrD,MAAM,aAAa,GAAG,CAAC,WAAW,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IAEvD,IAAI,aAAa,KAAK,EAAE,EAAE,CAAC;QACzB,MAAM,IAAI,+BAAmB,CAAC,6BAA6B,CAAC,CAAC;IAC/D,CAAC;IAED,yDAAyD;IACzD,OAAO,aAAa,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED,qDAAqD;AACrD,SAAS,aAAa,CAAC,KAAiB;IACtC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,kEAAkE;AAClE,SAAS,aAAa,CAAC,KAAa,EAAE,MAAc;IAClD,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IACtC,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,KAAK,IAAI,CAAC,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC,CAAC;QACtC,SAAS,KAAK,EAAE,CAAC;IACnB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ShroudFi Core Constants
|
|
3
|
+
*
|
|
4
|
+
* EIP-5564 / ERC-6538 scheme configuration for Base (EVM).
|
|
5
|
+
*/
|
|
6
|
+
/** EIP-5564 scheme ID for secp256k1 + view tags. */
|
|
7
|
+
export declare const SCHEME_ID = 1;
|
|
8
|
+
/** HKDF salt used for all key derivation from master seed. */
|
|
9
|
+
export declare const HKDF_SALT = "ShroudFi-EVM-v1";
|
|
10
|
+
/**
|
|
11
|
+
* ERC-5564 Announcer singleton address.
|
|
12
|
+
* Deterministic CREATE2 deployment -- same address on every EVM chain including Base.
|
|
13
|
+
*/
|
|
14
|
+
export declare const ERC5564_ANNOUNCER_ADDRESS: "0x55649E01B5Df198D18D95b5cc5051630cfD45564";
|
|
15
|
+
/**
|
|
16
|
+
* ERC-6538 Stealth Meta-Address Registry singleton address.
|
|
17
|
+
* Deterministic CREATE2 deployment -- same address on every EVM chain including Base.
|
|
18
|
+
*/
|
|
19
|
+
export declare const ERC6538_REGISTRY_ADDRESS: "0x6538E6bf4B0eBd30A8Ea093027Ac2422ce5d6538";
|
|
20
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,oDAAoD;AACpD,eAAO,MAAM,SAAS,IAAI,CAAC;AAE3B,8DAA8D;AAC9D,eAAO,MAAM,SAAS,oBAAoB,CAAC;AAE3C;;;GAGG;AACH,eAAO,MAAM,yBAAyB,EACpC,4CAAqD,CAAC;AAExD;;;GAGG;AACH,eAAO,MAAM,wBAAwB,EACnC,4CAAqD,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ShroudFi Core Constants
|
|
4
|
+
*
|
|
5
|
+
* EIP-5564 / ERC-6538 scheme configuration for Base (EVM).
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.ERC6538_REGISTRY_ADDRESS = exports.ERC5564_ANNOUNCER_ADDRESS = exports.HKDF_SALT = exports.SCHEME_ID = void 0;
|
|
9
|
+
/** EIP-5564 scheme ID for secp256k1 + view tags. */
|
|
10
|
+
exports.SCHEME_ID = 1;
|
|
11
|
+
/** HKDF salt used for all key derivation from master seed. */
|
|
12
|
+
exports.HKDF_SALT = 'ShroudFi-EVM-v1';
|
|
13
|
+
/**
|
|
14
|
+
* ERC-5564 Announcer singleton address.
|
|
15
|
+
* Deterministic CREATE2 deployment -- same address on every EVM chain including Base.
|
|
16
|
+
*/
|
|
17
|
+
exports.ERC5564_ANNOUNCER_ADDRESS = '0x55649E01B5Df198D18D95b5cc5051630cfD45564';
|
|
18
|
+
/**
|
|
19
|
+
* ERC-6538 Stealth Meta-Address Registry singleton address.
|
|
20
|
+
* Deterministic CREATE2 deployment -- same address on every EVM chain including Base.
|
|
21
|
+
*/
|
|
22
|
+
exports.ERC6538_REGISTRY_ADDRESS = '0x6538E6bf4B0eBd30A8Ea093027Ac2422ce5d6538';
|
|
23
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEH,oDAAoD;AACvC,QAAA,SAAS,GAAG,CAAC,CAAC;AAE3B,8DAA8D;AACjD,QAAA,SAAS,GAAG,iBAAiB,CAAC;AAE3C;;;GAGG;AACU,QAAA,yBAAyB,GACpC,4CAAqD,CAAC;AAExD;;;GAGG;AACU,QAAA,wBAAwB,GACnC,4CAAqD,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ShroudFi Privacy-Safe Error Hierarchy
|
|
3
|
+
*
|
|
4
|
+
* Rules:
|
|
5
|
+
* - NEVER include private keys, seeds, or scalars in error messages.
|
|
6
|
+
* - NEVER include amounts or balances.
|
|
7
|
+
* - NEVER include stealth addresses or ephemeral keys.
|
|
8
|
+
* - Safe to include: error codes, generic descriptions.
|
|
9
|
+
*/
|
|
10
|
+
/** Base error for all ShroudFi operations. */
|
|
11
|
+
export declare class ShroudFiError extends Error {
|
|
12
|
+
readonly code: string;
|
|
13
|
+
constructor(code: string, message: string);
|
|
14
|
+
}
|
|
15
|
+
/** Thrown when a private or public key fails validation. */
|
|
16
|
+
export declare class InvalidKeyError extends ShroudFiError {
|
|
17
|
+
constructor(message?: string);
|
|
18
|
+
}
|
|
19
|
+
/** Thrown when a stealth meta-address cannot be parsed or is malformed. */
|
|
20
|
+
export declare class InvalidMetaAddressError extends ShroudFiError {
|
|
21
|
+
constructor(message?: string);
|
|
22
|
+
}
|
|
23
|
+
/** Thrown when stealth address generation or verification fails. */
|
|
24
|
+
export declare class StealthAddressError extends ShroudFiError {
|
|
25
|
+
constructor(message?: string);
|
|
26
|
+
}
|
|
27
|
+
/** Discriminated union result type -- avoids throwing for sensitive operations. */
|
|
28
|
+
export type Result<T> = {
|
|
29
|
+
readonly ok: true;
|
|
30
|
+
readonly value: T;
|
|
31
|
+
} | {
|
|
32
|
+
readonly ok: false;
|
|
33
|
+
readonly error: ShroudFiError;
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,8CAA8C;AAC9C,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAM1C;AAED,4DAA4D;AAC5D,qBAAa,eAAgB,SAAQ,aAAa;gBACpC,OAAO,GAAE,MAA+B;CAIrD;AAED,2EAA2E;AAC3E,qBAAa,uBAAwB,SAAQ,aAAa;gBAC5C,OAAO,GAAE,MAAuC;CAI7D;AAED,oEAAoE;AACpE,qBAAa,mBAAoB,SAAQ,aAAa;gBACxC,OAAO,GAAE,MAA2C;CAIjE;AAED,mFAAmF;AACnF,MAAM,MAAM,MAAM,CAAC,CAAC,IAChB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GACxC;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAA;CAAE,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ShroudFi Privacy-Safe Error Hierarchy
|
|
4
|
+
*
|
|
5
|
+
* Rules:
|
|
6
|
+
* - NEVER include private keys, seeds, or scalars in error messages.
|
|
7
|
+
* - NEVER include amounts or balances.
|
|
8
|
+
* - NEVER include stealth addresses or ephemeral keys.
|
|
9
|
+
* - Safe to include: error codes, generic descriptions.
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.StealthAddressError = exports.InvalidMetaAddressError = exports.InvalidKeyError = exports.ShroudFiError = void 0;
|
|
13
|
+
/** Base error for all ShroudFi operations. */
|
|
14
|
+
class ShroudFiError extends Error {
|
|
15
|
+
code;
|
|
16
|
+
constructor(code, message) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.code = code;
|
|
19
|
+
this.name = 'ShroudFiError';
|
|
20
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.ShroudFiError = ShroudFiError;
|
|
24
|
+
/** Thrown when a private or public key fails validation. */
|
|
25
|
+
class InvalidKeyError extends ShroudFiError {
|
|
26
|
+
constructor(message = 'Invalid key material') {
|
|
27
|
+
super('INVALID_KEY', message);
|
|
28
|
+
this.name = 'InvalidKeyError';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.InvalidKeyError = InvalidKeyError;
|
|
32
|
+
/** Thrown when a stealth meta-address cannot be parsed or is malformed. */
|
|
33
|
+
class InvalidMetaAddressError extends ShroudFiError {
|
|
34
|
+
constructor(message = 'Invalid stealth meta-address') {
|
|
35
|
+
super('INVALID_META_ADDRESS', message);
|
|
36
|
+
this.name = 'InvalidMetaAddressError';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.InvalidMetaAddressError = InvalidMetaAddressError;
|
|
40
|
+
/** Thrown when stealth address generation or verification fails. */
|
|
41
|
+
class StealthAddressError extends ShroudFiError {
|
|
42
|
+
constructor(message = 'Stealth address operation failed') {
|
|
43
|
+
super('STEALTH_ADDRESS_ERROR', message);
|
|
44
|
+
this.name = 'StealthAddressError';
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
exports.StealthAddressError = StealthAddressError;
|
|
48
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAEH,8CAA8C;AAC9C,MAAa,aAAc,SAAQ,KAAK;IAC7B,IAAI,CAAS;IAEtB,YAAY,IAAY,EAAE,OAAe;QACvC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;QAC5B,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;CACF;AATD,sCASC;AAED,4DAA4D;AAC5D,MAAa,eAAgB,SAAQ,aAAa;IAChD,YAAY,UAAkB,sBAAsB;QAClD,KAAK,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AALD,0CAKC;AAED,2EAA2E;AAC3E,MAAa,uBAAwB,SAAQ,aAAa;IACxD,YAAY,UAAkB,8BAA8B;QAC1D,KAAK,CAAC,sBAAsB,EAAE,OAAO,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AALD,0DAKC;AAED,oEAAoE;AACpE,MAAa,mBAAoB,SAAQ,aAAa;IACpD,YAAY,UAAkB,kCAAkC;QAC9D,KAAK,CAAC,uBAAuB,EAAE,OAAO,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AALD,kDAKC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Identity Factory
|
|
3
|
+
*
|
|
4
|
+
* Creates a complete ShroudFi agent identity (key hierarchy + meta-address)
|
|
5
|
+
* from an optional master seed. If no seed is provided, generates 32
|
|
6
|
+
* cryptographically random bytes via crypto.getRandomValues.
|
|
7
|
+
*/
|
|
8
|
+
import type { KeyHierarchy, StealthMetaAddress } from './types.js';
|
|
9
|
+
export interface AgentIdentity {
|
|
10
|
+
readonly keys: KeyHierarchy;
|
|
11
|
+
readonly metaAddress: StealthMetaAddress;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Create a full agent identity with key hierarchy and meta-address.
|
|
15
|
+
*
|
|
16
|
+
* @param masterSeed - Optional 32-byte seed. If omitted, generates random bytes.
|
|
17
|
+
* @returns AgentIdentity with derived keys and meta-address
|
|
18
|
+
*/
|
|
19
|
+
export declare function createAgentIdentity(masterSeed?: Uint8Array): AgentIdentity;
|
|
20
|
+
//# sourceMappingURL=identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/identity.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAInE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,kBAAkB,CAAC;CAC1C;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,CAAC,EAAE,UAAU,GAAG,aAAa,CAmB1E"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Agent Identity Factory
|
|
4
|
+
*
|
|
5
|
+
* Creates a complete ShroudFi agent identity (key hierarchy + meta-address)
|
|
6
|
+
* from an optional master seed. If no seed is provided, generates 32
|
|
7
|
+
* cryptographically random bytes via crypto.getRandomValues.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.createAgentIdentity = createAgentIdentity;
|
|
11
|
+
const secp256k1_1 = require("@noble/curves/secp256k1");
|
|
12
|
+
const utils_1 = require("@noble/hashes/utils");
|
|
13
|
+
const keys_js_1 = require("./keys.js");
|
|
14
|
+
const constants_js_1 = require("./constants.js");
|
|
15
|
+
/**
|
|
16
|
+
* Create a full agent identity with key hierarchy and meta-address.
|
|
17
|
+
*
|
|
18
|
+
* @param masterSeed - Optional 32-byte seed. If omitted, generates random bytes.
|
|
19
|
+
* @returns AgentIdentity with derived keys and meta-address
|
|
20
|
+
*/
|
|
21
|
+
function createAgentIdentity(masterSeed) {
|
|
22
|
+
const seed = masterSeed ?? (0, utils_1.randomBytes)(32);
|
|
23
|
+
const keys = (0, keys_js_1.deriveKeys)(seed);
|
|
24
|
+
// Derive compressed public keys from the private keys.
|
|
25
|
+
// EIP-5564 scheme 1 has only spending + viewing keys, where "viewing" is the
|
|
26
|
+
// key used for ECDH scanning. In the @shroud-fi/core hierarchy we name that
|
|
27
|
+
// ECDH-scan key `scanningKey` (its semantic role). The separate `viewingKey`
|
|
28
|
+
// is reserved for future compliance/delegated-disclosure flows.
|
|
29
|
+
const spendingPubKey = secp256k1_1.secp256k1.getPublicKey(keys.spendingKey.bytes, true);
|
|
30
|
+
const viewingPubKey = secp256k1_1.secp256k1.getPublicKey(keys.scanningKey.bytes, true);
|
|
31
|
+
const metaAddress = {
|
|
32
|
+
spendingPubKey,
|
|
33
|
+
viewingPubKey,
|
|
34
|
+
schemeId: constants_js_1.SCHEME_ID,
|
|
35
|
+
};
|
|
36
|
+
return { keys, metaAddress };
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/identity.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAmBH,kDAmBC;AApCD,uDAAoD;AACpD,+CAAkD;AAElD,uCAAuC;AACvC,iDAA2C;AAO3C;;;;;GAKG;AACH,SAAgB,mBAAmB,CAAC,UAAuB;IACzD,MAAM,IAAI,GAAG,UAAU,IAAI,IAAA,mBAAW,EAAC,EAAE,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,IAAA,oBAAU,EAAC,IAAI,CAAC,CAAC;IAE9B,uDAAuD;IACvD,6EAA6E;IAC7E,4EAA4E;IAC5E,6EAA6E;IAC7E,gEAAgE;IAChE,MAAM,cAAc,GAAG,qBAAS,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC5E,MAAM,aAAa,GAAG,qBAAS,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAE3E,MAAM,WAAW,GAAuB;QACtC,cAAc;QACd,aAAa;QACb,QAAQ,EAAE,wBAAS;KACpB,CAAC;IAEF,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type { SpendingKey, ScanningKey, ViewingKey, StealthMetaAddress, StealthAddressResult, KeyHierarchy, } from './types.js';
|
|
2
|
+
export { ShroudFiError, InvalidKeyError, InvalidMetaAddressError, StealthAddressError, } from './errors.js';
|
|
3
|
+
export type { Result } from './errors.js';
|
|
4
|
+
export { SCHEME_ID, HKDF_SALT, ERC5564_ANNOUNCER_ADDRESS, ERC6538_REGISTRY_ADDRESS, } from './constants.js';
|
|
5
|
+
export { deriveKeys } from './keys.js';
|
|
6
|
+
export { generateStealthAddress } from './stealth.js';
|
|
7
|
+
export { computeStealthKey } from './compute-key.js';
|
|
8
|
+
export { extractViewTag, checkViewTag } from './view-tag.js';
|
|
9
|
+
export { encodeMetaAddress, decodeMetaAddress } from './meta-address.js';
|
|
10
|
+
export { createAgentIdentity } from './identity.js';
|
|
11
|
+
export type { AgentIdentity } from './identity.js';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,WAAW,EACX,WAAW,EACX,UAAU,EACV,kBAAkB,EAClB,oBAAoB,EACpB,YAAY,GACb,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,aAAa,EACb,eAAe,EACf,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAG1C,OAAO,EACL,SAAS,EACT,SAAS,EACT,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAGvC,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAGtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGrD,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAG7D,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAGzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createAgentIdentity = exports.decodeMetaAddress = exports.encodeMetaAddress = exports.checkViewTag = exports.extractViewTag = exports.computeStealthKey = exports.generateStealthAddress = exports.deriveKeys = exports.ERC6538_REGISTRY_ADDRESS = exports.ERC5564_ANNOUNCER_ADDRESS = exports.HKDF_SALT = exports.SCHEME_ID = exports.StealthAddressError = exports.InvalidMetaAddressError = exports.InvalidKeyError = exports.ShroudFiError = void 0;
|
|
4
|
+
// Errors
|
|
5
|
+
var errors_js_1 = require("./errors.js");
|
|
6
|
+
Object.defineProperty(exports, "ShroudFiError", { enumerable: true, get: function () { return errors_js_1.ShroudFiError; } });
|
|
7
|
+
Object.defineProperty(exports, "InvalidKeyError", { enumerable: true, get: function () { return errors_js_1.InvalidKeyError; } });
|
|
8
|
+
Object.defineProperty(exports, "InvalidMetaAddressError", { enumerable: true, get: function () { return errors_js_1.InvalidMetaAddressError; } });
|
|
9
|
+
Object.defineProperty(exports, "StealthAddressError", { enumerable: true, get: function () { return errors_js_1.StealthAddressError; } });
|
|
10
|
+
// Constants
|
|
11
|
+
var constants_js_1 = require("./constants.js");
|
|
12
|
+
Object.defineProperty(exports, "SCHEME_ID", { enumerable: true, get: function () { return constants_js_1.SCHEME_ID; } });
|
|
13
|
+
Object.defineProperty(exports, "HKDF_SALT", { enumerable: true, get: function () { return constants_js_1.HKDF_SALT; } });
|
|
14
|
+
Object.defineProperty(exports, "ERC5564_ANNOUNCER_ADDRESS", { enumerable: true, get: function () { return constants_js_1.ERC5564_ANNOUNCER_ADDRESS; } });
|
|
15
|
+
Object.defineProperty(exports, "ERC6538_REGISTRY_ADDRESS", { enumerable: true, get: function () { return constants_js_1.ERC6538_REGISTRY_ADDRESS; } });
|
|
16
|
+
// Key derivation
|
|
17
|
+
var keys_js_1 = require("./keys.js");
|
|
18
|
+
Object.defineProperty(exports, "deriveKeys", { enumerable: true, get: function () { return keys_js_1.deriveKeys; } });
|
|
19
|
+
// Stealth address generation (sender side)
|
|
20
|
+
var stealth_js_1 = require("./stealth.js");
|
|
21
|
+
Object.defineProperty(exports, "generateStealthAddress", { enumerable: true, get: function () { return stealth_js_1.generateStealthAddress; } });
|
|
22
|
+
// Stealth key computation (recipient side)
|
|
23
|
+
var compute_key_js_1 = require("./compute-key.js");
|
|
24
|
+
Object.defineProperty(exports, "computeStealthKey", { enumerable: true, get: function () { return compute_key_js_1.computeStealthKey; } });
|
|
25
|
+
// View tag utilities
|
|
26
|
+
var view_tag_js_1 = require("./view-tag.js");
|
|
27
|
+
Object.defineProperty(exports, "extractViewTag", { enumerable: true, get: function () { return view_tag_js_1.extractViewTag; } });
|
|
28
|
+
Object.defineProperty(exports, "checkViewTag", { enumerable: true, get: function () { return view_tag_js_1.checkViewTag; } });
|
|
29
|
+
// Meta-address encode/decode
|
|
30
|
+
var meta_address_js_1 = require("./meta-address.js");
|
|
31
|
+
Object.defineProperty(exports, "encodeMetaAddress", { enumerable: true, get: function () { return meta_address_js_1.encodeMetaAddress; } });
|
|
32
|
+
Object.defineProperty(exports, "decodeMetaAddress", { enumerable: true, get: function () { return meta_address_js_1.decodeMetaAddress; } });
|
|
33
|
+
// Agent identity factory
|
|
34
|
+
var identity_js_1 = require("./identity.js");
|
|
35
|
+
Object.defineProperty(exports, "createAgentIdentity", { enumerable: true, get: function () { return identity_js_1.createAgentIdentity; } });
|
|
36
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAUA,SAAS;AACT,yCAKqB;AAJnB,0GAAA,aAAa,OAAA;AACb,4GAAA,eAAe,OAAA;AACf,oHAAA,uBAAuB,OAAA;AACvB,gHAAA,mBAAmB,OAAA;AAIrB,YAAY;AACZ,+CAKwB;AAJtB,yGAAA,SAAS,OAAA;AACT,yGAAA,SAAS,OAAA;AACT,yHAAA,yBAAyB,OAAA;AACzB,wHAAA,wBAAwB,OAAA;AAG1B,iBAAiB;AACjB,qCAAuC;AAA9B,qGAAA,UAAU,OAAA;AAEnB,2CAA2C;AAC3C,2CAAsD;AAA7C,oHAAA,sBAAsB,OAAA;AAE/B,2CAA2C;AAC3C,mDAAqD;AAA5C,mHAAA,iBAAiB,OAAA;AAE1B,qBAAqB;AACrB,6CAA6D;AAApD,6GAAA,cAAc,OAAA;AAAE,2GAAA,YAAY,OAAA;AAErC,6BAA6B;AAC7B,qDAAyE;AAAhE,oHAAA,iBAAiB,OAAA;AAAE,oHAAA,iBAAiB,OAAA;AAE7C,yBAAyB;AACzB,6CAAoD;AAA3C,kHAAA,mBAAmB,OAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Key Derivation -- HKDF-SHA256
|
|
3
|
+
*
|
|
4
|
+
* Derives a full KeyHierarchy from a 32-byte master seed using
|
|
5
|
+
* HKDF with domain-separated info labels. Each derived key is
|
|
6
|
+
* validated as a valid secp256k1 scalar (1 < k < n).
|
|
7
|
+
*/
|
|
8
|
+
import type { KeyHierarchy } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Derive the full ShroudFi key hierarchy from a master seed.
|
|
11
|
+
*
|
|
12
|
+
* @param masterSeed - 32-byte cryptographically random seed
|
|
13
|
+
* @returns KeyHierarchy with spending, scanning, and viewing keys
|
|
14
|
+
* @throws InvalidKeyError if seed length is wrong or a derived key is invalid
|
|
15
|
+
*/
|
|
16
|
+
export declare function deriveKeys(masterSeed: Uint8Array): KeyHierarchy;
|
|
17
|
+
//# sourceMappingURL=keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../src/keys.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAwC,MAAM,YAAY,CAAC;AAiBrF;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,UAAU,GAAG,YAAY,CAmB/D"}
|
package/dist/cjs/keys.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Key Derivation -- HKDF-SHA256
|
|
4
|
+
*
|
|
5
|
+
* Derives a full KeyHierarchy from a 32-byte master seed using
|
|
6
|
+
* HKDF with domain-separated info labels. Each derived key is
|
|
7
|
+
* validated as a valid secp256k1 scalar (1 < k < n).
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.deriveKeys = deriveKeys;
|
|
11
|
+
const hkdf_1 = require("@noble/hashes/hkdf");
|
|
12
|
+
const sha256_1 = require("@noble/hashes/sha256");
|
|
13
|
+
const secp256k1_1 = require("@noble/curves/secp256k1");
|
|
14
|
+
const errors_js_1 = require("./errors.js");
|
|
15
|
+
const constants_js_1 = require("./constants.js");
|
|
16
|
+
/**
|
|
17
|
+
* Validate that a 32-byte array is a valid secp256k1 private key scalar.
|
|
18
|
+
* Must satisfy: 1 <= k < n (curve order).
|
|
19
|
+
*/
|
|
20
|
+
function assertValidScalar(bytes, label) {
|
|
21
|
+
if (bytes.length !== 32) {
|
|
22
|
+
throw new errors_js_1.InvalidKeyError(`Derived ${label} has invalid length`);
|
|
23
|
+
}
|
|
24
|
+
if (!secp256k1_1.secp256k1.utils.isValidPrivateKey(bytes)) {
|
|
25
|
+
throw new errors_js_1.InvalidKeyError(`Derived ${label} is not a valid secp256k1 scalar`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Derive the full ShroudFi key hierarchy from a master seed.
|
|
30
|
+
*
|
|
31
|
+
* @param masterSeed - 32-byte cryptographically random seed
|
|
32
|
+
* @returns KeyHierarchy with spending, scanning, and viewing keys
|
|
33
|
+
* @throws InvalidKeyError if seed length is wrong or a derived key is invalid
|
|
34
|
+
*/
|
|
35
|
+
function deriveKeys(masterSeed) {
|
|
36
|
+
if (masterSeed.length !== 32) {
|
|
37
|
+
throw new errors_js_1.InvalidKeyError('Master seed must be exactly 32 bytes');
|
|
38
|
+
}
|
|
39
|
+
const spendingBytes = (0, hkdf_1.hkdf)(sha256_1.sha256, masterSeed, constants_js_1.HKDF_SALT, 'spending-key', 32);
|
|
40
|
+
assertValidScalar(spendingBytes, 'spending key');
|
|
41
|
+
const scanningBytes = (0, hkdf_1.hkdf)(sha256_1.sha256, masterSeed, constants_js_1.HKDF_SALT, 'scanning-key', 32);
|
|
42
|
+
assertValidScalar(scanningBytes, 'scanning key');
|
|
43
|
+
const viewingBytes = (0, hkdf_1.hkdf)(sha256_1.sha256, masterSeed, constants_js_1.HKDF_SALT, 'viewing-key', 32);
|
|
44
|
+
assertValidScalar(viewingBytes, 'viewing key');
|
|
45
|
+
return {
|
|
46
|
+
spendingKey: { __brand: 'SpendingKey', bytes: spendingBytes },
|
|
47
|
+
scanningKey: { __brand: 'ScanningKey', bytes: scanningBytes },
|
|
48
|
+
viewingKey: { __brand: 'ViewingKey', bytes: viewingBytes },
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../../src/keys.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AA6BH,gCAmBC;AA9CD,6CAA0C;AAC1C,iDAA8C;AAC9C,uDAAoD;AAEpD,2CAA8C;AAC9C,iDAA2C;AAE3C;;;GAGG;AACH,SAAS,iBAAiB,CAAC,KAAiB,EAAE,KAAa;IACzD,IAAI,KAAK,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QACxB,MAAM,IAAI,2BAAe,CAAC,WAAW,KAAK,qBAAqB,CAAC,CAAC;IACnE,CAAC;IACD,IAAI,CAAC,qBAAS,CAAC,KAAK,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,2BAAe,CAAC,WAAW,KAAK,kCAAkC,CAAC,CAAC;IAChF,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,UAAU,CAAC,UAAsB;IAC/C,IAAI,UAAU,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QAC7B,MAAM,IAAI,2BAAe,CAAC,sCAAsC,CAAC,CAAC;IACpE,CAAC;IAED,MAAM,aAAa,GAAG,IAAA,WAAI,EAAC,eAAM,EAAE,UAAU,EAAE,wBAAS,EAAE,cAAc,EAAE,EAAE,CAAC,CAAC;IAC9E,iBAAiB,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;IAEjD,MAAM,aAAa,GAAG,IAAA,WAAI,EAAC,eAAM,EAAE,UAAU,EAAE,wBAAS,EAAE,cAAc,EAAE,EAAE,CAAC,CAAC;IAC9E,iBAAiB,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;IAEjD,MAAM,YAAY,GAAG,IAAA,WAAI,EAAC,eAAM,EAAE,UAAU,EAAE,wBAAS,EAAE,aAAa,EAAE,EAAE,CAAC,CAAC;IAC5E,iBAAiB,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;IAE/C,OAAO;QACL,WAAW,EAAE,EAAE,OAAO,EAAE,aAAsB,EAAE,KAAK,EAAE,aAAa,EAAiB;QACrF,WAAW,EAAE,EAAE,OAAO,EAAE,aAAsB,EAAE,KAAK,EAAE,aAAa,EAAiB;QACrF,UAAU,EAAE,EAAE,OAAO,EAAE,YAAqB,EAAE,KAAK,EAAE,YAAY,EAAgB;KAClF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ERC-6538 Stealth Meta-Address Encode/Decode
|
|
3
|
+
*
|
|
4
|
+
* Format: st:base:0x<spendingPubKey 33 bytes hex><viewingPubKey 33 bytes hex>
|
|
5
|
+
*
|
|
6
|
+
* Both keys are SEC1 compressed secp256k1 public keys (prefix 0x02 or 0x03).
|
|
7
|
+
* Total raw payload: 66 bytes = 132 hex characters.
|
|
8
|
+
*/
|
|
9
|
+
import type { StealthMetaAddress } from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Encode a StealthMetaAddress into the ERC-6538 URI format.
|
|
12
|
+
*
|
|
13
|
+
* @param meta - Stealth meta-address containing spending and viewing public keys
|
|
14
|
+
* @returns Encoded string: "st:base:0x<spendHex><viewHex>"
|
|
15
|
+
* @throws InvalidMetaAddressError if keys are invalid
|
|
16
|
+
*/
|
|
17
|
+
export declare function encodeMetaAddress(meta: StealthMetaAddress): string;
|
|
18
|
+
/**
|
|
19
|
+
* Decode an ERC-6538 URI string into a StealthMetaAddress.
|
|
20
|
+
*
|
|
21
|
+
* @param encoded - String in format "st:base:0x<66 bytes hex>"
|
|
22
|
+
* @returns Parsed StealthMetaAddress
|
|
23
|
+
* @throws InvalidMetaAddressError if format is invalid
|
|
24
|
+
*/
|
|
25
|
+
export declare function decodeMetaAddress(encoded: string): StealthMetaAddress;
|
|
26
|
+
//# sourceMappingURL=meta-address.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meta-address.d.ts","sourceRoot":"","sources":["../../src/meta-address.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAgCrD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAQlE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,kBAAkB,CAiCrE"}
|