Skip to content

Commit

Permalink
doc updates
Browse files Browse the repository at this point in the history
  • Loading branch information
Jörn Heissler committed Mar 20, 2023
1 parent 8c76e57 commit e3c79c4
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 140 deletions.
18 changes: 12 additions & 6 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,15 @@ sphinx:
formats: all

python:
version: 3.7
install:
- method: pip
path: .
extra_requirements:
- docs
install:
- method: pip
path: .
extra_requirements:
- docs

build:
os: "ubuntu-22.04"
apt_packages:
- libsodium23
tools:
python: "3.11"
4 changes: 2 additions & 2 deletions doc/math/operations/reencryption.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ hold. Compute:
| :math:`e' = a_i^{k_x} \cdot G_0^{k_{v_0}} \cdot G_1^{k_{v_1}}`
Compute the challenge for the zero knowledge proof using a cryptographic hash function
:math:`c = H(G, g_0, g_1, G_0, G_1, XXX, {y_r}_0, {y_r}_1, y'_i, Y'_i, a'_i, e')`
:math:`c = H(G_q, g_0, g_1, G_0, G_1, XXX, {y_r}_0, {y_r}_1, y'_i, Y'_i, a'_i, e')`

Compute the response for the zero knowledge proof:

Expand All @@ -77,7 +77,7 @@ out:
* :math:`Y'_i = b_i^{s_x} \cdot {y_r}_0^{s_{v_0}} \cdot {y_r}_1^{s_{v_1}} \cdot Y_i^{-c}`
* :math:`a'_i = G_0^{s_{w_0}} \cdot G_1^{s_{w_1}} \cdot a_i^{-c}`
* :math:`e' = a_i^{s_x} \cdot G_0^{s_{v_0}} \cdot G_1^{s_{v_1}}`
* :math:`c' = H(G, g_0, g_1, G_0, G_1, XXX, {y_r}_0, {y_r}_1, y'_i, Y'_i, a'_i, e')`
* :math:`c' = H(G_q, g_0, g_1, G_0, G_1, XXX, {y_r}_0, {y_r}_1, y'_i, Y'_i, a'_i, e')`
* Verify that :math:`c = c'`

Completeness
Expand Down
4 changes: 2 additions & 2 deletions doc/math/operations/secret-splitting.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ To achieve this, the dealer carries out the following steps:
| :math:`X'_i = g_0^{{k_i}_0} g_1^{{k_i}_1}`
* Compute the challenge for the zero knowledge proof using a cryptographic hash function
:math:`c = H(G, g_0, g_1, G_0, G_1, C_j, y_i, Y_i, Y'_i, X_i, X'_i)`
:math:`c = H(G_q, g_0, g_1, G_0, G_1, C_j, y_i, Y_i, Y'_i, X_i, X'_i)`
with :math:`j \in [0,t)` and for all users :math:`i`.

How those values are serialised into an input for the hash function is not important as long
Expand Down Expand Up @@ -80,7 +80,7 @@ the following steps are carried out:
- :math:`X_i' = g_0^{{s_i}_0} g_1^{{s_i}_1} X_i^{-c}`

* Compute the challenge for the zero knowledge proof using a cryptographic hash function
:math:`c' = H(G, g_0, g_1, G_0, G_1, C_j, y_i, Y_i, Y'_i, X_i, X'_i)`
:math:`c' = H(G_q, g_0, g_1, G_0, G_1, C_j, y_i, Y_i, Y'_i, X_i, X'_i)`
with :math:`j \in [0,t)` and for all users :math:`i`.

* Verify that :math:`c = c'`
Expand Down
52 changes: 41 additions & 11 deletions pvss/pvss.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ def _validate(self) -> None:

class SharedSecret(Asn1Object):
"""
All shares of a shared secret, along with Zero Knowledge proof.
All shares of a shared secret, along with Zero-Knowledge proof.
"""

asn1: _asn1.SharedSecret
Expand Down Expand Up @@ -574,34 +574,49 @@ def share(self) -> Share:
return self.pvss.shares.shares[self.idx - 1]

def _validate(self) -> None:
"""`
"""
Verify Zero-Knowledge proof of the ReencryptedShare.
Raises:
ValueError: If verification failed.
"""

# Compute -c
minus_c = -self.challenge

# Grab public key of share's sender.
pub = self.share.pub

# Compute commitment for public key.
rand_pub = ((self.params.G[0] * self.params.G[1]) ** self.response_priv) * (
(pub.pub[0] * pub.pub[1]) ** minus_c
)

# Compute commitment for share.
rand_share = (
(self.elg_b ** self.response_priv)
* (self.pvss.receiver_public_key.pub[0] ** self.response_v[0])
* (self.pvss.receiver_public_key.pub[1] ** self.response_v[1])
) * (self.pvss.shares.shares[self.idx - 1].share ** minus_c)

rand_pub = ((self.params.G[0] * self.params.G[1]) ** self.response_priv) * (
(pub.pub[0] * pub.pub[1]) ** minus_c
)
# Compute commitment for ElGamal value.
rand_elg_a = (
(self.params.G[0] ** self.response_w[0]) * (self.params.G[1] ** self.response_w[1])
) * (self.elg_a ** minus_c)

# Compute commitment for Identity.
rand_id = (
(self.elg_a ** self.response_priv)
* (self.params.G[0] ** self.response_v[0])
* (self.params.G[1] ** self.response_v[1])
)

# Compute challenge for Zero-Knowledge proof.
challenge = ReencryptedChallenge.create(
self.pvss, rand_pub, rand_share, rand_elg_a, rand_id
)

# Verify that the digests match.
if challenge.digest != self.digest:
raise ValueError("Verification failed: could not compute same challenge")

Expand All @@ -619,46 +634,61 @@ def reencrypt(cls, pvss: Pvss, private_key: PrivateKey) -> ReencryptedShare:
Re-encrypted share
"""

# Locate our share
# Locate our share.
for idx, enc_share in enumerate(pvss.shares.shares, 1):
if enc_share.pub == private_key.pub(enc_share.pub_name):
break
else:
raise ValueError("No matching public key found")

# decrypt our share
# Decrypt our share.
share = enc_share.share ** private_key.priv.inv

# Reencrypt share with Elgamal encryption using the receiver's public key
# Choose random values.
w = [pvss.params.pre_group.rand, pvss.params.pre_group.rand]

# Reencrypt share with ElGamal encryption using the receiver's public key.
elg_a = (pvss.params.G[0] ** w[0]) * (pvss.params.G[1] ** w[1])
elg_b = (
share
* (pvss.receiver_public_key.pub[0] ** w[0])
* (pvss.receiver_public_key.pub[1] ** w[1])
)

# Compute helper variables.
v = [-w[0] * private_key.priv, -w[1] * private_key.priv]

# Choose random pre-group values for the commitments.
kpi = pvss.params.pre_group.rand
kv = (pvss.params.pre_group.rand, pvss.params.pre_group.rand)
kw = (pvss.params.pre_group.rand, pvss.params.pre_group.rand)
kpi = pvss.params.pre_group.rand

# Compute commitment for public key.
rand_pub = (pvss.params.G[0] * pvss.params.G[1]) ** kpi

# Compute commitment for share.
rand_share = (
(elg_b ** kpi)
* (pvss.receiver_public_key.pub[0] ** kv[0])
* (pvss.receiver_public_key.pub[1] ** kv[1])
)
rand_pub = (pvss.params.G[0] * pvss.params.G[1]) ** kpi

# Compute commitment for ElGamal value.
rand_elg_a = (pvss.params.G[0] ** kw[0]) * (pvss.params.G[1] ** kw[1])

# Compute commitment for Identity.
rand_id = (elg_a ** kpi) * (pvss.params.G[0] ** kv[0]) * (pvss.params.G[1] ** kv[1])

# Compute challenge for Zero-Knowledge proof.
challenge = ReencryptedChallenge.create(pvss, rand_pub, rand_share, rand_elg_a, rand_id)

c = challenge.challenge

# Compute responses for Zero-Knowledge proof.
resp_priv = kpi + private_key.priv * c
resp_v = (kv[0] + v[0] * c, kv[1] + v[1] * c)
resp_w = (kw[0] + w[0] * c, kw[1] + w[1] * c)

# Assemble the values for the result.
return ReencryptedShare.create(
pvss, idx, elg_a, elg_b, resp_priv, resp_v, resp_w, challenge.digest
)
Expand Down
14 changes: 2 additions & 12 deletions pvss/qr.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,12 @@
from dataclasses import dataclass
from fractions import Fraction
from functools import cached_property
from os import environ
from typing import Optional, Union, cast

from asn1crypto.algos import DHParameters
from asn1crypto.core import Asn1Value, Integer
from asn1crypto.pem import unarmor

try:
from gmpy2 import invert, is_prime, legendre, mpz, powmod
except ImportError: # pragma: no cover
# Work around the fact that gmpy2 is not installed in the readthedocs build image
if "READTHEDOCS" not in environ:
raise
else:
# Will be fixed by gmpy2 2.1
mpz_type = mpz if isinstance(mpz, type) else type(mpz(0))
from gmpy2 import invert, is_prime, legendre, mpz, powmod

from .asn1 import ImgGroupValue
from .groups import ImageGroup, ImageValue, PgvOrInt
Expand Down Expand Up @@ -122,7 +112,7 @@ def __post_init__(self) -> None:
raise ValueError("(p - 1) / 2 not prime")

def __call__(self, value: Union[int, mpz, Integer, Asn1Value]) -> QrValue:
if isinstance(value, (int, mpz_type)):
if isinstance(value, (int, mpz)):
value %= self.p
if value == 0:
raise ValueError("0 not in group")
Expand Down

0 comments on commit e3c79c4

Please sign in to comment.