mirror of
https://github.com/aljazceru/nutshell.git
synced 2026-01-04 09:24:22 +01:00
* first working version but some sats go missing * back at it * make format * restore to main * move mint database * fix some tests * make format * remove old _construct_outputs we reintroduced in merge with main * add type annotations * add wallet private key to tests * wallet: load proofs * fix tests * _generate_secrets with deterministic generation (temporary) * allow wallet initialization with custom private key * add pk to wallet api test * mint scope=module * remove private_key from test_wallet.py to see if it helps with the github tests * readd private keys to tests * workflow without env * add more private key! * readd env * ledger scope session * add default private key for testing * generate private keys if not available * testing * its working!!! * first iteration of bip32 working * get mint info and add many type annotations * tests * fix tests with bip32 * restore from multiple mints * disable profiler * make format * failed POST /mint do not increment secret counter * store derivation path in each token * fix tests * refactor migrations so private keys can be generated by the wallet with .with_db() classmethod * start fixing tests * all tests passing except those that need to set a specific private key * bip39 mnemonic to seed - with db but restore doesnt work yet with custom seed * mnemonic restore works * enter mnemonic in cli * fix tests to use different mnemonic * properly ask user for seed input * tests: dont ask for inputs * try to fix tests * fix cashu -d * fixing * bump version and add more text to mnemonic enter * add more comments * add many more comments and type annotations in the wallet * dont print generated mnemonic and dont wait for input * fix test * does this fix tests? * sigh.... * make format * do not restore from an initialized wallet * fix mnemonics * fix nitpicks * print wallet name if nonstandard wallet * fix merge error and remove comments * poetry lock and requirements * remove unused code * fix tests * mnemonic.lower() and add keyset id if not present for backwards compat * edit comment
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:
|
|
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
|