mirror of
https://github.com/HelloZeroNet/ZeroNet.git
synced 2023-12-14 04:33:03 +01:00
102 lines
3.3 KiB
Python
102 lines
3.3 KiB
Python
import logging
|
|
import base64
|
|
import binascii
|
|
import time
|
|
import hashlib
|
|
|
|
from util.Electrum import dbl_format
|
|
from Config import config
|
|
|
|
import util.OpensslFindPatch
|
|
|
|
lib_verify_best = "sslcrypto"
|
|
|
|
from lib import sslcrypto
|
|
sslcurve_native = sslcrypto.ecc.get_curve("secp256k1")
|
|
sslcurve_fallback = sslcrypto.fallback.ecc.get_curve("secp256k1")
|
|
sslcurve = sslcurve_native
|
|
|
|
def loadLib(lib_name, silent=False):
|
|
global sslcurve, libsecp256k1message, lib_verify_best
|
|
if lib_name == "libsecp256k1":
|
|
s = time.time()
|
|
from lib import libsecp256k1message
|
|
import coincurve
|
|
lib_verify_best = "libsecp256k1"
|
|
if not silent:
|
|
logging.info(
|
|
"Libsecpk256k1 loaded: %s in %.3fs" %
|
|
(type(coincurve._libsecp256k1.lib).__name__, time.time() - s)
|
|
)
|
|
elif lib_name == "sslcrypto":
|
|
sslcurve = sslcurve_native
|
|
if sslcurve_native == sslcurve_fallback:
|
|
logging.warning("SSLCurve fallback loaded instead of native")
|
|
elif lib_name == "sslcrypto_fallback":
|
|
sslcurve = sslcurve_fallback
|
|
|
|
try:
|
|
if not config.use_libsecp256k1:
|
|
raise Exception("Disabled by config")
|
|
loadLib("libsecp256k1")
|
|
lib_verify_best = "libsecp256k1"
|
|
except Exception as err:
|
|
logging.info("Libsecp256k1 load failed: %s" % err)
|
|
|
|
|
|
def newPrivatekey(): # Return new private key
|
|
return sslcurve.private_to_wif(sslcurve.new_private_key()).decode()
|
|
|
|
|
|
def newSeed():
|
|
return binascii.hexlify(sslcurve.new_private_key()).decode()
|
|
|
|
|
|
def hdPrivatekey(seed, child):
|
|
# Too large child id could cause problems
|
|
privatekey_bin = sslcurve.derive_child(seed.encode(), child % 100000000)
|
|
return sslcurve.private_to_wif(privatekey_bin).decode()
|
|
|
|
|
|
def privatekeyToAddress(privatekey): # Return address from private key
|
|
try:
|
|
if len(privatekey) == 64:
|
|
privatekey_bin = bytes.fromhex(privatekey)
|
|
else:
|
|
privatekey_bin = sslcurve.wif_to_private(privatekey.encode())
|
|
return sslcurve.private_to_address(privatekey_bin).decode()
|
|
except Exception: # Invalid privatekey
|
|
return False
|
|
|
|
|
|
def sign(data, privatekey): # Return sign to data using private key
|
|
if privatekey.startswith("23") and len(privatekey) > 52:
|
|
return None # Old style private key not supported
|
|
return base64.b64encode(sslcurve.sign(
|
|
data.encode(),
|
|
sslcurve.wif_to_private(privatekey.encode()),
|
|
recoverable=True,
|
|
hash=dbl_format
|
|
)).decode()
|
|
|
|
|
|
def verify(data, valid_address, sign, lib_verify=None): # Verify data using address and sign
|
|
if not lib_verify:
|
|
lib_verify = lib_verify_best
|
|
|
|
if not sign:
|
|
return False
|
|
|
|
if lib_verify == "libsecp256k1":
|
|
sign_address = libsecp256k1message.recover_address(data.encode("utf8"), sign).decode("utf8")
|
|
elif lib_verify in ("sslcrypto", "sslcrypto_fallback"):
|
|
publickey = sslcurve.recover(base64.b64decode(sign), data.encode(), hash=dbl_format)
|
|
sign_address = sslcurve.public_to_address(publickey).decode()
|
|
else:
|
|
raise Exception("No library enabled for signature verification")
|
|
|
|
if type(valid_address) is list: # Any address in the list
|
|
return sign_address in valid_address
|
|
else: # One possible address
|
|
return sign_address == valid_address
|