aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Gaynor <alex.gaynor@gmail.com>2014-03-17 14:08:33 -0700
committerAlex Gaynor <alex.gaynor@gmail.com>2014-03-17 14:08:33 -0700
commit2e08a76057d29d92bbc7be76c8acf92479ad76fd (patch)
tree5c1a16123633514a006925ca6b7d495ab9c57a83
parentd46e63c7305ce3d027b5d5d2fc81aeae4291f698 (diff)
parente28b3ad6dba208b8652b321ffc895f35d9822ef3 (diff)
downloadcryptography-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
-rw-r--r--cryptography/hazmat/backends/openssl/backend.py49
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: