Skip to content

Commit

Permalink
Merge pull request #205 from blag/expose-allow-truncate
Browse files Browse the repository at this point in the history
Expose allow_truncate option in SigningKey.sign() and VerifyingKey.verify()
  • Loading branch information
tomato42 authored Aug 24, 2020
2 parents 14e673d + 4f7d534 commit 69e9735
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 3 deletions.
22 changes: 19 additions & 3 deletions src/ecdsa/keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,12 @@ def to_der(self, point_encoding="uncompressed"):
)

def verify(
self, signature, data, hashfunc=None, sigdecode=sigdecode_string
self,
signature,
data,
hashfunc=None,
sigdecode=sigdecode_string,
allow_truncate=True,
):
"""
Verify a signature made over provided data.
Expand All @@ -629,6 +634,11 @@ def verify(
second one. See :func:`ecdsa.util.sigdecode_string` and
:func:`ecdsa.util.sigdecode_der` for examples.
:type sigdecode: callable
:param bool allow_truncate: if True, the provided digest can have
bigger bit-size than the order of the curve, the extra bits (at
the end of the digest) will be truncated. Use it when verifying
SHA-384 output using NIST256p or in similar situations. Defaults to
True.
:raises BadSignatureError: if the signature is invalid or malformed
Expand All @@ -641,7 +651,7 @@ def verify(

hashfunc = hashfunc or self.default_hashfunc
digest = hashfunc(data).digest()
return self.verify_digest(signature, digest, sigdecode, True)
return self.verify_digest(signature, digest, sigdecode, allow_truncate)

def verify_digest(
self,
Expand Down Expand Up @@ -1262,6 +1272,7 @@ def sign(
hashfunc=None,
sigencode=sigencode_string,
k=None,
allow_truncate=True,
):
"""
Create signature over data using the probabilistic ECDSA algorithm.
Expand Down Expand Up @@ -1298,6 +1309,11 @@ def sign(
:param int k: a pre-selected nonce for calculating the signature.
In typical use cases, it should be set to None (the default) to
allow its generation from an entropy source.
:param bool allow_truncate: if True, the provided digest can have
bigger bit-size than the order of the curve, the extra bits (at
the end of the digest) will be truncated. Use it when signing
SHA-384 output using NIST256p or in similar situations. True by
default.
:raises RSZeroError: in the unlikely event when "r" parameter or
"s" parameter is equal 0 as that would leak the key. Calee should
Expand All @@ -1309,7 +1325,7 @@ def sign(
hashfunc = hashfunc or self.default_hashfunc
data = normalise_bytes(data)
h = hashfunc(data).digest()
return self.sign_digest(h, entropy, sigencode, k, allow_truncate=True)
return self.sign_digest(h, entropy, sigencode, k, allow_truncate)

def sign_digest(
self,
Expand Down
46 changes: 46 additions & 0 deletions src/ecdsa/test_pyecdsa.py
Original file line number Diff line number Diff line change
Expand Up @@ -1203,6 +1203,52 @@ def do_test_to_openssl(self, curve, hash_name="SHA1"):
)


class TooSmallCurve(unittest.TestCase):
OPENSSL_SUPPORTED_CURVES = set(
c.split(":")[0].strip()
for c in run_openssl("ecparam -list_curves").split("\n")
)

@pytest.mark.skipif(
"prime192v1" not in OPENSSL_SUPPORTED_CURVES,
reason="system openssl does not support prime192v1",
)
def test_sign_too_small_curve_dont_allow_truncate_raises(self):
sk = SigningKey.generate(curve=NIST192p)
vk = sk.get_verifying_key()
data = b("data")
with self.assertRaises(BadDigestError):
sk.sign(
data,
hashfunc=partial(hashlib.new, "SHA256"),
sigencode=sigencode_der,
allow_truncate=False,
)

@pytest.mark.skipif(
"prime192v1" not in OPENSSL_SUPPORTED_CURVES,
reason="system openssl does not support prime192v1",
)
def test_verify_too_small_curve_dont_allow_truncate_raises(self):
sk = SigningKey.generate(curve=NIST192p)
vk = sk.get_verifying_key()
data = b("data")
sig_der = sk.sign(
data,
hashfunc=partial(hashlib.new, "SHA256"),
sigencode=sigencode_der,
allow_truncate=True,
)
with self.assertRaises(BadDigestError):
vk.verify(
sig_der,
data,
hashfunc=partial(hashlib.new, "SHA256"),
sigdecode=sigdecode_der,
allow_truncate=False,
)


class DER(unittest.TestCase):
def test_integer(self):
self.assertEqual(der.encode_integer(0), b("\x02\x01\x00"))
Expand Down

0 comments on commit 69e9735

Please sign in to comment.