Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

investigate: ecdsa created signatures do not validate with coincurve #3532

Closed
eukreign opened this issue Dec 24, 2021 · 1 comment · Fixed by #3534
Closed

investigate: ecdsa created signatures do not validate with coincurve #3532

eukreign opened this issue Dec 24, 2021 · 1 comment · Fixed by #3534

Comments

@eukreign
Copy link
Member

Investigate why old signatures created using ecdsa do not validate with coincurve:

Old signing code (private_key in this case is instance of ecdsa.SigningKey):

self.signable.signature = channel.private_key.sign_digest_deterministic(digest, hashfunc=hashlib.sha256)

New signing code (calls the libsecp256k1 code wrapped by coincurve):

def sign_compact(self, digest):
""" Produce a compact signature. """
key = self.signing_key
signature = libsecp256k1_ffi.new('secp256k1_ecdsa_signature *')
signed = libsecp256k1.secp256k1_ecdsa_sign(
key.context.ctx, signature, digest, key.secret,
libsecp256k1_ffi.NULL, libsecp256k1_ffi.NULL
)
if not signed:
raise ValueError('The private key was invalid.')
serialized = libsecp256k1_ffi.new('unsigned char[%d]' % CDATA_SIG_LENGTH)
compacted = libsecp256k1.secp256k1_ecdsa_signature_serialize_compact(
key.context.ctx, serialized, signature
)
if compacted != 1:
raise ValueError('The signature could not be compacted.')
return bytes(libsecp256k1_ffi.buffer(serialized, CDATA_SIG_LENGTH))

New validation code includes the old validation as fallback for old signatures:

def is_signature_valid(signature, digest, public_key_bytes):
signature = cdata_to_der(deserialize_compact(signature))
public_key = cPublicKey(public_key_bytes)
is_valid = public_key.verify(signature, digest, None)
if not is_valid: # try old way
# ytsync signed claims don't seem to validate with coincurve
try:
pk = ec.EllipticCurvePublicKey.from_encoded_point(ec.SECP256K1(), public_key_bytes)
pk.verify(signature, digest, ec.ECDSA(Prehashed(hashes.SHA256())))
return True
except (ValueError, InvalidSignature):
pass
return is_valid

The following tests illustrate the problem, if you step through debugger you will see that it does not validate with coincurve and instead falls back to using the old validation with cryptography:

Example 1 (older):

def test_signed_claim_made_by_ytsync(self):

Example 2 (much more recent):

def test_another_signed_claim_made_by_ytsync(self):

Why can't coincurve validate those signatures? Is there anything we can do to get it to validate?

One interesting thing to note is that the new signatures do validate with the old validation scheme using cryptography library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant