26 releases

new 0.2.13 Apr 30, 2025
0.2.12 Feb 5, 2025
0.2.11 Oct 27, 2024
0.2.8 Sep 19, 2024
0.2.0-alpha.12 Aug 17, 2024

#359 in Cryptography

Download history 110/week @ 2025-01-08 117/week @ 2025-01-15 76/week @ 2025-01-22 51/week @ 2025-01-29 304/week @ 2025-02-05 200/week @ 2025-02-12 121/week @ 2025-02-19 94/week @ 2025-02-26 200/week @ 2025-03-05 147/week @ 2025-03-12 122/week @ 2025-03-19 257/week @ 2025-03-26 83/week @ 2025-04-02 76/week @ 2025-04-09 27/week @ 2025-04-16 13/week @ 2025-04-23

215 downloads per month
Used in 3 crates (2 directly)

ISC license

17KB
234 lines

Overview

Mizaru is a cryptographic protocol designed to provide privacy-preserving authentication in the Geph5 network, using blind signatures to protect user anonymity.

In Geph5, Mizaru allows clients to prove they are authenticated without revealing their identity or usage patterns to exit nodes. This means that even if Geph's servers are compromised, user identities cannot be linked.

The unifying design goal is for Geph to be as anonymous as an unauthenticated open proxy, despite having user accounts and payments.

Mizaru is inspired by anonymous-credential systems like Privacy Pass, but with these main differences:

  • Instead of one-time anonymous credentials, Mizaru anonymous credentials reusable within 24 hours. This is because while Privacy Pass is used in a context where we need unlinkability between different requests, Mizaru is used in a context where we want unlinkability between different days in a user's activity.
    • This may seem weaker, but VPN sessions last for a long time, and it's generally infeasible to provide unlinkability between different user actions within the same VPN session. Linkability within 24 hours is equivalent to everyone using 24-hour burner accounts, which is not meaningfully less anonymous compared to not having authentication.
  • Integer-math cryptographic primitives (FDH-RSA) are used instead of elliptic curves.

Protocol roles

There are three roles involved:

  • The client is the Geph user
  • The broker validates client authentication and interacts with the client to create an anonymous credential
  • The exit is the VPN server that the user actually connects to

Neither the broker nor the exit are trusted for anonymity.


Cryptographic components

Here we talk about the primitive building blocks of Mizaru, generally exposed in this library.

Client token

  • Let $T \in {0,1}^{256}$ be a client token, a 32-byte random value generated by the client.
  • $T$ is the client’s anonymous identity token for one epoch, and must remain private.

Blinding transform

We use the "standard" blind-signature scheme based on RSA and full-domain-hashes:

  • Suppose $(N, e)$ is an RSA public key, where $e$ is the standard RSA public exponent.
  • The client chooses a blinding factor $r$ coprime to $N$.
  • Define the blinded token:

$$ T' = \bigl(H(T) \cdot r^{,e}\bigr) \bmod N, $$

where $H$ is a cryptographically secure hash function used in a full-domain-hash (FDH) manner, constructed from SHA-256.

Broker's secret keys and public-key Merkle tree

  • The broker holds $2^{16}$ RSA key pairs:

$$ { (N_i, e_{i}, d_i) }_{i=0}^{2^{16}-1}, $$

each 2048 bits, indexed by $i$. These represent epoch keys, one for each day after the Unix epoch.

  • A Merkle tree based on blake3 is is constructed over all $2^{16}$ public keys $\bigl(N_i, e_{i}\bigr)$. Leaves are hashes of these public keys; internal nodes are hashes of their children.
  • The broker long-term public key is the Merkle root:

$$ \mathsf{Root} \in {0,1}^{256}. $$

  • Any party with $\mathsf{Root}$ and a proper Merkle proof for index $i$ can verify that $\bigl(N_i, e_{i}\bigr)$ is indeed one of the server’s valid public keys.

Protocol flow

  1. Token generation

    • The client generates a random 32-byte token:

$$ T \leftarrow { 0,1 }^{256} $$

  1. Epoch and key retrieval

    • Define the epoch: $E = \left\lfloor \frac{\text{UnixTime}}{86400} \right\rfloor$
    • A function $f(E)$ derives a key index $i \in {0,\dots,2^{16}-1}$. For example, $i = E \bmod 65536$.
    • The client requests both the broker's RSA public key $\bigl(N_i, e_{i}\bigr)$ and a corresponding Merkle proof from the broker.
    • Client validates the Merkle proof:
    • Using the known root $\mathsf{Root}$, which is hardcoded, the client checks that $\bigl(N_i, e_{i}\bigr)$ indeed appears as the valid leaf at index $i$.
    • This prevents an untrusted broker from substituting a rogue public key in order to allow exits to deanonymize users.
  2. Blinding process

    • Once the client verifies the key $\bigl(N_i, e_{i}\bigr)$, it selects a random $r$ (coprime to $N_i$) and computes: $T' = \bigl(H(T) \cdot r^{,e_{i}}\bigr) \bmod N_i.$

    • The client sends ${ E, i, T' }$ to the broker.

  3. Broker signing

    • The broker checks the client’s regular credentials (e.g., username/password).

    • If valid, the broker applies its private exponent $d_i$: $\sigma' = (T')^{d_i} \bmod N_i.$

    • The broker returns $\sigma'$ (plus the Merkle proof again if needed, though typically the client already has it from step 2).

  4. Unblinding

    • The client computes $r^{-1}$ modulo $N_i$ and calculates: $\sigma = \sigma' \cdot r^{-1} \bmod N_i.$

    • Thus, $\sigma$ is a valid RSA-FDH signature on $H(T)$.

  5. Verification

    • To prove authenticity (e.g., to an exit node), the client presents ${ T, \sigma, E, i, \text{MerkleProof}(i) }$.
    • The verifier checks:
      1. Merkle proof: that $\bigl(N_i, e_{i}\bigr)$ is a valid leaf at index $i$ under $\mathsf{Root}$.
      2. RSA signature: $\sigma^{,e_{i}} \bmod N_i \stackrel{?}{=} H(T)$.
      3. Epoch validity: $E$ is current (e.g., the correct 24-hour window).

Security considerations

  1. Broker key confidentiality
    • Protect private exponents ${ d_i }$. A leak enables forging of blind signatures for the corresponding epoch(s).
  2. Merkle proofs
    • If the client fails to verify the Merkle proof, it could blindly trust a malicious key.
    • Ensuring the client holds the correct $\mathsf{Root}$ is crucial (e.g., pinned or distributed securely).
  3. Replay within the epoch
    • By design, a valid token can be replayed. After 24 hours, it expires.
  4. Forward privacy
    • After an epoch ends, the user obtains a new token. Past tokens do not link to future tokens, as each day effectively resets the user’s identity handle.

Dependencies

~10MB
~206K SLoC