@ibgib/core-gib 0.1.59 → 0.1.61
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/CHANGELOG.md +12 -1
- package/dist/common/other/graph-helper.d.mts.map +1 -1
- package/dist/common/other/graph-helper.mjs +7 -6
- package/dist/common/other/graph-helper.mjs.map +1 -1
- package/dist/keystone/keystone-config-builder.d.mts +1 -2
- package/dist/keystone/keystone-config-builder.d.mts.map +1 -1
- package/dist/keystone/keystone-config-builder.mjs +4 -19
- package/dist/keystone/keystone-config-builder.mjs.map +1 -1
- package/dist/keystone/keystone-constants.d.mts +2 -0
- package/dist/keystone/keystone-constants.d.mts.map +1 -1
- package/dist/keystone/keystone-constants.mjs +2 -0
- package/dist/keystone/keystone-constants.mjs.map +1 -1
- package/dist/keystone/keystone-helpers.d.mts +5 -15
- package/dist/keystone/keystone-helpers.d.mts.map +1 -1
- package/dist/keystone/keystone-helpers.mjs +59 -73
- package/dist/keystone/keystone-helpers.mjs.map +1 -1
- package/dist/keystone/keystone-policy-types.d.mts +6 -4
- package/dist/keystone/keystone-policy-types.d.mts.map +1 -1
- package/dist/keystone/keystone-service-v1.d.mts.map +1 -1
- package/dist/keystone/keystone-service-v1.mjs +4 -8
- package/dist/keystone/keystone-service-v1.mjs.map +1 -1
- package/dist/keystone/keystone-service-v1.respec.mjs +182 -33
- package/dist/keystone/keystone-service-v1.respec.mjs.map +1 -1
- package/dist/keystone/keystone-types.d.mts +4 -11
- package/dist/keystone/keystone-types.d.mts.map +1 -1
- package/dist/keystone/policy/keystone-profile-builder.d.mts +25 -0
- package/dist/keystone/policy/keystone-profile-builder.d.mts.map +1 -0
- package/dist/keystone/policy/keystone-profile-builder.mjs +117 -0
- package/dist/keystone/policy/keystone-profile-builder.mjs.map +1 -0
- package/dist/keystone/policy/profiles/profile-high.json +84 -0
- package/dist/keystone/policy/profiles/profile-low.json +84 -0
- package/dist/keystone/policy/profiles/profile-medium.json +84 -0
- package/dist/keystone/policy/profiles/profile-session.json +84 -0
- package/dist/keystone/policy/profiles/profile-test.json +84 -0
- package/dist/keystone/policy/schemas/connect-pool.high.schema.json +23 -0
- package/dist/keystone/policy/schemas/connect-pool.low.schema.json +23 -0
- package/dist/keystone/policy/schemas/connect-pool.medium.schema.json +23 -0
- package/dist/keystone/policy/schemas/keystone.high.schema.json +26 -0
- package/dist/keystone/policy/schemas/keystone.low.schema.json +26 -0
- package/dist/keystone/policy/schemas/keystone.medium.schema.json +26 -0
- package/dist/keystone/policy/schemas/manage-pool.high.schema.json +23 -0
- package/dist/keystone/policy/schemas/manage-pool.low.schema.json +23 -0
- package/dist/keystone/policy/schemas/manage-pool.medium.schema.json +23 -0
- package/dist/keystone/policy/schemas/revoke-pool.high.schema.json +23 -0
- package/dist/keystone/policy/schemas/revoke-pool.low.schema.json +23 -0
- package/dist/keystone/policy/schemas/revoke-pool.medium.schema.json +23 -0
- package/dist/keystone/policy/schemas/sign-pool.high.schema.json +23 -0
- package/dist/keystone/policy/schemas/sign-pool.low.schema.json +23 -0
- package/dist/keystone/policy/schemas/sign-pool.medium.schema.json +23 -0
- package/dist/keystone/policy/schemas/sync-pool.high.schema.json +23 -0
- package/dist/keystone/policy/schemas/sync-pool.low.schema.json +23 -0
- package/dist/keystone/policy/schemas/sync-pool.medium.schema.json +23 -0
- package/dist/sync/sync-conflict-adv-multitimelines.withid.respec.d.mts +8 -0
- package/dist/sync/sync-conflict-adv-multitimelines.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-conflict-adv-multitimelines.withid.respec.mjs +582 -0
- package/dist/sync/sync-conflict-adv-multitimelines.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-conflict-basic-divergence.withid.respec.d.mts +7 -0
- package/dist/sync/sync-conflict-basic-divergence.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-conflict-basic-divergence.withid.respec.mjs +274 -0
- package/dist/sync/sync-conflict-basic-divergence.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-conflict-basic-multitimelines.withid.respec.d.mts +8 -0
- package/dist/sync/sync-conflict-basic-multitimelines.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-conflict-basic-multitimelines.withid.respec.mjs +322 -0
- package/dist/sync/sync-conflict-basic-multitimelines.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-conflict-text-merge.withid.respec.d.mts +7 -0
- package/dist/sync/sync-conflict-text-merge.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-conflict-text-merge.withid.respec.mjs +307 -0
- package/dist/sync/sync-conflict-text-merge.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-innerspace-constants.withid.respec.d.mts +8 -0
- package/dist/sync/sync-innerspace-constants.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-innerspace-constants.withid.respec.mjs +233 -0
- package/dist/sync/sync-innerspace-constants.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-innerspace-deep-updates.withid.respec.d.mts +7 -0
- package/dist/sync/sync-innerspace-deep-updates.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-innerspace-deep-updates.withid.respec.mjs +233 -0
- package/dist/sync/sync-innerspace-deep-updates.withid.respec.mjs.map +1 -0
- 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 +225 -0
- package/dist/sync/sync-innerspace-dest-ahead.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-innerspace-multiple-timelines.respec.mjs.map +1 -1
- package/dist/sync/sync-innerspace-multiple-timelines.withid.respec.d.mts +7 -0
- package/dist/sync/sync-innerspace-multiple-timelines.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-innerspace-multiple-timelines.withid.respec.mjs +235 -0
- package/dist/sync/sync-innerspace-multiple-timelines.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-innerspace-partial-update.withid.respec.d.mts +7 -0
- package/dist/sync/sync-innerspace-partial-update.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-innerspace-partial-update.withid.respec.mjs +211 -0
- package/dist/sync/sync-innerspace-partial-update.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-innerspace.withid.respec.d.mts +8 -0
- package/dist/sync/sync-innerspace.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-innerspace.withid.respec.mjs +260 -0
- package/dist/sync/sync-innerspace.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs +1 -1
- package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs.map +1 -1
- package/dist/sync/sync-peer/sync-peer-types.d.mts +12 -1
- package/dist/sync/sync-peer/sync-peer-types.d.mts.map +1 -1
- package/dist/sync/sync-peer/sync-peer-v1.d.mts +7 -0
- package/dist/sync/sync-peer/sync-peer-v1.d.mts.map +1 -1
- package/dist/sync/sync-peer/sync-peer-v1.mjs +43 -1
- package/dist/sync/sync-peer/sync-peer-v1.mjs.map +1 -1
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.d.mts +2 -0
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.d.mts.map +1 -1
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.mjs +28 -9
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.mjs.map +1 -1
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.d.mts +1 -1
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.d.mts.map +1 -1
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs +5 -3
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs.map +1 -1
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.d.mts +16 -0
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.d.mts.map +1 -1
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mjs +223 -79
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mjs.map +1 -1
- package/dist/sync/sync-saga-context/sync-saga-context-helpers.d.mts.map +1 -1
- package/dist/sync/sync-saga-context/sync-saga-context-helpers.mjs +41 -2
- package/dist/sync/sync-saga-context/sync-saga-context-helpers.mjs.map +1 -1
- package/dist/sync/sync-saga-context/sync-saga-context-types.d.mts +4 -0
- package/dist/sync/sync-saga-context/sync-saga-context-types.d.mts.map +1 -1
- package/dist/sync/sync-saga-coordinator.d.mts +6 -0
- package/dist/sync/sync-saga-coordinator.d.mts.map +1 -1
- package/dist/sync/sync-saga-coordinator.mjs +213 -137
- package/dist/sync/sync-saga-coordinator.mjs.map +1 -1
- package/dist/sync/sync-withid.pingpong.respec.mjs +70 -2
- package/dist/sync/sync-withid.pingpong.respec.mjs.map +1 -1
- package/dist/timeline/timeline-api.d.mts.map +1 -1
- package/dist/timeline/timeline-api.mjs +1 -14
- package/dist/timeline/timeline-api.mjs.map +1 -1
- package/dist/witness/space/reconciliation-space/reconciliation-space-base.d.mts.map +1 -1
- package/dist/witness/space/reconciliation-space/reconciliation-space-base.mjs +0 -40
- package/dist/witness/space/reconciliation-space/reconciliation-space-base.mjs.map +1 -1
- package/dist/witness/space/reconciliation-space/reconciliation-space-helper.d.mts.map +1 -1
- package/dist/witness/space/reconciliation-space/reconciliation-space-helper.mjs +6 -6
- package/dist/witness/space/reconciliation-space/reconciliation-space-helper.mjs.map +1 -1
- package/ibgib-foundations.md +2 -1
- package/package.json +1 -1
- package/src/common/other/graph-helper.mts +7 -6
- package/src/keystone/README.md +19 -15
- package/src/keystone/docs/CRYPTANALYSIS.md +185 -0
- package/src/keystone/docs/architecture.md +24 -1
- package/src/keystone/docs/profiles.md +124 -0
- package/src/keystone/keystone-config-builder.mts +3 -21
- package/src/keystone/keystone-constants.mts +2 -0
- package/src/keystone/keystone-helpers.mts +74 -77
- package/src/keystone/keystone-policy-types.mts +6 -4
- package/src/keystone/keystone-service-v1.mts +4 -9
- package/src/keystone/keystone-service-v1.respec.mts +214 -32
- package/src/keystone/keystone-types.mts +5 -9
- package/src/keystone/policy/IMPLEMENTATION.md +60 -0
- package/src/keystone/policy/README.md +94 -0
- package/src/keystone/policy/keystone-profile-builder.mts +131 -0
- package/src/keystone/policy/profiles/profile-high.json +84 -0
- package/src/keystone/policy/profiles/profile-low.json +84 -0
- package/src/keystone/policy/profiles/profile-medium.json +84 -0
- package/src/keystone/policy/profiles/profile-session.json +84 -0
- package/src/keystone/policy/profiles/profile-test.json +84 -0
- package/src/keystone/policy/schemas/connect-pool.high.schema.json +23 -0
- package/src/keystone/policy/schemas/connect-pool.low.schema.json +23 -0
- package/src/keystone/policy/schemas/connect-pool.medium.schema.json +23 -0
- package/src/keystone/policy/schemas/keystone.high.schema.json +26 -0
- package/src/keystone/policy/schemas/keystone.low.schema.json +26 -0
- package/src/keystone/policy/schemas/keystone.medium.schema.json +26 -0
- package/src/keystone/policy/schemas/manage-pool.high.schema.json +23 -0
- package/src/keystone/policy/schemas/manage-pool.low.schema.json +23 -0
- package/src/keystone/policy/schemas/manage-pool.medium.schema.json +23 -0
- package/src/keystone/policy/schemas/revoke-pool.high.schema.json +23 -0
- package/src/keystone/policy/schemas/revoke-pool.low.schema.json +23 -0
- package/src/keystone/policy/schemas/revoke-pool.medium.schema.json +23 -0
- package/src/keystone/policy/schemas/sign-pool.high.schema.json +23 -0
- package/src/keystone/policy/schemas/sign-pool.low.schema.json +23 -0
- package/src/keystone/policy/schemas/sign-pool.medium.schema.json +23 -0
- package/src/keystone/policy/schemas/sync-pool.high.schema.json +23 -0
- package/src/keystone/policy/schemas/sync-pool.low.schema.json +23 -0
- package/src/keystone/policy/schemas/sync-pool.medium.schema.json +23 -0
- package/src/sync/docs/security-3b.md +92 -0
- package/src/sync/docs/security.md +139 -38
- package/src/sync/sync-conflict-adv-multitimelines.withid.respec.mts +706 -0
- package/src/sync/sync-conflict-basic-divergence.withid.respec.mts +321 -0
- package/src/sync/sync-conflict-basic-multitimelines.withid.respec.mts +374 -0
- package/src/sync/sync-conflict-text-merge.withid.respec.mts +347 -0
- package/src/sync/sync-innerspace-constants.withid.respec.mts +264 -0
- package/src/sync/sync-innerspace-deep-updates.withid.respec.mts +272 -0
- package/src/sync/sync-innerspace-dest-ahead.withid.respec.mts +266 -0
- package/src/sync/sync-innerspace-multiple-timelines.respec.mts +0 -1
- package/src/sync/sync-innerspace-multiple-timelines.withid.respec.mts +273 -0
- package/src/sync/sync-innerspace-partial-update.withid.respec.mts +249 -0
- package/src/sync/sync-innerspace.withid.respec.mts +265 -0
- package/src/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mts +1 -1
- package/src/sync/sync-peer/sync-peer-types.mts +11 -1
- package/src/sync/sync-peer/sync-peer-v1.mts +47 -1
- package/src/sync/sync-peer/sync-peer-websocket/README.md +42 -0
- package/src/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.mts +26 -9
- package/src/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mts +5 -3
- package/src/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mts +242 -78
- package/src/sync/sync-saga-context/sync-saga-context-helpers.mts +46 -4
- package/src/sync/sync-saga-context/sync-saga-context-types.mts +5 -0
- package/src/sync/sync-saga-coordinator.mts +221 -137
- package/src/sync/sync-withid.pingpong.respec.mts +76 -3
- package/src/timeline/timeline-api.mts +1 -15
- package/src/timeline/timeline-api.respec.mts +3 -3
- package/src/witness/space/reconciliation-space/reconciliation-space-base.mts +0 -46
- package/src/witness/space/reconciliation-space/reconciliation-space-helper.mts +6 -5
- package/tsconfig.json +6 -1
- package/src/keystone/keystone-policy.schema.json +0 -51
- package/src/sync/docs/ping_pong_plan.md +0 -147
- package/src/witness/space/reconciliation-space/reconciliation-space-base.mts.OLD.md +0 -884
- package/src/witness/space/reconciliation-space/reconciliation-space-helper.mts.OLD.md +0 -125
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# Cryptanalysis of the Keystone Identity System
|
|
2
|
+
|
|
3
|
+
This document outlines the cryptographic specifications, mathematical bounds, and security assertions of the Keystone challenge-response identity system (V1).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Mathematical Bounds of Target Binding
|
|
8
|
+
|
|
9
|
+
Target Binding maps a target address (`ib` + `gib`) to a deterministic selection of challenge IDs from a pool.
|
|
10
|
+
|
|
11
|
+
### 1.1 Combinatorial Probability of Forgery
|
|
12
|
+
When Alice signs a claim, she reveals a subset of secrets. If a transmission fails, or if Alice interacts with a compromised node, an attacker may intercept these solutions.
|
|
13
|
+
|
|
14
|
+
Let:
|
|
15
|
+
* $M$ = Total number of active challenges in the pool.
|
|
16
|
+
* $C$ = Number of target binding challenges required per signature.
|
|
17
|
+
* $K$ = Number of unique solutions the attacker has intercepted.
|
|
18
|
+
|
|
19
|
+
The probability $P$ that a new, randomly selected target address maps entirely to a subset of the $K$ known secrets is given by:
|
|
20
|
+
|
|
21
|
+
$$P = \frac{\binom{K}{C}}{\binom{M}{C}}$$
|
|
22
|
+
|
|
23
|
+
The attacker can "grind" (tweak the salt, timestamp, or minor metadata of a forged claim) until they find a target address that has a target-binding selection mapping entirely to the $K$ solutions they possess.
|
|
24
|
+
|
|
25
|
+
The average number of grinding iterations required is:
|
|
26
|
+
$$N_{\text{grind}} = \frac{1}{P} = \frac{\binom{M}{C}}{\binom{K}{C}}$$
|
|
27
|
+
|
|
28
|
+
### 1.2 Quantitative Security Presets (at $C = 10$, $K = 20$)
|
|
29
|
+
|
|
30
|
+
Assuming $C = 10$ target binding characters are required, and the attacker has intercepted $K = 20$ solutions from a single aborted evolution:
|
|
31
|
+
|
|
32
|
+
| Pool Size ($M$) | Combinatorial Probability ($P$) | Avg. Grinding Operations ($1/P$) | Classical Security Rating |
|
|
33
|
+
| :--- | :--- | :--- | :--- |
|
|
34
|
+
| **50** (Medium/Low) | $1.8 \times 10^{-5}$ | $\approx 5.5 \times 10^4$ | **Insecure** (grinded in < 1 ms on a CPU) |
|
|
35
|
+
| **100** (Medium) | $1.07 \times 10^{-8}$ | $\approx 9.3 \times 10^7$ | **Low** (grinded in < 1 second on a CPU) |
|
|
36
|
+
| **500** (High) | $7.0 \times 10^{-16}$ | $\approx 1.4 \times 10^{15}$ | **Medium** (requires substantial CPU/GPU effort) |
|
|
37
|
+
| **1000** (Ultra) | $7.0 \times 10^{-19}$ | $\approx 1.4 \times 10^{18}$ | **High** (computationally infeasible for standard attackers) |
|
|
38
|
+
|
|
39
|
+
### 1.3 Key Takeaway for Pool Configurations
|
|
40
|
+
* **Small Pools ($M \le 100$)** are highly vulnerable to grinding attacks *if* the attacker intercepts even a single aborted/failed transition where the client modifies the target payload (e.g., updating the timestamp for a retry).
|
|
41
|
+
* **Mitigation**: For small pools to remain secure, **retries must be byte-for-byte identical** (no timestamp/nonce updates), ensuring no new secrets are leaked. Otherwise, pool sizes of **500+** are required to support arbitrary dynamic retries.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## 2. Hash Function Strength: SHA-256 vs. SHA-512
|
|
46
|
+
|
|
47
|
+
While the combinatorial distribution $P$ is identical for both hash functions, the underlying cryptographic strength differs.
|
|
48
|
+
|
|
49
|
+
| Metric | SHA-256 | SHA-512 |
|
|
50
|
+
| :--- | :--- | :--- |
|
|
51
|
+
| **Classical Pre-image Strength** | $2^{256}$ operations | $2^{512}$ operations |
|
|
52
|
+
| **Quantum Pre-image Strength (Grover)** | $2^{128}$ operations | $2^{256}$ operations (complete quantum immunity) |
|
|
53
|
+
| **ASIC Grinding Ecosystem** | Massive (repurposable Bitcoin hardware) | None (commodity CPUs/GPUs only) |
|
|
54
|
+
|
|
55
|
+
### 2.1 ASIC Grinding Mitigation
|
|
56
|
+
Because Bitcoin miners utilize SHA-256, specialized, highly efficient ASIC mining rigs exist globally. An attacker could theoretically lease SHA-256 hash power to perform grinding attacks on Keystone targets.
|
|
57
|
+
|
|
58
|
+
Transitioning to **SHA-512** removes this threat vector entirely, as there is no equivalent commodity hardware infrastructure, raising the real-world dollar cost of any grinding attack.
|
|
59
|
+
|
|
60
|
+
## 3. Challenge ID Length & Salting Analysis
|
|
61
|
+
|
|
62
|
+
In Keystone V1, the `challengeId` is generated as the truncated hash of the pool salt, timestamp, and challenge index. Crucially, the `challengeId` acts directly as the **cryptographic salt (`indexSalt`)** during the generation and verification of both the solution values and challenge hashes:
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
// Derivation in KeystoneStrategy_HashRevealV1:
|
|
66
|
+
const indexSalt = challengeId;
|
|
67
|
+
current = Hash(indexSalt + current + indexSalt) ^ Rounds;
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
This dual-role introduces two design constraints: collision resistance and multi-target pre-computation resistance.
|
|
71
|
+
|
|
72
|
+
### 3.1 Collision Probability (Birthday Paradox)
|
|
73
|
+
We analyze the probability of a collision (two challenges having the same ID) within a single active keystone frame's pool of size $M$ over a key space of $d = 2^{B \cdot 4}$ (where $B$ is the number of hex characters, each representing 4 bits of entropy):
|
|
74
|
+
|
|
75
|
+
$$P_{\text{collision}} \approx 1 - e^{-\frac{M^2}{2d}}$$
|
|
76
|
+
|
|
77
|
+
Let's evaluate collision probabilities across three key lengths at a large pool size of $M = 2000$:
|
|
78
|
+
|
|
79
|
+
* **10 characters (40 bits)**: $d = 2^{40} \approx 1.1 \times 10^{12}$
|
|
80
|
+
$$P_{\text{collision}} \approx 1 - e^{-\frac{4 \cdot 10^6}{2.2 \cdot 10^{12}}} \approx 1.8 \times 10^{-6}$$
|
|
81
|
+
*(Not acceptable: A collision is likely to occur once in every 550,000 frames.)*
|
|
82
|
+
* **12 characters (48 bits)**: $d = 2^{48} \approx 2.8 \times 10^{14}$
|
|
83
|
+
$$P_{\text{collision}} \approx 1 - e^{-\frac{4 \cdot 10^6}{5.6 \cdot 10^{14}}} \approx 7.1 \times 10^{-9}$$
|
|
84
|
+
*(Highly secure: 1 in 140 million chance of collision.)*
|
|
85
|
+
* **16 characters (64 bits)**: $d = 2^{64} \approx 1.8 \times 10^{19}$
|
|
86
|
+
$$P_{\text{collision}} \approx 1 - e^{-\frac{4 \cdot 10^6}{3.6 \cdot 10^{19}}} \approx 1.1 \times 10^{-13}$$
|
|
87
|
+
*(Astronomically secure.)*
|
|
88
|
+
|
|
89
|
+
### 3.2 Multi-Target Pre-computation (Rainbow Table) Defense
|
|
90
|
+
Because the `challengeId` is used as a salt (`indexSalt`) for the solution derivation, it prevents an attacker from building a generic, reusable pre-computation database (like rainbow tables) to crack solutions across different pools or different slots in the same pool.
|
|
91
|
+
|
|
92
|
+
If the salt is too short, an attacker can pre-compute a table of solutions for a large number of common salts:
|
|
93
|
+
* **40-bit salt (10 chars)**: The search space ($2^{40}$) is small enough that a well-funded adversary could pre-calculate a complete table mapping `poolSecret` and `challengeId` combinations, speeding up cracking times.
|
|
94
|
+
* **48-bit salt (12 chars)**: The search space ($2^{48}$) is significantly harder to pre-calculate, but still within theoretical reach of nation-state or high-end distributed cloud infrastructures.
|
|
95
|
+
* **64-bit salt (16 chars)**: The search space ($2^{64}$) is globally recognized as computationally impossible to pre-compute.
|
|
96
|
+
|
|
97
|
+
### 3.3 Influence of Truncation on Solution Entropy
|
|
98
|
+
Importantly, **truncating the `challengeId` does NOT reduce the entropy of the secret solution itself.**
|
|
99
|
+
The solution is a full-length hash (e.g. 256-bit or 512-bit) derived from the secret master key. The `challengeId` is only the salt. Therefore, even if the `challengeId` is truncated to 12 characters, a pre-image attack aiming to guess the secret solution still faces a search space of $2^{256}$ or $2^{512}$.
|
|
100
|
+
|
|
101
|
+
### 3.4 Quantum Pre-image Attacks & Grover's Algorithm
|
|
102
|
+
Quantum computers will theoretically accelerate pre-image search attacks using Grover's search algorithm, which provides a quadratic speedup.
|
|
103
|
+
* A search space of $2^b$ is reduced to $2^{b/2}$ quantum operations.
|
|
104
|
+
* For SHA-256 solutions, Grover's algorithm reduces the security margin from 256 bits to **128 bits**. 128 bits is still globally considered secure against any foreseeable quantum threat.
|
|
105
|
+
* For SHA-512 solutions, Grover's algorithm reduces the security margin from 512 bits to **256 bits** (the gold standard for quantum immunity).
|
|
106
|
+
* Grover's algorithm does not make pre-computation (rainbow tables) easier; it only speeds up direct brute-force guessing of the in-flight secret solution.
|
|
107
|
+
|
|
108
|
+
### 3.5 Storage Costs vs. Security Benefits
|
|
109
|
+
Comparing storage space requirements for a pool of size $M = 2000$:
|
|
110
|
+
* **12-char Keys**: $2000 \times 12 \text{ bytes} = 24 \text{ KB}$
|
|
111
|
+
* **16-char Keys**: $2000 \times 16 \text{ bytes} = 32 \text{ KB}$
|
|
112
|
+
|
|
113
|
+
**Conclusion**: 16 characters (64 bits) remains the recommended default for production deployments because it provides absolute collision immunity ($10^{-13}$) and complete protection against multi-target pre-computation attacks, for an insignificantly small storage premium (+8 KB per 2,000 challenges). For low-resource networks, 12 characters (48 bits) is a viable alternative.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## 4. Keystone Security & Performance Profiles (Presets)
|
|
118
|
+
|
|
119
|
+
To balance performance (CPU rounds, database footprint) with security (grinding protection, pre-image resistance), we define five standard profiles:
|
|
120
|
+
|
|
121
|
+
### 4.1 "Test" Profile
|
|
122
|
+
* **Purpose**: Unit testing and rapid local prototyping.
|
|
123
|
+
* **Performance**: Near-instantaneous execution.
|
|
124
|
+
* **Configuration**:
|
|
125
|
+
* Pool Size ($M$): `12`
|
|
126
|
+
* Algorithm: `SHA-256`
|
|
127
|
+
* Rounds: `1`
|
|
128
|
+
* Replenishment: `top-up`
|
|
129
|
+
* Selection: `1` Sequential (FIFO) + `1` Random
|
|
130
|
+
* Target Binding Count: `3`
|
|
131
|
+
* **Security Grade**: **Weak/Non-existent**. Easily broken by grinding. Strictly for offline/developer use.
|
|
132
|
+
|
|
133
|
+
### 4.2 "Session" (Very Short-Lived) Profile
|
|
134
|
+
* **Purpose**: Ephemeral session-scoped keystones (e.g., sync sagas).
|
|
135
|
+
* **Performance**: Fast generation/handshake, keeping UI responsiveness high.
|
|
136
|
+
* **Configuration**:
|
|
137
|
+
* Pool Size ($M$): `50`
|
|
138
|
+
* Algorithm: `SHA-256`
|
|
139
|
+
* Rounds: `1`
|
|
140
|
+
* Replenishment: `top-up`
|
|
141
|
+
* Selection: `2` Sequential (FIFO) + `2` Random
|
|
142
|
+
* Target Binding Count: `6` (12 characters recommended for `challengeId` salt)
|
|
143
|
+
* **Security Rationale**: A sync session saga typically evolves only 3 to 5 times (Init $\to$ Ack $\to$ Delta $\to$ Commit/Conflict) and is bound to a single transaction lifespan. Once completed, the session is discarded, preventing attackers from accumulating enough secrets to forge transitions before the transaction context expires.
|
|
144
|
+
|
|
145
|
+
### 4.3 "Low" Profile
|
|
146
|
+
* **Purpose**: Low-value transactions or high-frequency web hooks.
|
|
147
|
+
* **Configuration**:
|
|
148
|
+
* Pool Size ($M$): `100`
|
|
149
|
+
* Algorithm: `SHA-256`
|
|
150
|
+
* Rounds: `1`
|
|
151
|
+
* Replenishment: `top-up`
|
|
152
|
+
* Selection: `3` Sequential (FIFO) + `3` Random
|
|
153
|
+
* Target Binding Count: `8`
|
|
154
|
+
* **Security Grade**: **Moderate**. Requires strict client/server enforcement of byte-for-byte identical retries to prevent pool secret leakage under network failures.
|
|
155
|
+
|
|
156
|
+
### 4.4 "Medium" Profile (Standard Production Default)
|
|
157
|
+
* **Purpose**: Standard user identity, sync authorizations, and general credentials.
|
|
158
|
+
* **Configuration**:
|
|
159
|
+
* Pool Size ($M$): `500`
|
|
160
|
+
* Algorithm: `SHA-256`
|
|
161
|
+
* Rounds: `2`
|
|
162
|
+
* Replenishment: `top-up`
|
|
163
|
+
* Selection: `5` Sequential (FIFO) + `5` Random
|
|
164
|
+
* Target Binding Count: `10`
|
|
165
|
+
* **Security Grade**: **Strong**. Grinding search space is $\approx 1.4 \times 10^{15}$ hashes, rendering attacks economically impractical for standard targets.
|
|
166
|
+
|
|
167
|
+
### 4.5 "High" Profile (Root/Admin Default)
|
|
168
|
+
* **Purpose**: Root identity management (`manage`), recovery, and revocation (`revoke`).
|
|
169
|
+
* **Configuration**:
|
|
170
|
+
* Pool Size ($M$): `2000`
|
|
171
|
+
* Algorithm: `SHA-512`
|
|
172
|
+
* Rounds: `4`
|
|
173
|
+
* Replenishment: `replace-all` (or `delete-all` for revocation)
|
|
174
|
+
* Selection: `10` Sequential (FIFO) + `10` Random
|
|
175
|
+
* Target Binding Count: `16`
|
|
176
|
+
* **Security Grade**: **Ultra/Quantum-Resistant**. Fully immune to multi-target pre-computation, ASIC mining farms, and quantum pre-image attacks.
|
|
177
|
+
|
|
178
|
+
### 4.6 Mathematical Rationale for Lower Hashing Rounds
|
|
179
|
+
Because the Keystone system derives `indexSalt` (the `challengeId`) dynamically for each challenge, pre-computation lookup tables (rainbow tables) are completely blocked. An attacker must perform a first-preimage attack to crack any individual challenge solution, which requires brute-forcing a full-length hash (256-bit or 512-bit). Since $2^{256}$ is mathematically secure, raising `rounds` does not increase this pre-image margin.
|
|
180
|
+
|
|
181
|
+
Furthermore, **grinding target addresses does not require evaluating the hash rounds**. When an attacker grinds the claim metadata to find a target address that maps to their known solution indices, they only hash the target address to find the indices (which is a fast 1-round operation). They do not need to evaluate the challenge values themselves during grinding.
|
|
182
|
+
|
|
183
|
+
Therefore, increasing `rounds` to high numbers (e.g. 10 or 15) only adds significant CPU overhead during pool initialization/replenishment (e.g. computing 20,000 hashes on a weak device), without providing any corresponding security benefits against target grinding. Reducing `rounds` to **1 (Session/Low)**, **2 (Medium)**, or **4 (High)** maintains sub-millisecond execution times while preserving all mathematical security guarantees.
|
|
184
|
+
|
|
185
|
+
|
|
@@ -46,7 +46,7 @@ See [KeystoneService_V1.addPools()](file:../keystone-service-v1.mts) for impleme
|
|
|
46
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:
|
|
47
47
|
|
|
48
48
|
1. **Mandatory Demands**: The verifier explicitly requests specific challenge IDs.
|
|
49
|
-
2. **Target Binding**:
|
|
49
|
+
2. **Target Binding (Hash-Based Index Selection)**: We select challenges from the pool deterministically by sorting all available challenge IDs alphabetically, recursively hashing the `targetAddr` (ib + gib), and drawing challenges modulo the remaining pool size (Drawing Without Replacement). This guarantees collision resistance, avoids 'entropy exhaustion' crashes, and ensures that different targets select unique, unpredictable challenge sets without needing large pool sizes.
|
|
50
50
|
3. **FIFO**: Consumes $N$ challenges from the "front" of the pool (Performance).
|
|
51
51
|
4. **Stochastic**: Randomly selects $N$ additional challenges (Anti-Grinding).
|
|
52
52
|
|
|
@@ -100,3 +100,26 @@ The full state of a Keystone identity is reconstructed by walking back through t
|
|
|
100
100
|
To avoid O(N) walk-back performance for long-lived identities, the `KeystoneService_V1` automatically generates a **Checkpoint** every $N$ evolutions (configured via `KEYSTONE_CHECKPOINT_FREQUENCY`).
|
|
101
101
|
|
|
102
102
|
A Checkpoint stores the *full aggregated state* at that point in time. When the aggregation walker encounters a frame with `checkpointDetails`, it merges those details and **stops**, effectively capping the walk-back length.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 7. Next-Gen Deterministic Binding (Todo List)
|
|
107
|
+
|
|
108
|
+
This section outlines the plan to update the binding mechanism to use **Hash-Based Index Selection (Drawing Without Replacement)** instead of the rigid `bindingMap` bucketing scheme.
|
|
109
|
+
|
|
110
|
+
- [x] **Phase 1: Pre-Verification & Test Baselining**
|
|
111
|
+
- [x] Run current tests to ensure they are green (`respec-gib` test suite).
|
|
112
|
+
- [x] **Phase 2: Code Implementation**
|
|
113
|
+
- [x] Update `KeystonePoolBehavior` to support the new index selection parameter (re-purposing or keeping `targetBindingChars` parameter).
|
|
114
|
+
- [x] Implement the drawing-without-replacement deterministic index selection algorithm in `getDeterministicRequirements()` (in `keystone-helpers.mts`).
|
|
115
|
+
- [x] Sort available challenge IDs alphabetically.
|
|
116
|
+
- [x] Use `targetAddr` (combined `ib` + `gib`) as the binding input instead of just `targetGib`.
|
|
117
|
+
- [x] Recursively hash the binding input and select indices using modulo of the shrinking list size.
|
|
118
|
+
- [x] Add configuration validation check in `validateChallengePool()` (in `keystone-helpers.mts`) to enforce `selectSequentially + selectRandomly + targetBindingChars < size` (prevents MITM/exhaustion exposure).
|
|
119
|
+
- [x] Update JSDocs and parameter descriptions in `keystone-types.mts` and `keystone-helpers.mts`.
|
|
120
|
+
- [x] **Phase 3: Test Updates**
|
|
121
|
+
- [x] Refactor unit tests in `keystone-service-v1.respec.mts` to use the new selection logic.
|
|
122
|
+
- [x] Add specific validation tests proving zero entropy exhaustion and high sensitivity to single-bit changes in `targetAddr`.
|
|
123
|
+
- [x] **Phase 4: Documentation Audit**
|
|
124
|
+
- [x] Go through all Keystone docs (including this file, `README.md`, and any user-facing guides) and update all references to the binding mechanism to reflect the new hash-based selection algorithm.
|
|
125
|
+
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# Keystone Security Profiles & Policies
|
|
2
|
+
|
|
3
|
+
Keystone configurations are standardized using JSON-based Policy Profiles. These profiles allow downstream applications to select predefined security levels (from `test` to `high`) or define custom ones that validate against a strict JSON Schema.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Predefined Security Profiles
|
|
8
|
+
|
|
9
|
+
The repository provides five prebuilt profiles in `@ibgib/core-gib/dist/keystone/profiles/`:
|
|
10
|
+
|
|
11
|
+
| Profile | Target Size | Hash Algo | Rounds | Selection (Seq+Rand) | Binding Count | Use Case |
|
|
12
|
+
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|
|
13
|
+
| **`test`** | 12 | SHA-256 | 1 | 1 + 1 | 3 | Fast development / unit tests. |
|
|
14
|
+
| **`session`** | 50 | SHA-256 | 1 | 2 + 2 | 6 | Short-lived WS sync sagas (connect). |
|
|
15
|
+
| **`low`** | 100 | SHA-256 | 1 | 3 + 3 | 8 | Medium lifespan, low-overhead client keys. |
|
|
16
|
+
| **`medium`** | 500 | SHA-256 | 2 | 5 + 5 | 10 | Standard production identity keys. |
|
|
17
|
+
| **`high`** | 2000 | SHA-512 | 4 | 10 + 10 | 16 | High-security cold/warm root keys. |
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 2. Consuming Profile Policies in Code
|
|
22
|
+
|
|
23
|
+
To apply a profile to a Keystone identity at genesis, import the JSON file and use the `createPoolConfigFromJson` factory helper:
|
|
24
|
+
|
|
25
|
+
### Example: Initializing Genesis with the Medium Profile
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import { KeystoneService_V1 } from "@ibgib/core-gib/dist/keystone/keystone-service-v1.mjs";
|
|
29
|
+
import { createPoolConfigFromJson } from "@ibgib/core-gib/dist/keystone/keystone-config-builder.mjs";
|
|
30
|
+
|
|
31
|
+
// Import the prebuilt profile JSON
|
|
32
|
+
import profileMedium from "@ibgib/core-gib/dist/keystone/profiles/profile-medium.json" assert { type: 'json' };
|
|
33
|
+
|
|
34
|
+
async function createIdentity(masterSecret: string, metaspace: any, space: any) {
|
|
35
|
+
// 1. Map the JSON templates to concrete KeystonePoolConfig objects
|
|
36
|
+
const configs = Object.values(profileMedium.pools).map(template => {
|
|
37
|
+
return createPoolConfigFromJson({
|
|
38
|
+
template: template as any,
|
|
39
|
+
behaviorProfiles: profileMedium.behaviorProfiles as any,
|
|
40
|
+
salt: `${template.id}_pool_salt` // Unique salt per pool
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// 2. Perform genesis
|
|
45
|
+
const keystoneService = new KeystoneService_V1();
|
|
46
|
+
const keystoneIbGib = await keystoneService.genesis({
|
|
47
|
+
masterSecret,
|
|
48
|
+
configs,
|
|
49
|
+
metaspace,
|
|
50
|
+
space,
|
|
51
|
+
frameDetails: { client: 'my-app', timestamp: Date.now() }
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
return keystoneIbGib;
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 3. Creating Custom Profiles
|
|
61
|
+
|
|
62
|
+
Custom policy profiles must match the JSON Schema at [keystone-policy.schema.json](../keystone-policy.schema.json).
|
|
63
|
+
|
|
64
|
+
### Structure of a Profile JSON File
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"$schema": "../keystone-policy.schema.json",
|
|
69
|
+
"behaviorProfiles": {
|
|
70
|
+
"my-custom-behavior": {
|
|
71
|
+
"size": 300,
|
|
72
|
+
"replenish": "top-up",
|
|
73
|
+
"selectSequentially": 3,
|
|
74
|
+
"selectRandomly": 3,
|
|
75
|
+
"targetBindingCount": 8
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"pools": {
|
|
79
|
+
"sync": {
|
|
80
|
+
"id": "sync",
|
|
81
|
+
"allowedVerbs": ["sync"],
|
|
82
|
+
"behaviorProfile": "my-custom-behavior",
|
|
83
|
+
"algo": "SHA-256",
|
|
84
|
+
"rounds": 2
|
|
85
|
+
},
|
|
86
|
+
"manage": {
|
|
87
|
+
"id": "manage",
|
|
88
|
+
"allowedVerbs": ["manage"],
|
|
89
|
+
"behaviorInline": {
|
|
90
|
+
"size": 1000,
|
|
91
|
+
"replenish": "replace-all",
|
|
92
|
+
"selectSequentially": 5,
|
|
93
|
+
"selectRandomly": 5,
|
|
94
|
+
"targetBindingCount": 12
|
|
95
|
+
},
|
|
96
|
+
"algo": "SHA-512",
|
|
97
|
+
"rounds": 5
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Property Reference
|
|
104
|
+
|
|
105
|
+
#### behaviorProfiles
|
|
106
|
+
A dictionary of shared behavior templates. Each template contains:
|
|
107
|
+
* **`size`**: `number`. The capacity of the challenge pool.
|
|
108
|
+
* **`replenish`**: `string`. The strategy for refilling the pool when challenges are consumed:
|
|
109
|
+
* `"top-up"`: Generates new challenges to replace only those used. Recommended for normal, reusable signing keys.
|
|
110
|
+
* `"replace-all"`: Discards the remaining pool and generates a completely fresh set of challenges when any are used. Recommended for high-security pools to prevent long-term grinding.
|
|
111
|
+
* `"consume"`: Consumes challenges without replenishing them (limiting the total amount of evolutions possible).
|
|
112
|
+
* `"delete-all"`: Clears all challenges permanently (used for Scorched-Earth revocation).
|
|
113
|
+
* **`selectSequentially`**: `number`. Number of challenges solved in FIFO order from the front of the pool.
|
|
114
|
+
* **`selectRandomly`**: `number`. Number of challenges solved stochastically.
|
|
115
|
+
* **`targetBindingCount`**: `number`. Number of challenges selected deterministically via the hash-based selection algorithm bound to the `targetAddr` of the claim.
|
|
116
|
+
|
|
117
|
+
#### pools
|
|
118
|
+
Defines the individual challenge pools for the keystone:
|
|
119
|
+
* **`id`**: `string`. A unique identifier within the keystone frame.
|
|
120
|
+
* **`allowedVerbs`**: `string[]`. List of verbs (operations) this pool is authorized to sign.
|
|
121
|
+
* **`algo`**: `"SHA-256" | "SHA-512"`. Cryptographic hash algorithm used for challenges.
|
|
122
|
+
* **`rounds`**: `number`. Number of iterations for the key derivation function (KDF) challenge loop.
|
|
123
|
+
* **`behaviorProfile`**: `string`. (Optional) References a key in `behaviorProfiles`.
|
|
124
|
+
* **`behaviorInline`**: `object`. (Optional) An inline declaration of behavior properties if not using a shared profile.
|
|
@@ -113,7 +113,7 @@ export abstract class KeystoneConfigBuilderBase<TConfig extends KeystonePoolConf
|
|
|
113
113
|
replenish: this._replenish,
|
|
114
114
|
selectSequentially: this._seq,
|
|
115
115
|
selectRandomly: this._rand,
|
|
116
|
-
|
|
116
|
+
targetBindingCount: this._targetBinding,
|
|
117
117
|
};
|
|
118
118
|
}
|
|
119
119
|
|
|
@@ -347,30 +347,12 @@ export function createConnectPoolConfig(opts: KeystoneConfigFactoryOptions_Stand
|
|
|
347
347
|
*/
|
|
348
348
|
export function createPoolConfigFromJson({
|
|
349
349
|
template,
|
|
350
|
-
behaviorProfiles,
|
|
351
350
|
salt
|
|
352
351
|
}: {
|
|
353
352
|
template: KeystonePoolTemplate;
|
|
354
|
-
behaviorProfiles?: Record<string, KeystoneBehaviorProfileTemplate>;
|
|
355
353
|
salt: string;
|
|
356
354
|
}): KeystonePoolConfig {
|
|
357
|
-
|
|
358
|
-
if (template.behaviorProfile && behaviorProfiles) {
|
|
359
|
-
behavior = behaviorProfiles[template.behaviorProfile];
|
|
360
|
-
}
|
|
361
|
-
if (!behavior) {
|
|
362
|
-
behavior = template.behaviorInline;
|
|
363
|
-
}
|
|
364
|
-
if (!behavior) {
|
|
365
|
-
behavior = {
|
|
366
|
-
size: KEYSTONE_CONFIG_DEFAULT_SIZE,
|
|
367
|
-
replenish: KEYSTONE_CONFIG_DEFAULT_REPLENISH_STRATEGY,
|
|
368
|
-
selectSequentially: KEYSTONE_CONFIG_DEFAULT_SEQUENTIAL,
|
|
369
|
-
selectRandomly: KEYSTONE_CONFIG_DEFAULT_RANDOM,
|
|
370
|
-
targetBindingChars: KEYSTONE_CONFIG_DEFAULT_BINDING
|
|
371
|
-
};
|
|
372
|
-
}
|
|
373
|
-
|
|
355
|
+
const behavior = template.behavior;
|
|
374
356
|
return KeystoneConfig.hash()
|
|
375
357
|
.withId(template.id)
|
|
376
358
|
.withSalt(salt)
|
|
@@ -379,7 +361,7 @@ export function createPoolConfigFromJson({
|
|
|
379
361
|
seqCount: behavior.selectSequentially,
|
|
380
362
|
randCount: behavior.selectRandomly,
|
|
381
363
|
})
|
|
382
|
-
.withTargetBinding(behavior.
|
|
364
|
+
.withTargetBinding(behavior.targetBindingCount)
|
|
383
365
|
.withReplenishStrategy(behavior.replenish)
|
|
384
366
|
.withHash({
|
|
385
367
|
algo: template.algo,
|
|
@@ -4,6 +4,8 @@ import { KeystoneReplenishStrategy } from "./keystone-types.mjs";
|
|
|
4
4
|
export const KEYSTONE_ATOM = "keystone";
|
|
5
5
|
export const KEYSTONE_POOL_ID_REGEXP = /^\w[\w\-.]*$/;
|
|
6
6
|
export const KEYSTONE_SALT_REGEXP = /^[a-zA-Z0-9\-_]{1,64}$/;
|
|
7
|
+
export const KEYSTONE_USERNAME_REGEXP = /^[a-zA-Z0-9_\-.]{1,63}$/;
|
|
8
|
+
export const KEYSTONE_DESCRIPTION_REGEXP = /^[a-zA-Z0-9\s.,!?:;'"\-()[\]_+=@#$%&*\/]{0,128}$/;
|
|
7
9
|
/**
|
|
8
10
|
* arbitrary right now. don't want an easy DoS. this may still be too high.
|
|
9
11
|
*/
|