My understanding is that the example demonstrated is not what OP is looking for. In the example shown, the private key is created first and everything that follows is based on it. But the OP does
not know the private key, he wants to extract the pubkey from an existing signature without knowing the private key.
@yoshimitsu777: have a look at
https://pypi.org/project/secp256k1/, there is a function "recpub" which you can use comfortably and it does exactly what you are looking for. Example:
$ python -m secp256k1 recpub \
-s 515fe95d0780b11633f3352deb064f1517d58f295a99131e9389da8bfacd64422513d0cd4e18a58d9f4873b592afe54cf63e8f294351d1e612c8a297b5255079 \
-i 1 \
-m hello
Public key: 02477ce3b986ab14d123d6c4167b085f4d08c1569963a0201b2ffc7d9d6086d2f3
I do not understand what the switch -i 1 stands for, but the result seems to be correct.
I tried to implement the whole thing in Python using the ecdsa library. Here is my approach:
#!/usr/bin/env python3
# 2022-Dec-26 by citb0in
import hashlib
from ecdsa import SigningKey, VerifyingKey, SECP256k1
from ecdsa.util import sigencode_der, sigdecode_der
# private key in hex, 32 bytes
privateKeyHex = "2bb80d537b1da3e38bd30361aa855686bde0eacd7162fef6a25fe97bf527a25b"
# convert private key from hex to bytes
privateKeyBytes = bytes.fromhex(privateKeyHex)
# create a SigningKey object of the private key
privateKey = SigningKey.from_string(privateKeyBytes, curve=SECP256k1)
# get the associated public key
publicKey = privateKey.get_verifying_key()
# message to sign
message = "hello"
# calculate the hash of that message
messageHash = hashlib.sha256(message.encode("utf-8")).digest()
# create the signature
signature = privateKey.sign(messageHash, sigencode=sigencode_der)
# encode signatur in hex
signatureHex = signature.hex()
# show some output
print(f"privKey in hex: {privateKeyHex}")
print(f"SigningKey object: {privateKey}")
print(f"pubKey in hex: {publicKey}")
print(f"message: {message}")
print(f"messageHash: {messageHash}")
print(f"Signature: {signature}")
print(f"Signature in hex: {signatureHex}") # output is "3045022075ace5b099991073ef11947127249d0c43f16e1069762360ae1b892b13aeffb50221009792e26181f84f1882944626f669fdfc8eb0c63e80058e498ff56ee5ac1e6041" but is wrong
# the correct and expected signatureHex should be:
signatureHex = "304502210095ade2b0fd9caa90e4993e59232b774e4dc2082fdb8a30267abf21fc6a076715022016d762b4a23e30e8151f2852e88f6beebe65290266aafbbd0cbf2c1f6b3dc78c"
print(f"correct signature in hex should be: {signatureHex}")
# verify signature with pubKey
try:
publicKey.verify(signature, message, hashlib.sha256, sigdecode=sigdecode_der)
print("Signature is valid.")
except:
print("Invalid signature!")
Unfortunately, the generated signature is not correct, I would have expected something else. Even if I write the correct signature into the variable, I still get "Invalid signature" as error message.
Where do I have a (thinking) error ?