Skip to content

Commit 09786a2

Browse files
authored
Fix bug with ECDSA p521 curves (#153)
There was previously an assumption that ECDSA key sizes were multiples of 8 bits, but that is not true for p521 curves. The calculation that converts bits to bytes now rounds up, rather than rounding down.
1 parent 06e5f93 commit 09786a2

File tree

2 files changed

+13
-3
lines changed

2 files changed

+13
-3
lines changed

signxml/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
from .exceptions import InvalidSignature, InvalidDigest, InvalidInput, InvalidCertificate # noqa
1616
from .util import (bytes_to_long, long_to_bytes, strip_pem_header, add_pem_header, ensure_bytes, ensure_str, Namespace,
17-
XMLProcessor, iterate_pem, verify_x509_cert_chain)
17+
XMLProcessor, iterate_pem, verify_x509_cert_chain, bits_to_bytes_unit)
1818
from collections import namedtuple
1919

2020
methods = Enum("Methods", "enveloped enveloping detached")
@@ -382,7 +382,7 @@ def sign(self, data, key=None, passphrase=None, cert=None, reference_uri=None, k
382382
if self.sign_alg.startswith("dsa-") or self.sign_alg.startswith("ecdsa-"):
383383
# Note: The output of the DSA and ECDSA signers is a DER-encoded ASN.1 sequence of two DER integers.
384384
(r, s) = utils.decode_dss_signature(signature)
385-
int_len = key.key_size // 8
385+
int_len = bits_to_bytes_unit(key.key_size)
386386
signature = long_to_bytes(r, blocksize=int_len) + long_to_bytes(s, blocksize=int_len)
387387

388388
signature_value_element.text = ensure_str(b64encode(signature))
@@ -585,7 +585,7 @@ def _verify_signature_with_pubkey(self, signed_info_c14n, raw_signature, key_val
585585
raise NotImplementedError()
586586

587587
def _encode_dss_signature(self, raw_signature, key_size_bits):
588-
want_raw_signature_len = key_size_bits // 8 * 2
588+
want_raw_signature_len = bits_to_bytes_unit(key_size_bits) * 2
589589
if len(raw_signature) != want_raw_signature_len:
590590
raise InvalidSignature(
591591
"Expected %d byte SignatureValue, got %d"

signxml/util/__init__.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from __future__ import absolute_import, division, print_function, unicode_literals
88

9+
import math
910
import os, sys, re, struct, textwrap
1011
from xml.etree import ElementTree as stdlibElementTree
1112
from base64 import b64encode, b64decode
@@ -92,6 +93,15 @@ def long_to_bytes(n, blocksize=0):
9293
return s
9394

9495

96+
def bits_to_bytes_unit(num_of_bits):
97+
"""bits_to_bytes_unit(num_of_bits:int) : int
98+
Convert the unit of measurement for the argument from bits to bytes.
99+
100+
Rounds up to the nearest whole byte.
101+
"""
102+
return int(math.ceil(num_of_bits / 8))
103+
104+
95105
pem_regexp = re.compile("{header}{nl}(.+?){footer}".format(header=PEM_HEADER, nl="\r{0,1}\n", footer=PEM_FOOTER),
96106
flags=re.S)
97107

0 commit comments

Comments
 (0)