Zeth - Zerocash on Ethereum  0.8
Reference implementation of the Zeth protocol by Clearmatics
signing.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
2 
3 # Copyright (c) 2015-2022 Clearmatics Technologies Ltd
4 #
5 # SPDX-License-Identifier: LGPL-3.0+
6 
7 """
8 Implementation of Schnorr-based one-time signature from: "Two-tier
9 signatures, strongly unforgeable signatures, and Fiat-Shamir without random
10 oracles" by Bellare and Shoup (https://eprint.iacr.org/2007/273.pdf) over Curve
11 BN128
12 """
13 
14 from __future__ import annotations
15 from math import ceil
16 from os import urandom
17 from hashlib import sha256
18 from py_ecc import bn128 as ec
19 from typing import Dict, List, Tuple, Any
20 
21 FQ = ec.FQ
22 G1 = Tuple[ec.FQ, ec.FQ]
23 
24 
26  """
27  An OT-Schnorr verification key.
28  """
29  def __init__(self, ppk: G1, spk: G1):
30  self.ppk = ppk
31  self.spk = spk
32 
33  def to_bytes(self) -> bytes:
34  return g1_to_bytes(self.ppk) + g1_to_bytes(self.spk)
35 
36  def to_json_dict(self) -> Dict[str, Any]:
37  return {
38  "ppk": g1_to_json_dict(self.ppk),
39  "spk": g1_to_json_dict(self.spk),
40  }
41 
42  @staticmethod
43  def from_json_dict(json_dict: Dict[str, Any]) -> SigningVerificationKey:
45  ppk=g1_from_json_dict(json_dict["ppk"]),
46  spk=g1_from_json_dict(json_dict["spk"]))
47 
48 
50  """
51  An OT-Schnorr signing key.
52  """
53  def __init__(self, x: FQ, y: FQ, y_g1: G1):
54  self.psk = x
55  self.ssk = (y, y_g1)
56 
57  def to_json_dict(self) -> Dict[str, Any]:
58  return {
59  "psk": fq_to_hex(self.psk),
60  "ssk_y": fq_to_hex(self.ssk[0]),
61  "ssk_y_g1": g1_to_json_dict(self.ssk[1]),
62  }
63 
64  @staticmethod
65  def from_json_dict(json_dict: Dict[str, Any]) -> SigningSecretKey:
66  return SigningSecretKey(
67  x=fq_from_hex(json_dict["psk"]),
68  y=fq_from_hex(json_dict["ssk_y"]),
69  y_g1=g1_from_json_dict(json_dict["ssk_y_g1"]))
70 
71 
73  """
74  An OT-Schnorr signing and verification keypair.
75  """
76  def __init__(self, sk: SigningSecretKey, vk: SigningVerificationKey):
77  self.sk = sk
78  self.vk = vk
79 
80  def to_json_dict(self) -> Dict[str, Any]:
81  return {
82  "sk": self.sk.to_json_dict(),
83  "vk": self.vk.to_json_dict(),
84  }
85 
86  @staticmethod
87  def from_json_dict(json_dict: Dict[str, Any]) -> SigningKeyPair:
88  return SigningKeyPair(
89  SigningSecretKey.from_json_dict(json_dict["sk"]),
90  SigningVerificationKey.from_json_dict(json_dict["vk"]))
91 
92 
93 def gen_signing_keypair() -> SigningKeyPair:
94  """
95  Return a one-time signature key-pair
96  composed of elements of F_q and G1.
97  """
98  key_size_byte = ceil(len("{0:b}".format(ec.curve_order)) / 8)
99  x = FQ(
100  int(bytes(urandom(key_size_byte)).hex(), 16) % ec.curve_order)
101  y = FQ(
102  int(bytes(urandom(key_size_byte)).hex(), 16) % ec.curve_order)
103  X = ec.multiply(ec.G1, x.n)
104  Y = ec.multiply(ec.G1, y.n)
105 
106  # We include y_g1 in the signing key
107  sk = SigningSecretKey(x, y, Y)
108  vk = SigningVerificationKey(X, Y)
109  return SigningKeyPair(sk, vk)
110 
111 
112 Signature = int
113 
114 
115 def signature_to_bytes(signature: Signature) -> bytes:
116  return signature.to_bytes(32, byteorder='big')
117 
118 
119 def signature_from_bytes(sig_bytes: bytes) -> Signature:
120  return int.from_bytes(sig_bytes, byteorder='big')
121 
122 
123 def sign(
124  sk: SigningSecretKey,
125  m: bytes) -> Signature:
126  """
127  Generate a Schnorr signature on a message m.
128  We assume here that the message fits in an Ethereum word (i.e. bit_len(m)
129  <= 256), so that it can be represented by a single bytes32 on the smart-
130  contract during the signature verification.
131  """
132 
133  # Encode and hash the verifying key and input hashes
134  challenge_to_hash = g1_to_bytes(sk.ssk[1]) + m
135 
136  # Convert the hex digest into a field element
137  challenge = int(sha256(challenge_to_hash).hexdigest(), 16)
138  challenge = challenge % ec.curve_order
139 
140  # Compute the signature sigma
141  sigma = (sk.ssk[0].n + challenge * sk.psk.n) % ec.curve_order
142  return sigma
143 
144 
145 def verify(
146  vk: SigningVerificationKey,
147  m: bytes,
148  sigma: int) -> bool:
149  """
150  Return true if the signature sigma is valid on message m and vk.
151  We assume here that the message is an hexadecimal string written in
152  less than 256 bits to conform with Ethereum bytes32 type.
153  """
154  # Encode and hash the verifying key and input hashes
155  challenge_to_hash = g1_to_bytes(vk.spk) + m
156 
157  challenge = int(sha256(challenge_to_hash).hexdigest(), 16)
158  challenge = challenge % ec.curve_order
159 
160  left_part = ec.multiply(ec.G1, FQ(sigma).n)
161  right_part = ec.add(vk.spk, ec.multiply(vk.ppk, FQ(challenge).n))
162 
163  return ec.eq(left_part, right_part)
164 
165 
166 def verification_key_as_mix_parameter(vk: SigningVerificationKey) -> List[int]:
167  """
168  Transform a verification key to the format required by the mix function.
169  """
170  return [int(vk.ppk[0]), int(vk.ppk[1]), int(vk.spk[0]), int(vk.spk[1])]
171 
172 
174  param: List[int]) -> SigningVerificationKey:
175  """
176  Transform mix function parameter to verification key.
177  """
178  return SigningVerificationKey(
179  (FQ(param[0]), FQ(param[1])),
180  (FQ(param[2]), FQ(param[3])))
181 
182 
183 def signature_as_mix_parameter(signature: Signature) -> int:
184  """
185  Transform a signature to the format required by the mix function.
186  """
187  # This function happens to be the identity but in the general case some
188  # transform will be required.
189  return signature
190 
191 
192 def signature_from_mix_parameter(param: int) -> Signature:
193  """
194  Transform mix function parameters to a signature.
195  """
196  return param
197 
198 # Low level encoding / decoding functions
199 
200 
201 def fq_to_bytes(fq_element: FQ) -> bytes:
202  return int(fq_element.n).to_bytes(32, byteorder='big')
203 
204 
205 def fq_from_bytes(fq_bytes: bytes) -> FQ:
206  return FQ(int.from_bytes(fq_bytes, byteorder='big'))
207 
208 
209 def fq_to_hex(fq_element: FQ) -> str:
210  return fq_to_bytes(fq_element).hex()
211 
212 
213 def fq_from_hex(fq_hex: str) -> FQ:
214  return fq_from_bytes(bytes.fromhex(fq_hex))
215 
216 
217 def g1_to_bytes(group_el: G1) -> bytes:
218  """
219  Encode a group element into a byte string
220  We assume here the group prime $p$ is written in less than 256 bits
221  to conform with Ethereum bytes32 type.
222  """
223  return \
224  int(group_el[0]).to_bytes(32, byteorder='big') + \
225  int(group_el[1]).to_bytes(32, byteorder='big')
226 
227 
228 def g1_to_json_dict(group_el: G1) -> Dict[str, Any]:
229  return {
230  "x": fq_to_hex(group_el[0]),
231  "y": fq_to_hex(group_el[1]),
232  }
233 
234 
235 def g1_from_json_dict(json_dict: Dict[str, Any]) -> G1:
236  return (fq_from_hex(json_dict["x"]), fq_from_hex(json_dict["y"]))
zeth.core.signing.SigningSecretKey.ssk
ssk
Definition: signing.py:55
zeth.core.signing.SigningVerificationKey.to_json_dict
Dict[str, Any] to_json_dict(self)
Definition: signing.py:36
zeth.core.signing.SigningKeyPair.__init__
def __init__(self, SigningSecretKey sk, SigningVerificationKey vk)
Definition: signing.py:76
zeth.core.signing.g1_from_json_dict
G1 g1_from_json_dict(Dict[str, Any] json_dict)
Definition: signing.py:235
zeth.core.signing.SigningKeyPair.sk
sk
Definition: signing.py:77
zeth.cli.zeth_deploy.int
int
Definition: zeth_deploy.py:27
zeth.core.signing.signature_to_bytes
bytes signature_to_bytes(Signature signature)
Definition: signing.py:115
zeth.core.signing.SigningKeyPair.from_json_dict
SigningKeyPair from_json_dict(Dict[str, Any] json_dict)
Definition: signing.py:87
zeth.core.signing.SigningKeyPair.vk
vk
Definition: signing.py:78
zeth.core.signing.SigningVerificationKey.to_bytes
bytes to_bytes(self)
Definition: signing.py:33
zeth.core.signing.SigningSecretKey
Definition: signing.py:49
zeth.core.signing.SigningSecretKey.__init__
def __init__(self, FQ x, FQ y, G1 y_g1)
Definition: signing.py:53
zeth.core.signing.gen_signing_keypair
SigningKeyPair gen_signing_keypair()
Definition: signing.py:93
zeth.core.encryption.bytes
bytes
Definition: encryption.py:87
zeth.core.signing.SigningVerificationKey.ppk
ppk
Definition: signing.py:30
zeth.core.signing.SigningKeyPair.to_json_dict
Dict[str, Any] to_json_dict(self)
Definition: signing.py:80
zeth.core.signing.fq_to_hex
str fq_to_hex(FQ fq_element)
Definition: signing.py:209
zeth.core.signing.verify
bool verify(SigningVerificationKey vk, bytes m, int sigma)
Definition: signing.py:145
zeth.core.signing.SigningKeyPair
Definition: signing.py:72
zeth.core.signing.signature_from_mix_parameter
Signature signature_from_mix_parameter(int param)
Definition: signing.py:192
zeth.core.signing.SigningSecretKey.to_json_dict
Dict[str, Any] to_json_dict(self)
Definition: signing.py:57
zeth.core.signing.g1_to_bytes
bytes g1_to_bytes(G1 group_el)
Definition: signing.py:217
zeth.core.signing.FQ
FQ
Definition: signing.py:21
zeth.core.signing.signature_from_bytes
Signature signature_from_bytes(bytes sig_bytes)
Definition: signing.py:119
zeth.core.signing.signature_as_mix_parameter
int signature_as_mix_parameter(Signature signature)
Definition: signing.py:183
zeth.core.signing.g1_to_json_dict
Dict[str, Any] g1_to_json_dict(G1 group_el)
Definition: signing.py:228
zeth.core.signing.SigningVerificationKey.spk
spk
Definition: signing.py:31
zeth.core.signing.fq_from_bytes
FQ fq_from_bytes(bytes fq_bytes)
Definition: signing.py:205
zeth.core.signing.SigningVerificationKey.from_json_dict
SigningVerificationKey from_json_dict(Dict[str, Any] json_dict)
Definition: signing.py:43
zeth.core.signing.fq_to_bytes
bytes fq_to_bytes(FQ fq_element)
Definition: signing.py:201
zeth.core.signing.SigningSecretKey.psk
psk
Definition: signing.py:54
zeth.core.signing.SigningSecretKey.from_json_dict
SigningSecretKey from_json_dict(Dict[str, Any] json_dict)
Definition: signing.py:65
zeth.core.signing.verification_key_as_mix_parameter
List[int] verification_key_as_mix_parameter(SigningVerificationKey vk)
Definition: signing.py:166
zeth.core.signing.SigningVerificationKey.__init__
def __init__(self, G1 ppk, G1 spk)
Definition: signing.py:29
zeth.core.signing.fq_from_hex
FQ fq_from_hex(str fq_hex)
Definition: signing.py:213
zeth.core.signing.verification_key_from_mix_parameter
SigningVerificationKey verification_key_from_mix_parameter(List[int] param)
Definition: signing.py:173
zeth.core.signing.sign
Signature sign(SigningSecretKey sk, bytes m)
Definition: signing.py:123
zeth.core.signing.SigningVerificationKey
Definition: signing.py:25