diff --git a/signxml/__init__.py b/signxml/__init__.py index 91783592..129ef628 100644 --- a/signxml/__init__.py +++ b/signxml/__init__.py @@ -14,7 +14,7 @@ from .exceptions import InvalidSignature, InvalidDigest, InvalidInput, InvalidCertificate # noqa from .util import (bytes_to_long, long_to_bytes, strip_pem_header, add_pem_header, ensure_bytes, ensure_str, Namespace, - XMLProcessor, iterate_pem, verify_x509_cert_chain) + XMLProcessor, iterate_pem, verify_x509_cert_chain, bits_to_bytes_unit) from collections import namedtuple methods = Enum("Methods", "enveloped enveloping detached") @@ -382,7 +382,7 @@ def sign(self, data, key=None, passphrase=None, cert=None, reference_uri=None, k if self.sign_alg.startswith("dsa-") or self.sign_alg.startswith("ecdsa-"): # Note: The output of the DSA and ECDSA signers is a DER-encoded ASN.1 sequence of two DER integers. (r, s) = utils.decode_dss_signature(signature) - int_len = key.key_size // 8 + int_len = bits_to_bytes_unit(key.key_size) signature = long_to_bytes(r, blocksize=int_len) + long_to_bytes(s, blocksize=int_len) 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 raise NotImplementedError() def _encode_dss_signature(self, raw_signature, key_size_bits): - want_raw_signature_len = key_size_bits // 8 * 2 + want_raw_signature_len = bits_to_bytes_unit(key_size_bits) * 2 if len(raw_signature) != want_raw_signature_len: raise InvalidSignature( "Expected %d byte SignatureValue, got %d" diff --git a/signxml/util/__init__.py b/signxml/util/__init__.py index 53c66e27..a826702b 100644 --- a/signxml/util/__init__.py +++ b/signxml/util/__init__.py @@ -6,6 +6,7 @@ from __future__ import absolute_import, division, print_function, unicode_literals +import math import os, sys, re, struct, textwrap from xml.etree import ElementTree as stdlibElementTree from base64 import b64encode, b64decode @@ -92,6 +93,15 @@ def long_to_bytes(n, blocksize=0): return s +def bits_to_bytes_unit(num_of_bits): + """bits_to_bytes_unit(num_of_bits:int) : int + Convert the unit of measurement for the argument from bits to bytes. + + Rounds up to the nearest whole byte. + """ + return int(math.ceil(num_of_bits / 8)) + + pem_regexp = re.compile("{header}{nl}(.+?){footer}".format(header=PEM_HEADER, nl="\r{0,1}\n", footer=PEM_FOOTER), flags=re.S)