I am a noob with cryptography, just trying to learn using python and the library Coincurve ( https://github.com/ofek/coincurve ) which is a mature Python binding for libsecp256k1.

The following code creates a private key and produces a signature of the string "Hello world!".

pk = coincurve.PrivateKey()
message = b"this is a test!"
s = pk.sign_recoverable(message)

The signature s is a sequence 65 bytes.

The signature is recoverable: i can extract the public key of pk from s.

pub = pk.public_key
pub2 = coincurve.PublicKey.from_signature_and_message(s,message)
assert(pub == pub2)

So far all good! However I can't understand how to use the verify method. The following code

valid = coincurve.verify_signature(s,message,pub)

gives the following error:

ValueError: The DER-encoded signature could not be parsed.

So the problem is that the method verify_signature expects a signature in DER format. This is normally produced using the sign method, as opposed to the sign_recoverable method:

t = pk.sign(message)
valid = coincurve.verify_signature(t,message,pub.format())

which works fine.

So my question is:

QUESTION: How do I move back and forth from the "DER" format to the "recoverable" format in the Python library coincurve?


  • 3
    I don't know the coincurve package, but want to point out that you can't trivially move from the DER format to the compact recoverable format, as they don't contain the same information. There can be up to 4 (but typically only 2) valid public keys for a given message/signature combination, so the recoverable format contains a flag byte that indicates which of those public keys is to be recovered. This flag byte can't be computed from just the signature and message. Apr 15, 2019 at 0:22

1 Answer 1


Recoverable -> DER

Use recoverable_convert. (which calls secp256k1_ecdsa_sign_recoverable)

DER -> Recoverable

Use sign_recoverable. (which calls secp256k1_ecdsa_recoverable_signature_convert)

^^I couldn't find an easier way.

  • I am not sure if I understand but pk = coincurve.PrivateKey() message = b"this is a test!" s = pk.sign_recoverable(message) print(recoverable_convert(s)) gives me the error: TypeError: initializer for ctype 'secp256k1_ecdsa_recoverable_signature *' must be a cdata pointer, not bytes
    – makkiato
    Apr 14, 2019 at 12:50
  • 1
    Obviously this is an old question, but you need to deserialise the recoverable signature first: recoverable_convert(deserialize_recoverable(s)) Dec 30, 2021 at 2:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.