@ibgib/core-gib 0.1.6 → 0.1.8
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/keystone-config-builder.d.mts +77 -0
- package/dist/keystone/keystone-config-builder.d.mts.map +1 -0
- package/dist/keystone/keystone-config-builder.mjs +157 -0
- package/dist/keystone/keystone-config-builder.mjs.map +1 -0
- package/dist/keystone/keystone-constants.d.mts +36 -0
- package/dist/keystone/keystone-constants.d.mts.map +1 -0
- package/dist/keystone/keystone-constants.mjs +39 -0
- package/dist/keystone/keystone-constants.mjs.map +1 -0
- package/dist/keystone/keystone-helpers.d.mts +117 -0
- package/dist/keystone/keystone-helpers.d.mts.map +1 -0
- package/dist/keystone/keystone-helpers.mjs +455 -0
- package/dist/keystone/keystone-helpers.mjs.map +1 -0
- package/dist/keystone/keystone-service-v1.d.mts +77 -0
- package/dist/keystone/keystone-service-v1.d.mts.map +1 -0
- package/dist/keystone/keystone-service-v1.mjs +502 -0
- package/dist/keystone/keystone-service-v1.mjs.map +1 -0
- package/dist/keystone/keystone-service-v1.respec.d.mts +2 -0
- package/dist/keystone/keystone-service-v1.respec.d.mts.map +1 -0
- package/dist/keystone/keystone-service-v1.respec.mjs +460 -0
- package/dist/keystone/keystone-service-v1.respec.mjs.map +1 -0
- package/dist/keystone/keystone-types.d.mts +248 -0
- package/dist/keystone/keystone-types.d.mts.map +1 -0
- package/dist/keystone/keystone-types.mjs +50 -0
- package/dist/keystone/keystone-types.mjs.map +1 -0
- package/dist/keystone/strategy/hash-reveal-v1/hash-reveal-v1.d.mts +35 -0
- package/dist/keystone/strategy/hash-reveal-v1/hash-reveal-v1.d.mts.map +1 -0
- package/dist/keystone/strategy/hash-reveal-v1/hash-reveal-v1.mjs +107 -0
- package/dist/keystone/strategy/hash-reveal-v1/hash-reveal-v1.mjs.map +1 -0
- package/dist/keystone/strategy/keystone-strategy-factory.d.mts +15 -0
- package/dist/keystone/strategy/keystone-strategy-factory.d.mts.map +1 -0
- package/dist/keystone/strategy/keystone-strategy-factory.mjs +26 -0
- package/dist/keystone/strategy/keystone-strategy-factory.mjs.map +1 -0
- package/dist/keystone/strategy/keystone-strategy.d.mts +48 -0
- package/dist/keystone/strategy/keystone-strategy.d.mts.map +1 -0
- package/dist/keystone/strategy/keystone-strategy.mjs +14 -0
- package/dist/keystone/strategy/keystone-strategy.mjs.map +1 -0
- package/package.json +2 -1
- package/src/keystone/README.md +162 -0
- package/src/keystone/keystone-config-builder.mts +187 -0
- package/src/keystone/keystone-constants.mts +44 -0
- package/src/keystone/keystone-helpers.mts +571 -0
- package/src/keystone/keystone-service-v1.mts +611 -0
- package/src/keystone/keystone-service-v1.respec.mts +555 -0
- package/src/keystone/keystone-types.mts +315 -0
- package/src/keystone/strategy/hash-reveal-v1/hash-reveal-v1.mts +146 -0
- package/src/keystone/strategy/keystone-strategy-factory.mts +35 -0
- package/src/keystone/strategy/keystone-strategy.mts +71 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# keystone-gib
|
|
2
|
+
|
|
3
|
+
"Keystones" are a new ibgib-specific identity mechanism that leverages ibgib's unique Merkle-based DLT structure. These combine the aspect of the general CS concept of a "key" with the ibgib concept of a "stone", i.e., a non-living entity without `dna`.
|
|
4
|
+
|
|
5
|
+
## ibgib and keystones - how identity propagates through spacetime
|
|
6
|
+
|
|
7
|
+
To understand Keystones, you must understand the environment they live in. ibgib is a **Spacetime Distributed Ledger**. Data does not just "exist"; it propagates through **Spaces** (persistence layers like local storage, cloud nodes, or p2p relays).
|
|
8
|
+
|
|
9
|
+
In this universe, data falls into two categories based on how it handles time:
|
|
10
|
+
|
|
11
|
+
1. **"Living" Data:** These ibgibs have `dna` relations pointing to the transforms (mutations) that created them. They behave like CRDTs (Conflict-free Replicated Data Types) and can be merged, forked, and reconciled across different timelines.
|
|
12
|
+
2. **"Stones":** These are ibgibs **without** `dna`. They are fixed points in the causal graph. They do not merge; they only accrete. They are effectively constants.
|
|
13
|
+
|
|
14
|
+
A **Keystone** is a "Stone". It is an identity timeline (a graph of ibgib frames) that must remain historically intact to be valid. It does not support CRDT-style merging.
|
|
15
|
+
|
|
16
|
+
* **Validation is Replay:** In traditional PKI, a Certificate Authority (CA) acts as a centralized trust anchor to establish a secure channel. In ibgib, validation is **Auditability**. To verify an identity (e.g., "Is this Alice?"), one "replays" the Keystone timeline from its Genesis to the current Frame, verifying the cryptographic proofs at every step.
|
|
17
|
+
* **Propagation as Witnessing:** When a Keystone Frame is transmitted from Alice's Space to Bob's Space, Bob "witnesses" it. By accepting it into his Space, he effectively votes on its validity. If it is invalid, it is rejected and does not propagate.
|
|
18
|
+
|
|
19
|
+
## principles
|
|
20
|
+
|
|
21
|
+
### DRY - leverage the ubiquity of ibgib's already-existing crypto hypergraph
|
|
22
|
+
|
|
23
|
+
Ibgib already provides the foundations of hypergraph generation dynamics. This is core to the very being of all data within ibgib. Therefore, we do not need a separate library/algorithm that only works with specialized Merkle-based technologies like many NIST-approved technologies. We leverage the existing ibgib mechanism without having to maintain two codebases for things that do essentially the same thing.
|
|
24
|
+
|
|
25
|
+
With ibgib, keystones are one reified use case of the more general ibgib timeline dynamics.
|
|
26
|
+
|
|
27
|
+
### Non-Evil Root - ignore signing pre-optimization
|
|
28
|
+
|
|
29
|
+
Similar to the slowness of some blockchains, like Bitcoin, we prioritize security first over other optimization dimensions like signing speed or size of keys.
|
|
30
|
+
|
|
31
|
+
The "speed" of the security can occur in what I call "scoping", but this assumes a relatively small number of connections. This is not designed for general-purpose internet traffic, where signing size/rates are paramount.
|
|
32
|
+
|
|
33
|
+
### Hash-based - pre-imaging is hard
|
|
34
|
+
|
|
35
|
+
If this is not true, then the security of keystones fails. This does not mean that all hashes are equal of course, but the general principle exists.
|
|
36
|
+
|
|
37
|
+
Note that, similar to PoW, hash-based challenges must be hard only for the time of the keystone's proximal use case. The keystones themselves must be spread with witnessing protocols to make them durable beyond that proximal window.
|
|
38
|
+
|
|
39
|
+
### The need for `ib` - collisions in our future
|
|
40
|
+
|
|
41
|
+
We are nearing a future where hash-spaces may seem large to us now, much like our previous beliefs that 1 MB of RAM was a lot. But this is misleading of course. With the amount of hashes that will be used (not only in ibgib, but other technologies as well as this will be the primary addressing mechanism across all software) these hash spaces will shrink precipitously. It's a small world after all.
|
|
42
|
+
|
|
43
|
+
This is why ibgib's addressing mechanism has a per-use-case `ib` component, to reduce accidental collisions in a world of ubiquitous hashing.
|
|
44
|
+
|
|
45
|
+
### Merkle graphs - inherently optimal communication
|
|
46
|
+
|
|
47
|
+
A keystone is an entire dependency graph, not a single ibgib frame. This is like thinking, in today's understanding, of a keystone as an entire repo and not a single commit. Though, due to the coolness of Merkle graphs, we do not always need to transmit the entire dependency graph, just as we do not need to push/pull an entire repo every time. This is an inherent quality of Merkle graph transmission and is heavily relied upon.
|
|
48
|
+
|
|
49
|
+
## current implementation
|
|
50
|
+
|
|
51
|
+
The v1 implementation creates a pure TypeScript, isomorphic, hash-based identity system. It is designed to be "Non-Evil" (prioritizing security/correctness over bandwidth) and "Graph-Native" (the signature is part of the DAG).
|
|
52
|
+
|
|
53
|
+
### jargon - the language of the stone
|
|
54
|
+
|
|
55
|
+
* **Stone:** Any ibgib without `dna`. A constant or fixed point in the graph.
|
|
56
|
+
* **Keystone:** A specific type of Stone used for Identity. It is a graph of ibgib frames that evolves over time but maintains a strict, verifiable lineage.
|
|
57
|
+
* **Challenge Pool:** A collection of puzzles stored in a Keystone Frame.
|
|
58
|
+
* **Challenge/Solution:** An abstract pair where the `Challenge` is public and the `Solution` is private. Revealing the Solution proves authorization.
|
|
59
|
+
* **Claim:** The semantic intent of a signature. Composed of a `target` (ibgib addr), `verb` (e.g., "post"), and optional `scope`.
|
|
60
|
+
* **Proof:** The structure linking a `Claim` to a set of revealed `Solutions`.
|
|
61
|
+
* **Policy:** The strict rules determining *which* challenges must be solved to authorize a specific Claim.
|
|
62
|
+
|
|
63
|
+
### policy engine - selection and mitigation
|
|
64
|
+
|
|
65
|
+
Why do we need complex selection logic?
|
|
66
|
+
|
|
67
|
+
In a Keystone system, authorizing a frame involves **publicly revealing** solutions to challenges. Once revealed, a solution is known to the network. If a Man-In-The-Middle (MITM) isolates a victim, they might attempt to **replay** these known solutions to forge new frames.
|
|
68
|
+
|
|
69
|
+
Our policy engine enforces a multi-layered challenge selection pipeline to mitigate this. To sign a claim, the challenges consumed must satisfy **ALL** of the following layers (without double-dipping):
|
|
70
|
+
|
|
71
|
+
1. **Mandatory Demands (The "Alice" Layer):**
|
|
72
|
+
* *Mechanism:* The verifier (or context) explicitly demands specific `challengeIds`.
|
|
73
|
+
* *Why:* Enables parties to proactively include challenges if they think the existing layers are insufficient, e.g., Alice can demand Bob select certain challenges that Alice thinks may be stronger/more secure (for whatever reason).
|
|
74
|
+
2. **Target Binding (The "Content" Layer):**
|
|
75
|
+
* *Mechanism:* Challenges are explicitly mapped to buckets (e.g., Hex Characters), and the first N number of characters in the target `ibgib.gib` (frame's hash) are required to be solved.
|
|
76
|
+
* *Why:* **Content-Dependent Binding.** A revealed solution for "Target A" with first 5 characters of "a1c04" cannot be used to sign "a40d9", because they only overlap with "a" and "0". The attacker has to forge an ibgib frame whose hash matches the target binded characters in the target addr, which is hard, similar to existing PoW leading-zero hashing. This becomes harder with more binding characters required.
|
|
77
|
+
3. **FIFO (The "Order" Layer):**
|
|
78
|
+
* *Mechanism:* Must consume $N$ challenges from the "front" of the pool.
|
|
79
|
+
* *Why:* Enables lower security but faster keystones.
|
|
80
|
+
4. **Stochastic (The "Chaos" Layer):**
|
|
81
|
+
* *Mechanism:* Randomly select $N$ additional challenges from the remainder.
|
|
82
|
+
* *Why:* Mitigates pre-computation attacks and grinding.
|
|
83
|
+
|
|
84
|
+
#### replenishment - sustaining the timeline
|
|
85
|
+
|
|
86
|
+
Once challenges are consumed to sign a frame, the pool must react. This dictates the longevity and bandwidth profile of the identity.
|
|
87
|
+
|
|
88
|
+
* **Top-Up (Standard):**
|
|
89
|
+
* *Mechanism:* Generate $N$ new challenges to replace the $N$ consumed ones.
|
|
90
|
+
* *Use Case:* Long-lived identities (e.g., User Profiles). Maintains a constant pool size and consistent entropy.
|
|
91
|
+
* **Replace-All (Paranoid):**
|
|
92
|
+
* *Mechanism:* Discard *all* remaining challenges in the pool and generate a completely fresh set.
|
|
93
|
+
* *Use Case:* High-security contexts where one desires total forward secrecy for the entire pool after any usage. High bandwidth cost.
|
|
94
|
+
* **Consume (Burn):**
|
|
95
|
+
* *Mechanism:* Remove consumed challenges. Do *not* add new ones.
|
|
96
|
+
* *Use Case:* Revocation (Scorched Earth) or One-Time-Use ephemeral identities. When the pool is empty, the capability associated with that pool is permanently disabled.
|
|
97
|
+
|
|
98
|
+
### cryptographic engine - `strategy` is a concrete challenge/solution discriminator
|
|
99
|
+
|
|
100
|
+
While the Policy Engine handles *selection*, the Cryptographic Engine handles the concrete specifics.
|
|
101
|
+
|
|
102
|
+
We currently implement the `hash-reveal-v1` strategy, with other possibilities on the horizon:
|
|
103
|
+
|
|
104
|
+
* simpler math challenges
|
|
105
|
+
* for testing
|
|
106
|
+
* for low/no-security
|
|
107
|
+
* for other non-security-based requirements (captcha)
|
|
108
|
+
* encryption-based solutions
|
|
109
|
+
* must decrypt with known qualities
|
|
110
|
+
* can be much more novel, such as decrypt challenge text to a sonnet verified by an agent
|
|
111
|
+
* PoW-style solutions
|
|
112
|
+
* config qualities like leading/trailing 0s
|
|
113
|
+
* not necessarily known ahead of time/at time of challenge-generation
|
|
114
|
+
|
|
115
|
+
#### `strategy: 'hash-reveal-v1'`
|
|
116
|
+
|
|
117
|
+
In the `hash-reveal-v1` strategy, we do not use RSA or Elliptic Curves. We use
|
|
118
|
+
**Hash-Based Cryptography** preimages for quantum resistance and simplicity.
|
|
119
|
+
These are configurable in algorithm and number of recursive rounds.
|
|
120
|
+
|
|
121
|
+
* **The Mechanism:** A variation of a Sigma protocol.
|
|
122
|
+
* Alice commits to a value $H$ (The Challenge) in Frame $N$.
|
|
123
|
+
* To authorize Frame $N+1$, Alice reveals the pre-image $S$ (The Challenge's Solution) such that $Hash(S) = H$ (with `$Hash` being parameterizable in algo/rounds).
|
|
124
|
+
* **Key Derivation (The Salted Wrap):**
|
|
125
|
+
* To prevent exposure of the Master Secret, we use a derivation chain:
|
|
126
|
+
* `MasterSecret` + `PoolSalt` $\to$ `PoolSecret`
|
|
127
|
+
* `PoolSecret` + `ChallengeID` $\to$ `Solution`
|
|
128
|
+
* `Solution` $\to$ `Challenge`
|
|
129
|
+
* *Note:* We use a "Salted Wrap" technique (hashing `salt + secret + salt`) to act as a rudimentary Key Derivation Function without external dependencies that mitigates against length extension attacks.
|
|
130
|
+
|
|
131
|
+
### spacetime integration - the service facade
|
|
132
|
+
|
|
133
|
+
The `KeystoneService_V1` acts as a consumer's API for keystone manipulations. These include both the cryptographic requirements, as well as persistence in ibgib spaces via the metaspace. It ensures that every cryptographic action is executed and atomically persisted to the local Space.
|
|
134
|
+
|
|
135
|
+
#### 1. genesis (creation)
|
|
136
|
+
* **Input:** A Master Secret and Pool Configs.
|
|
137
|
+
* **Process:** Generates the initial challenges and the Genesis Frame.
|
|
138
|
+
* **Persistence:** The new Identity is immediately `put` into the local `Space`.
|
|
139
|
+
|
|
140
|
+
#### 2. sign (evolution)
|
|
141
|
+
* **Input:** The Latest Keystone, Master Secret, Claim, and optional Demands.
|
|
142
|
+
* **Process:**
|
|
143
|
+
1. **Auto-Routing:** Locates the correct Pool based on the Claim's Verb (e.g., routing "revoke" to the revocation pool).
|
|
144
|
+
2. **Selection:** Runs the Policy Engine (Binding -> FIFO -> Stochastic) to select challenges.
|
|
145
|
+
3. **Solving:** Generates solutions using the Master Secret.
|
|
146
|
+
4. **Replenishment:** Tops up the pool with fresh challenges (or burns them, depending on strategy).
|
|
147
|
+
* **Persistence:** The new Frame (containing the Proof) is persisted to the local `Space`. The `target` address is now cryptographically linked to this new frame.
|
|
148
|
+
|
|
149
|
+
#### 3. validate (audit)
|
|
150
|
+
* **Input:** The Previous Frame and the Current Frame.
|
|
151
|
+
* **Process:**
|
|
152
|
+
1. **Policy Check:** Reconstructs the deterministic requirements (Demands, Binding, FIFO) and ensures the Proof satisfies them.
|
|
153
|
+
2. **Crypto Check:** Verifies the revealed Solutions match the Challenges in the Previous Frame.
|
|
154
|
+
* **Result:** If valid, the Current Frame is accepted as the legitimate successor.
|
|
155
|
+
|
|
156
|
+
#### 4. revoke (kill switch)
|
|
157
|
+
* **Input:** The Latest Keystone and Master Secret.
|
|
158
|
+
* **Process:**
|
|
159
|
+
1. Locates the specialized **Revocation Pool**.
|
|
160
|
+
2. Consumes **ALL** challenges in that pool ("Scorched Earth").
|
|
161
|
+
3. Sets the `revocationInfo` on the new frame.
|
|
162
|
+
* **Result:** The Identity is permanently marked as dead. No further valid frames can be generated because the revocation pool (required for the 'revoke' verb) is empty.
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import {
|
|
2
|
+
KeystonePoolConfig,
|
|
3
|
+
KeystonePoolConfig_HashV1,
|
|
4
|
+
KeystonePoolBehavior,
|
|
5
|
+
KeystoneReplenishStrategy,
|
|
6
|
+
KeystonePoolConfigBase
|
|
7
|
+
} from './keystone-types.mjs';
|
|
8
|
+
import { POOL_ID_DEFAULT, POOL_ID_REVOKE, KEYSTONE_VERB_REVOKE } from './keystone-constants.mjs';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Abstract Base Builder.
|
|
12
|
+
* Handles configuration common to ALL strategies (Salt, Size, Replenishment, Selection).
|
|
13
|
+
*
|
|
14
|
+
* @template TConfig The concrete config type being built.
|
|
15
|
+
*/
|
|
16
|
+
export abstract class KeystoneConfigBuilderBase<TConfig extends KeystonePoolConfigBase> {
|
|
17
|
+
protected _salt: string = 'default';
|
|
18
|
+
protected _size: number = 100;
|
|
19
|
+
protected _replenish: KeystoneReplenishStrategy = 'top-up';
|
|
20
|
+
protected _seq: number = 0;
|
|
21
|
+
protected _rand: number = 0;
|
|
22
|
+
protected _verbs: string[] = [];
|
|
23
|
+
protected _targetBinding: number = 0; // Default 0
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Sets the unique salt/ID for this pool.
|
|
28
|
+
*/
|
|
29
|
+
withSalt(salt: string): this {
|
|
30
|
+
this._salt = salt;
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Sets the total number of challenges to maintain in the pool.
|
|
36
|
+
*/
|
|
37
|
+
withSize(size: number): this {
|
|
38
|
+
this._size = size;
|
|
39
|
+
return this;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Binds challenge selection to the content address of the target.
|
|
44
|
+
* @param chars Number of hex characters to match (e.g. 4).
|
|
45
|
+
*/
|
|
46
|
+
withTargetBinding(chars: number): this {
|
|
47
|
+
this._targetBinding = chars;
|
|
48
|
+
return this;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Configures the pool to use strictly Sequential (FIFO) selection.
|
|
53
|
+
* @param count Number of challenges to consume per sign.
|
|
54
|
+
*/
|
|
55
|
+
withFIFO(count: number): this {
|
|
56
|
+
this._seq = count;
|
|
57
|
+
this._rand = 0;
|
|
58
|
+
return this;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Configures the pool to use strictly Random selection.
|
|
63
|
+
* @param count Number of challenges to consume per sign.
|
|
64
|
+
*/
|
|
65
|
+
withRandom(count: number): this {
|
|
66
|
+
this._seq = 0;
|
|
67
|
+
this._rand = count;
|
|
68
|
+
return this;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Configures the pool to use Hybrid (Both FIFO and Random) selection.
|
|
73
|
+
*/
|
|
74
|
+
withHybrid(seqCount: number, randCount: number): this {
|
|
75
|
+
this._seq = seqCount;
|
|
76
|
+
this._rand = randCount;
|
|
77
|
+
return this;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Sets the replenishment strategy.
|
|
82
|
+
*/
|
|
83
|
+
withReplenishStrategy(strategy: KeystoneReplenishStrategy): this {
|
|
84
|
+
this._replenish = strategy;
|
|
85
|
+
return this;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Constructs the behavioral config object.
|
|
90
|
+
* Helper for subclasses.
|
|
91
|
+
*/
|
|
92
|
+
protected buildBehavior(): KeystonePoolBehavior {
|
|
93
|
+
return {
|
|
94
|
+
size: this._size,
|
|
95
|
+
replenish: this._replenish,
|
|
96
|
+
selectSequentially: this._seq,
|
|
97
|
+
selectRandomly: this._rand,
|
|
98
|
+
targetBindingChars: this._targetBinding,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Restricts this pool to specific verbs.
|
|
104
|
+
* @param verbs List of verb addresses (e.g. 'revoke^gib')
|
|
105
|
+
*/
|
|
106
|
+
forVerbs(verbs: string[]): this {
|
|
107
|
+
this._verbs = verbs;
|
|
108
|
+
return this;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
protected buildBase(): KeystonePoolConfigBase {
|
|
112
|
+
// Helper to keep the concrete build() clean
|
|
113
|
+
return {
|
|
114
|
+
type: 'hash-reveal-v1', // This is overridden by concrete/interface usually, but needed for base shape
|
|
115
|
+
salt: this._salt,
|
|
116
|
+
allowedVerbs: this._verbs
|
|
117
|
+
} as any;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
abstract build(): TConfig;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Concrete Builder for Hash-Reveal V1 Strategy.
|
|
125
|
+
*/
|
|
126
|
+
export class KeystoneConfigBuilder_HashV1 extends KeystoneConfigBuilderBase<KeystonePoolConfig_HashV1> {
|
|
127
|
+
private _algo: 'SHA-256' | 'SHA-512' = 'SHA-256';
|
|
128
|
+
private _rounds: number = 1;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Sets the hashing strength.
|
|
132
|
+
*/
|
|
133
|
+
withHash(algo: 'SHA-256' | 'SHA-512', rounds: number = 1): this {
|
|
134
|
+
this._algo = algo;
|
|
135
|
+
this._rounds = rounds;
|
|
136
|
+
return this;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
build(): KeystonePoolConfig_HashV1 {
|
|
140
|
+
return {
|
|
141
|
+
id: this._salt, // Using salt as the unique ID for the pool config
|
|
142
|
+
type: 'hash-reveal-v1',
|
|
143
|
+
salt: this._salt,
|
|
144
|
+
allowedVerbs: this._verbs, // <--- Mapped here
|
|
145
|
+
behavior: this.buildBehavior(),
|
|
146
|
+
algo: this._algo,
|
|
147
|
+
rounds: this._rounds,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// ===========================================================================
|
|
153
|
+
// STATIC ENTRY POINT (Optional Convenience)
|
|
154
|
+
// ===========================================================================
|
|
155
|
+
|
|
156
|
+
export class KeystoneConfig {
|
|
157
|
+
static hash(): KeystoneConfigBuilder_HashV1 {
|
|
158
|
+
return new KeystoneConfigBuilder_HashV1();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Future:
|
|
162
|
+
// static pow(): KeystoneConfigBuilder_PoW { ... }
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// ===========================================================================
|
|
166
|
+
// FACTORY FUNCTIONS (Presets)
|
|
167
|
+
// ===========================================================================
|
|
168
|
+
|
|
169
|
+
export function createStandardPoolConfig(salt: string = POOL_ID_DEFAULT): KeystonePoolConfig {
|
|
170
|
+
return KeystoneConfig.hash()
|
|
171
|
+
.withSalt(salt)
|
|
172
|
+
.withSize(100)
|
|
173
|
+
.withHybrid(2, 2)
|
|
174
|
+
.withReplenishStrategy('top-up')
|
|
175
|
+
.build();
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export function createRevocationPoolConfig(salt: string = POOL_ID_REVOKE): KeystonePoolConfig {
|
|
179
|
+
return KeystoneConfig.hash()
|
|
180
|
+
.withSalt(salt)
|
|
181
|
+
.withHash('SHA-256', 10)
|
|
182
|
+
.withSize(500)
|
|
183
|
+
.withHybrid(10, 10)
|
|
184
|
+
.withReplenishStrategy(KeystoneReplenishStrategy.scorchedEarth)
|
|
185
|
+
.forVerbs([KEYSTONE_VERB_REVOKE])
|
|
186
|
+
.build();
|
|
187
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export const KEYSTONE_ATOM = "keystone";
|
|
2
|
+
|
|
3
|
+
// #region KeystoneVerb enum
|
|
4
|
+
/**
|
|
5
|
+
* @see {@link KeystoneVerb.REVOKE}
|
|
6
|
+
*/
|
|
7
|
+
export const KEYSTONE_VERB_REVOKE = "revoke";
|
|
8
|
+
/**
|
|
9
|
+
* @see {@link KeystoneVerb.MANAGE}
|
|
10
|
+
*/
|
|
11
|
+
export const KEYSTONE_VERB_MANAGE = "manage";
|
|
12
|
+
export type KeystoneVerb =
|
|
13
|
+
| typeof KEYSTONE_VERB_REVOKE
|
|
14
|
+
| typeof KEYSTONE_VERB_MANAGE;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Verbs that describe actions that can be authorized by a Keystone.
|
|
18
|
+
*/
|
|
19
|
+
export const KeystoneVerb = {
|
|
20
|
+
/**
|
|
21
|
+
* The specific ibGib address for the 'revoke' verb.
|
|
22
|
+
* Used in Claims to indicate the Keystone should be considered dead.
|
|
23
|
+
*/
|
|
24
|
+
REVOKE: KEYSTONE_VERB_REVOKE,
|
|
25
|
+
/**
|
|
26
|
+
* The meta-verb used to authorize structural changes to the Keystone,
|
|
27
|
+
* specifically adding or removing challenge pools.
|
|
28
|
+
*
|
|
29
|
+
* "Root access" to the identity.
|
|
30
|
+
*/
|
|
31
|
+
MANAGE: KEYSTONE_VERB_MANAGE,
|
|
32
|
+
} satisfies { [key: string]: KeystoneVerb };
|
|
33
|
+
export const KEYSTONE_VERB_VALID_VALUES = Object.values(KeystoneVerb);
|
|
34
|
+
export function isKeystoneVerb(value: string): value is KeystoneVerb {
|
|
35
|
+
return KEYSTONE_VERB_VALID_VALUES.includes(value as KeystoneVerb);
|
|
36
|
+
}
|
|
37
|
+
// #endregion KeystoneVerb enum
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Standard pool IDs can be conventionally named after their primary verb.
|
|
41
|
+
*/
|
|
42
|
+
export const POOL_ID_REVOKE = KEYSTONE_VERB_REVOKE;
|
|
43
|
+
export const POOL_ID_MANAGE = KEYSTONE_VERB_MANAGE;
|
|
44
|
+
export const POOL_ID_DEFAULT = "default";
|