Skip to content

Commit 8533e51

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
1 parent 487f6d3 commit 8533e51

File tree

3 files changed

+65
-26
lines changed

3 files changed

+65
-26
lines changed

src/ecdsa/keys.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from .ecdsa import RSZeroError
88
from .util import string_to_number, number_to_string, randrange
99
from .util import sigencode_string, sigdecode_string
10-
from .util import oid_ecPublicKey, encoded_oid_ecPublicKey
10+
from .util import oid_ecPublicKey, encoded_oid_ecPublicKey, MalformedSignature
1111
from six import PY3, b
1212
from hashlib import sha1
1313

@@ -138,7 +138,7 @@ def verify_digest(self, signature, digest, sigdecode=sigdecode_string):
138138
number = string_to_number(digest)
139139
try:
140140
r, s = sigdecode(signature, self.pubkey.order)
141-
except der.UnexpectedDER as e:
141+
except (der.UnexpectedDER, MalformedSignature) as e:
142142
raise BadSignatureError("Malformed formatting of signature", e)
143143
sig = ecdsa.Signature(r, s)
144144
if self.pubkey.verifies(number, sig):

src/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

src/ecdsa/util.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,19 +233,39 @@ def sigencode_der_canonize(r, s, order):
233233
return sigencode_der(r, s, order)
234234

235235

236+
class MalformedSignature(Exception):
237+
pass
238+
239+
236240
def sigdecode_string(signature, order):
237241
l = orderlen(order)
238-
assert len(signature) == 2 * l, (len(signature), 2 * l)
242+
if not len(signature) == 2 * l:
243+
raise MalformedSignature(
244+
"Invalid length of signature, expected {0} bytes long, "
245+
"provided string is {1} bytes long"
246+
.format(2 * l, len(signature)))
239247
r = string_to_number_fixedlen(signature[:l], order)
240248
s = string_to_number_fixedlen(signature[l:], order)
241249
return r, s
242250

243251

244252
def sigdecode_strings(rs_strings, order):
253+
if not len(rs_strings) == 2:
254+
raise MalformedSignature(
255+
"Invalid number of strings provided: {0}, expected 2"
256+
.format(len(rs_strings)))
245257
(r_str, s_str) = rs_strings
246258
l = orderlen(order)
247-
assert len(r_str) == l, (len(r_str), l)
248-
assert len(s_str) == l, (len(s_str), l)
259+
if not len(r_str) == l:
260+
raise MalformedSignature(
261+
"Invalid length of first string ('r' parameter), "
262+
"expected {0} bytes long, provided string is {1} bytes long"
263+
.format(l, len(r_str)))
264+
if not len(s_str) == l:
265+
raise MalformedSignature(
266+
"Invalid length of second string ('s' parameter), "
267+
"expected {0} bytes long, provided string is {1} bytes long"
268+
.format(l, len(s_str)))
249269
r = string_to_number_fixedlen(r_str, order)
250270
s = string_to_number_fixedlen(s_str, order)
251271
return r, s

0 commit comments

Comments
 (0)