@ibgib/core-gib 0.1.42 → 0.1.44
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/dist/keystone/kdf/kdf-constants.d.mts +25 -0
- package/dist/keystone/kdf/kdf-constants.d.mts.map +1 -0
- package/dist/keystone/kdf/kdf-constants.mjs +28 -0
- package/dist/keystone/kdf/kdf-constants.mjs.map +1 -0
- package/dist/keystone/kdf/kdf-helpers.d.mts +45 -0
- package/dist/keystone/kdf/kdf-helpers.d.mts.map +1 -0
- package/dist/keystone/kdf/kdf-helpers.mjs +94 -0
- package/dist/keystone/kdf/kdf-helpers.mjs.map +1 -0
- package/dist/keystone/kdf/kdf-types.d.mts +49 -0
- package/dist/keystone/kdf/kdf-types.d.mts.map +1 -0
- package/dist/keystone/kdf/kdf-types.mjs +2 -0
- package/dist/keystone/kdf/kdf-types.mjs.map +1 -0
- package/dist/keystone/keystone-config-builder.d.mts +65 -12
- package/dist/keystone/keystone-config-builder.d.mts.map +1 -1
- package/dist/keystone/keystone-config-builder.mjs +138 -46
- package/dist/keystone/keystone-config-builder.mjs.map +1 -1
- package/dist/keystone/keystone-config-builder.respec.mjs +21 -13
- package/dist/keystone/keystone-config-builder.respec.mjs.map +1 -1
- package/dist/keystone/keystone-constants.d.mts +15 -0
- package/dist/keystone/keystone-constants.d.mts.map +1 -1
- package/dist/keystone/keystone-constants.mjs +16 -0
- package/dist/keystone/keystone-constants.mjs.map +1 -1
- package/dist/keystone/keystone-helpers.d.mts +4 -4
- package/dist/keystone/keystone-helpers.d.mts.map +1 -1
- package/dist/keystone/keystone-helpers.mjs +8 -5
- package/dist/keystone/keystone-helpers.mjs.map +1 -1
- package/dist/keystone/keystone-service-v1.d.mts +1 -1
- package/dist/keystone/keystone-service-v1.d.mts.map +1 -1
- package/dist/keystone/keystone-service-v1.mjs +6 -5
- package/dist/keystone/keystone-service-v1.mjs.map +1 -1
- package/dist/keystone/keystone-service-v1.respec.mjs +72 -45
- package/dist/keystone/keystone-service-v1.respec.mjs.map +1 -1
- package/dist/keystone/keystone-types.d.mts +28 -18
- package/dist/keystone/keystone-types.d.mts.map +1 -1
- package/dist/keystone/keystone-types.mjs +26 -15
- package/dist/keystone/keystone-types.mjs.map +1 -1
- package/dist/keystone/strategy/hash-reveal-v1/hash-reveal-v1.d.mts.map +1 -1
- package/dist/keystone/strategy/hash-reveal-v1/hash-reveal-v1.mjs +7 -10
- package/dist/keystone/strategy/hash-reveal-v1/hash-reveal-v1.mjs.map +1 -1
- package/dist/sync/sync-conflict-text-merge.respec.mjs +26 -26
- package/dist/sync/sync-conflict-text-merge.respec.mjs.map +1 -1
- package/dist/sync/sync-constants.d.mts +9 -0
- package/dist/sync/sync-constants.d.mts.map +1 -1
- package/dist/sync/sync-constants.mjs +10 -0
- package/dist/sync/sync-constants.mjs.map +1 -1
- package/dist/sync/sync-innerspace-dest-ahead-withid.respec.d.mts +7 -0
- package/dist/sync/sync-innerspace-dest-ahead-withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-innerspace-dest-ahead-withid.respec.mjs +282 -0
- package/dist/sync/sync-innerspace-dest-ahead-withid.respec.mjs.map +1 -0
- package/dist/sync/sync-saga-coordinator.d.mts +22 -11
- package/dist/sync/sync-saga-coordinator.d.mts.map +1 -1
- package/dist/sync/sync-saga-coordinator.mjs +120 -27
- package/dist/sync/sync-saga-coordinator.mjs.map +1 -1
- package/dist/sync/sync-saga-message/sync-saga-message-types.d.mts +1 -7
- package/dist/sync/sync-saga-message/sync-saga-message-types.d.mts.map +1 -1
- package/dist/sync/sync-types.d.mts +11 -0
- package/dist/sync/sync-types.d.mts.map +1 -1
- package/dist/sync/sync-types.mjs.map +1 -1
- package/dist/test/mock-space.d.mts +1 -38
- package/dist/test/mock-space.d.mts.map +1 -1
- package/dist/test/mock-space.mjs +73 -78
- package/dist/test/mock-space.mjs.map +1 -1
- package/package.json +1 -1
- package/src/keystone/README.md +119 -0
- package/src/keystone/docs/architecture.md +32 -1
- package/src/keystone/kdf/kdf-constants.mts +34 -0
- package/src/keystone/kdf/kdf-helpers.mts +105 -0
- package/src/keystone/kdf/kdf-types.mts +58 -0
- package/src/keystone/keystone-config-builder.mts +170 -47
- package/src/keystone/keystone-config-builder.respec.mts +21 -14
- package/src/keystone/keystone-constants.mts +21 -2
- package/src/keystone/keystone-helpers.mts +19 -14
- package/src/keystone/keystone-service-v1.mts +23 -22
- package/src/keystone/keystone-service-v1.respec.mts +71 -44
- package/src/keystone/keystone-types.mts +37 -23
- package/src/keystone/strategy/hash-reveal-v1/hash-reveal-v1.mts +9 -13
- package/src/sync/README.md +122 -5
- package/src/sync/docs/architecture.md +2 -2
- package/src/sync/{SYNC_TESTING.md → docs/testing.md} +113 -28
- package/src/sync/sync-conflict-text-merge.respec.mts +25 -25
- package/src/sync/sync-constants.mts +12 -0
- package/src/sync/sync-innerspace-dest-ahead-withid.respec.mts +349 -0
- package/src/sync/sync-saga-coordinator.mts +158 -33
- package/src/sync/sync-saga-message/sync-saga-message-types.mts +1 -7
- package/src/sync/sync-types.mts +12 -0
- package/src/test/mock-space.mts +72 -72
- package/tmp.md +0 -274
- package/src/sync/docs/verification.md +0 -43
package/dist/test/mock-space.mjs
CHANGED
|
@@ -1,79 +1,74 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
const addr = getIbGibAddr({ ibGib });
|
|
76
|
-
this.timelineHeads.set(tjpGib, addr);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
1
|
+
// import { IbGib_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';
|
|
2
|
+
// import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
|
|
3
|
+
export {};
|
|
4
|
+
// /**
|
|
5
|
+
// * A simple in-memory map acting as a Space.
|
|
6
|
+
// * Pure Storage. No Indexing logic.
|
|
7
|
+
// *
|
|
8
|
+
// * Copied/Adapted from Keystone Respecs.
|
|
9
|
+
// */
|
|
10
|
+
// export class MockIbGibSpace {
|
|
11
|
+
// store = new Map<string, IbGib_V1>();
|
|
12
|
+
// constructor(public name: string = "mock_space") { }
|
|
13
|
+
// async put({ ibGib }: { ibGib: IbGib_V1 }): Promise<void> {
|
|
14
|
+
// const addr = getIbGibAddr({ ibGib });
|
|
15
|
+
// this.store.set(addr, JSON.parse(JSON.stringify(ibGib))); // Deep copy
|
|
16
|
+
// }
|
|
17
|
+
// async get({ addr }: { addr: string }): Promise<IbGib_V1 | null> {
|
|
18
|
+
// const data = this.store.get(addr);
|
|
19
|
+
// return data ? JSON.parse(JSON.stringify(data)) : null;
|
|
20
|
+
// }
|
|
21
|
+
// async witness(arg: any): Promise<any> {
|
|
22
|
+
// const cmd = arg.data?.cmd;
|
|
23
|
+
// if (cmd === 'get') {
|
|
24
|
+
// const addrs = arg.data.ibGibAddrs || [];
|
|
25
|
+
// const ibGibs: IbGib_V1[] = [];
|
|
26
|
+
// for (const addr of addrs) {
|
|
27
|
+
// const ig = await this.get({ addr });
|
|
28
|
+
// if (ig) ibGibs.push(ig);
|
|
29
|
+
// }
|
|
30
|
+
// return { ibGibs };
|
|
31
|
+
// }
|
|
32
|
+
// if (cmd === 'put') {
|
|
33
|
+
// const ibGibs = arg.ibGibs || [];
|
|
34
|
+
// for (const ibGib of ibGibs) {
|
|
35
|
+
// await this.put({ ibGib });
|
|
36
|
+
// }
|
|
37
|
+
// return { ibGibs: [] }; // Return empty result or whatever witness expects
|
|
38
|
+
// }
|
|
39
|
+
// return undefined;
|
|
40
|
+
// }
|
|
41
|
+
// }
|
|
42
|
+
// /**
|
|
43
|
+
// * A partial mock of Metaspace.
|
|
44
|
+
// */
|
|
45
|
+
// export class MockMetaspaceService {
|
|
46
|
+
// /**
|
|
47
|
+
// * Map of TJP Gib (Timeline ID) -> Latest IbGib Addr (Head)
|
|
48
|
+
// */
|
|
49
|
+
// timelineHeads = new Map<string, string>();
|
|
50
|
+
// constructor(public space: MockIbGibSpace) { }
|
|
51
|
+
// async getLocalUserSpace({ lock }: { lock: boolean }): Promise<MockIbGibSpace> {
|
|
52
|
+
// return this.space;
|
|
53
|
+
// }
|
|
54
|
+
// async put(args: any): Promise<void> {
|
|
55
|
+
// const target = args.space || this.space;
|
|
56
|
+
// return target.put(args);
|
|
57
|
+
// }
|
|
58
|
+
// async registerNewIbGib(args: { ibGib: IbGib_V1, space?: any }): Promise<void> {
|
|
59
|
+
// const { ibGib } = args;
|
|
60
|
+
// const targetSpace = args.space || this.space;
|
|
61
|
+
// // 1. Ensure it is stored
|
|
62
|
+
// await targetSpace.put({ ibGib });
|
|
63
|
+
// // 2. Extract TJP
|
|
64
|
+
// const gib = ibGib.gib || '';
|
|
65
|
+
// let tjpGib = gib;
|
|
66
|
+
// if (gib.includes('.')) {
|
|
67
|
+
// const parts = gib.split('.');
|
|
68
|
+
// tjpGib = parts.slice(1).join('.');
|
|
69
|
+
// }
|
|
70
|
+
// const addr = getIbGibAddr({ ibGib });
|
|
71
|
+
// this.timelineHeads.set(tjpGib, addr);
|
|
72
|
+
// }
|
|
73
|
+
// }
|
|
79
74
|
//# sourceMappingURL=mock-space.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mock-space.mjs","sourceRoot":"","sources":["../../src/test/mock-space.mts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mock-space.mjs","sourceRoot":"","sources":["../../src/test/mock-space.mts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,gEAAgE;;AAEhE,MAAM;AACN,+CAA+C;AAC/C,sCAAsC;AACtC,KAAK;AACL,2CAA2C;AAC3C,MAAM;AACN,gCAAgC;AAChC,2CAA2C;AAE3C,0DAA0D;AAE1D,iEAAiE;AACjE,gDAAgD;AAChD,gFAAgF;AAChF,QAAQ;AAER,wEAAwE;AACxE,6CAA6C;AAC7C,iEAAiE;AACjE,QAAQ;AAER,8CAA8C;AAC9C,qCAAqC;AACrC,+BAA+B;AAC/B,uDAAuD;AACvD,6CAA6C;AAC7C,0CAA0C;AAC1C,uDAAuD;AACvD,2CAA2C;AAC3C,gBAAgB;AAChB,iCAAiC;AACjC,YAAY;AACZ,+BAA+B;AAC/B,+CAA+C;AAC/C,4CAA4C;AAC5C,6CAA6C;AAC7C,gBAAgB;AAChB,wFAAwF;AACxF,YAAY;AACZ,4BAA4B;AAC5B,QAAQ;AACR,IAAI;AAEJ,MAAM;AACN,kCAAkC;AAClC,MAAM;AACN,sCAAsC;AAEtC,UAAU;AACV,kEAAkE;AAClE,UAAU;AACV,iDAAiD;AAEjD,oDAAoD;AAEpD,sFAAsF;AACtF,6BAA6B;AAC7B,QAAQ;AAER,4CAA4C;AAC5C,mDAAmD;AACnD,mCAAmC;AACnC,QAAQ;AAER,sFAAsF;AACtF,kCAAkC;AAClC,wDAAwD;AAExD,oCAAoC;AACpC,4CAA4C;AAE5C,4BAA4B;AAC5B,uCAAuC;AACvC,4BAA4B;AAC5B,mCAAmC;AACnC,4CAA4C;AAC5C,iDAAiD;AACjD,YAAY;AACZ,gDAAgD;AAChD,gDAAgD;AAChD,QAAQ;AACR,IAAI"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ibgib/core-gib",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.44",
|
|
4
4
|
"description": "ibgib core functionality, including base architecture for witnesses, spaces, apps, robbots, etc., as well as shared utility functions. Node v19+ needed for heavily-used isomorphic webcrypto hashing consumed in both node and browsers.",
|
|
5
5
|
"funding": {
|
|
6
6
|
"type": "individual",
|
package/src/keystone/README.md
CHANGED
|
@@ -16,5 +16,124 @@ Validation in this system is **Auditability**: to verify an identity (e.g., "Is
|
|
|
16
16
|
3. **Hash-based**: Uses hash pre-imaging for quantum resistance (`hash-reveal-v1`).
|
|
17
17
|
4. **Merkle Graphs**: Efficient communication by only transmitting missing graph nodes.
|
|
18
18
|
|
|
19
|
+
## Challenge Pools
|
|
20
|
+
|
|
21
|
+
Keystones organize challenges into **pools** with specific purposes:
|
|
22
|
+
|
|
23
|
+
* **Default Pool**: General-purpose signing operations
|
|
24
|
+
* **Revoke Pool**: Permanent identity termination (one-time use, `verb: revoke`)
|
|
25
|
+
* **Manage Pool**: Structural changes like adding pools (`verb: manage`)
|
|
26
|
+
* **Foreign Pools**: Delegation to external identities (SSO-like workflows)
|
|
27
|
+
|
|
28
|
+
Each pool configuration specifies:
|
|
29
|
+
* **`poolId`**: Unique identifier within the keystone
|
|
30
|
+
* **`verb`**: Auto-routes operations (e.g., `revoke`, `manage`, `login`)
|
|
31
|
+
* **`replenishStrategy`**: What to do after using challenges in a pool, e.g.
|
|
32
|
+
`'top-up'`, `'replace-all'`, `'delete-all'`, etc.
|
|
33
|
+
* **`challengeCount`**: Number of hash challenges in the pool
|
|
34
|
+
|
|
35
|
+
## Basic Usage
|
|
36
|
+
|
|
37
|
+
### Genesis (Create Identity)
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
const keystone = await keystoneService.genesis({
|
|
41
|
+
masterSecret: "user-password",
|
|
42
|
+
configs: [
|
|
43
|
+
{ poolId: 'default', challengeCount: 100, replenishStrategy: KeystoneReplenishStrategy.topUp },
|
|
44
|
+
{ poolId: 'revoke', verb: 'revoke', challengeCount: 10, replenishStrategy: KeystoneReplenishStrategy.deleteAll }
|
|
45
|
+
],
|
|
46
|
+
metaspace,
|
|
47
|
+
space
|
|
48
|
+
});
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Sign a Claim
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
const signedKeystone = await keystoneService.sign({
|
|
55
|
+
latestKeystone: keystone,
|
|
56
|
+
claim: { action: 'login', timestamp: Date.now() },
|
|
57
|
+
masterSecret: "user-password",
|
|
58
|
+
poolId: 'default', // or use verb-based auto-routing
|
|
59
|
+
metaspace,
|
|
60
|
+
space
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Revoke Identity
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
await keystoneService.revoke({
|
|
68
|
+
latestKeystone: keystone,
|
|
69
|
+
reason: "Device compromised",
|
|
70
|
+
masterSecret: "user-password",
|
|
71
|
+
metaspace,
|
|
72
|
+
space
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Delegation via Foreign Pools
|
|
77
|
+
|
|
78
|
+
> [!IMPORTANT]
|
|
79
|
+
> **🔑 Foreign pools enable delegation** - Alice can grant Bob signing authority for specific operations.
|
|
80
|
+
|
|
81
|
+
Alice can delegate signing authority to Bob by adding his challenge pool:
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
const aliceWithBobPool = await keystoneService.addPools({
|
|
85
|
+
latestKeystone: aliceKeystone,
|
|
86
|
+
newPoolConfigs: [
|
|
87
|
+
{
|
|
88
|
+
poolId: 'bob-sso',
|
|
89
|
+
verb: 'login',
|
|
90
|
+
foreignServerUrl: 'https://bob-server.com',
|
|
91
|
+
challengeCount: 50
|
|
92
|
+
}
|
|
93
|
+
],
|
|
94
|
+
masterSecret: aliceSecret,
|
|
95
|
+
metaspace,
|
|
96
|
+
space
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Now Bob can sign login claims on Alice's behalf, but only for operations using the `login` verb.
|
|
101
|
+
|
|
102
|
+
**Trust Model**:
|
|
103
|
+
- Alice validates Bob's pool **shape** when adding (via `validateChallengePool`)
|
|
104
|
+
- Bob never transmits his secrets
|
|
105
|
+
- Communication secured via TLS
|
|
106
|
+
- Bob can validate his pool section when Alice evolves keystone
|
|
107
|
+
|
|
108
|
+
## Validation
|
|
109
|
+
|
|
110
|
+
To verify a keystone timeline:
|
|
111
|
+
|
|
112
|
+
1. **Replay** from genesis to current frame
|
|
113
|
+
2. **Verify** each proof's hash pre-images match challenges
|
|
114
|
+
3. **Validate** challenge selection matches policy engine rules
|
|
115
|
+
4. **Check** revocation status (if revoked, identity cannot evolve)
|
|
116
|
+
|
|
117
|
+
Validation helpers:
|
|
118
|
+
* `validateEvolution()`: Verifies transition from previous to current frame
|
|
119
|
+
* `validateKeystoneTimeline()`: Replays entire timeline from genesis
|
|
120
|
+
|
|
121
|
+
## Integration with Sync
|
|
122
|
+
|
|
123
|
+
Keystones integrate with the sync protocol to provide **session identity**:
|
|
124
|
+
|
|
125
|
+
* **Session Keystones**: Ephemeral identities created per sync saga
|
|
126
|
+
* **Saga Binding**: Session keystone salted with `sagaId`
|
|
127
|
+
* **Signature Frames**: Each saga frame can be signed with session identity
|
|
128
|
+
|
|
129
|
+
> [!CAUTION]
|
|
130
|
+
> **🚧 Session identity integration is NOT yet functional.** See [sync README](file:../sync/README.md#session-identity-usesessionidentity) for current status.
|
|
131
|
+
|
|
19
132
|
## Implementation
|
|
133
|
+
|
|
20
134
|
The v1 implementation creates a pure TypeScript, isomorphic, hash-based identity system. It is designed to be "Non-Evil" and "Graph-Native".
|
|
135
|
+
|
|
136
|
+
**Key Files**:
|
|
137
|
+
* [keystone-service-v1.mts](file:./keystone-service-v1.mts): Core service implementation
|
|
138
|
+
* [keystone-types.mts](file:./keystone-types.mts): TypeScript type definitions
|
|
139
|
+
* [keystone-helpers.mts](file:./keystone-helpers.mts): Utility functions
|
|
@@ -14,6 +14,33 @@
|
|
|
14
14
|
* **Challenge Pool**: A collection of puzzles stored in each Keystone Frame.
|
|
15
15
|
* **Constraint/Policy Engine**: Logic that determines *which* challenges must be solved to authorize a specific action (Binding, FIFO, Stochastic).
|
|
16
16
|
|
|
17
|
+
### Foreign Pools (Delegation)
|
|
18
|
+
|
|
19
|
+
> [!IMPORTANT]
|
|
20
|
+
> **🔀 Keystones support delegation** by embedding challenges from external identities.
|
|
21
|
+
|
|
22
|
+
**Mechanism**:
|
|
23
|
+
* **Use Case**: Alice adds Bob's challenge pool to her keystone
|
|
24
|
+
* **Validation**: Alice validates Bob's pool **shape** when adding (via `validateChallengePool`)
|
|
25
|
+
* **Signing**: Bob can sign claims on Alice's behalf (limited by `verb` field)
|
|
26
|
+
* **Trust Model**:
|
|
27
|
+
- Bob never transmits secrets across network
|
|
28
|
+
- Communication secured via TLS
|
|
29
|
+
- Bob can validate his pool section when Alice evolves keystone
|
|
30
|
+
* **SSO Pattern**: Enables Single Sign-On workflows without shared secrets
|
|
31
|
+
|
|
32
|
+
**Configuration**:
|
|
33
|
+
```typescript
|
|
34
|
+
{
|
|
35
|
+
poolId: 'bob-sso',
|
|
36
|
+
verb: 'login',
|
|
37
|
+
foreignServerUrl: 'https://bob-server.com',
|
|
38
|
+
challengeCount: 50
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
See [KeystoneService_V1.addPools()](file:../keystone-service-v1.mts) for implementation.
|
|
43
|
+
|
|
17
44
|
## 3. Policy Engine (Selection & Mitigation)
|
|
18
45
|
|
|
19
46
|
To prevent replay attacks by Man-in-the-Middle (MITM) actors, the challenges required to sign a frame are selected via a multi-layered pipeline:
|
|
@@ -45,7 +72,11 @@ Inputs: `LatestKeystone`, `Claim`, `MasterSecret`.
|
|
|
45
72
|
1. **Auto-Routing**: Selects pool based on Verb (e.g., 'revoke').
|
|
46
73
|
2. **Selection**: Runs Policy Engine.
|
|
47
74
|
3. **Solving**: Generates solutions.
|
|
48
|
-
4. **Replenishment**: Adds new challenges
|
|
75
|
+
4. **Replenishment**: Adds new challenges based on pool's `replenishStrategy`:
|
|
76
|
+
* **`'top-up'`**: Refills consumed challenges (default, reusable identity)
|
|
77
|
+
* **`'replace-all'`**: Establishes completely new challenges (mitigate long-term pre-image attacks)
|
|
78
|
+
* **`'consume'`**: Do not re-add any challenges (limited number of uses)
|
|
79
|
+
* **`'delete-all'`**: Removes all challenges permanently (revocation, one-time operations)
|
|
49
80
|
|
|
50
81
|
### 5.3 Validate
|
|
51
82
|
Inputs: `PreviousFrame`, `CurrentFrame`.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KDF Strategy Constants
|
|
3
|
+
*
|
|
4
|
+
* Defines available key derivation function strategies.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// #region KdfStrategy
|
|
8
|
+
export const KDF_STRATEGY_RECURSIVE_SALT_WRAP = 'recursive-salt-wrap';
|
|
9
|
+
export type KdfStrategy =
|
|
10
|
+
| typeof KDF_STRATEGY_RECURSIVE_SALT_WRAP
|
|
11
|
+
;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Available KDF strategies for deriving keys from master secrets.
|
|
15
|
+
*
|
|
16
|
+
* - `recursive-salt-wrap`: Hash(salt + current + salt) ^ rounds
|
|
17
|
+
* Used by KeystoneStrategy_HashRevealV1 for pool secret derivation
|
|
18
|
+
*/
|
|
19
|
+
export const KdfStrategy = {
|
|
20
|
+
/**
|
|
21
|
+
* Recursive salt wrap strategy: Hash(salt + current + salt) ^ rounds
|
|
22
|
+
*
|
|
23
|
+
* This is the primary strategy used by keystones for deriving pool secrets
|
|
24
|
+
* from master secrets with configurable rounds for key stretching.
|
|
25
|
+
*/
|
|
26
|
+
recursive_salt_wrap: KDF_STRATEGY_RECURSIVE_SALT_WRAP,
|
|
27
|
+
} satisfies { [key: string]: KdfStrategy };
|
|
28
|
+
|
|
29
|
+
export const KDF_STRATEGY_VALID_VALUES = Object.values(KdfStrategy);
|
|
30
|
+
|
|
31
|
+
export function isValidKdfStrategy(strategy: string): strategy is KdfStrategy {
|
|
32
|
+
return KDF_STRATEGY_VALID_VALUES.includes(strategy as KdfStrategy);
|
|
33
|
+
}
|
|
34
|
+
// #endregion KdfStrategy
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { extractErrorMsg, hash, HashAlgorithm } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
|
|
2
|
+
|
|
3
|
+
import { GLOBAL_LOG_A_LOT } from '../../core-constants.mjs';
|
|
4
|
+
import { KDF_STRATEGY_RECURSIVE_SALT_WRAP, KDF_STRATEGY_VALID_VALUES, KdfStrategy } from './kdf-constants.mjs';
|
|
5
|
+
import { DeriveKeyParams, KdfOptions_RecursiveSaltWrap } from './kdf-types.mjs';
|
|
6
|
+
|
|
7
|
+
const logalot = GLOBAL_LOG_A_LOT;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Derive a key from a master secret using the specified KDF strategy
|
|
11
|
+
*
|
|
12
|
+
* This is the main dispatch function for all KDF operations. It routes to the
|
|
13
|
+
* appropriate strategy implementation based on `kdfOpts.strategy`.
|
|
14
|
+
*
|
|
15
|
+
* @param params - Derivation parameters including master secret and KDF options
|
|
16
|
+
* @returns Derived key
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const derivedKey = await deriveKey({
|
|
21
|
+
* masterSecret: 'my-strong-password',
|
|
22
|
+
* kdfOpts: {
|
|
23
|
+
* strategy: KdfStrategy.recursiveSaltWrap,
|
|
24
|
+
* salt: 'pool-identifier',
|
|
25
|
+
* rounds: 10000,
|
|
26
|
+
* algorithm: 'SHA-256'
|
|
27
|
+
* }
|
|
28
|
+
* });
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export async function deriveKey({
|
|
32
|
+
masterSecret,
|
|
33
|
+
kdfOpts
|
|
34
|
+
}: DeriveKeyParams): Promise<string> {
|
|
35
|
+
const lc = `[${deriveKey.name}]`;
|
|
36
|
+
try {
|
|
37
|
+
if (logalot) { console.log(`${lc} starting... (I: 268e87ec311874ee6822bf459c5a5426)`); }
|
|
38
|
+
|
|
39
|
+
const strategy = kdfOpts.strategy;
|
|
40
|
+
|
|
41
|
+
switch (strategy) {
|
|
42
|
+
case KdfStrategy['recursive-salt-wrap']:
|
|
43
|
+
return await kdf_recursiveSaltWrap({
|
|
44
|
+
masterSecret,
|
|
45
|
+
salt: kdfOpts.salt,
|
|
46
|
+
rounds: kdfOpts.rounds,
|
|
47
|
+
algorithm: kdfOpts.algorithm
|
|
48
|
+
});
|
|
49
|
+
default:
|
|
50
|
+
throw new Error(`Unknown KDF strategy: ${strategy}. valid values: ${KDF_STRATEGY_VALID_VALUES.join(', ')} (E: a1b2c3d4e5f6g7h8i9j0)`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
} catch (error) {
|
|
54
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
55
|
+
throw error;
|
|
56
|
+
} finally {
|
|
57
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Recursive Salt Wrap KDF Strategy
|
|
63
|
+
*
|
|
64
|
+
* Derives a key by recursively applying: Hash(salt + current + salt) for N rounds
|
|
65
|
+
*
|
|
66
|
+
* This is the strategy used by KeystoneStrategy_HashRevealV1 for deriving pool secrets.
|
|
67
|
+
*
|
|
68
|
+
* @param masterSecret - The initial secret/password to derive from
|
|
69
|
+
* @param salt - Salt value to wrap around the secret
|
|
70
|
+
* @param rounds - Number of hash iterations (key stretching)
|
|
71
|
+
* @param algorithm - Hash algorithm to use (default: SHA-256)
|
|
72
|
+
* @returns Derived key
|
|
73
|
+
*/
|
|
74
|
+
export async function kdf_recursiveSaltWrap({
|
|
75
|
+
masterSecret,
|
|
76
|
+
salt,
|
|
77
|
+
rounds,
|
|
78
|
+
algorithm = HashAlgorithm.sha_256,
|
|
79
|
+
}: {
|
|
80
|
+
masterSecret: string;
|
|
81
|
+
salt: string;
|
|
82
|
+
rounds: number;
|
|
83
|
+
algorithm?: HashAlgorithm;
|
|
84
|
+
}): Promise<string> {
|
|
85
|
+
const lc = `[${kdf_recursiveSaltWrap.name}]`;
|
|
86
|
+
try {
|
|
87
|
+
if (logalot) { console.log(`${lc} starting... (I: 850868e50aba82ff28c77da8169e4c26)`); }
|
|
88
|
+
|
|
89
|
+
let current = masterSecret;
|
|
90
|
+
|
|
91
|
+
for (let i = 0; i < rounds; i++) {
|
|
92
|
+
current = await hash({
|
|
93
|
+
s: `${salt}${current}${salt}`,
|
|
94
|
+
algorithm
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return current;
|
|
99
|
+
} catch (error) {
|
|
100
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
101
|
+
throw error;
|
|
102
|
+
} finally {
|
|
103
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { HashAlgorithm } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
|
|
2
|
+
import { KdfStrategy } from './kdf-constants.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Base options for all KDF strategies
|
|
6
|
+
*/
|
|
7
|
+
export interface KdfOptionsBase {
|
|
8
|
+
/**
|
|
9
|
+
* Name of the KDF strategy to use
|
|
10
|
+
*/
|
|
11
|
+
strategy: KdfStrategy;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Options for recursive-salt-wrap KDF strategy
|
|
16
|
+
*
|
|
17
|
+
* Derives key by recursively applying: Hash(salt + current + salt) for N rounds
|
|
18
|
+
*/
|
|
19
|
+
export interface KdfOptions_RecursiveSaltWrap extends KdfOptionsBase {
|
|
20
|
+
strategy: typeof import('./kdf-constants.mjs').KDF_STRATEGY_RECURSIVE_SALT_WRAP;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Salt value to wrap around the secret during each iteration
|
|
24
|
+
*/
|
|
25
|
+
salt: string;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Number of hash iterations for key stretching
|
|
29
|
+
*/
|
|
30
|
+
rounds: number;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Hash algorithm to use (default: SHA-256)
|
|
34
|
+
*/
|
|
35
|
+
algorithm?: HashAlgorithm;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Union of all KDF option types
|
|
40
|
+
*/
|
|
41
|
+
export type KdfOptions =
|
|
42
|
+
| KdfOptions_RecursiveSaltWrap
|
|
43
|
+
;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Parameters for deriving a key using KDF
|
|
47
|
+
*/
|
|
48
|
+
export interface DeriveKeyParams {
|
|
49
|
+
/**
|
|
50
|
+
* The initial secret/password to derive from
|
|
51
|
+
*/
|
|
52
|
+
masterSecret: string;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* KDF options specifying strategy and strategy-specific parameters
|
|
56
|
+
*/
|
|
57
|
+
kdfOpts: KdfOptions;
|
|
58
|
+
}
|