|
1 | 1 | import bip32utils |
2 | | -import hashlib |
3 | | -import base64 |
4 | 2 |
|
5 | | -from ecpy.curves import Curve |
6 | | -from ecpy.keys import ECPrivateKey |
| 3 | +from ecpy.curves import Curve, Point |
| 4 | +from ecpy.keys import ECPrivateKey, ECPublicKey |
7 | 5 | from ecpy.ecdsa import ECDSA |
8 | | -from ecdsa import SigningKey, SECP256k1, util |
| 6 | +from ecdsa import SigningKey, SECP256k1 |
| 7 | +from coincurve import PublicKey as CoincurvePublicKey |
| 8 | + |
| 9 | +def secp256k1_sign(private_key: bytes, message: bytes) -> bytes: |
| 10 | + """Signs a message using secp256k1 private key. |
| 11 | +
|
| 12 | + Args: |
| 13 | + private_key (bytes): Secp256k1 private key. |
| 14 | + message (bytes): The message to sign. |
| 15 | +
|
| 16 | + Returns: |
| 17 | + bytes: The generated signature in bytes. |
| 18 | + """ |
| 19 | + cv = Curve.get_curve('secp256k1') |
| 20 | + pv_key = ECPrivateKey(int.from_bytes(private_key, 'big'), cv) |
| 21 | + signer = ECDSA() |
| 22 | + |
| 23 | + sig = signer.sign(message, pv_key) |
| 24 | + if sig is None: |
| 25 | + raise ValueError("Failed to sign the message.") |
| 26 | + |
| 27 | + return bytes(sig) |
| 28 | + |
| 29 | +def secp256k1_verify(public_key: bytes, message: bytes, signature: bytes) -> bool: |
| 30 | + """Verifies secp256k1 signature. |
| 31 | +
|
| 32 | + Args: |
| 33 | + public_key (bytes): Compressed public key. |
| 34 | + message (bytes): The original message that was signed. |
| 35 | + signature (bytes): The signature to verify. |
| 36 | +
|
| 37 | + Returns: |
| 38 | + bool: True if signature is valid, False otherwise. |
| 39 | + """ |
| 40 | + cv = Curve.get_curve('secp256k1') |
| 41 | + |
| 42 | + # check if the public key is in compressed format |
| 43 | + uncompressed_public_key = None |
| 44 | + |
| 45 | + if len(public_key) == 33: |
| 46 | + coincurve_pub_key = CoincurvePublicKey(public_key) |
| 47 | + uncompressed_public_key = coincurve_pub_key.format(compressed=False) |
| 48 | + elif len(public_key) == 65: |
| 49 | + uncompressed_public_key = public_key |
| 50 | + else: |
| 51 | + raise ValueError(f"Invalid public key of length {len(public_key)}.") |
| 52 | + |
| 53 | + # Form public key object |
| 54 | + x = int.from_bytes(uncompressed_public_key[1:33], 'big') |
| 55 | + y = int.from_bytes(uncompressed_public_key[33:], 'big') |
| 56 | + ec_point = Point(x, y, cv) |
| 57 | + pub_key_obj = ECPublicKey(ec_point) |
| 58 | + |
| 59 | + # Verify signature |
| 60 | + verifier = ECDSA() |
| 61 | + return verifier.verify(message, signature, pub_key_obj) |
9 | 62 |
|
10 | 63 | class Secp256k1Keypair: |
11 | 64 | def __init__(self, private_key: str, public_key: str): |
@@ -68,33 +121,4 @@ def sign(self, message: bytes) -> bytes: |
68 | 121 | Returns: |
69 | 122 | bytes: The generated signature in bytes. |
70 | 123 | """ |
71 | | - cv = Curve.get_curve('secp256k1') |
72 | | - pv_key = ECPrivateKey(int(self.__private_key, 16), cv) |
73 | | - signer = ECDSA() |
74 | | - |
75 | | - sig = signer.sign(message, pv_key) |
76 | | - if sig is None: |
77 | | - raise ValueError("Failed to sign the message.") |
78 | | - |
79 | | - return sig |
80 | | - |
81 | | - def verify(self, message: bytes, signature: bytes) -> bool: |
82 | | - """Verifies secp256k1 signature. |
83 | | -
|
84 | | - Args: |
85 | | - message (bytes): The original message that was signed. |
86 | | - signature (bytes): The signature to verify. |
87 | | -
|
88 | | - Returns: |
89 | | - bool: True if signature is valid, False otherwise. |
90 | | - """ |
91 | | - cv = Curve.get_curve('secp256k1') |
92 | | - priv_key = ECPrivateKey(int(self.__private_key, 16), cv) |
93 | | - |
94 | | - pub_key = priv_key.get_public_key() |
95 | | - signer = ECDSA() |
96 | | - |
97 | | - try: |
98 | | - return signer.verify(message, signature, pub_key) |
99 | | - except Exception: |
100 | | - return False |
| 124 | + return secp256k1_sign(bytes.fromhex(self.__private_key), message) |
0 commit comments