Threshold Point Encryption

This page describes the cryptographic scheme implemented in fedimint-tpe: an encryption of a 32-byte secret to a keyholder, built from a pairing-based committed Diffie–Hellman construction over BLS12-381. It is used by the Lightning v2 module to encrypt a payment preimage to the federation, bound to a contract commitment, so that the secret can be recovered once the contract's conditions are met.

Sections 1–5 present the complete scheme with a single keyholder; Section 6 then replaces the keyholder by a $t$-of-$n$ federation of guardians — a standard transformation that exploits only the linearity of the decryption operation in the secret key, and is the same threshold backbone as the blind signature scheme. Throughout, the encryptor and the keyholder play the two sides of a Diffie–Hellman exchange: the same shared secret is computed by the encryptor from its ephemeral key and the keyholder's public key, and by the keyholder from its secret key and the ephemeral public key.

Where this is used. This encrypts the Lightning preimage in Fedimint's lnv2 module. The binding commitment $\mathit{cm}$ is the payment hash of the contract, so a ciphertext is cryptographically tied to the specific contract it pays. The federation produces decryption shares — and thereby reveals the preimage — only once the contract's spend conditions are satisfied, which is what lets a Lightning payment settle atomically against the on-ledger contract.

1. Setting and notation

$K := \mathbb{Z}/p\mathbb{Z}$ is the field of integers modulo the prime $p$. Let $\mathbb{G}_1, \mathbb{G}_2, \mathbb{G}_T$ be the BLS12-381 pairing groups of order $p$, written additively, with generators $g_1 \in \mathbb{G}_1$, $g_2 \in \mathbb{G}_2$ and nondegenerate $K$-bilinear pairing $e : \mathbb{G}_1 \times \mathbb{G}_2 \to \mathbb{G}_T$. Keys and the ephemeral public key live in $\mathbb{G}_1$; hashed messages and signatures live in $\mathbb{G}_2$.

Groups as vector spaces. Because $|\mathbb{G}_i| = p$ is prime, each $\mathbb{G}_i$ is a one-dimensional $K$-vector space under scalar multiplication, and the maps below are $K$-linear. The single fact driving the construction is bilinearity of $e$: it lets anyone check ciphertext well-formedness with a pairing equation, and (in §6) lets a federation recombine a Diffie–Hellman secret across key shares.

The plaintext and the binding value are:

ValueMeaning
$\mathit{preimage} \in \{0,1\}^{256}$the 32-byte secret to be encrypted (a Lightning preimage)
$\mathit{cm}$a SHA-256 commitment the ciphertext is bound to (the contract / payment hash)

A hash $\mathsf{H}_{\mathbb{G}_2} : \{0,1\}^* \to \mathbb{G}_2$ maps bytes into the second group, modeled as a random oracle.

2. Keys and encryption

The keyholder's secret key is a scalar $x \in K$ with public key in $\mathbb{G}_1$: $$\mathsf{sk} = x \in K, \qquad \mathsf{pk} = x\, g_1 \in \mathbb{G}_1.$$

To encrypt under $\mathsf{pk}$ and bind to commitment $\mathit{cm}$, the encryptor derives an ephemeral scalar $\eta \in K$ from a 32-byte encryption seed and forms:

$$\begin{aligned} E &= \eta\, g_1 \in \mathbb{G}_1 && \text{(ephemeral public key)} \\[2pt] D &= \eta\, \mathsf{pk} = \eta x\, g_1 \in \mathbb{G}_1 && \text{(Diffie–Hellman shared secret)} \\[2pt] \mathit{ct} &= \mathit{preimage} \,\oplus\, \mathsf{SHA256}(D) && \text{(one-time-pad encryption)} \\[2pt] M &= \mathsf{H}_{\mathbb{G}_2}(\mathit{ct} \,\|\, E \,\|\, \mathit{cm}) \in \mathbb{G}_2 && \text{(message point binding } \mathit{ct}, E, \mathit{cm}) \\[2pt] S &= \eta\, M \in \mathbb{G}_2 && \text{(ephemeral BLS signature)} \end{aligned}$$

The ciphertext is the triple $(\mathit{ct}, E, S)$. The shared secret $D$ is the ECDH point of the ephemeral key $\eta$ and the keyholder's key $x$; its hash is used as a one-time pad over the preimage.

Why the embedded signature? $S = \eta\, M$ is a BLS signature under the ephemeral key $E$ on the message point $M = \mathsf{H}_{\mathbb{G}_2}(\mathit{ct} \,\|\, E \,\|\, \mathit{cm})$, which itself hashes the full ciphertext together with the commitment. It makes the ciphertext non-malleable and publicly checkable: nobody can alter $\mathit{ct}$, $E$, or the bound commitment without invalidating $S$, so the keyholder can safely decrypt only well-formed ciphertexts tied to the intended contract.

3. Ciphertext validity

Anyone can check that a ciphertext is well formed, against its commitment, with a single pairing equation: $$e(g_1,\; S) \;\stackrel{?}{=}\; e(E,\; M), \qquad M = \mathsf{H}_{\mathbb{G}_2}(\mathit{ct} \,\|\, E \,\|\, \mathit{cm}).$$ This holds for an honest ciphertext because, by bilinearity, $$e(g_1,\; \eta M) = e(g_1, M)^{\eta} = e(\eta g_1,\; M) = e(E,\; M).$$ A passing check certifies that $S$ is the ephemeral key's signature on the exact bytes of $(\mathit{ct}, E, \mathit{cm})$ — i.e. that $S = \eta M$ for the same $\eta$ as $E = \eta g_1$.

4. Decryption

The keyholder recovers the shared secret from the other side of the Diffie–Hellman exchange. Where the encryptor formed $D = \eta\,\mathsf{pk}$ from the ephemeral scalar and the public key, the keyholder applies its secret key to the ephemeral public key: $$D \;=\; x\, E \;=\; x\,\eta\, g_1 \;=\; \eta\,(x\, g_1) \;=\; \eta\,\mathsf{pk},$$ the very same group element. The preimage is then unmasked with the one-time pad: $$\mathit{preimage} \;=\; \mathit{ct} \,\oplus\, \mathsf{SHA256}(D).$$

The two sides of the exchange. Scalar multiplication commutes, $x\,(\eta g_1) = \eta\,(x g_1)$, so the encryptor (who knows $\eta$ and $\mathsf{pk}$) and the keyholder (who knows $x$ and $E$) arrive at the identical point $D = \eta x\, g_1$ without either learning the other's scalar. This is plain ElGamal / ECDH decryption; §6 performs exactly this step without ever assembling $x$.

5. Security properties (informal)

6. The threshold construction

Nothing above requires a single keyholder. Because decryption $$D \;=\; x\, E$$ is $K$-linear in the secret key $x$, the keyholder can be replaced by a $t$-of-$n$ federation via Shamir secret sharing plus Lagrange interpolation in the exponent — the same construction that thresholdizes BLS signing. Encryption (§2) and the validity check (§3) are unchanged; only the recovery of $D$ is distributed.

6.1 Key sharing

The key $x$ is Shamir-shared: pick a random polynomial $f \in K[X]$ of degree at most $t-1$ with $f(0) = x$, and give guardian $i \in \{1, \dots, n\}$ the key share and public key share $$\mathsf{sk}_i = f(i) \in K, \qquad \mathsf{pk}_i = f(i)\, g_1 \in \mathbb{G}_1.$$ The aggregate public key is unchanged: $\mathsf{pk} = f(0)\, g_1 = x\, g_1$. Evaluation points are the indices $i = \texttt{peer} + 1$, since the point $0$ is reserved for the secret. In a real federation this sharing is set up without a trusted dealer by a distributed key generation.

6.2 Decryption shares and aggregation

Each guardian applies its share to the ephemeral public key, producing a decryption-key share $$D_i \;=\; f(i)\, E \;\in\; \mathbb{G}_1,$$ which the requester verifies independently (on a ciphertext already known to be valid, §3) by the pairing equation $$e(D_i,\; M) \;\stackrel{?}{=}\; e(\mathsf{pk}_i,\; S),$$ both sides being $e(g_1, M)^{f(i)\,\eta}$: the left is $e(f(i)\eta g_1, M)$ and the right is $e(f(i) g_1,\, \eta M)$. So a misbehaving guardian is identified immediately and its share discarded.

Any set $S$ of $t$ valid shares then interpolates to the shared secret. With the Lagrange coefficients $\lambda_i^S$ that reconstruct a degree-$(t-1)$ polynomial at the point $0$, $$\lambda_i^S \;=\; \prod_{\substack{j \in S \\ j \neq i}} \frac{j}{\,j - i\,}, \qquad \sum_{i \in S} \lambda_i^S\, f(i) \;=\; f(0) \;=\; x,$$ the recombination is a Lagrange combination in the exponent. As with signing, it lands on the single-keyholder secret because scalar multiplication $K \times \mathbb{G}_1 \to \mathbb{G}_1$ is bilinear, hence linear in its scalar argument, so it commutes with the Lagrange sum: $$\begin{aligned} D &\;=\; \sum_{i \in S} \lambda_i^S\, D_i && \text{(combine the shares)} \\[2pt] &\;=\; \sum_{i \in S} \lambda_i^S\, \bigl(f(i)\, E\bigr) && \text{(each share is } D_i = f(i)\,E) \\[2pt] &\;=\; \Bigl(\sum_{i \in S} \lambda_i^S\, f(i)\Bigr) E && \text{(linearity in the scalar argument)} \\[2pt] &\;=\; f(0)\, E && \text{(Lagrange interpolation at } 0) \\[2pt] &\;=\; x\, E \;=\; \eta\,\mathsf{pk}, && (f(0) = x) \end{aligned}$$ which is exactly the shared secret of §4, so the preimage is unmasked as before, $\mathit{preimage} = \mathit{ct} \oplus \mathsf{SHA256}(D)$. Fewer than $t$ guardians learn nothing about $x$ and cannot assemble $D$.

Verifying the recombined key. The aggregate $D$ can itself be checked against the public key without decrypting, by $$e(D,\; M) \;\stackrel{?}{=}\; e(\mathsf{pk},\; S),$$ again both sides being $e(g_1, M)^{x\eta}$. This certifies that $D$ is the correct ECDH point $\eta\,\mathsf{pk}$ before it is used to unmask the preimage.
Implementation caveat (prototype). Hash-to-group is implemented by seeding a ChaCha RNG with SHA-256 rather than a standard hash_to_curve ciphersuite — fine as a random oracle into the group, but non-interoperable. Note also that the share- and aggregate-verification routines assert ciphertext validity internally and will panic on a malformed ciphertext, so callers must run the ciphertext check of §3 first.

References