update hash_to_curve

This commit is contained in:
callebtc
2022-10-10 19:00:33 +02:00
parent e0d8f7b816
commit 88a7e38da0
7 changed files with 33 additions and 24 deletions

View File

@@ -6,7 +6,7 @@ Alice:
A = a*G A = a*G
return A return A
Bob: Bob:
Y = hash_to_point(secret_message) Y = hash_to_curve(secret_message)
r = random blinding factor r = random blinding factor
B'= Y + r*G B'= Y + r*G
return B' return B'
@@ -20,7 +20,7 @@ C = C' - r*A
(= a*Y) (= a*Y)
return C, secret_message return C, secret_message
Alice: Alice:
Y = hash_to_point(secret_message) Y = hash_to_curve(secret_message)
C == a*Y C == a*Y
If true, C must have originated from Alice If true, C must have originated from Alice
""" """
@@ -30,28 +30,22 @@ import hashlib
from secp256k1 import PrivateKey, PublicKey from secp256k1 import PrivateKey, PublicKey
def hash_to_point(secret_msg): def hash_to_curve(message: bytes):
"""Generates x coordinate from the message hash and checks if the point lies on the curve. """Generates a point from the message hash and checks if the point lies on the curve.
If it does not, it tries computing again a new x coordinate from the hash of the coordinate.""" If it does not, it tries computing a new point from the hash."""
point = None point = None
msg = secret_msg msg_to_hash = message
while point is None: while point is None:
_hash = hashlib.sha256(msg).hexdigest().encode("utf-8")
try: try:
# We construct compressed pub which has x coordinate encoded with even y _hash = hashlib.sha256(msg_to_hash).digest()
_hash = list(_hash[:33]) # take the 33 bytes and get a list of bytes point = PublicKey(b"\x02" + _hash, raw=True)
_hash[0] = 0x02 # set first byte to represent even y coord
_hash = bytes(_hash)
point = PublicKey(_hash, raw=True)
except: except:
msg = _hash msg_to_hash = _hash
return point return point
def step1_alice(secret_msg): def step1_alice(secret_msg: str):
secret_msg = secret_msg.encode("utf-8") Y = hash_to_curve(secret_msg.encode("utf-8"))
Y = hash_to_point(secret_msg)
r = PrivateKey() r = PrivateKey()
B_ = Y + r.pubkey B_ = Y + r.pubkey
return B_, r return B_, r
@@ -68,7 +62,7 @@ def step3_alice(C_, r, A):
def verify(a, C, secret_msg): def verify(a, C, secret_msg):
Y = hash_to_point(secret_msg.encode("utf-8")) Y = hash_to_curve(secret_msg.encode("utf-8"))
return C == Y.mult(a) return C == Y.mult(a)

View File

@@ -247,7 +247,7 @@ class MintKeyset:
first_seen=None, first_seen=None,
active=None, active=None,
seed: Union[None, str] = None, seed: Union[None, str] = None,
derivation_path: str = "0", derivation_path: str = None,
): ):
self.derivation_path = derivation_path self.derivation_path = derivation_path
self.id = id self.id = id

View File

@@ -6,6 +6,20 @@ from cashu.core.secp import PrivateKey, PublicKey
from cashu.core.settings import MAX_ORDER from cashu.core.settings import MAX_ORDER
def derivation_path_newer_than(d1: str, d2: str):
"""
Returns whether derivation path d1 is newer (deeper down the derivation tree)
than d2. Used for treating tokens with old keysets differently.
"""
# NOTE: Derivation paths are still just simple integers for now. This function needs
# to change once we upgrade to BIP32.
# the very first derivation path was "" (empty string) so anything is newer than itself
if d1 == "" and d2 != "":
return False
return int(d1) > int(d2)
def derive_keys(master_key: str, derivation_path: str = ""): def derive_keys(master_key: str, derivation_path: str = ""):
""" """
Deterministic derivation of keys for 2^n values. Deterministic derivation of keys for 2^n values.

View File

@@ -1,4 +1,4 @@
from cashu.core.settings import MINT_PRIVATE_KEY from cashu.core.settings import MINT_PRIVATE_KEY
from cashu.mint.ledger import Ledger from cashu.mint.ledger import Ledger
ledger = Ledger(MINT_PRIVATE_KEY, "data/mint") ledger = Ledger(MINT_PRIVATE_KEY, "data/mint", derivation_path="0")

View File

@@ -112,6 +112,7 @@ class Ledger:
secret_key = self.keysets.keysets[proof.id].private_keys[proof.amount] secret_key = self.keysets.keysets[proof.id].private_keys[proof.amount]
C = PublicKey(bytes.fromhex(proof.C), raw=True) C = PublicKey(bytes.fromhex(proof.C), raw=True)
return b_dhke.verify(secret_key, C, proof.secret) return b_dhke.verify(secret_key, C, proof.secret)
def _verify_script(self, idx: int, proof: Proof): def _verify_script(self, idx: int, proof: Proof):

View File

@@ -17,9 +17,9 @@ Mint: `Bob`
# Blind Diffie-Hellmann key exchange (BDH) # Blind Diffie-Hellmann key exchange (BDH)
- Mint `Bob` publishes `K = kG` - Mint `Bob` publishes `K = kG`
- `Alice` picks secret `x` and computes `Y = hash_to_point(x)` - `Alice` picks secret `x` and computes `Y = hash_to_curve(x)`
- `Alice` sends to `Bob`: `T = Y + rG` with `r` being a random nonce - `Alice` sends to `Bob`: `T = Y + rG` with `r` being a random nonce
- `Bob` sends back to `Alice` blinded key: `Q = kT` (these two steps are the DH key exchange) - `Bob` sends back to `Alice` blinded key: `Q = kT` (these two steps are the DH key exchange)
- `Alice` can calculate the unblinded key as `Q - rK = kY + krG - krG = kY = Z` - `Alice` can calculate the unblinded key as `Q - rK = kY + krG - krG = kY = Z`
- Alice can take the pair `(x, Z)` as a token and can send it to `Carol`. - Alice can take the pair `(x, Z)` as a token and can send it to `Carol`.
- `Carol` can send `(x, Z)` to `Bob` who then checks that `k*hash_to_point(x) == Z`, and if so treats it as a valid spend of a token, adding `x` to the list of spent secrets. - `Carol` can send `(x, Z)` to `Bob` who then checks that `k*hash_to_curve(x) == Z`, and if so treats it as a valid spend of a token, adding `x` to the list of spent secrets.

View File

@@ -17,12 +17,12 @@ Mint: `Bob`
# Blind Diffie-Hellmann key exchange (BDH) # Blind Diffie-Hellmann key exchange (BDH)
- Mint `Bob` publishes `K = kG` - Mint `Bob` publishes `K = kG`
- `Alice` picks secret `x` and computes `Y = hash_to_point(x)` - `Alice` picks secret `x` and computes `Y = hash_to_curve(x)`
- `Alice` sends to `Bob`: `T = Y + rG` with `r` being a random nonce - `Alice` sends to `Bob`: `T = Y + rG` with `r` being a random nonce
- `Bob` sends back to `Alice` blinded key: `Q = kT` (these two steps are the DH key exchange) - `Bob` sends back to `Alice` blinded key: `Q = kT` (these two steps are the DH key exchange)
- `Alice` can calculate the unblinded key as `Q - rK = kY + krG - krG = kY = Z` - `Alice` can calculate the unblinded key as `Q - rK = kY + krG - krG = kY = Z`
- Alice can take the pair `(x, Z)` as a token and can send it to `Carol`. - Alice can take the pair `(x, Z)` as a token and can send it to `Carol`.
- `Carol` can send `(x, Z)` to `Bob` who then checks that `k*hash_to_point(x) == Z`, and if so treats it as a valid spend of a token, adding `x` to the list of spent secrets. - `Carol` can send `(x, Z)` to `Bob` who then checks that `k*hash_to_curve(x) == Z`, and if so treats it as a valid spend of a token, adding `x` to the list of spent secrets.
# Cashu client protocol # Cashu client protocol