Skip to content

Commit f7c08bd

Browse files
committed
get rid of the s[x] if isintance(s[x]... idiom
this is repeating the s[x] three times for every element extracted, use a function for that also decreases number of tests needed for condition coverage
1 parent 31b28fb commit f7c08bd

File tree

3 files changed

+39
-22
lines changed

3 files changed

+39
-22
lines changed

src/ecdsa/_compat.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22
Common functions for providing cross-python version compatibility.
33
"""
44
import sys
5+
from six import integer_types
6+
7+
8+
def str_idx_as_int(string, index):
9+
"""Take index'th byte from string, return as integer"""
10+
val = string[index]
11+
if isinstance(val, integer_types):
12+
return val
13+
return ord(val)
514

615

716
if sys.version_info < (3, 0):

src/ecdsa/der.py

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
import binascii
44
import base64
55
import warnings
6-
from six import int2byte, b, integer_types, text_type
6+
from six import int2byte, b, text_type
7+
from ._compat import str_idx_as_int
78

89

910
class UnexpectedDER(Exception):
@@ -20,7 +21,7 @@ def encode_integer(r):
2021
if len(h) % 2:
2122
h = b("0") + h
2223
s = binascii.unhexlify(h)
23-
num = s[0] if isinstance(s[0], integer_types) else ord(s[0])
24+
num = str_idx_as_int(s, 0)
2425
if num <= 0x7f:
2526
return b("\x02") + int2byte(len(s)) + s
2627
else:
@@ -83,7 +84,7 @@ def encode_bitstring(s, unused=_sentry):
8384
if unused:
8485
if not s:
8586
raise ValueError("unused is non-zero but s is empty")
86-
last = s[-1] if isinstance(s[-1], integer_types) else ord(s[-1])
87+
last = str_idx_as_int(s, -1)
8788
if last & (2 ** unused - 1):
8889
raise ValueError("unused bits must be zeros in DER")
8990
encoded_unused = int2byte(unused)
@@ -121,7 +122,7 @@ def encode_number(n):
121122

122123

123124
def remove_constructed(string):
124-
s0 = string[0] if isinstance(string[0], integer_types) else ord(string[0])
125+
s0 = str_idx_as_int(string, 0)
125126
if (s0 & 0xe0) != 0xa0:
126127
raise UnexpectedDER("wanted type 'constructed tag' (0xa0-0xbf), "
127128
"got 0x%02x" % s0)
@@ -136,8 +137,7 @@ def remove_sequence(string):
136137
if not string:
137138
raise UnexpectedDER("Empty string does not encode a sequence")
138139
if string[:1] != b"\x30":
139-
n = string[0] if isinstance(string[0], integer_types) else \
140-
ord(string[0])
140+
n = str_idx_as_int(string, 0)
141141
raise UnexpectedDER("wanted type 'sequence' (0x30), got 0x%02x" % n)
142142
length, lengthlength = read_length(string[1:])
143143
if length > len(string) - 1 - lengthlength:
@@ -148,7 +148,7 @@ def remove_sequence(string):
148148

149149
def remove_octet_string(string):
150150
if string[:1] != b"\x04":
151-
n = string[0] if isinstance(string[0], integer_types) else ord(string[0])
151+
n = str_idx_as_int(string, 0)
152152
raise UnexpectedDER("wanted type 'octetstring' (0x04), got 0x%02x" % n)
153153
length, llen = read_length(string[1:])
154154
body = string[1+llen:1+llen+length]
@@ -158,7 +158,7 @@ def remove_octet_string(string):
158158

159159
def remove_object(string):
160160
if string[:1] != b"\x06":
161-
n = string[0] if isinstance(string[0], integer_types) else ord(string[0])
161+
n = str_idx_as_int(string, 0)
162162
raise UnexpectedDER("wanted type 'object' (0x06), got 0x%02x" % n)
163163
length, lengthlength = read_length(string[1:])
164164
body = string[1+lengthlength:1+lengthlength+length]
@@ -181,8 +181,7 @@ def remove_integer(string):
181181
raise UnexpectedDER("Empty string is an invalid encoding of an "
182182
"integer")
183183
if string[:1] != b"\x02":
184-
n = string[0] if isinstance(string[0], integer_types) \
185-
else ord(string[0])
184+
n = str_idx_as_int(string, 0)
186185
raise UnexpectedDER("wanted type 'integer' (0x02), got 0x%02x" % n)
187186
length, llen = read_length(string[1:])
188187
if length > len(string) - 1 - llen:
@@ -191,16 +190,14 @@ def remove_integer(string):
191190
raise UnexpectedDER("0-byte long encoding of integer")
192191
numberbytes = string[1+llen:1+llen+length]
193192
rest = string[1+llen+length:]
194-
msb = numberbytes[0] if isinstance(numberbytes[0], integer_types) \
195-
else ord(numberbytes[0])
193+
msb = str_idx_as_int(numberbytes, 0)
196194
if not msb < 0x80:
197195
raise UnexpectedDER("Negative integers are not supported")
198196
# check if the encoding is the minimal one (DER requirement)
199197
if length > 1 and not msb:
200198
# leading zero byte is allowed if the integer would have been
201199
# considered a negative number otherwise
202-
smsb = numberbytes[1] if isinstance(numberbytes[1], integer_types) \
203-
else ord(numberbytes[1])
200+
smsb = str_idx_as_int(numberbytes, 1)
204201
if smsb < 0x80:
205202
raise UnexpectedDER("Invalid encoding of integer, unnecessary "
206203
"zero padding bytes")
@@ -215,7 +212,7 @@ def read_number(string):
215212
if llen > len(string):
216213
raise UnexpectedDER("ran out of length bytes")
217214
number = number << 7
218-
d = string[llen] if isinstance(string[llen], integer_types) else ord(string[llen])
215+
d = str_idx_as_int(string, llen)
219216
number += (d & 0x7f)
220217
llen += 1
221218
if not d & 0x80:
@@ -238,7 +235,7 @@ def encode_length(l):
238235
def read_length(string):
239236
if not string:
240237
raise UnexpectedDER("Empty string can't encode valid length value")
241-
num = string[0] if isinstance(string[0], integer_types) else ord(string[0])
238+
num = str_idx_as_int(string, 0)
242239
if not (num & 0x80):
243240
# short form
244241
return (num & 0x7f), 1
@@ -250,7 +247,7 @@ def read_length(string):
250247
if llen > len(string)-1:
251248
raise UnexpectedDER("Length of length longer than provided buffer")
252249
# verify that the encoding is minimal possible (DER requirement)
253-
msb = string[1] if isinstance(string[1], integer_types) else ord(string[1])
250+
msb = str_idx_as_int(string, 1)
254251
if not msb or llen == 1 and msb < 0x80:
255252
raise UnexpectedDER("Not minimal encoding of length")
256253
return int(binascii.hexlify(string[1:1+llen]), 16), 1+llen
@@ -301,7 +298,7 @@ def remove_bitstring(string, expect_unused=_sentry):
301298
warnings.warn("Legacy call convention used, expect_unused= needs to be"
302299
" specified",
303300
DeprecationWarning)
304-
num = string[0] if isinstance(string[0], integer_types) else ord(string[0])
301+
num = str_idx_as_int(string, 0)
305302
if string[:1] != b"\x03":
306303
raise UnexpectedDER("wanted bitstring (0x03), got 0x%02x" % num)
307304
length, llen = read_length(string[1:])
@@ -310,8 +307,7 @@ def remove_bitstring(string, expect_unused=_sentry):
310307
body = string[1+llen:1+llen+length]
311308
rest = string[1+llen+length:]
312309
if expect_unused is not _sentry:
313-
unused = body[0] if isinstance(body[0], integer_types) \
314-
else ord(body[0])
310+
unused = str_idx_as_int(body, 0)
315311
if not 0 <= unused <= 7:
316312
raise UnexpectedDER("Invalid encoding of unused bits")
317313
if expect_unused is not None and expect_unused != unused:
@@ -320,8 +316,7 @@ def remove_bitstring(string, expect_unused=_sentry):
320316
if unused:
321317
if not body:
322318
raise UnexpectedDER("Invalid encoding of empty bit string")
323-
last = body[-1] if isinstance(body[-1], integer_types) else \
324-
ord(body[-1])
319+
last = str_idx_as_int(body, -1)
325320
# verify that all the unused bits are set to zero (DER requirement)
326321
if last & (2 ** unused - 1):
327322
raise UnexpectedDER("Non zero padding bits in bit string")

src/ecdsa/test_der.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
from six import b
1111
import pytest
1212
import warnings
13+
from ._compat import str_idx_as_int
14+
1315

1416
class TestRemoveInteger(unittest.TestCase):
1517
# DER requires the integers to be 0-padded only if they would be
@@ -229,3 +231,14 @@ def test_invalid_encoding_of_empty_string(self):
229231
def test_invalid_padding_bits(self):
230232
with self.assertRaises(UnexpectedDER):
231233
remove_bitstring(b'\x03\x02\x01\xff', None)
234+
235+
236+
class TestStrIdxAsInt(unittest.TestCase):
237+
def test_str(self):
238+
self.assertEqual(115, str_idx_as_int('str', 0))
239+
240+
def test_bytes(self):
241+
self.assertEqual(115, str_idx_as_int(b'str', 0))
242+
243+
def test_bytearray(self):
244+
self.assertEqual(115, str_idx_as_int(bytearray(b'str'), 0))

0 commit comments

Comments
 (0)