diff options
author | Alex Gaynor <alex.gaynor@gmail.com> | 2014-03-17 14:08:33 -0700 |
---|---|---|
committer | Alex Gaynor <alex.gaynor@gmail.com> | 2014-03-17 14:08:33 -0700 |
commit | 2e08a76057d29d92bbc7be76c8acf92479ad76fd (patch) | |
tree | 5c1a16123633514a006925ca6b7d495ab9c57a83 /cryptography | |
parent | d46e63c7305ce3d027b5d5d2fc81aeae4291f698 (diff) | |
parent | e28b3ad6dba208b8652b321ffc895f35d9822ef3 (diff) | |
download | cryptography-2e08a76057d29d92bbc7be76c8acf92479ad76fd.tar.gz cryptography-2e08a76057d29d92bbc7be76c8acf92479ad76fd.tar.bz2 cryptography-2e08a76057d29d92bbc7be76c8acf92479ad76fd.zip |
Merge pull request #759 from public/no-hex
Don't go via hex() when working with BNs
Diffstat (limited to 'cryptography')
-rw-r--r-- | cryptography/hazmat/backends/openssl/backend.py | 49 |
1 files changed, 38 insertions, 11 deletions
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py index a68bc089..b977b4c8 100644 --- a/cryptography/hazmat/backends/openssl/backend.py +++ b/cryptography/hazmat/backends/openssl/backend.py @@ -16,6 +16,8 @@ from __future__ import absolute_import, division, print_function import collections import itertools +import six + from cryptography import utils from cryptography.exceptions import ( InvalidTag, InternalError, AlreadyFinalized, UnsupportedCipher, @@ -259,11 +261,24 @@ class Backend(object): ) def _bn_to_int(self, bn): - hex_cdata = self._lib.BN_bn2hex(bn) - assert hex_cdata != self._ffi.NULL - hex_str = self._ffi.string(hex_cdata) - self._lib.OPENSSL_free(hex_cdata) - return int(hex_str, 16) + if six.PY3: + # Python 3 has constant time from_bytes, so use that. + + bn_num_bytes = (self._lib.BN_num_bits(bn) + 7) // 8 + bin_ptr = self._ffi.new("unsigned char[]", bn_num_bytes) + bin_len = self._lib.BN_bn2bin(bn, bin_ptr) + assert bin_len > 0 + assert bin_ptr != self._ffi.NULL + return int.from_bytes(self._ffi.buffer(bin_ptr)[:bin_len], "big") + + else: + # Under Python 2 the best we can do is hex() + + hex_cdata = self._lib.BN_bn2hex(bn) + assert hex_cdata != self._ffi.NULL + hex_str = self._ffi.string(hex_cdata) + self._lib.OPENSSL_free(hex_cdata) + return int(hex_str, 16) def _int_to_bn(self, num): """ @@ -272,12 +287,24 @@ class Backend(object): ownership of the object). Be sure to register it for GC if it will be discarded after use. """ - hex_num = hex(num).rstrip("L").lstrip("0x").encode("ascii") or b"0" - bn_ptr = self._ffi.new("BIGNUM **") - res = self._lib.BN_hex2bn(bn_ptr, hex_num) - assert res != 0 - assert bn_ptr[0] != self._ffi.NULL - return bn_ptr[0] + + if six.PY3: + # Python 3 has constant time to_bytes, so use that. + + binary = num.to_bytes(int(num.bit_length() / 8.0 + 1), "big") + bn_ptr = self._lib.BN_bin2bn(binary, len(binary), self._ffi.NULL) + assert bn_ptr != self._ffi.NULL + return bn_ptr + + else: + # Under Python 2 the best we can do is hex() + + hex_num = hex(num).rstrip("L").lstrip("0x").encode("ascii") or b"0" + bn_ptr = self._ffi.new("BIGNUM **") + res = self._lib.BN_hex2bn(bn_ptr, hex_num) + assert res != 0 + assert bn_ptr[0] != self._ffi.NULL + return bn_ptr[0] def generate_rsa_private_key(self, public_exponent, key_size): if public_exponent < 3: |