mirror of
https://github.com/aljazceru/nutshell.git
synced 2025-12-24 03:54:21 +01:00
* 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>
96 lines
2.4 KiB
Python
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
|