Skip to content

Commit

Permalink
Merge pull request #126 from tomato42/more-test-coverage
Browse files Browse the repository at this point in the history
More test coverage
  • Loading branch information
tomato42 committed Oct 10, 2019
2 parents 93d2619 + 83dab29 commit 1db6b3c
Show file tree
Hide file tree
Showing 6 changed files with 233 additions and 26 deletions.
6 changes: 1 addition & 5 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,5 @@
include =
src/ecdsa/*
omit =
src/ecdsa/six.py
src/ecdsa/_version.py
src/ecdsa/test_ecdsa.py
src/ecdsa/test_ellipticcurve.py
src/ecdsa/test_numbertheory.py
src/ecdsa/test_pyecdsa.py
src/ecdsa/test_*
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ is to call `s=sk.to_string()`, and then re-create it with
`SigningKey.from_string(s, curve)` . This short form does not record the
curve, so you must be sure to tell from_string() the same curve you used for
the original key. The short form of a NIST192p-based signing key is just 24
bytes long. If the point encoding is invalid or it does not lie on the
specified curve, `from_string()` will raise MalformedPointError.
bytes long. If a point encoding is invalid or it does not lie on the specified
curve, `from_string()` will raise MalformedPointError.

```python
from ecdsa import SigningKey, NIST384p
Expand Down
5 changes: 4 additions & 1 deletion src/ecdsa/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from .keys import SigningKey, VerifyingKey, BadSignatureError, BadDigestError
from .keys import SigningKey, VerifyingKey, BadSignatureError, BadDigestError,\
MalformedPointError
from .curves import NIST192p, NIST224p, NIST256p, NIST384p, NIST521p, SECP256k1
from .der import UnexpectedDER

# This code comes from http://github.com/warner/python-ecdsa
from ._version import get_versions
Expand All @@ -10,5 +12,6 @@
"test_pyecdsa", "util", "six"]

_hush_pyflakes = [SigningKey, VerifyingKey, BadSignatureError, BadDigestError,
MalformedPointError, UnexpectedDER,
NIST192p, NIST224p, NIST256p, NIST384p, NIST521p, SECP256k1]
del _hush_pyflakes
24 changes: 15 additions & 9 deletions src/ecdsa/keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,14 @@ def from_public_point(klass, point, curve=NIST192p, hashfunc=sha1):
@staticmethod
def _from_raw_encoding(string, curve, validate_point):
order = curve.order
assert (len(string) == curve.verifying_key_length), \
(len(string), curve.verifying_key_length)
# real assert, from_string() should not call us with different length
assert len(string) == curve.verifying_key_length
xs = string[:curve.baselen]
ys = string[curve.baselen:]
assert len(xs) == curve.baselen, (len(xs), curve.baselen)
assert len(ys) == curve.baselen, (len(ys), curve.baselen)
if len(xs) != curve.baselen:
raise MalformedPointError("Unexpected length of encoded x")
if len(ys) != curve.baselen:
raise MalformedPointError("Unexpected length of encoded y")
x = string_to_number(xs)
y = string_to_number(ys)
if validate_point and not ecdsa.point_is_valid(curve.generator, x, y):
Expand Down Expand Up @@ -86,6 +88,7 @@ def _from_compressed(string, curve, validate_point):

@classmethod
def _from_hybrid(cls, string, curve, validate_point):
# real assert, from_string() should not call us with different types
assert string[:1] in (b('\x06'), b('\x07'))

# primarily use the uncompressed as it's easiest to handle
Expand Down Expand Up @@ -223,9 +226,6 @@ def to_pem(self):
return der.topem(self.to_der(), "PUBLIC KEY")

def to_der(self, point_encoding="uncompressed"):
order = self.pubkey.order
x_str = number_to_string(self.pubkey.point.x(), order)
y_str = number_to_string(self.pubkey.point.y(), order)
point_str = b("\x00") + self.to_string(point_encoding)
return der.encode_sequence(der.encode_sequence(encoded_oid_ecPublicKey,
self.curve.encoded_oid),
Expand Down Expand Up @@ -274,7 +274,10 @@ def from_secret_exponent(klass, secexp, curve=NIST192p, hashfunc=sha1):
self.default_hashfunc = hashfunc
self.baselen = curve.baselen
n = curve.order
assert 1 <= secexp < n
if not 1 <= secexp < n:
raise MalformedPointError(
"Invalid value for secexp, expected integer between 1 and {0}"
.format(n))
pubkey_point = curve.generator * secexp
pubkey = ecdsa.Public_key(curve.generator, pubkey_point)
pubkey.order = n
Expand All @@ -286,7 +289,10 @@ def from_secret_exponent(klass, secexp, curve=NIST192p, hashfunc=sha1):

@classmethod
def from_string(klass, string, curve=NIST192p, hashfunc=sha1):
assert len(string) == curve.baselen, (len(string), curve.baselen)
if len(string) != curve.baselen:
raise MalformedPointError(
"Invalid length of private key, received {0}, expected {1}"
.format(len(string), curve.baselen))
secexp = string_to_number(string)
return klass.from_secret_exponent(secexp, curve, hashfunc)

Expand Down
50 changes: 43 additions & 7 deletions src/ecdsa/numbertheory.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
xrange = range

import math
import warnings


class Error(Exception):
Expand Down Expand Up @@ -326,8 +327,13 @@ def factorization(n):
return result


def phi(n):
def phi(n): # pragma: no cover
"""Return the Euler totient function of n."""
# deprecated in 0.14
warnings.warn("Function is unused by library code. If you use this code, "
"please open an issue in "
"https://github.com/warner/python-ecdsa",
DeprecationWarning)

assert isinstance(n, integer_types)

Expand All @@ -345,20 +351,30 @@ def phi(n):
return result


def carmichael(n):
def carmichael(n): # pragma: no cover
"""Return Carmichael function of n.
Carmichael(n) is the smallest integer x such that
m**x = 1 mod n for all m relatively prime to n.
"""
# deprecated in 0.14
warnings.warn("Function is unused by library code. If you use this code, "
"please open an issue in "
"https://github.com/warner/python-ecdsa",
DeprecationWarning)

return carmichael_of_factorized(factorization(n))


def carmichael_of_factorized(f_list):
def carmichael_of_factorized(f_list): # pragma: no cover
"""Return the Carmichael function of a number that is
represented as a list of (prime,exponent) pairs.
"""
# deprecated in 0.14
warnings.warn("Function is unused by library code. If you use this code, "
"please open an issue in "
"https://github.com/warner/python-ecdsa",
DeprecationWarning)

if len(f_list) < 1:
return 1
Expand All @@ -370,9 +386,14 @@ def carmichael_of_factorized(f_list):
return result


def carmichael_of_ppower(pp):
def carmichael_of_ppower(pp): # pragma: no cover
"""Carmichael function of the given power of the given prime.
"""
# deprecated in 0.14
warnings.warn("Function is unused by library code. If you use this code, "
"please open an issue in "
"https://github.com/warner/python-ecdsa",
DeprecationWarning)

p, a = pp
if p == 2 and a > 2:
Expand All @@ -381,9 +402,14 @@ def carmichael_of_ppower(pp):
return (p - 1) * p**(a - 1)


def order_mod(x, m):
def order_mod(x, m): # pragma: no cover
"""Return the order of x in the multiplicative group mod m.
"""
# deprecated in 0.14
warnings.warn("Function is unused by library code. If you use this code, "
"please open an issue in "
"https://github.com/warner/python-ecdsa",
DeprecationWarning)

# Warning: this implementation is not very clever, and will
# take a long time if m is very large.
Expand All @@ -401,9 +427,14 @@ def order_mod(x, m):
return result


def largest_factor_relatively_prime(a, b):
def largest_factor_relatively_prime(a, b): # pragma: no cover
"""Return the largest factor of a relatively prime to b.
"""
# deprecated in 0.14
warnings.warn("Function is unused by library code. If you use this code, "
"please open an issue in "
"https://github.com/warner/python-ecdsa",
DeprecationWarning)

while 1:
d = gcd(a, b)
Expand All @@ -418,10 +449,15 @@ def largest_factor_relatively_prime(a, b):
return a


def kinda_order_mod(x, m):
def kinda_order_mod(x, m): # pragma: no cover
"""Return the order of x in the multiplicative group mod m',
where m' is the largest factor of m relatively prime to x.
"""
# deprecated in 0.14
warnings.warn("Function is unused by library code. If you use this code, "
"please open an issue in "
"https://github.com/warner/python-ecdsa",
DeprecationWarning)

return order_mod(x, largest_factor_relatively_prime(m, x))

Expand Down

0 comments on commit 1db6b3c

Please sign in to comment.