Files
nutshell/cashu/core/crypto/b_dhke.py
dni ⚡ e3ed00640f FEAT: Add flake8 (#267)
* init flake8

* exclude nostr client, and add ds_store to gitignore

* fix flake8 F811 issue, redefinition of unused variables

* add flake8 to workflow

* F401 unused imports

* F541 f-string is missing placeholders

* E501 line too long > 150 characters

* E722 no bare except

* E402 module level import not at top of file

* F405 no star imports

* E712 comparison to False should be 'if cond is False:'

* F841 local variable is assigned to but never used

* E266 too many leading '#' for block comment

* E265, E261

* E713 test for membership should be 'not in'

* E711, E741

E741 ambiguous variable name 'l'
E711 comparison to None should be 'if cond is None:'

* flake config

* isort

* refactor makefile flake8 usage

* reflaking the rebase

* black

* fix tests?

* black

* fix line lenght it test_cli

* sort out makefile

* fix strings

* reintroduce black-check

* reflake and mypy

* isort

* Update cashu/wallet/wallet.py

Co-authored-by: Angus Pearson <angus@toaster.cc>

* Update cashu/mint/ledger.py

Co-authored-by: Angus Pearson <angus@toaster.cc>

---------

Co-authored-by: Angus Pearson <angus@toaster.cc>
2023-07-28 18:42:16 +02:00

96 lines
2.4 KiB
Python

# Don't trust me with cryptography.
"""
Implementation of https://gist.github.com/RubenSomsen/be7a4760dd4596d06963d67baf140406
Bob (Mint):
A = a*G
return A
Alice (Client):
Y = hash_to_curve(secret_message)
r = random blinding factor
B'= Y + r*G
return B'
Bob:
C' = a*B'
(= a*Y + a*r*G)
return C'
Alice:
C = C' - r*A
(= C' - a*r*G)
(= a*Y)
return C, secret_message
Bob:
Y = hash_to_curve(secret_message)
C == a*Y
If true, C must have originated from Bob
"""
import hashlib
from typing import Optional
from secp256k1 import PrivateKey, PublicKey
def hash_to_curve(message: bytes) -> PublicKey:
"""Generates a point from the message hash and checks if the point lies on the curve.
If it does not, it tries computing a new point from the hash."""
point = None
msg_to_hash = message
while point is None:
_hash = hashlib.sha256(msg_to_hash).digest()
try:
point = PublicKey(b"\x02" + _hash, raw=True)
except Exception:
msg_to_hash = _hash
return point
def step1_alice(
secret_msg: str, blinding_factor: Optional[PrivateKey] = None
) -> tuple[PublicKey, PrivateKey]:
Y: PublicKey = hash_to_curve(secret_msg.encode("utf-8"))
r = blinding_factor or PrivateKey()
B_: PublicKey = Y + r.pubkey # type: ignore
return B_, r
def step2_bob(B_: PublicKey, a: PrivateKey) -> PublicKey:
C_: PublicKey = B_.mult(a) # type: ignore
return C_
def step3_alice(C_: PublicKey, r: PrivateKey, A: PublicKey) -> PublicKey:
C: PublicKey = C_ - A.mult(r) # type: ignore
return C
def verify(a: PrivateKey, C: PublicKey, secret_msg: str) -> bool:
Y: PublicKey = hash_to_curve(secret_msg.encode("utf-8"))
return C == Y.mult(a) # type: ignore
# Below is a test of a simple positive and negative case
# # Alice's keys
# a = PrivateKey()
# A = a.pubkey
# secret_msg = "test"
# B_, r = step1_alice(secret_msg)
# C_ = step2_bob(B_, a)
# C = step3_alice(C_, r, A)
# print("C:{}, secret_msg:{}".format(C, secret_msg))
# assert verify(a, C, secret_msg)
# assert verify(a, C + C, secret_msg) == False # adding C twice shouldn't pass
# assert verify(a, A, secret_msg) == False # A shouldn't pass
# # Test operations
# b = PrivateKey()
# B = b.pubkey
# assert -A -A + A == -A # neg
# assert B.mult(a) == A.mult(b) # a*B = A*b