Initial commit: 首次建仓,建立目录结构
This commit is contained in:
131
dashboard/venv/lib/python3.12/site-packages/coincurve/ecdsa.py
Normal file
131
dashboard/venv/lib/python3.12/site-packages/coincurve/ecdsa.py
Normal file
@ -0,0 +1,131 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from coincurve._libsecp256k1 import ffi, lib
|
||||
from coincurve.context import GLOBAL_CONTEXT, Context
|
||||
from coincurve.utils import bytes_to_int, int_to_bytes, sha256
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from coincurve.types import Hasher
|
||||
|
||||
MAX_SIG_LENGTH = 72
|
||||
CDATA_SIG_LENGTH = 64
|
||||
|
||||
|
||||
def cdata_to_der(cdata, context: Context = GLOBAL_CONTEXT) -> bytes:
|
||||
der = ffi.new("unsigned char[72]")
|
||||
der_length = ffi.new("size_t *", MAX_SIG_LENGTH)
|
||||
|
||||
lib.secp256k1_ecdsa_signature_serialize_der(context.ctx, der, der_length, cdata)
|
||||
|
||||
return bytes(ffi.buffer(der, der_length[0]))
|
||||
|
||||
|
||||
def der_to_cdata(der: bytes, context: Context = GLOBAL_CONTEXT):
|
||||
cdata = ffi.new("secp256k1_ecdsa_signature *")
|
||||
parsed = lib.secp256k1_ecdsa_signature_parse_der(context.ctx, cdata, der, len(der))
|
||||
|
||||
if not parsed:
|
||||
msg = "The DER-encoded signature could not be parsed."
|
||||
raise ValueError(msg)
|
||||
|
||||
return cdata
|
||||
|
||||
|
||||
def recover(message: bytes, recover_sig, hasher: Hasher = sha256, context: Context = GLOBAL_CONTEXT):
|
||||
msg_hash = hasher(message) if hasher is not None else message
|
||||
if len(msg_hash) != 32: # noqa: PLR2004
|
||||
msg = "Message hash must be 32 bytes long."
|
||||
raise ValueError(msg)
|
||||
pubkey = ffi.new("secp256k1_pubkey *")
|
||||
|
||||
recovered = lib.secp256k1_ecdsa_recover(context.ctx, pubkey, recover_sig, msg_hash)
|
||||
if recovered:
|
||||
return pubkey
|
||||
msg = "failed to recover ECDSA public key"
|
||||
raise ValueError(msg)
|
||||
|
||||
|
||||
def serialize_recoverable(recover_sig, context: Context = GLOBAL_CONTEXT) -> bytes:
|
||||
output = ffi.new("unsigned char[64]")
|
||||
recid = ffi.new("int *")
|
||||
|
||||
lib.secp256k1_ecdsa_recoverable_signature_serialize_compact(context.ctx, output, recid, recover_sig)
|
||||
|
||||
return bytes(ffi.buffer(output, CDATA_SIG_LENGTH)) + int_to_bytes(recid[0])
|
||||
|
||||
|
||||
def deserialize_recoverable(serialized: bytes, context: Context = GLOBAL_CONTEXT):
|
||||
if len(serialized) != 65: # noqa: PLR2004
|
||||
msg = "Serialized signature must be 65 bytes long."
|
||||
raise ValueError(msg)
|
||||
|
||||
ser_sig, rec_id = serialized[:64], bytes_to_int(serialized[64:])
|
||||
|
||||
if not 0 <= rec_id <= 3: # noqa: PLR2004
|
||||
msg = "Invalid recovery id."
|
||||
raise ValueError(msg)
|
||||
|
||||
recover_sig = ffi.new("secp256k1_ecdsa_recoverable_signature *")
|
||||
|
||||
parsed = lib.secp256k1_ecdsa_recoverable_signature_parse_compact(context.ctx, recover_sig, ser_sig, rec_id)
|
||||
if not parsed:
|
||||
msg = "Failed to parse recoverable signature."
|
||||
raise ValueError(msg)
|
||||
|
||||
return recover_sig
|
||||
|
||||
|
||||
"""
|
||||
Warning:
|
||||
The functions below may change and are not tested!
|
||||
"""
|
||||
|
||||
|
||||
def serialize_compact(raw_sig, context: Context = GLOBAL_CONTEXT): # no cov
|
||||
output = ffi.new("unsigned char[64]")
|
||||
|
||||
res = lib.secp256k1_ecdsa_signature_serialize_compact(context.ctx, output, raw_sig)
|
||||
if not res:
|
||||
msg = "secp256k1_ecdsa_signature_serialize_compact"
|
||||
raise ValueError(msg)
|
||||
|
||||
return bytes(ffi.buffer(output, CDATA_SIG_LENGTH))
|
||||
|
||||
|
||||
def deserialize_compact(ser_sig: bytes, context: Context = GLOBAL_CONTEXT): # no cov
|
||||
if len(ser_sig) != 64: # noqa: PLR2004
|
||||
msg = "invalid signature length"
|
||||
raise ValueError(msg)
|
||||
|
||||
raw_sig = ffi.new("secp256k1_ecdsa_signature *")
|
||||
res = lib.secp256k1_ecdsa_signature_parse_compact(context.ctx, raw_sig, ser_sig)
|
||||
if not res:
|
||||
msg = "secp256k1_ecdsa_signature_parse_compact"
|
||||
raise ValueError(msg)
|
||||
|
||||
return raw_sig
|
||||
|
||||
|
||||
def signature_normalize(raw_sig, context: Context = GLOBAL_CONTEXT): # no cov
|
||||
"""
|
||||
Check and optionally convert a signature to a normalized lower-S form.
|
||||
|
||||
This function always return a tuple containing a boolean (True if
|
||||
not previously normalized or False if signature was already
|
||||
normalized), and the normalized signature.
|
||||
"""
|
||||
sigout = ffi.new("secp256k1_ecdsa_signature *")
|
||||
|
||||
res = lib.secp256k1_ecdsa_signature_normalize(context.ctx, sigout, raw_sig)
|
||||
|
||||
return not not res, sigout # noqa: SIM208
|
||||
|
||||
|
||||
def recoverable_convert(recover_sig, context: Context = GLOBAL_CONTEXT): # no cov
|
||||
normal_sig = ffi.new("secp256k1_ecdsa_signature *")
|
||||
|
||||
lib.secp256k1_ecdsa_recoverable_signature_convert(context.ctx, normal_sig, recover_sig)
|
||||
|
||||
return normal_sig
|
||||
Reference in New Issue
Block a user