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

Public Key Recovery Operation #101

Closed
gianlucafrei opened this issue Dec 28, 2018 · 4 comments · Fixed by #102
Closed

Public Key Recovery Operation #101

gianlucafrei opened this issue Dec 28, 2018 · 4 comments · Fixed by #102
Labels
feature functionality to be implemented
Milestone

Comments

@gianlucafrei
Copy link
Contributor

Given a signature and the corresponding message it's possible to compute multiple public keys for which the signature is valid.

I would like to add a method to the signature class which does this according to http://www.secg.org/sec1-v2.pdf chapter 4.1.6.

@tomato42 tomato42 added the feature functionality to be implemented label Jan 4, 2019
@tomato42 tomato42 added this to the someday/future milestone Jan 4, 2019
@tomato42
Copy link
Member

tomato42 commented Jan 4, 2019

sounds good

a new static or class method in ecdsa.keys.VerifyingKey would likely be a good place to have it

post a design here or prepare a proof-of-concept PR if you want to discuss it further

@gianlucafrei
Copy link
Contributor Author

Here is a prototype of the maths.
I tested the code below with some examples.

class Signature(object):
  """ECDSA signature.
  """
  def __init__(self, r, s):
    self.r = r
    self.s = s

  def recover_public_keys(self, hash, generator):
    """Returns two public keys for which the signature is valid
    hash is signed hash
    generator is the used generator of the signature
    """
    curve = generator.curve()
    n = generator.order()
    r = self.r
    s = self.s
    e = hash
    x = r

    # Compute the curve point with x as x-coordinate
    alpha = ((x * x * x) + (curve.a() * x) + curve.b()) % curve.p()
    beta = numbertheory.square_root_mod_prime(alpha, curve.p())
    y = beta if beta % 2 == 0 else curve.p() - beta

    # Compute the public key
    R1 = ellipticcurve.Point(curve, x, y, n)
    Q1 = numbertheory.inverse_mod(r, n) * (s * R1 + (-e % n) * generator)
    Pk1 = Public_key(generator, Q1)

    # And the second solution
    R2 = ellipticcurve.Point(curve, x, -y, n)
    Q2 = numbertheory.inverse_mod(r, n) * (s * R2 + (-e % n) * generator)
    Pk2 = Public_key(generator, Q2)

    return [Pk1, Pk2]

@tomato42
Copy link
Member

tomato42 commented Jan 7, 2019

hash is a builtin method, so some other name would be better

(x * x * x)
using pow(x, 3, curve.p()) should yield faster code

looks good otherwise, please add test cases and propose a PR

@gianlucafrei
Copy link
Contributor Author

hash is a builtin method, so some other name would be better

The sign and verify methods also have a parameter called hash, so I propose to not change it for consistency.

@tomato42 tomato42 modified the milestones: someday/future, v0.14 Oct 7, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature functionality to be implemented
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants