aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cryptography/hazmat/bindings/openssl/bio.py6
-rw-r--r--src/cryptography/hazmat/bindings/openssl/cms.py61
-rw-r--r--src/cryptography/hazmat/bindings/openssl/ecdsa.py8
-rw-r--r--src/cryptography/hazmat/bindings/openssl/err.py8
-rw-r--r--src/cryptography/hazmat/bindings/openssl/ssl.py24
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/dsa.py32
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/ec.py26
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/rsa.py26
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/utils.py46
-rw-r--r--src/cryptography/hazmat/primitives/serialization.py77
-rw-r--r--src/cryptography/utils.py7
11 files changed, 296 insertions, 25 deletions
diff --git a/src/cryptography/hazmat/bindings/openssl/bio.py b/src/cryptography/hazmat/bindings/openssl/bio.py
index 854b2bc6..6cc1bcb2 100644
--- a/src/cryptography/hazmat/bindings/openssl/bio.py
+++ b/src/cryptography/hazmat/bindings/openssl/bio.py
@@ -17,7 +17,7 @@ struct bio_method_st {
int (*bwrite)(BIO *, const char *, int);
int (*bread)(BIO *, char *, int);
int (*bputs)(BIO *, const char *);
- int (*bgets)(BIO *, char*, int);
+ int (*bgets)(BIO *, char *, int);
long (*ctrl)(BIO *, int, long, void *);
int (*create)(BIO *);
int (*destroy)(BIO *);
@@ -27,7 +27,7 @@ struct bio_method_st {
typedef struct bio_method_st BIO_METHOD;
struct bio_st {
BIO_METHOD *method;
- long (*callback)(struct bio_st*, int, const char*, int, long, long);
+ long (*callback)(struct bio_st *, int, const char *, int, long, long);
char *cb_arg;
int init;
int shutdown;
@@ -89,7 +89,7 @@ static const int BIO_TYPE_FILTER;
"""
FUNCTIONS = """
-BIO* BIO_new(BIO_METHOD *);
+BIO *BIO_new(BIO_METHOD *);
int BIO_set(BIO *, BIO_METHOD *);
int BIO_free(BIO *);
void BIO_vfree(BIO *);
diff --git a/src/cryptography/hazmat/bindings/openssl/cms.py b/src/cryptography/hazmat/bindings/openssl/cms.py
index 7cbedf44..a43df5d9 100644
--- a/src/cryptography/hazmat/bindings/openssl/cms.py
+++ b/src/cryptography/hazmat/bindings/openssl/cms.py
@@ -25,6 +25,27 @@ typedef ... CMS_RevocationInfoChoice;
typedef ... CMS_RecipientInfo;
typedef ... CMS_ReceiptRequest;
typedef ... CMS_Receipt;
+
+static const int CMS_TEXT;
+static const int CMS_NOCERTS;
+static const int CMS_NO_CONTENT_VERIFY;
+static const int CMS_NO_ATTR_VERIFY;
+static const int CMS_NOSIGS;
+static const int CMS_NOINTERN;
+static const int CMS_NO_SIGNER_CERT_VERIFY;
+static const int CMS_NOVERIFY;
+static const int CMS_DETACHED;
+static const int CMS_BINARY;
+static const int CMS_NOATTR;
+static const int CMS_NOSMIMECAP;
+static const int CMS_NOOLDMIMETYPE;
+static const int CMS_CRLFEOL;
+static const int CMS_STREAM;
+static const int CMS_NOCRL;
+static const int CMS_PARTIAL;
+static const int CMS_REUSE_DIGEST;
+static const int CMS_USE_KEYID;
+static const int CMS_DEBUG_DECRYPT;
"""
FUNCTIONS = """
@@ -59,6 +80,26 @@ typedef void CMS_RevocationInfoChoice;
typedef void CMS_RecipientInfo;
typedef void CMS_ReceiptRequest;
typedef void CMS_Receipt;
+const long CMS_TEXT = 0;
+const long CMS_NOCERTS = 0;
+const long CMS_NO_CONTENT_VERIFY = 0;
+const long CMS_NO_ATTR_VERIFY = 0;
+const long CMS_NOSIGS = 0;
+const long CMS_NOINTERN = 0;
+const long CMS_NO_SIGNER_CERT_VERIFY = 0;
+const long CMS_NOVERIFY = 0;
+const long CMS_DETACHED = 0;
+const long CMS_BINARY = 0;
+const long CMS_NOATTR = 0;
+const long CMS_NOSMIMECAP = 0;
+const long CMS_NOOLDMIMETYPE = 0;
+const long CMS_CRLFEOL = 0;
+const long CMS_STREAM = 0;
+const long CMS_NOCRL = 0;
+const long CMS_PARTIAL = 0;
+const long CMS_REUSE_DIGEST = 0;
+const long CMS_USE_KEYID = 0;
+const long CMS_DEBUG_DECRYPT = 0;
BIO *(*BIO_new_CMS)(BIO *, CMS_ContentInfo *) = NULL;
int (*i2d_CMS_bio_stream)(BIO *, CMS_ContentInfo *, BIO *, int) = NULL;
int (*PEM_write_bio_CMS_stream)(BIO *, CMS_ContentInfo *, BIO *, int) = NULL;
@@ -87,5 +128,25 @@ CONDITIONAL_NAMES = {
"CMS_encrypt",
"CMS_decrypt",
"CMS_add1_signer",
+ "CMS_TEXT",
+ "CMS_NOCERTS",
+ "CMS_NO_CONTENT_VERIFY",
+ "CMS_NO_ATTR_VERIFY",
+ "CMS_NOSIGS",
+ "CMS_NOINTERN",
+ "CMS_NO_SIGNER_CERT_VERIFY",
+ "CMS_NOVERIFY",
+ "CMS_DETACHED",
+ "CMS_BINARY",
+ "CMS_NOATTR",
+ "CMS_NOSMIMECAP",
+ "CMS_NOOLDMIMETYPE",
+ "CMS_CRLFEOL",
+ "CMS_STREAM",
+ "CMS_NOCRL",
+ "CMS_PARTIAL",
+ "CMS_REUSE_DIGEST",
+ "CMS_USE_KEYID",
+ "CMS_DEBUG_DECRYPT",
]
}
diff --git a/src/cryptography/hazmat/bindings/openssl/ecdsa.py b/src/cryptography/hazmat/bindings/openssl/ecdsa.py
index 30866d11..db21025c 100644
--- a/src/cryptography/hazmat/bindings/openssl/ecdsa.py
+++ b/src/cryptography/hazmat/bindings/openssl/ecdsa.py
@@ -34,7 +34,7 @@ ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **s, const unsigned char **, long);
ECDSA_SIG *ECDSA_do_sign(const unsigned char *, int, EC_KEY *);
ECDSA_SIG *ECDSA_do_sign_ex(const unsigned char *, int, const BIGNUM *,
const BIGNUM *, EC_KEY *);
-int ECDSA_do_verify(const unsigned char *, int, const ECDSA_SIG *, EC_KEY*);
+int ECDSA_do_verify(const unsigned char *, int, const ECDSA_SIG *, EC_KEY *);
int ECDSA_sign_setup(EC_KEY *, BN_CTX *, BIGNUM **, BIGNUM **);
int ECDSA_sign(int, const unsigned char *, int, unsigned char *,
unsigned int *, EC_KEY *);
@@ -44,9 +44,9 @@ int ECDSA_verify(int, const unsigned char *, int, const unsigned char *, int,
EC_KEY *);
int ECDSA_size(const EC_KEY *);
-const ECDSA_METHOD* ECDSA_OpenSSL();
+const ECDSA_METHOD *ECDSA_OpenSSL();
void ECDSA_set_default_method(const ECDSA_METHOD *);
-const ECDSA_METHOD* ECDSA_get_default_method();
+const ECDSA_METHOD *ECDSA_get_default_method();
int ECDSA_get_ex_new_index(long, void *, CRYPTO_EX_new *,
CRYPTO_EX_dup *, CRYPTO_EX_free *);
int ECDSA_set_method(EC_KEY *, const ECDSA_METHOD *);
@@ -72,7 +72,7 @@ ECDSA_SIG* (*ECDSA_do_sign)(const unsigned char *, int, EC_KEY *eckey) = NULL;
ECDSA_SIG* (*ECDSA_do_sign_ex)(const unsigned char *, int, const BIGNUM *,
const BIGNUM *, EC_KEY *) = NULL;
int (*ECDSA_do_verify)(const unsigned char *, int, const ECDSA_SIG *,
- EC_KEY*) = NULL;
+ EC_KEY *) = NULL;
int (*ECDSA_sign_setup)(EC_KEY *, BN_CTX *, BIGNUM **, BIGNUM **) = NULL;
int (*ECDSA_sign)(int, const unsigned char *, int, unsigned char *,
unsigned int *, EC_KEY *) = NULL;
diff --git a/src/cryptography/hazmat/bindings/openssl/err.py b/src/cryptography/hazmat/bindings/openssl/err.py
index 1d43acd7..ec393c1b 100644
--- a/src/cryptography/hazmat/bindings/openssl/err.py
+++ b/src/cryptography/hazmat/bindings/openssl/err.py
@@ -231,11 +231,11 @@ FUNCTIONS = """
void ERR_load_crypto_strings(void);
void ERR_load_SSL_strings(void);
void ERR_free_strings(void);
-char* ERR_error_string(unsigned long, char *);
+char *ERR_error_string(unsigned long, char *);
void ERR_error_string_n(unsigned long, char *, size_t);
-const char* ERR_lib_error_string(unsigned long);
-const char* ERR_func_error_string(unsigned long);
-const char* ERR_reason_error_string(unsigned long);
+const char *ERR_lib_error_string(unsigned long);
+const char *ERR_func_error_string(unsigned long);
+const char *ERR_reason_error_string(unsigned long);
void ERR_print_errors(BIO *);
void ERR_print_errors_fp(FILE *);
unsigned long ERR_get_error(void);
diff --git a/src/cryptography/hazmat/bindings/openssl/ssl.py b/src/cryptography/hazmat/bindings/openssl/ssl.py
index 1aed28d5..9a48f586 100644
--- a/src/cryptography/hazmat/bindings/openssl/ssl.py
+++ b/src/cryptography/hazmat/bindings/openssl/ssl.py
@@ -15,7 +15,7 @@ TYPES = """
* Internally invented symbols to tell which versions of SSL/TLS are supported.
*/
static const long Cryptography_HAS_SSL2;
-static const long Cryptography_HAS_SSL3_METHOD;
+static const long Cryptography_HAS_SSL3;
static const long Cryptography_HAS_TLSv1_1;
static const long Cryptography_HAS_TLSv1_2;
static const long Cryptography_HAS_SECURE_RENEGOTIATION;
@@ -211,6 +211,8 @@ int SSL_CTX_use_certificate_file(SSL_CTX *, const char *, int);
int SSL_CTX_use_certificate_chain_file(SSL_CTX *, const char *);
int SSL_CTX_use_PrivateKey(SSL_CTX *, EVP_PKEY *);
int SSL_CTX_use_PrivateKey_file(SSL_CTX *, const char *, int);
+int SSL_CTX_check_private_key(const SSL_CTX *);
+
void SSL_CTX_set_cert_store(SSL_CTX *, X509_STORE *);
X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *);
int SSL_CTX_add_client_CA(SSL_CTX *, X509 *);
@@ -320,7 +322,7 @@ void (*SSL_CTX_get_info_callback(SSL_CTX *))(const SSL *, int, int);
RHEL/CentOS 5 this can be moved back to FUNCTIONS. */
SSL_CTX *SSL_set_SSL_CTX(SSL *, SSL_CTX *);
-const SSL_METHOD* Cryptography_SSL_CTX_get_method(const SSL_CTX*);
+const SSL_METHOD *Cryptography_SSL_CTX_get_method(const SSL_CTX *);
/* NPN APIs were introduced in OpenSSL 1.0.1. To continue to support earlier
* versions some special handling of these is necessary.
@@ -351,8 +353,8 @@ SSL_CIPHER *sk_SSL_CIPHER_value(Cryptography_STACK_OF_SSL_CIPHER *, int);
/* ALPN APIs were introduced in OpenSSL 1.0.2. To continue to support earlier
* versions some special handling of these is necessary.
*/
-int SSL_CTX_set_alpn_protos(SSL_CTX *, const unsigned char*, unsigned);
-int SSL_set_alpn_protos(SSL *, const unsigned char*, unsigned);
+int SSL_CTX_set_alpn_protos(SSL_CTX *, const unsigned char *, unsigned);
+int SSL_set_alpn_protos(SSL *, const unsigned char *, unsigned);
void SSL_CTX_set_alpn_select_cb(SSL_CTX *,
int (*) (SSL *,
const unsigned char **,
@@ -385,13 +387,13 @@ SSL_METHOD* (*SSLv2_server_method)(void) = NULL;
static const long Cryptography_HAS_SSL2 = 1;
#endif
-#ifdef OPENSSL_NO_SSL3_METHOD
-static const long Cryptography_HAS_SSL3_METHOD = 0;
+#ifdef OPENSSL_NO_SSL3
+static const long Cryptography_HAS_SSL3 = 0;
SSL_METHOD* (*SSLv3_method)(void) = NULL;
SSL_METHOD* (*SSLv3_client_method)(void) = NULL;
SSL_METHOD* (*SSLv3_server_method)(void) = NULL;
#else
-static const long Cryptography_HAS_SSL3_METHOD = 1;
+static const long Cryptography_HAS_SSL3 = 1;
#endif
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
@@ -485,7 +487,7 @@ static const long Cryptography_HAS_NETBSD_D1_METH = 1;
#endif
/* Workaround for #794 caused by cffi const** bug. */
-const SSL_METHOD* Cryptography_SSL_CTX_get_method(const SSL_CTX* ctx) {
+const SSL_METHOD *Cryptography_SSL_CTX_get_method(const SSL_CTX *ctx) {
return ctx->method;
}
@@ -523,9 +525,9 @@ static const long Cryptography_HAS_NEXTPROTONEG = 1;
/* ALPN was added in OpenSSL 1.0.2. */
#if OPENSSL_VERSION_NUMBER < 0x10002001L
int (*SSL_CTX_set_alpn_protos)(SSL_CTX *,
- const unsigned char*,
+ const unsigned char *,
unsigned) = NULL;
-int (*SSL_set_alpn_protos)(SSL *, const unsigned char*, unsigned) = NULL;
+int (*SSL_set_alpn_protos)(SSL *, const unsigned char *, unsigned) = NULL;
void (*SSL_CTX_set_alpn_select_cb)(SSL_CTX *,
int (*) (SSL *,
const unsigned char **,
@@ -564,7 +566,7 @@ CONDITIONAL_NAMES = {
"SSLv2_server_method",
],
- "Cryptography_HAS_SSL3_METHOD": [
+ "Cryptography_HAS_SSL3": [
"SSLv3_method",
"SSLv3_client_method",
"SSLv3_server_method",
diff --git a/src/cryptography/hazmat/primitives/asymmetric/dsa.py b/src/cryptography/hazmat/primitives/asymmetric/dsa.py
index 5d942e04..9b06f3e6 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/dsa.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/dsa.py
@@ -59,6 +59,15 @@ class DSAParameterNumbers(object):
def parameters(self, backend):
return backend.load_dsa_parameter_numbers(self)
+ def __eq__(self, other):
+ if not isinstance(other, DSAParameterNumbers):
+ return NotImplemented
+
+ return self.p == other.p and self.q == other.q and self.g == other.g
+
+ def __ne__(self, other):
+ return not self == other
+
class DSAPublicNumbers(object):
def __init__(self, y, parameter_numbers):
@@ -79,6 +88,18 @@ class DSAPublicNumbers(object):
def public_key(self, backend):
return backend.load_dsa_public_numbers(self)
+ def __eq__(self, other):
+ if not isinstance(other, DSAPublicNumbers):
+ return NotImplemented
+
+ return (
+ self.y == other.y and
+ self.parameter_numbers == other.parameter_numbers
+ )
+
+ def __ne__(self, other):
+ return not self == other
+
class DSAPrivateNumbers(object):
def __init__(self, x, public_numbers):
@@ -97,3 +118,14 @@ class DSAPrivateNumbers(object):
def private_key(self, backend):
return backend.load_dsa_private_numbers(self)
+
+ def __eq__(self, other):
+ if not isinstance(other, DSAPrivateNumbers):
+ return NotImplemented
+
+ return (
+ self.x == other.x and self.public_numbers == other.public_numbers
+ )
+
+ def __ne__(self, other):
+ return not self == other
diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py
index d9c41c19..202f1c97 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/ec.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py
@@ -161,6 +161,20 @@ class EllipticCurvePublicNumbers(object):
x = utils.read_only_property("_x")
y = utils.read_only_property("_y")
+ def __eq__(self, other):
+ if not isinstance(other, EllipticCurvePublicNumbers):
+ return NotImplemented
+
+ return (
+ self.x == other.x and
+ self.y == other.y and
+ self.curve.name == other.curve.name and
+ self.curve.key_size == other.curve.key_size
+ )
+
+ def __ne__(self, other):
+ return not self == other
+
class EllipticCurvePrivateNumbers(object):
def __init__(self, private_value, public_numbers):
@@ -184,3 +198,15 @@ class EllipticCurvePrivateNumbers(object):
private_value = utils.read_only_property("_private_value")
public_numbers = utils.read_only_property("_public_numbers")
+
+ def __eq__(self, other):
+ if not isinstance(other, EllipticCurvePrivateNumbers):
+ return NotImplemented
+
+ return (
+ self.private_value == other.private_value and
+ self.public_numbers == other.public_numbers
+ )
+
+ def __ne__(self, other):
+ return not self == other
diff --git a/src/cryptography/hazmat/primitives/asymmetric/rsa.py b/src/cryptography/hazmat/primitives/asymmetric/rsa.py
index 6aeed006..0cc6b22b 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/rsa.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/rsa.py
@@ -160,6 +160,23 @@ class RSAPrivateNumbers(object):
def private_key(self, backend):
return backend.load_rsa_private_numbers(self)
+ def __eq__(self, other):
+ if not isinstance(other, RSAPrivateNumbers):
+ return NotImplemented
+
+ return (
+ self.p == other.p and
+ self.q == other.q and
+ self.d == other.d and
+ self.dmp1 == other.dmp1 and
+ self.dmq1 == other.dmq1 and
+ self.iqmp == other.iqmp and
+ self.public_numbers == other.public_numbers
+ )
+
+ def __ne__(self, other):
+ return not self == other
+
class RSAPublicNumbers(object):
def __init__(self, e, n):
@@ -180,3 +197,12 @@ class RSAPublicNumbers(object):
def __repr__(self):
return "<RSAPublicNumbers(e={0}, n={1})>".format(self._e, self._n)
+
+ def __eq__(self, other):
+ if not isinstance(other, RSAPublicNumbers):
+ return NotImplemented
+
+ return self.e == other.e and self.n == other.n
+
+ def __ne__(self, other):
+ return not self == other
diff --git a/src/cryptography/hazmat/primitives/asymmetric/utils.py b/src/cryptography/hazmat/primitives/asymmetric/utils.py
new file mode 100644
index 00000000..71f4ff8e
--- /dev/null
+++ b/src/cryptography/hazmat/primitives/asymmetric/utils.py
@@ -0,0 +1,46 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+from pyasn1.codec.der import decoder, encoder
+from pyasn1.error import PyAsn1Error
+from pyasn1.type import namedtype, univ
+
+import six
+
+
+class _DSSSigValue(univ.Sequence):
+ componentType = namedtype.NamedTypes(
+ namedtype.NamedType('r', univ.Integer()),
+ namedtype.NamedType('s', univ.Integer())
+ )
+
+
+def decode_rfc6979_signature(signature):
+ try:
+ data, remaining = decoder.decode(signature, asn1Spec=_DSSSigValue())
+ except PyAsn1Error:
+ raise ValueError("Invalid signature data. Unable to decode ASN.1")
+
+ if remaining:
+ raise ValueError(
+ "The signature contains bytes after the end of the ASN.1 sequence."
+ )
+ r = int(data.getComponentByName('r'))
+ s = int(data.getComponentByName('s'))
+ return (r, s)
+
+
+def encode_rfc6979_signature(r, s):
+ if (
+ not isinstance(r, six.integer_types) or
+ not isinstance(s, six.integer_types)
+ ):
+ raise ValueError("Both r and s must be integers")
+
+ sig = _DSSSigValue()
+ sig.setComponentByName('r', r)
+ sig.setComponentByName('s', s)
+ return encoder.encode(sig)
diff --git a/src/cryptography/hazmat/primitives/serialization.py b/src/cryptography/hazmat/primitives/serialization.py
index b9cf5967..0dbbc85c 100644
--- a/src/cryptography/hazmat/primitives/serialization.py
+++ b/src/cryptography/hazmat/primitives/serialization.py
@@ -4,9 +4,13 @@
from __future__ import absolute_import, division, print_function
+import base64
+import struct
import warnings
from cryptography import utils
+from cryptography.exceptions import UnsupportedAlgorithm
+from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicNumbers
def load_pem_traditional_openssl_private_key(data, password, backend):
@@ -39,3 +43,76 @@ def load_pem_private_key(data, password, backend):
def load_pem_public_key(data, backend):
return backend.load_pem_public_key(data)
+
+
+def load_ssh_public_key(data, backend):
+ key_parts = data.split(b' ')
+
+ if len(key_parts) != 2 and len(key_parts) != 3:
+ raise ValueError(
+ 'Key is not in the proper format or contains extra data.')
+
+ key_type = key_parts[0]
+ key_body = key_parts[1]
+
+ if not key_type.startswith(b'ssh-'):
+ raise ValueError('SSH-formatted keys must begin with \'ssh-\'.')
+
+ if not key_type.startswith(b'ssh-rsa'):
+ raise UnsupportedAlgorithm('Only RSA keys are currently supported.')
+
+ return _load_ssh_rsa_public_key(key_body, backend)
+
+
+def _load_ssh_rsa_public_key(key_body, backend):
+ data = base64.b64decode(key_body)
+
+ key_type, rest = _read_next_string(data)
+ e, rest = _read_next_mpint(rest)
+ n, rest = _read_next_mpint(rest)
+
+ if key_type != b'ssh-rsa':
+ raise ValueError(
+ 'Key header and key body contain different key type values.')
+
+ if rest:
+ raise ValueError('Key body contains extra bytes.')
+
+ return backend.load_rsa_public_numbers(RSAPublicNumbers(e, n))
+
+
+def _read_next_string(data):
+ """Retrieves the next RFC 4251 string value from the data."""
+ str_len, = struct.unpack('>I', data[:4])
+ return data[4:4 + str_len], data[4 + str_len:]
+
+
+def _read_next_mpint(data):
+ """
+ Reads the next mpint from the data.
+
+ Currently, all mpints are interpreted as unsigned.
+ """
+ mpint_data, rest = _read_next_string(data)
+
+ return _int_from_bytes(mpint_data, byteorder='big', signed=False), rest
+
+
+if hasattr(int, "from_bytes"):
+ _int_from_bytes = int.from_bytes
+else:
+ def _int_from_bytes(data, byteorder, signed=False):
+ assert byteorder == 'big'
+ assert not signed
+
+ if len(data) % 4 != 0:
+ data = (b'\x00' * (4 - (len(data) % 4))) + data
+
+ result = 0
+
+ while len(data) > 0:
+ digit, = struct.unpack('>I', data[:4])
+ result = (result << 32) + digit
+ data = data[4:]
+
+ return result
diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py
index 63464dfa..78f73464 100644
--- a/src/cryptography/utils.py
+++ b/src/cryptography/utils.py
@@ -48,8 +48,9 @@ def verify_interface(iface, klass):
)
-def bit_length(x):
- if sys.version_info >= (2, 7):
+if sys.version_info >= (2, 7):
+ def bit_length(x):
return x.bit_length()
- else:
+else:
+ def bit_length(x):
return len(bin(x)) - (2 + (x <= 0))