Skip to content

Commit 76833c8

Browse files
committed
new class RValue to propagate the ECPoint value to sigencode
1 parent 4984db1 commit 76833c8

File tree

5 files changed

+63
-74
lines changed

5 files changed

+63
-74
lines changed

src/ecdsa/ecdsa.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,21 @@ class InvalidPointError(RuntimeError):
8181
pass
8282

8383

84+
class RValue(int):
85+
"""An r signature value that also carries the originating EC point.
86+
87+
Behaves as a regular ``int`` (equal to ``point.x() % order``) so
88+
existing :func:`sigencode_*` functions that expect an integer work
89+
unchanged. Functions that need the full EC point can access it via
90+
the :attr:`point` attribute.
91+
"""
92+
93+
def __new__(cls, r, point):
94+
obj = super(RValue, cls).__new__(cls, r)
95+
obj.point = point
96+
return obj
97+
98+
8499
class Signature(object):
85100
"""
86101
ECDSA signature.
@@ -244,7 +259,7 @@ def __ne__(self, other):
244259
"""Return False if the points are identical, True otherwise."""
245260
return not self == other
246261

247-
def sign(self, hash, random_k, accelerate=False):
262+
def sign(self, hash, random_k):
248263
"""Return a signature for the provided hash, using the provided
249264
random nonce. It is absolutely vital that random_k be an unpredictable
250265
number in the range [1, self.public_key.point.order()-1]. If
@@ -280,9 +295,7 @@ def sign(self, hash, random_k, accelerate=False):
280295
) % n
281296
if s == 0:
282297
raise RSZeroError("amazingly unlucky random number s")
283-
if accelerate:
284-
return Signature(p1, s)
285-
return Signature(r, s)
298+
return Signature(RValue(r, p1), s)
286299

287300

288301
def int_to_string(x): # pragma: no cover

src/ecdsa/keys.py

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,7 +1318,6 @@ def sign_deterministic(
13181318
hashfunc=None,
13191319
sigencode=sigencode_string,
13201320
extra_entropy=b"",
1321-
accelerate=False,
13221321
):
13231322
"""
13241323
Create signature over data.
@@ -1355,10 +1354,6 @@ def sign_deterministic(
13551354
number generator used in the RFC6979 process. Entirely optional.
13561355
Ignored with EdDSA.
13571356
:type extra_entropy: :term:`bytes-like object`
1358-
:param accelerate: an indicator for ECDSA sign operation to return
1359-
an ECPoint instead of a number of "r" parameter.
1360-
Applicable only for ECDSA key.
1361-
:type accelerate: boolean
13621357
13631358
:return: encoded signature over `data`
13641359
:rtype: bytes or sigencode function dependent type
@@ -1378,7 +1373,6 @@ def sign_deterministic(
13781373
sigencode=sigencode,
13791374
extra_entropy=extra_entropy,
13801375
allow_truncate=True,
1381-
accelerate=accelerate,
13821376
)
13831377

13841378
def sign_digest_deterministic(
@@ -1388,7 +1382,6 @@ def sign_digest_deterministic(
13881382
sigencode=sigencode_string,
13891383
extra_entropy=b"",
13901384
allow_truncate=False,
1391-
accelerate=False,
13921385
):
13931386
"""
13941387
Create signature for digest using the deterministic RFC6979 algorithm.
@@ -1424,10 +1417,6 @@ def sign_digest_deterministic(
14241417
bigger bit-size than the order of the curve, the extra bits (at
14251418
the end of the digest) will be truncated. Use it when signing
14261419
SHA-384 output using NIST256p or in similar situations.
1427-
:param accelerate: an indicator for ECDSA sign operation to return
1428-
an ECPoint instead of a number of "r" parameter.
1429-
Applicable only for ECDSA key.
1430-
:type accelerate: boolean
14311420
14321421
:return: encoded signature for the `digest` hash
14331422
:rtype: bytes or sigencode function dependent type
@@ -1458,7 +1447,6 @@ def simple_r_s(r, s, order):
14581447
sigencode=simple_r_s,
14591448
k=k,
14601449
allow_truncate=allow_truncate,
1461-
accelerate=accelerate,
14621450
)
14631451
break
14641452
except RSZeroError:
@@ -1474,7 +1462,6 @@ def sign(
14741462
sigencode=sigencode_string,
14751463
k=None,
14761464
allow_truncate=True,
1477-
accelerate=False,
14781465
):
14791466
"""
14801467
Create signature over data.
@@ -1538,10 +1525,6 @@ def sign(
15381525
leak the key. Caller should try a better entropy source, retry with
15391526
different ``k``, or use the
15401527
:func:`~SigningKey.sign_deterministic` in such case.
1541-
:param accelerate: an indicator for ECDSA sign operation to return
1542-
an ECPoint instead of a number of "r" parameter.
1543-
Applicable only for ECDSA key.
1544-
:type accelerate: boolean
15451528
15461529
:return: encoded signature of the hash of `data`
15471530
:rtype: bytes or sigencode function dependent type
@@ -1551,9 +1534,7 @@ def sign(
15511534
if isinstance(self.curve.curve, CurveEdTw):
15521535
return self.sign_deterministic(data)
15531536
h = hashfunc(data).digest()
1554-
return self.sign_digest(
1555-
h, entropy, sigencode, k, allow_truncate, accelerate
1556-
)
1537+
return self.sign_digest(h, entropy, sigencode, k, allow_truncate)
15571538

15581539
def sign_digest(
15591540
self,
@@ -1562,7 +1543,6 @@ def sign_digest(
15621543
sigencode=sigencode_string,
15631544
k=None,
15641545
allow_truncate=False,
1565-
accelerate=False,
15661546
):
15671547
"""
15681548
Create signature over digest using the probabilistic ECDSA algorithm.
@@ -1599,10 +1579,6 @@ def sign_digest(
15991579
leak the key. Caller should try a better entropy source, retry with
16001580
different 'k', or use the
16011581
:func:`~SigningKey.sign_digest_deterministic` in such case.
1602-
:param accelerate: an indicator for ECDSA sign operation to return
1603-
an ECPoint instead of a number of "r" parameter.
1604-
Applicable only for ECDSA key.
1605-
:type accelerate: boolean
16061582
16071583
:return: encoded signature for the `digest` hash
16081584
:rtype: bytes or sigencode function dependent type
@@ -1615,10 +1591,10 @@ def sign_digest(
16151591
self.curve,
16161592
allow_truncate,
16171593
)
1618-
r, s = self.sign_number(number, entropy, k, accelerate)
1594+
r, s = self.sign_number(number, entropy, k)
16191595
return sigencode(r, s, self.privkey.order)
16201596

1621-
def sign_number(self, number, entropy=None, k=None, accelerate=False):
1597+
def sign_number(self, number, entropy=None, k=None):
16221598
"""
16231599
Sign an integer directly.
16241600
@@ -1637,10 +1613,6 @@ def sign_number(self, number, entropy=None, k=None, accelerate=False):
16371613
leak the key. Caller should try a better entropy source, retry with
16381614
different 'k', or use the
16391615
:func:`~SigningKey.sign_digest_deterministic` in such case.
1640-
:param accelerate: an indicator for ECDSA sign operation to return
1641-
an ECPoint instead of a number of "r" parameter.
1642-
Applicable only for ECDSA key.
1643-
:type accelerate: boolean
16441616
16451617
:return: the "r" and "s" parameters of the signature
16461618
:rtype: tuple of ints
@@ -1655,5 +1627,5 @@ def sign_number(self, number, entropy=None, k=None, accelerate=False):
16551627
_k = randrange(order, entropy)
16561628

16571629
assert 1 <= _k < order
1658-
sig = self.privkey.sign(number, _k, accelerate)
1630+
sig = self.privkey.sign(number, _k)
16591631
return sig.r, sig.s

src/ecdsa/test_keys.py

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ def test_ed25519_sig_verify_malformed(self):
429429

430430
# modified signature from test_ed25519_sig_verify
431431
sig = (
432-
b"\xAA\x47\xab\x6a\x33\xcd\x79\x45\xad\x98\x11\x6c\xb9\xf2\x20\xeb"
432+
b"\xaa\x47\xab\x6a\x33\xcd\x79\x45\xad\x98\x11\x6c\xb9\xf2\x20\xeb"
433433
b"\x90\xd6\x50\xe3\xc7\x8f\x9f\x60\x10\xec\x75\xe0\x2f\x27\xd3\x96"
434434
b"\xda\xe8\x58\x7f\xe0\xfe\x46\x5c\x81\xef\x50\xec\x29\x9f\xae\xd5"
435435
b"\xad\x46\x3c\x91\x68\x83\x4d\xea\x8d\xa8\x19\x04\x04\x79\x03\x0b"
@@ -663,8 +663,8 @@ def test_ed25519_from_pem(self):
663663
sk = SigningKey.from_pem(pem_str)
664664

665665
sk_str = SigningKey.from_string(
666-
b"\x34\xBA\xC7\xD1\x4E\xD4\xF1\xBC\x4F\x8C\x48\x3E\x0F\x19\x77\x4C"
667-
b"\xFC\xB8\xBE\xAC\x54\x66\x45\x11\x9A\xD7\xD7\xB8\x07\x0B\xF5\xD4",
666+
b"\x34\xba\xc7\xd1\x4e\xd4\xf1\xbc\x4f\x8c\x48\x3e\x0f\x19\x77\x4c"
667+
b"\xfc\xb8\xbe\xac\x54\x66\x45\x11\x9a\xd7\xd7\xb8\x07\x0b\xf5\xd4",
668668
Ed25519,
669669
)
670670

@@ -700,8 +700,8 @@ def test_ed25519_from_der_junk_after_priv_key(self):
700700

701701
def test_ed25519_sign(self):
702702
sk_str = SigningKey.from_string(
703-
b"\x34\xBA\xC7\xD1\x4E\xD4\xF1\xBC\x4F\x8C\x48\x3E\x0F\x19\x77\x4C"
704-
b"\xFC\xB8\xBE\xAC\x54\x66\x45\x11\x9A\xD7\xD7\xB8\x07\x0B\xF5\xD4",
703+
b"\x34\xba\xc7\xd1\x4e\xd4\xf1\xbc\x4f\x8c\x48\x3e\x0f\x19\x77\x4c"
704+
b"\xfc\xb8\xbe\xac\x54\x66\x45\x11\x9a\xd7\xd7\xb8\x07\x0b\xf5\xd4",
705705
Ed25519,
706706
)
707707

@@ -718,8 +718,8 @@ def test_ed25519_sign(self):
718718

719719
def test_ed25519_sign_digest_deterministic(self):
720720
sk_str = SigningKey.from_string(
721-
b"\x34\xBA\xC7\xD1\x4E\xD4\xF1\xBC\x4F\x8C\x48\x3E\x0F\x19\x77\x4C"
722-
b"\xFC\xB8\xBE\xAC\x54\x66\x45\x11\x9A\xD7\xD7\xB8\x07\x0B\xF5\xD4",
721+
b"\x34\xba\xc7\xd1\x4e\xd4\xf1\xbc\x4f\x8c\x48\x3e\x0f\x19\x77\x4c"
722+
b"\xfc\xb8\xbe\xac\x54\x66\x45\x11\x9a\xd7\xd7\xb8\x07\x0b\xf5\xd4",
723723
Ed25519,
724724
)
725725
with self.assertRaises(ValueError) as e:
@@ -729,8 +729,8 @@ def test_ed25519_sign_digest_deterministic(self):
729729

730730
def test_ed25519_sign_digest(self):
731731
sk_str = SigningKey.from_string(
732-
b"\x34\xBA\xC7\xD1\x4E\xD4\xF1\xBC\x4F\x8C\x48\x3E\x0F\x19\x77\x4C"
733-
b"\xFC\xB8\xBE\xAC\x54\x66\x45\x11\x9A\xD7\xD7\xB8\x07\x0B\xF5\xD4",
732+
b"\x34\xba\xc7\xd1\x4e\xd4\xf1\xbc\x4f\x8c\x48\x3e\x0f\x19\x77\x4c"
733+
b"\xfc\xb8\xbe\xac\x54\x66\x45\x11\x9a\xd7\xd7\xb8\x07\x0b\xf5\xd4",
734734
Ed25519,
735735
)
736736
with self.assertRaises(ValueError) as e:
@@ -740,8 +740,8 @@ def test_ed25519_sign_digest(self):
740740

741741
def test_ed25519_sign_number(self):
742742
sk_str = SigningKey.from_string(
743-
b"\x34\xBA\xC7\xD1\x4E\xD4\xF1\xBC\x4F\x8C\x48\x3E\x0F\x19\x77\x4C"
744-
b"\xFC\xB8\xBE\xAC\x54\x66\x45\x11\x9A\xD7\xD7\xB8\x07\x0B\xF5\xD4",
743+
b"\x34\xba\xc7\xd1\x4e\xd4\xf1\xbc\x4f\x8c\x48\x3e\x0f\x19\x77\x4c"
744+
b"\xfc\xb8\xbe\xac\x54\x66\x45\x11\x9a\xd7\xd7\xb8\x07\x0b\xf5\xd4",
745745
Ed25519,
746746
)
747747
with self.assertRaises(ValueError) as e:
@@ -765,8 +765,8 @@ def test_ed25519_to_der_ssleay(self):
765765

766766
def test_ed25519_to_pem(self):
767767
sk = SigningKey.from_string(
768-
b"\x34\xBA\xC7\xD1\x4E\xD4\xF1\xBC\x4F\x8C\x48\x3E\x0F\x19\x77\x4C"
769-
b"\xFC\xB8\xBE\xAC\x54\x66\x45\x11\x9A\xD7\xD7\xB8\x07\x0B\xF5\xD4",
768+
b"\x34\xba\xc7\xd1\x4e\xd4\xf1\xbc\x4f\x8c\x48\x3e\x0f\x19\x77\x4c"
769+
b"\xfc\xb8\xbe\xac\x54\x66\x45\x11\x9a\xd7\xd7\xb8\x07\x0b\xf5\xd4",
770770
Ed25519,
771771
)
772772

@@ -780,8 +780,8 @@ def test_ed25519_to_pem(self):
780780

781781
def test_ed25519_to_ssh(self):
782782
sk = SigningKey.from_string(
783-
b"\x34\xBA\xC7\xD1\x4E\xD4\xF1\xBC\x4F\x8C\x48\x3E\x0F\x19\x77\x4C"
784-
b"\xFC\xB8\xBE\xAC\x54\x66\x45\x11\x9A\xD7\xD7\xB8\x07\x0B\xF5\xD4",
783+
b"\x34\xba\xc7\xd1\x4e\xd4\xf1\xbc\x4f\x8c\x48\x3e\x0f\x19\x77\x4c"
784+
b"\xfc\xb8\xbe\xac\x54\x66\x45\x11\x9a\xd7\xd7\xb8\x07\x0b\xf5\xd4",
785785
Ed25519,
786786
)
787787

@@ -825,21 +825,21 @@ def test_ed448_from_pem(self):
825825
sk = SigningKey.from_pem(pem_str)
826826

827827
sk_str = SigningKey.from_string(
828-
b"\x3C\x85\xB9\x7A\x85\x2D\x78\x09\x95\x5F\x2E\x0E\xA7\x0E\xC3\xD9"
829-
b"\xC6\xE0\x8A\xB3\x2E\x26\x7F\x8B\x93\x5F\x04\x3A\x07\x3F\x39\x8F"
830-
b"\x38\xFD\x09\x31\x86\x8B\x1A\x54\xF3\xC2\x8B\xE6\xBC\x20\xC9\xDB"
831-
b"\x32\xDA\x7B\x3B\xBD\x34\xBC\xFD\x69",
828+
b"\x3c\x85\xb9\x7a\x85\x2d\x78\x09\x95\x5f\x2e\x0e\xa7\x0e\xc3\xd9"
829+
b"\xc6\xe0\x8a\xb3\x2e\x26\x7f\x8b\x93\x5f\x04\x3a\x07\x3f\x39\x8f"
830+
b"\x38\xfd\x09\x31\x86\x8b\x1a\x54\xf3\xc2\x8b\xe6\xbc\x20\xc9\xdb"
831+
b"\x32\xda\x7b\x3b\xbd\x34\xbc\xfd\x69",
832832
Ed448,
833833
)
834834

835835
self.assertEqual(sk, sk_str)
836836

837837
def test_ed448_to_pem(self):
838838
sk = SigningKey.from_string(
839-
b"\x3C\x85\xB9\x7A\x85\x2D\x78\x09\x95\x5F\x2E\x0E\xA7\x0E\xC3\xD9"
840-
b"\xC6\xE0\x8A\xB3\x2E\x26\x7F\x8B\x93\x5F\x04\x3A\x07\x3F\x39\x8F"
841-
b"\x38\xFD\x09\x31\x86\x8B\x1A\x54\xF3\xC2\x8B\xE6\xBC\x20\xC9\xDB"
842-
b"\x32\xDA\x7B\x3B\xBD\x34\xBC\xFD\x69",
839+
b"\x3c\x85\xb9\x7a\x85\x2d\x78\x09\x95\x5f\x2e\x0e\xa7\x0e\xc3\xd9"
840+
b"\xc6\xe0\x8a\xb3\x2e\x26\x7f\x8b\x93\x5f\x04\x3a\x07\x3f\x39\x8f"
841+
b"\x38\xfd\x09\x31\x86\x8b\x1a\x54\xf3\xc2\x8b\xe6\xbc\x20\xc9\xdb"
842+
b"\x32\xda\x7b\x3b\xbd\x34\xbc\xfd\x69",
843843
Ed448,
844844
)
845845
pem_str = (

src/ecdsa/test_pyecdsa.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,7 +1013,7 @@ def test_sigencode_der_full_r(self):
10131013
priv1 = SigningKey.generate()
10141014
pub1 = priv1.get_verifying_key()
10151015
data = b"data"
1016-
sig = priv1.sign(data, sigencode=sigencode_der_full_r, accelerate=True)
1016+
sig = priv1.sign(data, sigencode=sigencode_der_full_r)
10171017

10181018
self.assertEqual(type(sig), binary_type)
10191019
self.assertTrue(pub1.verify(sig, data, sigdecode=sigdecode_der_full_r))
@@ -1022,7 +1022,7 @@ def test_sigencode_der_full_r_uncompressed(self):
10221022
priv1 = SigningKey.generate()
10231023
pub1 = priv1.get_verifying_key()
10241024
data = b"data"
1025-
sig = priv1.sign(data, sigencode=sigencode_der_full_r, accelerate=True)
1025+
sig = priv1.sign(data, sigencode=sigencode_der_full_r)
10261026
r, s = sigdecode_der_full_r(sig, None)
10271027
point = ellipticcurve.Point.from_bytes(
10281028
priv1.privkey.public_key.generator.curve(), r
@@ -1036,7 +1036,7 @@ def test_sigencode_der_full_r_compressed(self):
10361036
priv1 = SigningKey.generate()
10371037
pub1 = priv1.get_verifying_key()
10381038
data = b"data"
1039-
sig = priv1.sign(data, sigencode=sigencode_der_full_r, accelerate=True)
1039+
sig = priv1.sign(data, sigencode=sigencode_der_full_r)
10401040
r, s = sigdecode_der_full_r(sig, None)
10411041
point = ellipticcurve.Point.from_bytes(
10421042
priv1.privkey.public_key.generator.curve(), r
@@ -1050,9 +1050,7 @@ def test_sigencode_der_sig_value_with_y_boolean(self):
10501050
priv1 = SigningKey.generate()
10511051
pub1 = priv1.get_verifying_key()
10521052
data = b"data"
1053-
sig = priv1.sign(
1054-
data, sigencode=sigencode_der_sig_value_y_boolean, accelerate=True
1055-
)
1053+
sig = priv1.sign(data, sigencode=sigencode_der_sig_value_y_boolean)
10561054
self.assertEqual(type(sig), binary_type)
10571055
self.assertTrue(
10581056
pub1.verify(sig, data, sigdecode=sigdecode_der_extended)
@@ -1065,7 +1063,6 @@ def test_sigencode_der_sig_value_with_y_field_elem(self):
10651063
sig = priv1.sign(
10661064
data,
10671065
sigencode=sigencode_der_sig_value_y_field_elem,
1068-
accelerate=True,
10691066
)
10701067
self.assertEqual(type(sig), binary_type)
10711068
self.assertTrue(

0 commit comments

Comments
 (0)