Skip to content

Commit 69e9735

Browse files
authored
Merge pull request #205 from blag/expose-allow-truncate
Expose allow_truncate option in SigningKey.sign() and VerifyingKey.verify()
2 parents 14e673d + 4f7d534 commit 69e9735

File tree

2 files changed

+65
-3
lines changed

2 files changed

+65
-3
lines changed

src/ecdsa/keys.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,12 @@ def to_der(self, point_encoding="uncompressed"):
602602
)
603603

604604
def verify(
605-
self, signature, data, hashfunc=None, sigdecode=sigdecode_string
605+
self,
606+
signature,
607+
data,
608+
hashfunc=None,
609+
sigdecode=sigdecode_string,
610+
allow_truncate=True,
606611
):
607612
"""
608613
Verify a signature made over provided data.
@@ -629,6 +634,11 @@ def verify(
629634
second one. See :func:`ecdsa.util.sigdecode_string` and
630635
:func:`ecdsa.util.sigdecode_der` for examples.
631636
:type sigdecode: callable
637+
:param bool allow_truncate: if True, the provided digest can have
638+
bigger bit-size than the order of the curve, the extra bits (at
639+
the end of the digest) will be truncated. Use it when verifying
640+
SHA-384 output using NIST256p or in similar situations. Defaults to
641+
True.
632642
633643
:raises BadSignatureError: if the signature is invalid or malformed
634644
@@ -641,7 +651,7 @@ def verify(
641651

642652
hashfunc = hashfunc or self.default_hashfunc
643653
digest = hashfunc(data).digest()
644-
return self.verify_digest(signature, digest, sigdecode, True)
654+
return self.verify_digest(signature, digest, sigdecode, allow_truncate)
645655

646656
def verify_digest(
647657
self,
@@ -1262,6 +1272,7 @@ def sign(
12621272
hashfunc=None,
12631273
sigencode=sigencode_string,
12641274
k=None,
1275+
allow_truncate=True,
12651276
):
12661277
"""
12671278
Create signature over data using the probabilistic ECDSA algorithm.
@@ -1298,6 +1309,11 @@ def sign(
12981309
:param int k: a pre-selected nonce for calculating the signature.
12991310
In typical use cases, it should be set to None (the default) to
13001311
allow its generation from an entropy source.
1312+
:param bool allow_truncate: if True, the provided digest can have
1313+
bigger bit-size than the order of the curve, the extra bits (at
1314+
the end of the digest) will be truncated. Use it when signing
1315+
SHA-384 output using NIST256p or in similar situations. True by
1316+
default.
13011317
13021318
:raises RSZeroError: in the unlikely event when "r" parameter or
13031319
"s" parameter is equal 0 as that would leak the key. Calee should
@@ -1309,7 +1325,7 @@ def sign(
13091325
hashfunc = hashfunc or self.default_hashfunc
13101326
data = normalise_bytes(data)
13111327
h = hashfunc(data).digest()
1312-
return self.sign_digest(h, entropy, sigencode, k, allow_truncate=True)
1328+
return self.sign_digest(h, entropy, sigencode, k, allow_truncate)
13131329

13141330
def sign_digest(
13151331
self,

src/ecdsa/test_pyecdsa.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,6 +1203,52 @@ def do_test_to_openssl(self, curve, hash_name="SHA1"):
12031203
)
12041204

12051205

1206+
class TooSmallCurve(unittest.TestCase):
1207+
OPENSSL_SUPPORTED_CURVES = set(
1208+
c.split(":")[0].strip()
1209+
for c in run_openssl("ecparam -list_curves").split("\n")
1210+
)
1211+
1212+
@pytest.mark.skipif(
1213+
"prime192v1" not in OPENSSL_SUPPORTED_CURVES,
1214+
reason="system openssl does not support prime192v1",
1215+
)
1216+
def test_sign_too_small_curve_dont_allow_truncate_raises(self):
1217+
sk = SigningKey.generate(curve=NIST192p)
1218+
vk = sk.get_verifying_key()
1219+
data = b("data")
1220+
with self.assertRaises(BadDigestError):
1221+
sk.sign(
1222+
data,
1223+
hashfunc=partial(hashlib.new, "SHA256"),
1224+
sigencode=sigencode_der,
1225+
allow_truncate=False,
1226+
)
1227+
1228+
@pytest.mark.skipif(
1229+
"prime192v1" not in OPENSSL_SUPPORTED_CURVES,
1230+
reason="system openssl does not support prime192v1",
1231+
)
1232+
def test_verify_too_small_curve_dont_allow_truncate_raises(self):
1233+
sk = SigningKey.generate(curve=NIST192p)
1234+
vk = sk.get_verifying_key()
1235+
data = b("data")
1236+
sig_der = sk.sign(
1237+
data,
1238+
hashfunc=partial(hashlib.new, "SHA256"),
1239+
sigencode=sigencode_der,
1240+
allow_truncate=True,
1241+
)
1242+
with self.assertRaises(BadDigestError):
1243+
vk.verify(
1244+
sig_der,
1245+
data,
1246+
hashfunc=partial(hashlib.new, "SHA256"),
1247+
sigdecode=sigdecode_der,
1248+
allow_truncate=False,
1249+
)
1250+
1251+
12061252
class DER(unittest.TestCase):
12071253
def test_integer(self):
12081254
self.assertEqual(der.encode_integer(0), b("\x02\x01\x00"))

0 commit comments

Comments
 (0)