Skip to content

Commit 4c4653d

Browse files
committed
#256 add validation process steps docs
1 parent ecff559 commit 4c4653d

4 files changed

Lines changed: 217 additions & 11 deletions

File tree

docs/concepts/concepts-index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ The reader is expected to have basic familiarity with the following concepts:
1616
## Threshold Encryption
1717

1818
- [High Level Client Integration Flow](./threshold-encryption/3-full-client-flow.md)
19-
Explains the client role in th full process. Includes detailed data structured used, but provides very little detail on the processes. Good if you just need to know the basics.
19+
Explains the client role in the full process. Includes detailes about data structures used, but provides little detail on the underlying processes. Good if you just need to know the basics.
2020

2121
- [Threshold Encryption: Full Flow](./threshold-encryption/2-te-full-flow.md)
2222
End-to-end description of the API-exposed threshold encryption process involving key generation, encryption, and decryption. Includes all process details of all stages. Does not include details on the underlying mathematics. Good if you need to know how the entire process works, and how threshold encryption is used.

docs/concepts/threshold-encryption/1-threshold-encryption.md

Lines changed: 203 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,9 @@ This means that:
100100
r * Y = r * (s * P) = s * (r * P) = s * U
101101
```
102102

103-
Since we have access to `U`, we need to somehow `s`. This is what the decryption process is about - collecting enough private key shares in order to merge them into `s`. This is all done implicitely, without ever allowing any party to know `s`. That is, the decryption process results in the production of `r * Y = s * U`, without ever:
104-
- Knowing any private key share `s_i`
105-
- Knowing the sphemeral secret `r`
103+
Since we have access to `U`, we need to somehow compute `s`. This is what the decryption process is about - collecting enough private key shares in order to merge them into `s`. This is all done implicitly, without ever allowing any party to know `s`. That is, the decryption process results in the production of `r * Y = s * U`, without ever:
104+
- Knowing any private key share `s_i` (besides possibly its own)
105+
- Knowing the ephemeral secret `r`
106106
- Knowing the common private key `s`
107107

108108

@@ -191,9 +191,207 @@ and we get the original plaintext.
191191

192192
---
193193

194-
# 3. Validation (soon)
194+
# 3. Validation
195+
196+
`libBLS` provides a validation step after each main step in the TE flow.
197+
Below we describe the encryption-time validation in detail.
198+
199+
## 3.1 Validate Encryption
200+
201+
**Goal.** Prove that the ciphertext `{U, V, W}` was built consistently with a single randomness `r`, i.e., that the same `r` links `U` and `W`, and that `W` binds to `(U, V)`.
202+
203+
**Setup.**
204+
- Groups: `G1`, `G2` with a bilinear pairing `e : G1 × G2 → GT`.
205+
- Generators: `P ∈ G2`.
206+
- Types: `U ∈ G2`, `W ∈ G1`, `H(U,V) ∈ G1`.
207+
- Construction: `U = r ⋅ P`, `W = r ⋅ H(U,V)`.
208+
209+
**Verifier computation.**
210+
1. Recompute the hash-to-curve point:
211+
`H' = H(U, V) ∈ G1`.
212+
2. Check the pairing equation:
213+
$$
214+
e(W, P) \stackrel{?}{=} e(H', U)
215+
$$
216+
217+
**Why it works (bilinear proof).**
218+
Assuming honest formation with the *same* scalar `r`:
219+
- Left side: $e(W, P) = e(r ⋅ H, P) = e(H, P)^r$.
220+
- Right side: $e(H', U) = e(H, r ⋅ P) = e(H, P)^r$ (since $H' = H$).
221+
222+
Thus both sides are equal **iff**:
223+
- `W` was formed as `r ⋅ H(U,V)` for the same `U`, and
224+
- `U` encodes the *same* scalar `r` as used in `W`.
225+
226+
**What it guarantees.**
227+
- **Consistency of randomness:** `U` and `W` use the same `r`.
228+
- **Binding to ciphertext:** Because `H` hashes `(U,V)`, any change to `U` or `V` alters `H` and breaks the check.
229+
- **Public verifiability:** Anyone can verify without knowing `r` or the plaintext `m`.
230+
- **No leakage:** The check reveals nothing about `r`, `s`, or `m`.
231+
232+
**Failure modes caught.**
233+
- If an adversary swaps `U` or `V`, the recomputed `H'` changes and the equation fails.
234+
- If `U` and `W` are created with different scalars, bilinearity no longer aligns and the equation fails.
235+
- If `W` is random/forged, it will not satisfy the equality with overwhelming probability.
236+
237+
238+
239+
## 3.2 Validate Each Decryption Share
240+
241+
**Goal.**
242+
243+
Given a ciphertext `{U, V, W}` and a purported decryption share $D_i$ from node $i$, verify that $D_i$ was computed correctly from the node’s secret share $s_i$ and that it matches the same encryption randomness $r$ that binds `{U,V,W}`.
244+
245+
246+
**Setup.**
247+
248+
During encryption:
249+
$$
250+
U = rP \in G_2,\qquad
251+
W = r\,H(U,V) \in G_1,
252+
$$
253+
where $H(U,V)\in G_1$ is a hash-to-curve of `(U,V)`.
254+
For node $i$:
255+
$$
256+
Y_i = s_i P \in G_2,\qquad
257+
D_i = s_i U = s_i (rP) = (r s_i) P \in G_2.
258+
$$
259+
Let $e: G_1 \times G_2 \to G_T$ be a bilinear pairing.
260+
261+
262+
**Validation equations.**
263+
264+
1) **Ciphertext integrity (same $r$ across `U` and `W`).**
265+
$$
266+
e(W, P)\;\stackrel{?}{=}\;e(H(U,V), U).
267+
$$
268+
If true, then $W = r H(U,V)$ and $U = rP$ share the same randomness $r$. (Smae as we did in 3.1)
269+
270+
2) **Per-share correctness (same $s_i$, same $r$).**
271+
$$
272+
e(W, Y_i)\;\stackrel{?}{=}\;e(H(U,V), D_i).
273+
$$
274+
275+
**Why it works.**
276+
277+
- For 1), we have already seen why it works from 3.1.
278+
279+
- For 2), for a valid share with $Y_i=s_iP$ and $D_i=s_iU=s_i(rP)$:
280+
$$
281+
e(W,Y_i)=e(rH, s_iP)=e(H,P)^{r s_i},\qquad
282+
e(H,D_i)=e(H, s_i r P)=e(H,P)^{r s_i},
283+
$$
284+
so the second equality holds **iff** $D_i$ was computed from the *same* $r$ (via $U$) and the *correct* secret share $s_i$ (via $Y_i$).
285+
286+
287+
288+
## 3.3 Validate Combined Decryption Shares
289+
290+
**Goal.**
291+
292+
Verify that the decrypted message is mathematically consistent with the ciphertext `{U, V, W}` and the public key $Y$, ensuring that the random scalar $r'$ recovered from the decrypted data corresponds to the same randomness $r$ used during encryption.
293+
294+
295+
**Setup.**
296+
297+
During encryption:
298+
299+
$$
300+
U = rP, \quad V = G(rY) \oplus m
301+
$$
302+
303+
where
304+
- $r \in \mathbb{F}_r$ is a random scalar,
305+
- $Y = sP$ is the public key,
306+
- $G: G_2 \rightarrow \{0,1\}^{32}$ is a key-derivation hash,
307+
- $m$ is the AES-256 key (plaintext).
308+
309+
After decryption, the payload reveals a candidate scalar $r'$, which should equal $r$ if the decryption shares were correctly combined.
310+
311+
**Validation Equation.**
312+
313+
Compute:
314+
315+
$$
316+
Y' = r'Y
317+
$$
318+
319+
Derive:
320+
321+
$$
322+
m' = V \oplus G(Y')
323+
$$
324+
325+
and verify:
326+
327+
$$
328+
m' = m
329+
$$
330+
331+
**Why it works.**
332+
333+
If the combined decryption shares are correct, then $r' = r$.
334+
Hence:
335+
336+
$$
337+
Y' = r'Y = rY
338+
$$
339+
340+
and
341+
342+
$$
343+
G(Y') = G(rY)
344+
$$
345+
346+
Substituting into the expression for $m'$ gives:
347+
348+
$$
349+
m' = V \oplus G(rY) = (G(rY) \oplus m) \oplus G(rY) = m
350+
$$
351+
352+
The equality holds **if and only if** $r'$ matches the original randomness $r$ and the ciphertext `{U, V}` was not tampered with. Any alteration in $r'$, $V$, or $Y$ breaks the equality, making the decryption invalid.
353+
354+
## 3.4 Validate Deciphered Message
355+
356+
**Goal.**
357+
358+
Verify that the AES key recovered from the decrypted payload is consistent with the ciphertext `{U, V, W}` and the public key $Y$, by confirming that the random scalar $r'$ extracted from the plaintext explains $V$.
359+
360+
**Setup.**
361+
362+
During encryption:
363+
$$
364+
U = rP,\qquad V = G(rY)\oplus m,
365+
$$
366+
where $r\in\mathbb{F}_r$ is random, $Y=sP$ is the public key, $G: G_2\to\{0,1\}^{32}$ is a KDF/hash-to-key, and $m$ is the AES-256 key.
367+
368+
After decryption of the outer AES-GCM payload, we obtain a candidate scalar $r'$ (encoded in the plaintext). The ciphertext component $V$ is available from `{U,V,W}`.
369+
370+
371+
**Validation Equation.**
372+
373+
Compute:
374+
$$
375+
Y' = r'Y,\qquad K' = G(Y'),\qquad m' = V \oplus K'.
376+
$$
377+
Accept iff:
378+
$$
379+
m' = m.
380+
$$
381+
382+
383+
**Why it works.**
384+
385+
If the decrypted payload is correct and the combine of shares was honest, then $r'=r$. Hence:
386+
$$
387+
Y' = r'Y = rY,\qquad K' = G(Y') = G(rY).
388+
$$
389+
Substitute into $m'$:
390+
$$
391+
m' = V \oplus G(rY) = (G(rY)\oplus m)\oplus G(rY) = m.
392+
$$
393+
Therefore the equality holds **iff** $r'$ matches the original randomness and $V$ was not altered.
195394

196-
---
197395

198396
## Next Steps
199397

docs/concepts/threshold-encryption/2-te-full-flow.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ Next we explain the decryption process without delving into math details. If you
130130
In the threshold decryption process, each node uses its private key share to compute a **partial decryption** of the ciphertext and broadcasts this decryption share to the network. Once a supermajority (i.e., at least the threshold number of valid shares) is received, any node can combine these shares to reconstruct the original plaintext, without needing the full private key.
131131

132132
Since only the `CipheredKey` structure was ciphered using threshold encryption, only this needs to be merged using threshold encryption semantics.
133-
The **result of such merging will not be the original ciphertext, but the deciphered `AESKey`**
133+
The **result of such merging will not be the original plaintext, but the deciphered `AESKey`**
134134

135135
The process is shown below:
136136

@@ -143,7 +143,7 @@ The process is shown below:
143143

144144
The **merge** process itself is detailed [here](./1-threshold-encryption.md).
145145

146-
Having seen the threshold encryption decryption process to get the `AESKey`, we see next how we can use this to get the original plaintext `T` from the `Ciphertext` struct:
146+
Having seen the threshold encryption-decryption process to get the `AESKey`, we see next how we can use this to get the original plaintext `T` from the `Ciphertext` struct:
147147

148148

149149
<br>
@@ -161,6 +161,7 @@ Although the `r` field is not used during decryption, it is essential for valida
161161

162162
# 3. Validation
163163

164+
This section explains the validation checkpoints exposed by libBLS at a high level. Mathematical details are explain [here](./1-threshold-encryption.md)
164165

165166
## Overview
166167

@@ -175,10 +176,10 @@ The validation stages are positioned at critical transition points - usually aft
175176

176177
- **After Encryption**: Validates that the received ciphertext was properly formed before starting the decryption process.
177178
- **After Share Generation**: Ensures each decryption share is authentic upon receival, thus, before merging.
178-
- **After Share Combination**: Verifies the merged result before final decryption.
179+
- **After Share Merging**: Verifies the merged result before final decryption.
179180
- **After Final Decryption**: Confirms end-to-end integrity of the entire process.
180181

181-
This creates a defense-in-depth strategy where each validation stage guards against different types of failures or attacks. By validating at these specific points, we prevent corrupted or malicious data from advancing to subsequent stages where it could cause otherwise have delayed the system into detecting the corrupted data only at the final stage.
182+
This creates a defense-in-depth strategy where each validation stage guards against different types of failures or attacks. By validating at these specific points, we prevent corrupted or malicious data from advancing to subsequent stages where it could otherwise have delayed the system into detecting the corrupted data only at the final stage.
182183

183184
## Validation Stages
184185

@@ -229,3 +230,4 @@ The layered validation approach provides several key security benefits:
229230
**System Reliability**: The validations catch not just malicious behavior but also honest errors, hardware failures, and software bugs, making the entire system more robust and reliable.
230231

231232
**Auditability**: Each validation stage provides a clear checkpoint where system integrity can be verified, making it easier to audit the system's behavior and troubleshoot any issues that arise.
233+

docs/concepts/threshold-encryption/3-full-client-flow.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ This document does not cover the details of encryption / decryption. These can b
66

77
---
88

9+
The following diagram shows the flow process, as well as some details on the ciphertext structure. The steps are all explained below the diagram.
10+
911
<img src="../../diagrams/threshold-encryption/full-client-flow.svg" alt="Diagram" style="width: 100%; max-width: 1200px;" />
1012

1113
<br>
@@ -25,8 +27,12 @@ The client begins by querying the network to obtain the current threshold encryp
2527

2628
This dual-key mechanism allows the client to encrypt data such that it is decryptable by either the current or the upcoming committee. This is essential during periods when both committees must temporarily coexist.
2729

30+
Note that this method is not provided by libBLS. It should be implemented by the application using libBLS. libBLS only deals with the two keys sent to the library.
31+
2832
### 1.2. Encrypt Data
2933

34+
From this step on, eveything is implemented by libBLS.
35+
3036
The client generates:
3137
- A **symmetric key** `m` (AES key).
3238
- A **random scalar** `r` used as input to the threshold encryption scheme.
@@ -93,7 +99,7 @@ At this stage, the decryption is started. Each node first computes one decryptio
9399

94100
<img src="../../diagrams/threshold-encryption/simplified-process-overview.svg" alt="Diagram" style="width: 100%; max-width: 1200px;" />
95101

96-
At this stage, we have already gone through the `Ciphering` part on the left of the diagram, and we are exactly at the middle.
102+
At this stage, we have already gone through the `Ciphering` part ( **m** being the message, and $Y_1$ being the group's public key) on the left of the diagram, and we are exactly at the middle.
97103

98104

99105
### 3.1. Compute Decryption Shares

0 commit comments

Comments
 (0)