mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-02-22 12:32:02 +00:00
refactor(core): move Zcash generators module to Rust
This commit is contained in:
parent
ac73bfaf1e
commit
dc2057d10e
@ -1,13 +1,8 @@
|
|||||||
import gc
|
import gc
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from trezor.crypto.pallas import Point, Scalar, scalar_from_i64
|
from trezor.crypto.pallas import Point, Scalar, generators as gen, scalar_from_i64
|
||||||
|
|
||||||
from .generators import (
|
|
||||||
SPENDING_KEY_BASE,
|
|
||||||
VALUE_COMMITMENT_RANDOMNESS_BASE,
|
|
||||||
VALUE_COMMITMENT_VALUE_BASE,
|
|
||||||
)
|
|
||||||
from .keys import FullViewingKey, sk_to_ask
|
from .keys import FullViewingKey, sk_to_ask
|
||||||
from .note import Note
|
from .note import Note
|
||||||
from .note_encryption import encrypt_note
|
from .note_encryption import encrypt_note
|
||||||
@ -19,8 +14,8 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
# https://zips.z.cash/protocol/nu5.pdf#concretehomomorphiccommit
|
# https://zips.z.cash/protocol/nu5.pdf#concretehomomorphiccommit
|
||||||
def commit_value(rcv: Scalar, v: int):
|
def commit_value(rcv: Scalar, v: int):
|
||||||
V = scalar_from_i64(v) * VALUE_COMMITMENT_VALUE_BASE
|
V = scalar_from_i64(v) * gen.VALUE_COMMITMENT_VALUE_BASE
|
||||||
R = rcv * VALUE_COMMITMENT_RANDOMNESS_BASE
|
R = rcv * gen.VALUE_COMMITMENT_RANDOMNESS_BASE
|
||||||
return V + R
|
return V + R
|
||||||
|
|
||||||
|
|
||||||
@ -87,7 +82,7 @@ def build_action(
|
|||||||
# verification key
|
# verification key
|
||||||
alpha = rng.alpha()
|
alpha = rng.alpha()
|
||||||
akP = Point(input.fvk.ak.to_bytes())
|
akP = Point(input.fvk.ak.to_bytes())
|
||||||
rk = akP + alpha * SPENDING_KEY_BASE
|
rk = akP + alpha * gen.SPENDING_KEY_BASE
|
||||||
|
|
||||||
# note commitment
|
# note commitment
|
||||||
note = Note(
|
note = Note(
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
"""Precomputed Orchard generators."""
|
|
||||||
|
|
||||||
from trezor.crypto.pallas import Point
|
|
||||||
|
|
||||||
# https://zips.z.cash/protocol/nu5.pdf#concretespendauthsig
|
|
||||||
SPENDING_KEY_BASE = Point(
|
|
||||||
b"\x63\xc9\x75\xb8\x84\x72\x1a\x8d\x0c\xa1\x70\x7b\xe3\x0c\x7f\x0c\x5f\x44\x5f\x3e\x7c\x18\x8d\x3b\x06\xd6\xf1\x28\xb3\x23\x55\xb7"
|
|
||||||
)
|
|
||||||
|
|
||||||
# https://zips.z.cash/protocol/nu5.pdf#commitmentsandnullifiers
|
|
||||||
NULLIFIER_K_BASE = Point(
|
|
||||||
b"\x75\xca\x47\xe4\xa7\x6a\x6f\xd3\x9b\xdb\xb5\xcc\x92\xb1\x7e\x5e\xcf\xc9\xf4\xfa\x71\x55\x37\x2e\x8d\x19\xa8\x9c\x16\xaa\xe7\x25"
|
|
||||||
)
|
|
||||||
|
|
||||||
# https://zips.z.cash/protocol/nu5.pdf#concretehomomorphiccommit
|
|
||||||
VALUE_COMMITMENT_VALUE_BASE = Point(
|
|
||||||
b"\x67\x43\xf9\x3a\x6e\xbd\xa7\x2a\x8c\x7c\x5a\x2b\x7f\xa3\x04\xfe\x32\xb2\x9b\x4f\x70\x6a\xa8\xf7\x42\x0f\x3d\x8e\x7a\x59\x70\x2f"
|
|
||||||
)
|
|
||||||
VALUE_COMMITMENT_RANDOMNESS_BASE = Point(
|
|
||||||
b"\x91\x5a\x3c\x88\x68\xc6\xc3\x0e\x2f\x80\x90\xee\x45\xd7\x6e\x40\x48\x20\x8d\xea\x5b\x23\x66\x4f\xbb\x09\xa4\x0f\x55\x44\xf4\x07"
|
|
||||||
)
|
|
||||||
|
|
||||||
# https://zips.z.cash/protocol/protocol.pdf#concretesinsemillacommit
|
|
||||||
NOTE_COMMITMENT_BASE = Point(
|
|
||||||
b"\x13\x6e\xfc\x0f\x48\x2c\x02\x2c\x7c\xa4\x14\xfc\x5c\xc5\x9e\x23\xf2\x3d\x6f\x93\xab\x9f\x23\xcd\x33\x45\xa9\x28\xc3\x06\xb2\xa6"
|
|
||||||
)
|
|
||||||
NOTE_COMMITMENT_Q = Point(
|
|
||||||
b"\x5d\x74\xa8\x40\x09\xba\x0e\x32\x2a\xdd\x46\xfd\x5a\x0f\x96\xc5\x5d\xed\xb0\x79\xb4\xf2\x9f\xf7\x0d\xcd\xfb\x56\xa0\x07\x80\x97"
|
|
||||||
)
|
|
||||||
IVK_COMMITMENT_BASE = Point(
|
|
||||||
b"\x18\xa1\xf8\x5f\x6e\x48\x23\x98\xc7\xed\x1a\xd3\xe2\x7f\x95\x02\x48\x89\x80\x40\x0a\x29\x34\x16\x4e\x13\x70\x50\xcd\x2c\xa2\xa5"
|
|
||||||
)
|
|
||||||
IVK_COMMITMENT_Q = Point(
|
|
||||||
b"\xf2\x82\x0f\x79\x92\x2f\xcb\x6b\x32\xa2\x28\x51\x24\xcc\x1b\x42\xfa\x41\xa2\x5a\xb8\x81\xcc\x7d\x11\xc8\xa9\x4a\xf1\x0c\xbc\x05"
|
|
||||||
)
|
|
@ -1,11 +1,10 @@
|
|||||||
# https://zips.z.cash/protocol/protocol.pdf#orchardkeycomponents
|
# https://zips.z.cash/protocol/protocol.pdf#orchardkeycomponents
|
||||||
|
|
||||||
from trezor.crypto.pallas import Fp, Scalar, to_base, to_scalar
|
from trezor.crypto.pallas import Fp, Scalar, generators as gen, to_base, to_scalar
|
||||||
from trezor.utils import ensure
|
from trezor.utils import ensure
|
||||||
|
|
||||||
from . import ff1
|
from . import ff1
|
||||||
from .address import Address
|
from .address import Address
|
||||||
from .generators import IVK_COMMITMENT_BASE, IVK_COMMITMENT_Q, SPENDING_KEY_BASE
|
|
||||||
from .sinsemilla import Sinsemilla
|
from .sinsemilla import Sinsemilla
|
||||||
from .utils import i2lebsp, prf_expand
|
from .utils import i2lebsp, prf_expand
|
||||||
|
|
||||||
@ -13,7 +12,7 @@ from .utils import i2lebsp, prf_expand
|
|||||||
def sk_to_ask(sk: bytes) -> Scalar:
|
def sk_to_ask(sk: bytes) -> Scalar:
|
||||||
"""Derives Spend Authorizing Key from Spending Key."""
|
"""Derives Spend Authorizing Key from Spending Key."""
|
||||||
ask = to_scalar(prf_expand(sk, b"\x06"))
|
ask = to_scalar(prf_expand(sk, b"\x06"))
|
||||||
akP = ask * SPENDING_KEY_BASE
|
akP = ask * gen.SPENDING_KEY_BASE
|
||||||
if akP.to_bytes()[-1] & 0x80 != 0:
|
if akP.to_bytes()[-1] & 0x80 != 0:
|
||||||
ask = -ask
|
ask = -ask
|
||||||
ensure(ask) # ask != 0
|
ensure(ask) # ask != 0
|
||||||
@ -57,7 +56,7 @@ class FullViewingKey:
|
|||||||
nk = to_base(prf_expand(sk, b"\x07"))
|
nk = to_base(prf_expand(sk, b"\x07"))
|
||||||
rivk = to_scalar(prf_expand(sk, b"\x08"))
|
rivk = to_scalar(prf_expand(sk, b"\x08"))
|
||||||
ensure(ask) # ask != 0
|
ensure(ask) # ask != 0
|
||||||
ak = (ask * SPENDING_KEY_BASE).extract()
|
ak = (ask * gen.SPENDING_KEY_BASE).extract()
|
||||||
return FullViewingKey(ak, nk, rivk)
|
return FullViewingKey(ak, nk, rivk)
|
||||||
|
|
||||||
# https://zips.z.cash/protocol/protocol.pdf#orchardfullviewingkeyencoding
|
# https://zips.z.cash/protocol/protocol.pdf#orchardfullviewingkeyencoding
|
||||||
@ -107,8 +106,8 @@ class FullViewingKey:
|
|||||||
|
|
||||||
# https://zips.z.cash/protocol/nu5.pdf#concreteNotecommit
|
# https://zips.z.cash/protocol/nu5.pdf#concreteNotecommit
|
||||||
def commit_ivk(rivk: Scalar, ak: Fp, nk: Fp) -> Fp:
|
def commit_ivk(rivk: Scalar, ak: Fp, nk: Fp) -> Fp:
|
||||||
h = Sinsemilla(IVK_COMMITMENT_Q)
|
h = Sinsemilla(gen.IVK_COMMITMENT_Q)
|
||||||
h.update(i2lebsp(255, ak))
|
h.update(i2lebsp(255, ak))
|
||||||
h.update(i2lebsp(255, nk))
|
h.update(i2lebsp(255, nk))
|
||||||
commitment = h.finalize() + rivk * IVK_COMMITMENT_BASE
|
commitment = h.finalize() + rivk * gen.IVK_COMMITMENT_BASE
|
||||||
return commitment.extract()
|
return commitment.extract()
|
||||||
|
@ -1,7 +1,14 @@
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from trezor.crypto.hashlib import poseidon
|
from trezor.crypto.hashlib import poseidon
|
||||||
from trezor.crypto.pallas import Fp, Point, Scalar, to_base, to_scalar
|
from trezor.crypto.pallas import (
|
||||||
|
Fp,
|
||||||
|
Point,
|
||||||
|
Scalar,
|
||||||
|
generators as gen,
|
||||||
|
to_base,
|
||||||
|
to_scalar,
|
||||||
|
)
|
||||||
from trezor.messages import ZcashOrchardInput
|
from trezor.messages import ZcashOrchardInput
|
||||||
|
|
||||||
from apps.common.writers import (
|
from apps.common.writers import (
|
||||||
@ -12,7 +19,6 @@ from apps.common.writers import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
from .address import Address
|
from .address import Address
|
||||||
from .generators import NOTE_COMMITMENT_BASE, NOTE_COMMITMENT_Q, NULLIFIER_K_BASE
|
|
||||||
from .sinsemilla import Sinsemilla
|
from .sinsemilla import Sinsemilla
|
||||||
from .utils import i2lebsp, leos2bsp, prf_expand
|
from .utils import i2lebsp, leos2bsp, prf_expand
|
||||||
|
|
||||||
@ -52,19 +58,19 @@ class Note:
|
|||||||
|
|
||||||
# https://zips.z.cash/protocol/nu5.pdf#concreteNotecommit
|
# https://zips.z.cash/protocol/nu5.pdf#concreteNotecommit
|
||||||
def commitment(self) -> Point:
|
def commitment(self) -> Point:
|
||||||
h = Sinsemilla(NOTE_COMMITMENT_Q)
|
h = Sinsemilla(gen.NOTE_COMMITMENT_Q)
|
||||||
h.update(leos2bsp(self.recipient.g_d().to_bytes()))
|
h.update(leos2bsp(self.recipient.g_d().to_bytes()))
|
||||||
h.update(leos2bsp(self.recipient.pk_d.to_bytes()))
|
h.update(leos2bsp(self.recipient.pk_d.to_bytes()))
|
||||||
h.update(i2lebsp(64, self.value))
|
h.update(i2lebsp(64, self.value))
|
||||||
h.update(i2lebsp(255, self.rho))
|
h.update(i2lebsp(255, self.rho))
|
||||||
h.update(i2lebsp(255, self.psi()))
|
h.update(i2lebsp(255, self.psi()))
|
||||||
return h.finalize() + self.rcm() * NOTE_COMMITMENT_BASE
|
return h.finalize() + self.rcm() * gen.NOTE_COMMITMENT_BASE
|
||||||
|
|
||||||
# https://zips.z.cash/protocol/protocol.pdf#commitmentsandnullifiers
|
# https://zips.z.cash/protocol/protocol.pdf#commitmentsandnullifiers
|
||||||
def nullifier(self, nk: Fp) -> Fp:
|
def nullifier(self, nk: Fp) -> Fp:
|
||||||
base = poseidon(nk, self.rho) + self.psi()
|
base = poseidon(nk, self.rho) + self.psi()
|
||||||
scalar = Scalar(base.to_bytes())
|
scalar = Scalar(base.to_bytes())
|
||||||
point = scalar * NULLIFIER_K_BASE + self.commitment()
|
point = scalar * gen.NULLIFIER_K_BASE + self.commitment()
|
||||||
return point.extract()
|
return point.extract()
|
||||||
|
|
||||||
# https://zips.z.cash/protocol/nu5.pdf#notept
|
# https://zips.z.cash/protocol/nu5.pdf#notept
|
||||||
|
@ -3,9 +3,8 @@
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from trezor.crypto.hashlib import blake2b
|
from trezor.crypto.hashlib import blake2b
|
||||||
from trezor.crypto.pallas import to_scalar
|
from trezor.crypto.pallas import generators as gen, to_scalar
|
||||||
|
|
||||||
from .generators import SPENDING_KEY_BASE
|
|
||||||
from .utils import xor
|
from .utils import xor
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@ -32,9 +31,9 @@ def sign_spend_auth(sk: Scalar, message: bytes, rng: ActionShieldingRng) -> byte
|
|||||||
# - `rng.spend_auth_T()` randomizes the signature
|
# - `rng.spend_auth_T()` randomizes the signature
|
||||||
# - xoring with bytes of `sk` makes `T` unpredictable for outside
|
# - xoring with bytes of `sk` makes `T` unpredictable for outside
|
||||||
|
|
||||||
vk: bytes = (sk * SPENDING_KEY_BASE).to_bytes()
|
vk: bytes = (sk * gen.SPENDING_KEY_BASE).to_bytes()
|
||||||
r: Scalar = H_star(T + vk + message)
|
r: Scalar = H_star(T + vk + message)
|
||||||
R: bytes = (r * SPENDING_KEY_BASE).to_bytes()
|
R: bytes = (r * gen.SPENDING_KEY_BASE).to_bytes()
|
||||||
e: Scalar = H_star(R + vk + message)
|
e: Scalar = H_star(R + vk + message)
|
||||||
S: bytes = (r + e * sk).to_bytes()
|
S: bytes = (r + e * sk).to_bytes()
|
||||||
return R + S
|
return R + S
|
||||||
|
@ -11,4 +11,5 @@ if utils.ZCASH_SHIELDED:
|
|||||||
scalar_from_i64,
|
scalar_from_i64,
|
||||||
to_base,
|
to_base,
|
||||||
to_scalar,
|
to_scalar,
|
||||||
|
generators,
|
||||||
)
|
)
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
from common import *
|
from common import *
|
||||||
from trezor.crypto.pallas import group_hash, Point
|
from trezor.crypto.pallas import group_hash, Point, generators as gen
|
||||||
from apps.zcash.orchard.crypto import generators as gen
|
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipUnless(not utils.BITCOIN_ONLY, "altcoin")
|
@unittest.skipUnless(not utils.BITCOIN_ONLY, "altcoin")
|
||||||
|
Loading…
Reference in New Issue
Block a user