aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml8
-rwxr-xr-x.travis/install.sh12
-rw-r--r--CHANGELOG.rst7
-rw-r--r--cryptography/hazmat/backends/openssl/backend.py49
-rw-r--r--cryptography/hazmat/bindings/utils.py38
-rw-r--r--cryptography/hazmat/primitives/interfaces.py6
-rw-r--r--docs/hazmat/primitives/interfaces.rst8
-rw-r--r--setup.py1
-rw-r--r--tests/hazmat/bindings/test_utils.py25
-rw-r--r--tox.ini2
10 files changed, 131 insertions, 25 deletions
diff --git a/.travis.yml b/.travis.yml
index b7fa090e..7d5663d8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -16,11 +16,13 @@ env:
- TOX_ENV=py27
- TOX_ENV=py32
- TOX_ENV=py33
+ - TOX_ENV=py34
- TOX_ENV=pypy
- TOX_ENV=py26 OPENSSL=0.9.8
- TOX_ENV=py27 OPENSSL=0.9.8
- TOX_ENV=py32 OPENSSL=0.9.8
- TOX_ENV=py33 OPENSSL=0.9.8
+ - TOX_ENV=py34 OPENSSL=0.9.8
- TOX_ENV=pypy OPENSSL=0.9.8
- TOX_ENV=docs
- TOX_ENV=pep8
@@ -60,6 +62,9 @@ matrix:
env: TOX_ENV=py33
compiler: gcc
- os: osx
+ env: TOX_ENV=py34
+ compiler: gcc
+ - os: osx
env: TOX_ENV=pypy
compiler: gcc
- os: osx
@@ -75,6 +80,9 @@ matrix:
env: TOX_ENV=py33 OPENSSL=0.9.8
compiler: gcc
- os: osx
+ env: TOX_ENV=py34 OPENSSL=0.9.8
+ compiler: gcc
+ - os: osx
env: TOX_ENV=pypy OPENSSL=0.9.8
compiler: gcc
- os: osx
diff --git a/.travis/install.sh b/.travis/install.sh
index 7e77fc87..58d7404d 100755
--- a/.travis/install.sh
+++ b/.travis/install.sh
@@ -52,8 +52,13 @@ if [[ "$(uname -s)" == "Darwin" ]]; then
pip install virtualenv
;;
py33)
- pyenv install 3.3.2
- pyenv global 3.3.2
+ pyenv install 3.3.5
+ pyenv global 3.3.5
+ pip install virtualenv
+ ;;
+ py34)
+ pyenv install 3.4.0
+ pyenv global 3.4.0
pip install virtualenv
;;
docs)
@@ -78,6 +83,9 @@ else
py33)
sudo apt-get install python3.3 python3.3-dev
;;
+ py34)
+ sudo apt-get install python3.4 python3.4-dev
+ ;;
py3pep8)
sudo apt-get install python3.3 python3.3-dev
;;
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 391427d7..abbea9fa 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,8 +1,10 @@
Changelog
=========
-0.3 - 2014-XX-XX
-~~~~~~~~~~~~~~~~
+0.3 - `master`_
+~~~~~~~~~~~~~~~
+
+.. note:: This version is not yet released and is under active development.
* Added :class:`~cryptography.hazmat.primitives.twofactor.hotp.HOTP`.
* Added :class:`~cryptography.hazmat.primitives.twofactor.totp.TOTP`.
@@ -40,3 +42,4 @@ Changelog
* Initial release.
+.. _`master`: https://github.com/pyca/cryptography/
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index 9b8e8f0f..7c058f58 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,
@@ -262,11 +264,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):
"""
@@ -275,12 +290,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:
diff --git a/cryptography/hazmat/bindings/utils.py b/cryptography/hazmat/bindings/utils.py
index b8253483..318b82bb 100644
--- a/cryptography/hazmat/bindings/utils.py
+++ b/cryptography/hazmat/bindings/utils.py
@@ -13,6 +13,8 @@
from __future__ import absolute_import, division, print_function
+import binascii
+
import sys
import cffi
@@ -50,7 +52,8 @@ def build_ffi(module_prefix, modules, pre_include, post_include, libraries):
includes.append(module.INCLUDES)
customizations.append(module.CUSTOMIZATIONS)
- ffi.cdef("\n".join(types + functions + macros))
+ cdef_sources = types + functions + macros
+ ffi.cdef("\n".join(cdef_sources))
# We include functions here so that if we got any of their definitions
# wrong, the underlying C compiler will explode. In C you are allowed
@@ -60,14 +63,16 @@ def build_ffi(module_prefix, modules, pre_include, post_include, libraries):
# is legal, but the following will fail to compile:
# int foo(int);
# int foo(short);
+ source = "\n".join(
+ [pre_include] +
+ includes +
+ [post_include] +
+ functions +
+ customizations
+ )
lib = ffi.verify(
- source="\n".join(
- [pre_include] +
- includes +
- [post_include] +
- functions +
- customizations
- ),
+ source=source,
+ modulename=_create_modulename(cdef_sources, source, sys.version),
libraries=libraries,
ext_package="cryptography",
)
@@ -81,3 +86,20 @@ def build_ffi(module_prefix, modules, pre_include, post_include, libraries):
delattr(lib, name)
return ffi, lib
+
+
+def _create_modulename(cdef_sources, source, sys_version):
+ """
+ cffi creates a modulename internally that incorporates the cffi version.
+ This will cause cryptography's wheels to break when the version of cffi
+ the user has does not match what was used when building the wheel. To
+ resolve this we build our own modulename that uses most of the same code
+ from cffi but elides the version key.
+ """
+ key = '\x00'.join([sys_version[:3], source] + cdef_sources)
+ key = key.encode('utf-8')
+ k1 = hex(binascii.crc32(key[0::2]) & 0xffffffff)
+ k1 = k1.lstrip('0x').rstrip('L')
+ k2 = hex(binascii.crc32(key[1::2]) & 0xffffffff)
+ k2 = k2.lstrip('0').rstrip('L')
+ return '_Cryptography_cffi_{0}{1}'.format(k1, k2)
diff --git a/cryptography/hazmat/primitives/interfaces.py b/cryptography/hazmat/primitives/interfaces.py
index 3824bcde..eab48b4d 100644
--- a/cryptography/hazmat/primitives/interfaces.py
+++ b/cryptography/hazmat/primitives/interfaces.py
@@ -367,6 +367,12 @@ class DSAPrivateKey(six.with_metaclass(abc.ABCMeta)):
class DSAPublicKey(six.with_metaclass(abc.ABCMeta)):
@abc.abstractproperty
+ def key_size(self):
+ """
+ The bit length of the prime modulus.
+ """
+
+ @abc.abstractproperty
def y(self):
"""
The public key.
diff --git a/docs/hazmat/primitives/interfaces.rst b/docs/hazmat/primitives/interfaces.rst
index cc2a3000..cefd81ac 100644
--- a/docs/hazmat/primitives/interfaces.rst
+++ b/docs/hazmat/primitives/interfaces.rst
@@ -323,7 +323,13 @@ Asymmetric Interfaces
.. versionadded:: 0.3
- A `DSA`_ private key.
+ A `DSA`_ public key.
+
+ .. attribute:: key_size
+
+ :type: int
+
+ The bit length of the modulus.
.. method:: parameters()
diff --git a/setup.py b/setup.py
index 7f7ba9ef..f8b84a3b 100644
--- a/setup.py
+++ b/setup.py
@@ -119,6 +119,7 @@ setup(
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.2",
"Programming Language :: Python :: 3.3",
+ "Programming Language :: Python :: 3.4",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Topic :: Security :: Cryptography",
diff --git a/tests/hazmat/bindings/test_utils.py b/tests/hazmat/bindings/test_utils.py
new file mode 100644
index 00000000..0d5b34de
--- /dev/null
+++ b/tests/hazmat/bindings/test_utils.py
@@ -0,0 +1,25 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import absolute_import, division, print_function
+
+from cryptography.hazmat.bindings import utils
+
+
+def test_create_modulename():
+ cdef_sources = ["cdef sources go here"]
+ source = "source code"
+ name = utils._create_modulename(cdef_sources, source, "2.7")
+ assert name == "_Cryptography_cffi_bcba7f4bx4a14b588"
+ name = utils._create_modulename(cdef_sources, source, "3.2")
+ assert name == "_Cryptography_cffi_a7462526x4a14b588"
diff --git a/tox.ini b/tox.ini
index 3ee449f1..72884654 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
[tox]
-envlist = py26,py27,pypy,py32,py33,docs,pep8,py3pep8
+envlist = py26,py27,pypy,py32,py33,py34,docs,pep8,py3pep8
[testenv]
deps =