Retroactive Grant Application : Blindvault

Blindvault - Privacy-Preserving Credentials Issuance Service

Ask: $17,000 USD
FPF issue: Retroactive Grant Application - Blindvault · Issue #39 · Financial-Privacy-Foundation/ZcashCoinholderGrantsProgram · GitHub
GitHub: GitHub - rawbytedev/blindvault: Blindvault is a privacy-preserving credential issuance service that allows clients(applications) to issue and verify one time anonymous credentials without tracking users. It makes uses of BLS12-381 blind signatures and DLEQ proofs alongside deterministic key derivation · GitHub
Release(v1.3.0): Release v1.3.0: fix: included utils.ts in the connfig · rawbytedev/blindvault · GitHub
Binaries: Windows, Linux(Server and client), Js(client)
License: MIT

Why it exists

Zcash enables private transactions between people, but still lacks the tools for private identity and credentials verification.

Most of the time when it is needed to distribute ZEC to a group of people, prevent sybil attacks or issue access to private event, you have to build complex cryptography infrastructure or tool from scratch. And developers would certainly prefer a simpler approach such as centralized database which stores user details, this does not align at all with privacy.

Blindvault mainly serves to solve that problem. It allows an application to ensure eligible users, can perform actions in private without their identity being exposed(private community voting). Making use of BLS12-381 blind signatures and DLEQ proof, blindvault issue a credential to a user and then be redeemed later by the user without the server linking the initial issuance to the redemption request.

Blindvault enables private interactions, without ever exposing or knowing a user identity therefore preserving their privacy

What It Does

Blindvault does 3 things:

  • Issuance: when the client request a credential, Blindvault signs it blindly using BLS12-381.
  • Verification: Blindvault attach a DLEQ proof to every issuance, ensuring the issuance was signed with the correct key. This prevent malicious servers from issuing fake credentials.
  • Redemption: The client redeems the credential sending over the unblinded signature, the server after ensuring it belongs to the appropriate class and epoch verify that the signature is valid, before computing a nullifier(deterministic hash). The server checks Redis to ensure that the credential was never used before. This allow granting access or recording a vote without knowing who asked for the credential in the first place.

Blindvault provide classes and Epoch which allow for keys rotation.

Values to Zcash

Blindvault has many practical uses for the zcash community, and that’s precisely why I’ve built it as an infrastructure service.
For pratical use cases:

  • Private Governance: Allow voting throughout the zcash community, without having to compromise the voter privacy, each eligible user is given a credentials that can be used later for the vote.
  • Community Users Privacy: Users can prove their hold a specific status(“admin”, “moderator”) without revealing their forum username

Current Features

  • Deterministic Key Derivation
  • Replay protection using deterministic nullifiers
  • In-memory backend for testing
  • Credential namespace isolation
  • DLEQ proof generation and verification
  • REST API for credential issuance and consumption
  • Epoch and class revocation

Future Features

  • Distributed Key Generation
  • Trusted‑dealer threshold
  • Threshold DLEQ proof generation
  • Batch Verification

I’ll be happy to answer any question and take any suggestion

I’ve started reviewing the code, mainly to identify issues that might came up, as of now the issues I was able to find are as follow:

  • When generating the DLEQ proof we didn’t create a copy for a scalar which is modified later, although the scalar is used once then no longer called throughout the process of proof generation, due to the modification debugging issues would become extremely hard
  • The key generation uses HKDF which derives from the master seed and other fields class, epoch, after we convert it directly into a scalar which might result in overflow or silent fails(very unlikely), so for fixing that I decided to used the built in hash to scalar function from the library.
  • When storing revocation in redis I made used of * wildcard but we use the same wildcard when listing all revocation so I decided to go with a simpler approach: once
    revoke:<class>:all is present all epochs of that class are marked as revoke, the behavior doesn’t change at all

I’ll make a new release with all fixes and issues sorted out this would allow all present features to be entirely safe and reliable to use.

I applied additional fixes and improvements:

  • Blindvault was not checking for context before heavy operation which my lead to ressource being consumed when the client disconnects or cancels requests, the newest commit fix that propagating the context and checking it before every cryptographic operation
  • A small fix to the key derivation which might create considerable issues later one, the previous derivation append strings together ProtocalTag + purpose + epoch + credential without any delimitation which can lead to collusion:
    • Epoch = "2026-01", Class = "test"info = "BCISSIGNING_KEY2026-01test"
    • Epoch = "2026", Class = "-01test"info = "BCISSIGNING_KEY2026-01test"

All those have been fixed

1 Like

I’ve started implementing memguard enclave to zero out sensitive data such as masterseed and passwords, the package was already created entirely and only needed to be integrated. It does aim to make blindvault more secure, with enclaves the byte of the master seed are only visible only when needed and can’t be viewed otherwise.

I’m essentially writing a thin wrapper over memguard GitHub - awnumar/memguard: Software sandbox for storage of sensitive information in memory. · GitHub as to only expose the functions that would be needed by blindvault