1
$\begingroup$

End-to-end encrypted web services (like cryptpad) often include a 128-bit seed in the hash part of the URL (that is not sent to the server), to derive both an identifier that is sent to the server, and the encryption key that is used on client-side only. This seed allows shorter URLs than storing both the identifier and the encryption key directly.

However, while non-cryptographic identifiers are usually generated by the server, the seed needs to be generated exclusively on the client-side, so the encryption key remains secret. Therefore, modified clients can choose arbitrary seeds, like a readable name when encoded in the URL. Is there a cryptographic scheme to prevent arbitrary seeds? Something like this:

  1. The server sends entropy E to the client.
  2. The client generates the seed S based on E and extra entropy E'. The server cannot infer S. S should be short (~ 128 bit). S is based on E only to ensure the client cannot choose S freely.
  3. The client derives the identifier I (128 bit) and the encryption key K (128 bit) from S deterministically.
  4. The client reveals I to the server and proves that I is indirectly based on E without revealing E', S, or K. Then, the server can allow creating a resource with identifier I.

For the proof, multiple round trips between server and client would be acceptable.

$\endgroup$
0

2 Answers 2

1
$\begingroup$

Using Ed25519:

The group size $\ell$ generated by the base point $G$ on the curve is approximately $2^{252}$. As an abbreviation, references below to "252-bit" numbers refer to scalars less than $\ell$.

The client has 128-bit entropy $e$, and picks a uniformly random 252-bit scalar $b$.

The client uses $b$ as a blinding factor to derive the Pedersen commitment $C=eG+bH$. $H$ is a second well-known base point on the curve, picked using a 'nothing-up-my-sleeve' technique such that the discrete log of $H$ w.r.t. $G$ is unknowable.

The client sends $C$ to the server, and the server picks random 128-bit entropy $e'$. The server sends $e'$ to the client.

The client calculates the 128-bit seed $s=(e+e')\ mod\ 2^{128}$. As long as either $e$ or $e'$ is uniformly randomly distributed, $s$ will be uniformly randomly distributed.

The client calculates the commitment: $C'=C+e'G$. Depending on the values of $e$ and $e'$, and thus depending on whether the $mod\ 2^{128}$ operation caused $2^{128}$ to be subtracted from $e+e'$, either $C'$ or $C'-2^{128}G$ will be a commitment to the value $s$.

The server also calculates the same value $C'$ for itself.

If $2^{128}$ was not subtracted during the $mod\ 2^{128}$ operation, this will mean that $C'=C+e'G==eG+bH+e'G==(e+e')G+bH==sG+bH$.

Otherwise, $C'-2^{128}G$ will be a commitment to the value $s$.

At this point, the server could allow both $H_{128}(C')$ and $H_{128}(C'-2^{128}G)$ as the identifier, where $H_{128}(\texttt{input})$ means to hash the input (using a cryptographically secure hash such as SHA512) and return the first 128 bits of the result.

However, that would require the client to remember not only $s$, but also the blinding factor $b$.

To solve this problem, the client now calculates the commitment $C''=sG+H_{252}(s)H$.

$H_{252}(\texttt{input})$ means to hash the input using a cryptographically secure hash and return a 252-bit scalar as the output.

The client creates a proof that $C''$ is a commitment to the same value $s$ as either $C'$ or $C'-2^{128}G$. This proof will allow the server to accept $H_{128}(C'')$ as an identifier because it knows it is based on the same value as $C'$, which itself is based on the server's entropy $e'$.

If we do not care about disclosing whether the $mod\ 2^{128}$ operation caused $2^{128}$ to be subtracted from $e+e'$, we could just inform the server about whether the subtraction occurred or not. Then, the client would provide a signature $\sigma$ (such as a simple Schnorr signature) proving knowledge of the private key $(H_{252}(s)-b)\ mod\ \ell$ for either the public key $C''-C'$ or the public key $C''-C'-2^{128}G$ on the base point $H$.

The reason this signature proves that the commitments are to the same value is that unless $C''-C'$ or $C''-C'-2^{128}G$ causes the values on $G$ to cancel each other out, the discrete log w.r.t $H$ is unknowable.

We can avoid disclosing whether the $mod\ 2^{128}$ operation caused $2^{128}$ to be subtracted from $e+e'$, by using a ring signature. We would prove that we know the private key on the base point $H$ for either $C''-C'$ or $C''-C'-2^{128}G$, but the ring signature will not disclose which.

The client sends $C''$ and the signature or ring signature to the server.

The server verifies the signature, and then records in its database that the identifier $H_{128}(C'')$ will be allowed.

The client now only needs to remember the seed $s$, which will be the hash part of the URL used to access the encrypted resource. The client will reconstruct the identifier $H_{128}(sG+H_{252}(s)H)$, and will encrypt data using a symmetric key derived from $s$ (using a derivation technique such as HKDF-extract).

$\endgroup$
3
  • $\begingroup$ I appreciate that this scheme also prevents offline brute forcing of the client entropy. However, it should be noted that s is not uniformly distributed, because it is the sum of two uniformly distributed variables. Is the security better or equal to a 127 bit uniformly random key? It would be easy to add some more bits of entropy if needed. $\endgroup$
    – lukasl
    Commented Jul 19, 2022 at 10:32
  • $\begingroup$ @lukasl that's a really good point. I have asked the question here: crypto.stackexchange.com/questions/101077/… $\endgroup$
    – knaccc
    Commented Jul 19, 2022 at 14:44
  • $\begingroup$ @lukasl I realised that it's possible to do $(e+e')\ mod\ 2^{128}$ and preserve the uniform distribution of $s$. I've updated the answer. $\endgroup$
    – knaccc
    Commented Jul 19, 2022 at 17:52
0
$\begingroup$

It seems like zk-SNARK can be used to implement such a scheme. First, derive the keys simply with a cryptographic hash H:

S = H(E||E') truncated to 128 bit
I = H(S)

Then, use zk-SNARK to prove for a given E and I that I = H(H(E||E') truncated to 128 bit) without leaking E'. This double hash proof is the main example of bellman (using SHA-256): https://docs.rs/bellman/latest/bellman/index.html

Remaining challenges:

  • In the bellman example, the preimage is completely variable. For this use case, the preimage part containing E needs to be preset. The blake2s gadget of bellman supports fixed personalization, which could be used to set E, albeit the entropy of 64 bit is rather low.
  • The example does not truncate the mid hash to 128 bit.
  • zk-SNARK needs a trusted setup, which is too expensive. In this case, the proof is only for the server. Can the server just announce random data that the client then uses for the proof? Or would this solution increase attack surface?
  • Computing the proof takes 2 seconds natively (maybe more on WebAssembly or slower machines), which is acceptable, but improvements would be noticeable by the end user. There are other hash functions that perform better with zk-SNARK based on MiMC. However, are these hashes suitable (secure enough) for key derivation?
$\endgroup$
1
  • $\begingroup$ The seed S is encoded in the hash part of the URL. That's why S needs to be truncated to 128 bit. $\endgroup$
    – lukasl
    Commented Jul 17, 2022 at 14:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.