Documentation ¶
Overview ¶
Verifiable encryption
Verifiable encryption addresses a problem about proving statements for encrypted data. Verifiable encryption allows a prover to convince a verifier that a given ciphertext is an encryption under a given public key. A verifiable encryption scheme proves that a ciphertext encrypts a plaintext satisfying a certain relation. Our implementation is a non-interactive zero-knowledge proof (NIZK) i.e. the prover creates the proof and sends it to the verifier with no further interaction. A verifiable encryption is transferred to a verifier and possibly to a trusted party for decryption. It does not need to be stored at the prover’s side as it usually is not repeatedly needed.
Why? Think of scenarios that allow signers or provers to remain anonymous but where some information about the prover needs to be known and is put into escrow. The escrow service can be a trusted third party or the verifier themselves. The prover encrypts an attribute to a specific public key and creates a NIZK proof of knowledge of the attribute for the resulting ciphertext. To recover the attribute, the opener simply decrypts the ciphertext. It is recommended that a trusted escrow service serve this purpose and not the verifier such that only the trusted authority can actually recover the attribute. The attribute can be anything including a secret key. Another term for this can be a Verifiable Escrow Service.
Note that a key escrow scheme cannot prevent parties from double-encrypting messages under a non-escrowed key, or applying steganography to hide the fact that they are communicating altogether. The goal, therefore, is rather to prevent “dishonest” usage of public-key infrastructures, e.g., by using it to certify non-escrowed keys.
How it works ¶
Camenisch-Shoup Verifiable encryption is similar to RSA and based on Paillier's Decision Composite Residuosity http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.112.4035&rep=rep1&type=pdf. A group of unknown order is created from two safe primes p, q where p = 2p'+1, q = 2q'+1 and p', q' are also prime and p ≠ q.
The group parameters are computed as follows:
- Set n = p * q
- Sample a random g' < n^2
- Set g = g'^2n
- Set h = n + 1
Secret keys are computed as follows
- Sample three random values x_1,x_2,x_3 < n^2/4
- The secret key is {x_1,x_2,x_3}
Public keys are computed as follows
- Compute y_1 = g^x1
- Compute y_2 = g^x2
- Compute y_3 = g^x3
- The public key is {y_1, y_2, y_3}
The group parameters can be stored separate or together with each key.
Proving ¶
Verifiable encryption not only produces a ciphertext that can be decrypted, but also yields a proof that the plaintext is encrypted to a specific public key. The ciphertext is represented as the triplet {u, e, v}, the proof is represented as the Schnorr proof challenge c with responses m, r.
References ¶
Practical Verifiable Encryption and Decryption of Discrete Logarithms - Jan Camenisch and Victor Shoup 2003. https://eprint.iacr.org/2002/161.pdf
Specification of the Identity Mixer Cryptographic Library - IBM Zurich 2009. https://dominoweb.draco.res.ibm.com/reports/rz3730_revised.pdf
Public-Key Cryptosystems Based on Composite Degree Residuosity Classes - Pascall Paillier 1999. http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.112.4035&rep=rep1&type=pdf
Index ¶
- func NewKeys(numMsgs uint, group *PaillierGroup) (*EncryptionKey, *DecryptionKey, error)
- type CipherText
- type DecryptionKey
- type EncryptionKey
- func (ek EncryptionKey) Encrypt(domain []byte, msgs []*big.Int) (*CipherText, error)
- func (ek EncryptionKey) EncryptAndProve(nonce []byte, msgs []*big.Int) (*CipherText, *ProofVerEnc, error)
- func (ek EncryptionKey) EncryptAndProveBlindings(nonce []byte, msgs []*big.Int, blindings []*big.Int) (*CipherText, *ProofVerEnc, error)
- func (ek EncryptionKey) MarshalBinary() ([]byte, error)
- func (ek *EncryptionKey) UnmarshalBinary(data []byte) error
- func (ek EncryptionKey) VerifyEncryptProof(nonce []byte, ciphertext *CipherText, proof *ProofVerEnc) error
- type PaillierGroup
- func (pg PaillierGroup) Abs(a *big.Int) *big.Int
- func (pg PaillierGroup) Exp(base, exp *big.Int) *big.Int
- func (pg PaillierGroup) Gexp(exp *big.Int) *big.Int
- func (pg PaillierGroup) Hash(u *big.Int, e []*big.Int, data []byte) (*big.Int, error)
- func (pg PaillierGroup) Hexp(exp *big.Int) *big.Int
- func (pg PaillierGroup) Inv(val *big.Int) *big.Int
- func (pg PaillierGroup) MarshalBinary() ([]byte, error)
- func (pg PaillierGroup) Mul(lhs, rhs *big.Int) *big.Int
- func (pg PaillierGroup) Rand() (*big.Int, error)
- func (pg PaillierGroup) RandForEncrypt() (*big.Int, error)
- func (pg *PaillierGroup) UnmarshalBinary(data []byte) error
- type ProofVerEnc
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NewKeys ¶
func NewKeys(numMsgs uint, group *PaillierGroup) (*EncryptionKey, *DecryptionKey, error)
Types ¶
type CipherText ¶
type CipherText struct {
// contains filtered or unexported fields
}
CipherText represents verifiably encrypted ciphertext as described in section 3.2 in <https://shoup.net/papers/verenc.pdf>.
func (CipherText) MarshalBinary ¶
func (c CipherText) MarshalBinary() ([]byte, error)
func (*CipherText) UnmarshalBinary ¶
func (c *CipherText) UnmarshalBinary(data []byte) error
type DecryptionKey ¶
type DecryptionKey struct {
// contains filtered or unexported fields
}
DecryptionKey decrypts verifiable ciphertext as described in section 3.2 in <https://shoup.net/papers/verenc.pdf>
func (DecryptionKey) Decrypt ¶
func (dk DecryptionKey) Decrypt(domain []byte, cipherText *CipherText) ([]*big.Int, error)
Decrypt as described in section 3.2 in <https://shoup.net/papers/verenc.pdf>
func (DecryptionKey) EncryptionKey ¶
func (dk DecryptionKey) EncryptionKey() *EncryptionKey
EncryptionKey returns the corresponding encryption key for this decryption key
func (DecryptionKey) MarshalBinary ¶
func (dk DecryptionKey) MarshalBinary() ([]byte, error)
MarshalBinary serializes a key to bytes
func (*DecryptionKey) UnmarshalBinary ¶
func (dk *DecryptionKey) UnmarshalBinary(data []byte) error
UnmarshalBinary deserializes a key from bytes
type EncryptionKey ¶
type EncryptionKey struct {
// contains filtered or unexported fields
}
EncryptionKey encrypts a message to a ciphertext from which zero-knowledge proofs can be derived as described in section 3.2 in <https://shoup.net/papers/verenc.pdf>. n, g are stored in the `PaillierGroup` struct
func (EncryptionKey) Encrypt ¶
func (ek EncryptionKey) Encrypt(domain []byte, msgs []*big.Int) (*CipherText, error)
Encrypt multiple messages as described in <https://shoup.net/papers/verenc.pdf> `domain` represents a domain separation tag or nonce
func (EncryptionKey) EncryptAndProve ¶
func (ek EncryptionKey) EncryptAndProve(nonce []byte, msgs []*big.Int) (*CipherText, *ProofVerEnc, error)
EncryptAndProve is a NIZK where the ciphertext and commitments are computed (t values). The blindings are generated as part of calling this function Return ciphertext and proof created during encryption. "The protocol" from section 5.2 in <https://shoup.net/papers/verenc.pdf> Not using t = g^m*h^s as the idemix protocol does not use it. Guess is that since the knowledge of m is proved in the credential attribute proving protocol. Use this function if the proof is by itself and not part of a bigger composite proof.
func (EncryptionKey) EncryptAndProveBlindings ¶
func (ek EncryptionKey) EncryptAndProveBlindings(nonce []byte, msgs []*big.Int, blindings []*big.Int) (*CipherText, *ProofVerEnc, error)
EncryptAndProveBlindings is a NIZK where the ciphertext and commitments are computed (t values). The blindings are generated prior to calling this function Return ciphertext and proof created during encryption. "The protocol" from section 5.2 in <https://shoup.net/papers/verenc.pdf> Not using t = g^m*h^s as the idemix protocol does not use it. Guess is that since the knowledge of m is proved in the credential attribute proving protocol. Use this function if the proof will be part of more proofs.
func (EncryptionKey) MarshalBinary ¶
func (ek EncryptionKey) MarshalBinary() ([]byte, error)
MarshalBinary serializes a key to bytes
func (*EncryptionKey) UnmarshalBinary ¶
func (ek *EncryptionKey) UnmarshalBinary(data []byte) error
UnmarshalBinary deserializes a key from bytes
func (EncryptionKey) VerifyEncryptProof ¶
func (ek EncryptionKey) VerifyEncryptProof(nonce []byte, ciphertext *CipherText, proof *ProofVerEnc) error
VerifyEncryptProof a Proof of Verifiable Encryption See section 6.2.19 in <https://dominoweb.draco.res.ibm.com/reports/rz3730_revised.pdf>
type PaillierGroup ¶
type PaillierGroup struct {
// contains filtered or unexported fields
}
PaillierGroup holds public values for Verifiable Encryption g and h correspond to the symbols with the same name in the paper. n = p * q, where p = 2p' + 1, q = 2q' + 1, p, q, p', q' are all prime See section 3.1 and 3.2 in verenc.pdf. nd4 = n / 4 integer division n2 = n^2 nd4 = n^2 / 4 integer division
func NewPaillierGroup ¶
func NewPaillierGroup() (*PaillierGroup, error)
NewPaillierGroup creates a new Paillier group for verifiable encryption and generates safe primes for p and q.
func NewPaillierGroupWithPrimes ¶
func NewPaillierGroupWithPrimes(p, q *big.Int) (*PaillierGroup, error)
NewPaillierGroupWithPrimes create a new Paillier group for verifiable encryption Order n^2 where n = p * q
func (PaillierGroup) Abs ¶
func (pg PaillierGroup) Abs(a *big.Int) *big.Int
Abs computes a mod n^2 where 0 < a < n^2 or (n^2 - a) mod n^2 if a > n^2/2 See section 3.2
func (PaillierGroup) Exp ¶
func (pg PaillierGroup) Exp(base, exp *big.Int) *big.Int
Exp computes base^exp mod n^2
func (PaillierGroup) Gexp ¶
func (pg PaillierGroup) Gexp(exp *big.Int) *big.Int
Gexp computes g^exp mod n^2
func (PaillierGroup) Hexp ¶
func (pg PaillierGroup) Hexp(exp *big.Int) *big.Int
Hexp computes h^exp mod n^2
func (PaillierGroup) Inv ¶
func (pg PaillierGroup) Inv(val *big.Int) *big.Int
Inv computes val^-1 mod n^2
func (PaillierGroup) MarshalBinary ¶
func (pg PaillierGroup) MarshalBinary() ([]byte, error)
MarshalBinary serializes a paillier group to a byte sequence
func (PaillierGroup) Rand ¶
func (pg PaillierGroup) Rand() (*big.Int, error)
Rand returns a random v ∈ [1, n^2 / 4)
func (PaillierGroup) RandForEncrypt ¶
func (pg PaillierGroup) RandForEncrypt() (*big.Int, error)
RandForEncrypt returns a random v ∈ [1, n / 4)
func (*PaillierGroup) UnmarshalBinary ¶
func (pg *PaillierGroup) UnmarshalBinary(data []byte) error
UnmarshalBinary deserializes a paillier group from a byte sequence
type ProofVerEnc ¶
type ProofVerEnc struct {
// contains filtered or unexported fields
}
ProofVerEnc is a proof of verifiable encryption for a discrete log
func (ProofVerEnc) MarshalBinary ¶
func (pf ProofVerEnc) MarshalBinary() ([]byte, error)
func (*ProofVerEnc) UnmarshalBinary ¶
func (pf *ProofVerEnc) UnmarshalBinary(data []byte) error