Files
homomorphic-encryption/README.md
T
2026-10-19 16:51:24 +02:00

9.3 KiB
Raw Blame History

homomorphic encryption

DGHV implementation in Rust.

tests and build

tests

cargo test

build

cargo build --release

commands

The binary is target/release/dghv (or cargo run --release -- <command>). Run dghv --help or dghv <command> --help for the full option list.

command description
keygen generate a secret key p (a random prime)
keygen-pair generate a key pair (.privkey + .pubkey files)
encrypt encrypt a single bit
decrypt decrypt a single bit
bootstrap-keygen generate a bootstrap key (.bskey) from a key pair
bootstrap refresh a ciphertext (same bit, fresh noise)

All keys and ciphertexts are hex-encoded. Messages are single bits (0 or 1).

keygen

Generates a secret key p, a random size-bit prime (found with the Fermat primality test), and prints it in hex.

dghv keygen [-s <SIZE>]
option default description
-s, --size 6400 bit length of p (security parameter η)
$ dghv keygen -s 256
Secret key (p): 91aa598acb05314a2618fdd261b5f8fb0ca8fa03a560f2786bd3cb3b94397595

Prime generation is slow for large sizes: the default 6400 bits takes about 30 s.

keygen-pair

Generates a private/public key pair and writes it to <path>.privkey and <path>.pubkey.

dghv keygen-pair -o <PATH> [-s <SIZE>] [-n <NOISE>] [-t <THETA>]
option default description
-o, --path required output path prefix for the key files
-s, --size 6400 bit length of the secret prime p (η)
-n, --noise 80 noise parameter ρ (bit length of the noise)
-t, --theta 10 number of public key elements (at least 2)
$ dghv keygen-pair -o alice -s 1024 -n 16 -t 10
keys written to alice.[privkey|pubkey]

File formats:

  • <path>.privkey: the secret prime p, one hex line.
  • <path>.pubkey: one hex line per public element x_i, largest first (x_0, which is an exact multiple of p, comes first).

encrypt

Encrypts one bit. Exactly one key source is required.

dghv encrypt -b <BIT> (--pubkey <FILE> | --privkey <FILE> | -k <HEX>) [-n <NOISE>] [-o <FILE>]
option default description
-b, --bit required bit to encrypt (0 or 1)
--pubkey public key file: asymmetric encryption
--privkey private key file: symmetric encryption
-k, --key secret key p as a hex string: symmetric encryption
-n, --noise 80 noise parameter ρ
-o, --output stdout write the hex ciphertext to a file instead of printing it

Use the same --noise value as the one used in keygen-pair. It must be small enough compared to the key size (the noise has to stay well below p).

# asymmetric: only the public key is needed
dghv encrypt -b 1 --pubkey alice.pubkey -n 16 -o ct.hex

# symmetric: with the private key file, or with the key given directly as hex
dghv encrypt -b 1 --privkey alice.privkey -n 16
dghv encrypt -b 0 -k "$(cat alice.privkey)" -n 16

Without -o, the ciphertext is printed as Encrypted bit (hex): <ciphertext>.

decrypt

Decrypts a ciphertext with the secret key. One ciphertext source and one key source are required.

dghv decrypt (-c <HEX> | -f <FILE>) (--privkey <FILE> | -k <HEX>)
option description
-c, --ciphertext ciphertext as a hex string
-f, --file file containing the hex ciphertext
--privkey private key file
-k, --key secret key p as a hex string
$ dghv decrypt -f ct.hex --privkey alice.privkey
Decrypted bit: 1

bootstrap-keygen

Generates the bootstrap key needed to refresh ciphertexts, and writes it to <path>.bskey. It needs both keys of the pair: it hides the secret key p as a sparse subset sum (weight selected elements out of hint-size) and encrypts the selector bits under the public key.

dghv bootstrap-keygen --pubkey <FILE> --privkey <FILE> -o <PATH> [-n <NOISE>] [-w <WEIGHT>] [-m <HINT_SIZE>] [--kappa <KAPPA>]
option default description
--pubkey required public key file
--privkey required private key file
-o, --path required output path prefix (writes <path>.bskey)
-n, --noise 80 noise parameter ρ, use the one given to keygen-pair
-w, --weight 5 Hamming weight θ of the secret subset
-m, --hint-size 20 number of hint elements (at least weight)
--kappa bitlen(x₀) + 8 precision of the hint (at least bitlen(x₀) + 4)
$ dghv bootstrap-keygen --pubkey alice.pubkey --privkey alice.privkey -o alice -n 16
bootstrap key written to alice.bskey (kappa=1048, weight=5, hint size=20), self-test passed

After generating the key, the command bootstraps a few test ciphertexts and checks that they still decrypt correctly. If they don't, nothing is written and the command fails: the noise of the bootstrapping circuit grows with weight and has to stay below the capacity of p. In that case use a larger --size for keygen-pair, or a smaller --weight. With the default key sizes (-s 6400 -n 80), weights up to 7 work; a larger --hint-size increases the cost, not the noise.

<path>.bskey is a text file: a first line kappa weight hint-size, then one u_i enc_s_i line (both hex) per hint element. It contains no secret in clear: the secret subset is only present as ciphertexts.

bootstrap

Refreshes a ciphertext: the output encrypts the same bit, but its noise no longer depends on the noise accumulated by the input. It only uses the public key and the bootstrap key, so it can be run by anyone.

dghv bootstrap (-c <HEX> | -f <FILE>) --pubkey <FILE> --bskey <FILE> [-o <FILE>]
option default description
-c, --ciphertext ciphertext as a hex string
-f, --file file containing the hex ciphertext
--pubkey required public key file
--bskey required bootstrap key file (from bootstrap-keygen)
-o, --output stdout write the new hex ciphertext to a file
dghv bootstrap -f ct.hex --pubkey alice.pubkey --bskey alice.bskey -o ct2.hex
dghv decrypt -f ct2.hex --privkey alice.privkey
# Decrypted bit: 1

Without -o, the result is printed as Bootstrapped bit (hex): <ciphertext>. The input must come from the same key pair as the bootstrap key, and its noise must still be below p/4 (i.e. it must still decrypt correctly).

The command line only handles single ciphertexts, so it cannot chain homomorphic additions and multiplications. Use the library (src/dghv.rs, src/dghv_asym.rs, src/bootstrapping.rs) for that; cargo test bootstrapping has examples of multiplying ciphertexts and bootstrapping in between.

full example

# 1. generate a key pair (small parameters, fast)
dghv keygen-pair -o alice -s 1024 -n 16 -t 10

# 2. anyone with the public key can encrypt
dghv encrypt -b 1 --pubkey alice.pubkey -n 16 -o ct.hex

# 3. only the owner of the private key can decrypt
dghv decrypt -f ct.hex --privkey alice.privkey
# Decrypted bit: 1

# 4. optionally, generate a bootstrap key (needs both keys) ...
dghv bootstrap-keygen --pubkey alice.pubkey --privkey alice.privkey -o alice -n 16

# 5. ... then anyone can refresh a ciphertext with the public material only
dghv bootstrap -f ct.hex --pubkey alice.pubkey --bskey alice.bskey -o ct2.hex
dghv decrypt -f ct2.hex --privkey alice.privkey
# Decrypted bit: 1