Skip to content

Commit 897178c

Browse files
committed
give the same handling to string encoded signatures as to DER
Verify that strings of unexpected lengths are rejected with the same BadSignatureError exception backport of 8533e51
1 parent 20b3774 commit 897178c

File tree

3 files changed

+65
-26
lines changed

3 files changed

+65
-26
lines changed

ecdsa/keys.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from .curves import NIST192p, find_curve
77
from .util import string_to_number, number_to_string, randrange
88
from .util import sigencode_string, sigdecode_string
9-
from .util import oid_ecPublicKey, encoded_oid_ecPublicKey
9+
from .util import oid_ecPublicKey, encoded_oid_ecPublicKey, MalformedSignature
1010
from .six import PY3, b
1111
from hashlib import sha1
1212

@@ -108,7 +108,7 @@ def verify_digest(self, signature, digest, sigdecode=sigdecode_string):
108108
number = string_to_number(digest)
109109
try:
110110
r, s = sigdecode(signature, self.pubkey.order)
111-
except der.UnexpectedDER as e:
111+
except (der.UnexpectedDER, MalformedSignature) as e:
112112
raise BadSignatureError("Malformed formatting of signature", e)
113113
sig = ecdsa.Signature(r, s)
114114
if self.pubkey.verifies(number, sig):

ecdsa/test_malformed_sigs.py

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,16 @@
11
from __future__ import with_statement, division
22

3-
import unittest
4-
import os
5-
import time
6-
import shutil
7-
import subprocess
83
import pytest
9-
from binascii import hexlify, unhexlify
10-
from hashlib import sha1, sha256, sha512
114
import hashlib
125

136
from six import b, binary_type
147
from .keys import SigningKey, VerifyingKey
158
from .keys import BadSignatureError
16-
from . import util
17-
from .util import sigencode_der, sigencode_strings
18-
from .util import sigdecode_der, sigdecode_strings
9+
from .util import sigencode_der, sigencode_string
10+
from .util import sigdecode_der, sigdecode_string
1911
from .curves import curves, NIST256p, NIST521p
20-
from .ellipticcurve import Point
21-
from . import der
22-
from . import rfc6979
23-
import copy
2412

25-
sigs = []
13+
der_sigs = []
2614
example_data = b("some data to sign")
2715

2816
# Just NIST256p with SHA256 is 560 test cases, all curves with all hashes is
@@ -37,14 +25,14 @@
3725
sigencode=sigencode_der)
3826
for pos in range(len(signature)):
3927
for xor in (1<<i for i in range(8)):
40-
sigs.append(pytest.param(
28+
der_sigs.append(pytest.param(
4129
key.verifying_key, hash_alg,
4230
signature, pos, xor,
4331
id="{0}-{1}-pos-{2}-xor-{3}".format(
4432
curve.name, hash_alg, pos, xor)))
4533

4634

47-
@pytest.mark.parametrize("verifying_key,hash_alg,signature,pos,xor", sigs)
35+
@pytest.mark.parametrize("verifying_key,hash_alg,signature,pos,xor", der_sigs)
4836
def test_fuzzed_der_signatures(verifying_key, hash_alg, signature, pos, xor):
4937
# check if a malformed DER encoded signature causes the same exception
5038
# to be raised irrespective of the type of error
@@ -60,9 +48,40 @@ def test_fuzzed_der_signatures(verifying_key, hash_alg, signature, pos, xor):
6048
assert True
6149

6250

63-
def __main__():
64-
unittest.main()
51+
####
52+
#
53+
# For string encoded signatures, only the length of string is important
54+
#
55+
####
6556

57+
str_sigs = []
6658

67-
if __name__ == "__main__":
68-
__main__()
59+
#for curve in curves:
60+
for curve in [NIST256p]:
61+
#for hash_alg in ["md5", "sha1", "sha224", "sha256", "sha384", "sha512"]:
62+
for hash_alg in ["sha256"]:
63+
key = SigningKey.generate(curve)
64+
signature = key.sign(example_data, hashfunc=getattr(hashlib, hash_alg),
65+
sigencode=sigencode_string)
66+
for trunc in range(len(signature)):
67+
str_sigs.append(pytest.param(
68+
key.verifying_key, hash_alg,
69+
signature, trunc,
70+
id="{0}-{1}-trunc-{2}".format(
71+
curve.name, hash_alg, trunc)))
72+
73+
74+
@pytest.mark.parametrize("verifying_key,hash_alg,signature,trunc", str_sigs)
75+
def test_truncated_string_signatures(verifying_key, hash_alg, signature, trunc):
76+
# check if a malformed string encoded signature causes the same exception
77+
# to be raised irrespective of the type of error
78+
sig = bytearray(signature)
79+
sig = sig[:trunc]
80+
sig = binary_type(sig)
81+
82+
try:
83+
verifying_key.verify(sig, example_data, getattr(hashlib, hash_alg),
84+
sigdecode_string)
85+
assert False
86+
except BadSignatureError:
87+
assert True

ecdsa/util.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,18 +216,38 @@ def sigencode_der_canonize(r, s, order):
216216
return sigencode_der(r, s, order)
217217

218218

219+
class MalformedSignature(Exception):
220+
pass
221+
222+
219223
def sigdecode_string(signature, order):
220224
l = orderlen(order)
221-
assert len(signature) == 2*l, (len(signature), 2*l)
225+
if not len(signature) == 2 * l:
226+
raise MalformedSignature(
227+
"Invalid length of signature, expected {0} bytes long, "
228+
"provided string is {1} bytes long"
229+
.format(2 * l, len(signature)))
222230
r = string_to_number_fixedlen(signature[:l], order)
223231
s = string_to_number_fixedlen(signature[l:], order)
224232
return r, s
225233

226234
def sigdecode_strings(rs_strings, order):
235+
if not len(rs_strings) == 2:
236+
raise MalformedSignature(
237+
"Invalid number of strings provided: {0}, expected 2"
238+
.format(len(rs_strings)))
227239
(r_str, s_str) = rs_strings
228240
l = orderlen(order)
229-
assert len(r_str) == l, (len(r_str), l)
230-
assert len(s_str) == l, (len(s_str), l)
241+
if not len(r_str) == l:
242+
raise MalformedSignature(
243+
"Invalid length of first string ('r' parameter), "
244+
"expected {0} bytes long, provided string is {1} bytes long"
245+
.format(l, len(r_str)))
246+
if not len(s_str) == l:
247+
raise MalformedSignature(
248+
"Invalid length of second string ('s' parameter), "
249+
"expected {0} bytes long, provided string is {1} bytes long"
250+
.format(l, len(s_str)))
231251
r = string_to_number_fixedlen(r_str, order)
232252
s = string_to_number_fixedlen(s_str, order)
233253
return r, s

0 commit comments

Comments
 (0)