From 9604d9e9839703636843595b52a4f01f3de8e2fe Mon Sep 17 00:00:00 2001 From: Dominic Chen Date: Sat, 10 Oct 2015 05:13:31 +0000 Subject: add shebang for setup.py scripts --- setup.py | 2 ++ vectors/setup.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/setup.py b/setup.py index 7afa84c3..9c97e1dd 100644 --- a/setup.py +++ b/setup.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + # 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. diff --git a/vectors/setup.py b/vectors/setup.py index 53ec82eb..bf02e389 100644 --- a/vectors/setup.py +++ b/vectors/setup.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + # 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. -- cgit v1.2.3 From 937aa47a99d488687febe25b813b350b5f492b4a Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 11 Oct 2015 12:09:27 -0500 Subject: update docs to point at newer, fancier openssl builder --- docs/installation.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/installation.rst b/docs/installation.rst index 5d629e9f..7c4b91e9 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -46,7 +46,9 @@ dependencies are included. Just run If you prefer to compile it yourself you'll need to have OpenSSL installed. You can compile OpenSSL yourself as well or use the binaries we build for our -release infrastructure (`32-bit`_ and `64-bit`_). Wherever you place your copy +release infrastructure (`openssl-release`_). Be sure to download the proper +version for your architecture and Python (2010 works for Python 2.6, 2.7, 3.3, +and 3.4 while 2015 is required for 3.5). Wherever you place your copy of OpenSSL you'll need to set the ``LIB`` and ``INCLUDE`` environment variables to include the proper locations. For example: @@ -250,8 +252,7 @@ information, consult `Greg Wilson's blog post`_ on the subject. .. _`Homebrew`: http://brew.sh .. _`MacPorts`: https://www.macports.org -.. _`32-bit`: https://jenkins.cryptography.io/job/openssl-win32-release/ -.. _`64-bit`: https://jenkins.cryptography.io/job/openssl-win64-release/ +.. _`openssl-release`: https://jenkins.cryptography.io/job/openssl-release/ .. _`bug in conda`: https://github.com/conda/conda-recipes/issues/110 .. _`Greg Wilson's blog post`: http://software-carpentry.org/blog/2014/04/mr-biczo-was-right.html .. _virtualenv: https://virtualenv.pypa.io/en/latest/ -- cgit v1.2.3 From 06f360feedb740aa0b4db7683d02accd14bc1732 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 12 Oct 2015 11:00:30 -0500 Subject: add some links to public key loading in the RSA/DSA verification sections --- docs/hazmat/primitives/asymmetric/dsa.rst | 8 ++++++-- docs/hazmat/primitives/asymmetric/rsa.rst | 10 +++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/docs/hazmat/primitives/asymmetric/dsa.rst b/docs/hazmat/primitives/asymmetric/dsa.rst index 4eb17e30..9431ff57 100644 --- a/docs/hazmat/primitives/asymmetric/dsa.rst +++ b/docs/hazmat/primitives/asymmetric/dsa.rst @@ -86,8 +86,12 @@ described in :rfc:`3279`. This can be decoded using Verification ~~~~~~~~~~~~ -Using a :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey` -provider. +Verification is performed using a +:class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey` provider. +Public keys are obtained by using +:func:`~cryptography.hazmat.primitives.serialization.load_pem_public_key`, +:func:`~cryptography.hazmat.primitives.serialization.load_der_public_key`, or +:meth:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey.public_key`. .. doctest:: diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst index f88750cf..de8b2fd0 100644 --- a/docs/hazmat/primitives/asymmetric/rsa.rst +++ b/docs/hazmat/primitives/asymmetric/rsa.rst @@ -163,9 +163,13 @@ Verification ~~~~~~~~~~~~ The previous section describes what to do if you have a private key and want to -sign something. If you have a public key, a message, and a signature, you can -check that the public key genuinely was used to sign that specific message. You -also need to know which signing algorithm was used: +sign something. If you have a public key, a message, a signature, and the +signing algorithm that was used you can check that the private key associated +with a given public key was used to sign that specific message. You can obtain +a public key to use in verification using +:func:`~cryptography.hazmat.primitives.serialization.load_pem_public_key`, +:func:`~cryptography.hazmat.primitives.serialization.load_der_public_key`, or +:meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey.public_key`. .. doctest:: -- cgit v1.2.3 From 3697db262cb5f9c61840139f37c34e24c3dfb7d1 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 12 Oct 2015 12:42:08 -0500 Subject: address review comments --- docs/hazmat/primitives/asymmetric/dsa.rst | 6 ++++-- docs/hazmat/primitives/asymmetric/rsa.rst | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/hazmat/primitives/asymmetric/dsa.rst b/docs/hazmat/primitives/asymmetric/dsa.rst index 9431ff57..1429cb09 100644 --- a/docs/hazmat/primitives/asymmetric/dsa.rst +++ b/docs/hazmat/primitives/asymmetric/dsa.rst @@ -88,9 +88,11 @@ Verification Verification is performed using a :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey` provider. -Public keys are obtained by using +You can get a public key object with :func:`~cryptography.hazmat.primitives.serialization.load_pem_public_key`, -:func:`~cryptography.hazmat.primitives.serialization.load_der_public_key`, or +:func:`~cryptography.hazmat.primitives.serialization.load_der_public_key`, +:meth:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicNumbers.public_key` +, or :meth:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey.public_key`. .. doctest:: diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst index de8b2fd0..bc2402de 100644 --- a/docs/hazmat/primitives/asymmetric/rsa.rst +++ b/docs/hazmat/primitives/asymmetric/rsa.rst @@ -168,7 +168,9 @@ signing algorithm that was used you can check that the private key associated with a given public key was used to sign that specific message. You can obtain a public key to use in verification using :func:`~cryptography.hazmat.primitives.serialization.load_pem_public_key`, -:func:`~cryptography.hazmat.primitives.serialization.load_der_public_key`, or +:func:`~cryptography.hazmat.primitives.serialization.load_der_public_key`, +:meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicNumbers.public_key` +, or :meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey.public_key`. .. doctest:: -- cgit v1.2.3 From 00f94097219d14036d7172994e54dc6a6d2fa8f3 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 10 Oct 2015 15:42:17 -0400 Subject: Catch Invalid X or Y points and raise a ValueError Signed-off-by: Simo Sorce --- .../hazmat/backends/openssl/backend.py | 8 ++++-- tests/hazmat/primitives/test_ec.py | 29 ++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index ac025e95..0d3b3dd4 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -1776,9 +1776,13 @@ class Backend(object): self.openssl_assert(res == 1) res = self._lib.BN_cmp(bn_x, check_x) - self.openssl_assert(res == 0) + if res != 0: + self._consume_errors() + raise ValueError("Invalid EC Key X point.") res = self._lib.BN_cmp(bn_y, check_y) - self.openssl_assert(res == 0) + if res != 0: + self._consume_errors() + raise ValueError("Invalid EC Key Y point.") res = self._lib.EC_KEY_set_public_key(ctx, point) self.openssl_assert(res == 1) diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py index 59bdc525..5467464a 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -285,6 +285,35 @@ class TestECDSAVectors(object): with pytest.raises(ValueError): numbers.private_key(backend) + def test_load_invalid_public_ec_key_from_numbers(self, backend): + _skip_curve_unsupported(backend, ec.SECP521R1()) + + # Bad X coordinate + numbers = ec.EllipticCurvePublicNumbers( + int("000003647356b91f8ace114c7247ecf4f4a622553fc025e04a178f179ef27" + "9090c184af678a4c78f635483bdd8aa544851c6ef291c1f0d6a241ebfd145" + "77d1d30d9903ce", 16), + int("000001499bc7e079322ea0fcfbd6b40103fa6a1536c2257b182db0df4b369" + "6ec643adf100eb4f2025d1b873f82e5a475d6e4400ba777090eeb4563a115" + "09e4c87319dc26", 16), + ec.SECP521R1() + ) + with pytest.raises(ValueError): + numbers.public_key(backend) + + # Bad Y coordinate + numbers = ec.EllipticCurvePublicNumbers( + int("0000019aadc221cc0525118ab6d5aa1f64720603de0be128cbfea0b381ad8" + "02a2facc6370bb58cf88b3f0c692bc654ee19d6cad198f10d4b681b396f20" + "d2e40603fa945b", 16), + int("0000025da392803a320717a08d4cb3dea932039badff363b71bdb8064e726" + "6c7f4f4b748d4d425347fc33e3885d34b750fa7fcd5691f4d90c89522ce33" + "feff5db10088a5", 16), + ec.SECP521R1() + ) + with pytest.raises(ValueError): + numbers.public_key(backend) + @pytest.mark.parametrize( "vector", itertools.chain( -- cgit v1.2.3 From 87494d19398334c328f0a0c9bd750f66c14da8e1 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 12 Oct 2015 20:46:09 -0700 Subject: Indicate the return type of CertificateBuilder.sign --- docs/x509/reference.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst index 87383db1..c8c58efb 100644 --- a/docs/x509/reference.rst +++ b/docs/x509/reference.rst @@ -503,6 +503,8 @@ X.509 Certificate Builder handled by whoever reads the certificate. .. method:: sign(private_key, algorithm, backend) + + :type: :class:`~cryptography.x509.Certificate` Sign the certificate using the CA's private key. -- cgit v1.2.3 From 9ed312baba7f4024d207a5fc56c3050b8d55b227 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 12 Oct 2015 20:51:34 -0700 Subject: use :returns: and put annotation in the correct place --- docs/x509/reference.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst index c8c58efb..15078e9d 100644 --- a/docs/x509/reference.rst +++ b/docs/x509/reference.rst @@ -503,8 +503,6 @@ X.509 Certificate Builder handled by whoever reads the certificate. .. method:: sign(private_key, algorithm, backend) - - :type: :class:`~cryptography.x509.Certificate` Sign the certificate using the CA's private key. @@ -522,6 +520,8 @@ X.509 Certificate Builder Must support the :class:`~cryptography.hazmat.backends.interfaces.X509Backend` interface. + + :returns: :class:`~cryptography.x509.Certificate` X.509 CSR (Certificate Signing Request) Object -- cgit v1.2.3 From 4c2561afecdbd25226f093698404facb8b49abee Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 12 Oct 2015 23:53:39 -0400 Subject: Use the right reST syntax for these --- docs/x509/reference.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst index 87383db1..25e3e5db 100644 --- a/docs/x509/reference.rst +++ b/docs/x509/reference.rst @@ -226,13 +226,13 @@ X.509 Certificate Object .. method:: public_key() - :type: + The public key associated with the certificate. + + :returns: :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey` or :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey` or :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey` - The public key associated with the certificate. - .. doctest:: >>> from cryptography.hazmat.primitives.asymmetric import rsa @@ -531,13 +531,13 @@ X.509 CSR (Certificate Signing Request) Object .. method:: public_key() - :type: + The public key associated with the request. + + :returns: :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey` or :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey` or :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey` - The public key associated with the request. - .. doctest:: >>> from cryptography.hazmat.primitives.asymmetric import rsa -- cgit v1.2.3 From 7f1aa4e9d4a766a7354d3e8f488bca0ec9f8e9da Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 12 Oct 2015 20:59:07 -0700 Subject: nuke trailing whitespace --- docs/x509/reference.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst index 15078e9d..72603f42 100644 --- a/docs/x509/reference.rst +++ b/docs/x509/reference.rst @@ -520,7 +520,7 @@ X.509 Certificate Builder Must support the :class:`~cryptography.hazmat.backends.interfaces.X509Backend` interface. - + :returns: :class:`~cryptography.x509.Certificate` -- cgit v1.2.3 From 90ddd354784ffcf8723d4a7b81e9b399bc2a6c9c Mon Sep 17 00:00:00 2001 From: Dominic Chen Date: Mon, 12 Oct 2015 18:50:21 +0000 Subject: extend pkcs7 openssl bindings --- src/_cffi_src/build_openssl.py | 4 ++-- src/_cffi_src/openssl/pkcs7.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/_cffi_src/build_openssl.py b/src/_cffi_src/build_openssl.py index defa69d3..c856e3d9 100644 --- a/src/_cffi_src/build_openssl.py +++ b/src/_cffi_src/build_openssl.py @@ -79,7 +79,6 @@ ffi = build_ffi_for_binding( "objects", "opensslv", "pem", - "pkcs7", "pkcs12", "rand", "rsa", @@ -87,7 +86,8 @@ ffi = build_ffi_for_binding( "x509", "x509name", "x509v3", - "x509_vfy" + "x509_vfy", + "pkcs7", ], pre_include=_OSX_PRE_INCLUDE, post_include=_OSX_POST_INCLUDE, diff --git a/src/_cffi_src/openssl/pkcs7.py b/src/_cffi_src/openssl/pkcs7.py index 5d6ee45f..0dd89582 100644 --- a/src/_cffi_src/openssl/pkcs7.py +++ b/src/_cffi_src/openssl/pkcs7.py @@ -9,8 +9,34 @@ INCLUDES = """ """ TYPES = """ +typedef struct { + Cryptography_STACK_OF_X509 *cert; + Cryptography_STACK_OF_X509_CRL *crl; + ...; +} PKCS7_SIGNED; + +typedef struct { + Cryptography_STACK_OF_X509 *cert; + Cryptography_STACK_OF_X509_CRL *crl; + ...; +} PKCS7_SIGN_ENVELOPE; + +typedef ... PKCS7_DIGEST; +typedef ... PKCS7_ENCRYPT; +typedef ... PKCS7_ENVELOPE; + typedef struct { ASN1_OBJECT *type; + union { + char *ptr; + ASN1_OCTET_STRING *data; + PKCS7_SIGNED *sign; + PKCS7_ENVELOPE *enveloped; + PKCS7_SIGN_ENVELOPE *signed_and_enveloped; + PKCS7_DIGEST *digest; + PKCS7_ENCRYPT *encrypted; + ASN1_TYPE *other; + } d; ...; } PKCS7; @@ -44,13 +70,17 @@ Cryptography_STACK_OF_X509 *PKCS7_get0_signers(PKCS7 *, PKCS7 *PKCS7_encrypt(Cryptography_STACK_OF_X509 *, BIO *, const EVP_CIPHER *, int); int PKCS7_decrypt(PKCS7 *, EVP_PKEY *, X509 *, BIO *, int); + +BIO *PKCS7_dataInit(PKCS7 *, BIO *); """ MACROS = """ +int PKCS7_type_is_encrypted(PKCS7 *); int PKCS7_type_is_signed(PKCS7 *); int PKCS7_type_is_enveloped(PKCS7 *); int PKCS7_type_is_signedAndEnveloped(PKCS7 *); int PKCS7_type_is_data(PKCS7 *); +int PKCS7_type_is_digest(PKCS7 *); """ CUSTOMIZATIONS = "" -- cgit v1.2.3 From 6e3b155bb684bb036fba277756a0ca47ce551443 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 13 Oct 2015 14:45:21 -0400 Subject: Fix load_kasvs_ecdh_vectors() COUNT sourcing COUNT is a decimal number in test files, but was erroneously read and converted as if the source was a hexadecimal number. Fix the loader and test the fix. Signed-off-by: Simo Sorce --- tests/test_utils.py | 4 ++-- tests/utils.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index 04182a06..72e20725 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -3363,7 +3363,7 @@ def test_load_kasvs_ecdh_kdf_vectors(): [EB - SHA224] - COUNT = 0 + COUNT = 50 dsCAVS = 540904b67b3716823dd621ed72ad3dbc615887b4f56f910b78a57199 QsCAVSx = 28e5f3a72d8f6b8499dd1bcdfceafcecec68a0d715789bcf4b55fe15 QsCAVSy = 8c8006a7da7c1a19f5328d7e865522b0c0dfb9a29b2c46dc96590d2a @@ -3385,7 +3385,7 @@ ffdfa60dd7 expected = [ {'errno': 12, 'fail': True, - 'COUNT': 0, + 'COUNT': 50, 'CAVS': { 'd': int("540904b67b3716823dd621ed72ad3dbc615887b4f56f910b" "78a57199", 16), diff --git a/tests/utils.py b/tests/utils.py index cc3f9fcc..3970109e 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -722,7 +722,7 @@ def load_kasvs_ecdh_vectors(vector_data): if line.startswith("["): tag = line.split()[0][1:] elif line.startswith("COUNT = "): - data["COUNT"] = int(line.split("=")[1], 16) + data["COUNT"] = int(line.split("=")[1]) elif line.startswith("dsCAVS = "): data["CAVS"]["d"] = int(line.split("=")[1], 16) elif line.startswith("QsCAVSx = "): -- cgit v1.2.3 From f115e0548001452de7d2ffc81fdbac1d5ec8b418 Mon Sep 17 00:00:00 2001 From: Erik Trauschke Date: Thu, 15 Oct 2015 15:30:55 -0700 Subject: add binding for d2i_GENERAL_NAMES() --- src/_cffi_src/openssl/x509v3.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/_cffi_src/openssl/x509v3.py b/src/_cffi_src/openssl/x509v3.py index 84e49640..8e163dc2 100644 --- a/src/_cffi_src/openssl/x509v3.py +++ b/src/_cffi_src/openssl/x509v3.py @@ -202,6 +202,8 @@ void OTHERNAME_free(OTHERNAME *); void *X509V3_set_ctx_nodb(X509V3_CTX *); int i2d_GENERAL_NAMES(GENERAL_NAMES *, unsigned char **); +GENERAL_NAMES *d2i_GENERAL_NAMES(GENERAL_NAMES **, const unsigned char **, + long); int i2d_EXTENDED_KEY_USAGE(EXTENDED_KEY_USAGE *, unsigned char **); -- cgit v1.2.3 -- cgit v1.2.3 From fcf08d66967265a45b33acf4da9988c45b6c7a11 Mon Sep 17 00:00:00 2001 From: Erik Trauschke Date: Thu, 15 Oct 2015 15:36:44 -0700 Subject: add new CRL to test invalid certIssuer entry extension --- .../x509/custom/crl_inval_cert_issuer_entry_ext.pem | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 vectors/cryptography_vectors/x509/custom/crl_inval_cert_issuer_entry_ext.pem diff --git a/vectors/cryptography_vectors/x509/custom/crl_inval_cert_issuer_entry_ext.pem b/vectors/cryptography_vectors/x509/custom/crl_inval_cert_issuer_entry_ext.pem new file mode 100644 index 00000000..a54f2409 --- /dev/null +++ b/vectors/cryptography_vectors/x509/custom/crl_inval_cert_issuer_entry_ext.pem @@ -0,0 +1,11 @@ +-----BEGIN X509 CRL----- +MIIBlzCBgAIBAjANBgkqhkiG9w0BAQsFADAnMQswCQYDVQQGEwJVUzEYMBYGA1UE +AwwPY3J5cHRvZ3JhcGh5LmlvGA8yMDE1MDEwMTAwMDAwMFoYDzIwMTYwMTAxMDAw +MDAwWjAhMB8CAQAYDzIwMTUwMTAxMDAwMDAwWjAJMAcGA1UdHQQAMA0GCSqGSIb3 +DQEBCwUAA4IBAQCRSNP2LfnpubvOrZ8/UsETlVTvMNc38xM6dqzYKQV8vN+fcMXP +1z/nTMBGNvnp7u7S+Dx/1Klq/iArtP5oOdNDeVuapfUdDgFJryXkvgX+2B0g/l9+ +/fiH9YNTEG6Yj2XC3lsVwXhid1Sx+A+b8ZXBdyjyZSJSoejPhzO5p/SQAk+ahY3I +FZeL3CXlUUi1v3MtVLBPUQZvepZ9mIv5uRsEmHXFf6uTLmMdV/j7cQn4/K53Qb1N +e+2WpNJOv0UIDugn2DKACF108T1YgZTcx2F4TYpnVDDkyjK4J1IMBrNie8hWA/R3 +y/9oP0PihPDhi4jcVBpDW7pRPqee+4z1KqXg +-----END X509 CRL----- -- cgit v1.2.3 From e6abbfd2ad055b8be81c49a1d9cd4c01a890dd55 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 15 Oct 2015 22:58:52 -0400 Subject: Kill Key Exchange as a separate interface Ultimately it was decided that ECDH and the others can be implemented as simple classes without the overhead of an interface. So ... let's kill it, it was a fun process. Signed-off-by: Simo Sorce --- docs/hazmat/primitives/index.rst | 1 - docs/hazmat/primitives/key-exchange-agreements.rst | 23 ---------------------- .../hazmat/primitives/asymmetric/key_exchange.py | 18 ----------------- 3 files changed, 42 deletions(-) delete mode 100644 docs/hazmat/primitives/key-exchange-agreements.rst delete mode 100644 src/cryptography/hazmat/primitives/asymmetric/key_exchange.py diff --git a/docs/hazmat/primitives/index.rst b/docs/hazmat/primitives/index.rst index 675111bb..a9ab38a0 100644 --- a/docs/hazmat/primitives/index.rst +++ b/docs/hazmat/primitives/index.rst @@ -15,4 +15,3 @@ Primitives constant-time interfaces twofactor - key-exchange-agreements diff --git a/docs/hazmat/primitives/key-exchange-agreements.rst b/docs/hazmat/primitives/key-exchange-agreements.rst deleted file mode 100644 index 8d79fbad..00000000 --- a/docs/hazmat/primitives/key-exchange-agreements.rst +++ /dev/null @@ -1,23 +0,0 @@ -.. hazmat:: - -Key Exchange agreements -======================= - -.. module:: cryptography.hazmat.primitives.asymmetric.key_exchange - -Key exchange agreements are cryptographic operations, like Diffie-Hellman -key exchanges, that allow two parties to use their public-private key pairs -to establish a shared secret key over an insecure channel. Usually the -negotiated key is further derived before using it for symmetric operations. - -Interfaces -~~~~~~~~~~ - -.. class:: KeyExchangeContext - - .. versionadded:: 1.1 - - .. method:: agree(public_key) - - :param public_key: The peer public key, the type depends on the - crypto system used, for example :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey` diff --git a/src/cryptography/hazmat/primitives/asymmetric/key_exchange.py b/src/cryptography/hazmat/primitives/asymmetric/key_exchange.py deleted file mode 100644 index a9846e28..00000000 --- a/src/cryptography/hazmat/primitives/asymmetric/key_exchange.py +++ /dev/null @@ -1,18 +0,0 @@ -# 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 - -import abc - -import six - - -@six.add_metaclass(abc.ABCMeta) -class KeyExchangeContext(object): - @abc.abstractmethod - def agree(self, public_key): - """ - Returns the agreed key material. - """ -- cgit v1.2.3 From a6c8259cf7941a715aada4c8cf14c4499163d3d2 Mon Sep 17 00:00:00 2001 From: Erik Trauschke Date: Thu, 15 Oct 2015 21:10:20 -0700 Subject: add crl file to test-vectors.rst --- docs/development/test-vectors.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index bfe76330..0b249ccb 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -302,6 +302,8 @@ Custom X.509 Certificate Revocation List Vectors to "1.2.3.4". The CRL uses an unsupported MD2 signature algorithm. * ``crl_unsupported_reason.pem`` - Contains a CRL with one revocation which has an unsupported reason code. +* ``crl_inval_cert_issuer_entry_ext.pem`` - Contains a CRL with one revocation + which has one entry extension for certificate issuer with an empty value. Hashes ~~~~~~ -- cgit v1.2.3 From 0d6a74ea07a599371faddc2e33d746484dbaf92b Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 17 Oct 2015 09:33:27 -0500 Subject: make it clearer when PEM and DER encoding support was added --- docs/hazmat/primitives/asymmetric/serialization.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/hazmat/primitives/asymmetric/serialization.rst b/docs/hazmat/primitives/asymmetric/serialization.rst index 8d51f0d7..6d354dff 100644 --- a/docs/hazmat/primitives/asymmetric/serialization.rst +++ b/docs/hazmat/primitives/asymmetric/serialization.rst @@ -337,8 +337,6 @@ Serialization Encodings .. class:: Encoding - .. versionadded:: 0.8 - An enumeration for encoding types. Used with the ``private_bytes`` method available on :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization` @@ -353,10 +351,14 @@ Serialization Encodings .. attribute:: PEM + .. versionadded:: 0.8 + For PEM format. This is a base64 format with delimiters. .. attribute:: DER + .. versionadded :: 0.9 + For DER format. This is a binary format. -- cgit v1.2.3 From 943c7a8dc0d047c43109331ba79fa7b7bed36c03 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 17 Oct 2015 09:52:55 -0500 Subject: fix extra space --- docs/hazmat/primitives/asymmetric/serialization.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/hazmat/primitives/asymmetric/serialization.rst b/docs/hazmat/primitives/asymmetric/serialization.rst index 6d354dff..f14f4037 100644 --- a/docs/hazmat/primitives/asymmetric/serialization.rst +++ b/docs/hazmat/primitives/asymmetric/serialization.rst @@ -357,7 +357,7 @@ Serialization Encodings .. attribute:: DER - .. versionadded :: 0.9 + .. versionadded:: 0.9 For DER format. This is a binary format. -- cgit v1.2.3 From 9aaeee0dc62189204f38097c815a0913fabe006c Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 30 Apr 2015 14:06:47 -0400 Subject: Add an Elliptic Curve Key Exchange Algorithm(ECDH) The ECDH Key Exchange algorithm as standardized in NIST publication 800-56A Revision 2 Includes tests with vectors from NIST. Signed-off-by: Simo Sorce --- docs/hazmat/primitives/asymmetric/ec.rst | 44 ++++++++++ src/cryptography/exceptions.py | 1 + src/cryptography/hazmat/backends/interfaces.py | 6 ++ src/cryptography/hazmat/backends/multibackend.py | 6 ++ .../hazmat/backends/openssl/backend.py | 20 +++++ .../hazmat/primitives/asymmetric/ec.py | 25 ++++++ tests/hazmat/backends/test_multibackend.py | 12 ++- tests/hazmat/backends/test_openssl.py | 14 ++++ tests/hazmat/primitives/test_ec.py | 94 +++++++++++++++++++++- 9 files changed, 219 insertions(+), 3 deletions(-) diff --git a/docs/hazmat/primitives/asymmetric/ec.rst b/docs/hazmat/primitives/asymmetric/ec.rst index 6356c278..910ce5d8 100644 --- a/docs/hazmat/primitives/asymmetric/ec.rst +++ b/docs/hazmat/primitives/asymmetric/ec.rst @@ -122,6 +122,48 @@ Elliptic Curve Signature Algorithms :returns: A new instance of a :class:`EllipticCurvePublicKey` provider. +Elliptic Curve Key Exchange algorithm +------------------------------------- + +.. class:: ECDH(private_key) + + .. versionadded:: 1.1 + + The ECDH Key Exchange algorithm first standardized in NIST publication + `800-56A`_, and later in `800-56Ar2`_. + + :param private_key: An instance of :class:`EllipticCurvePrivateKey`. + + .. doctest:: + + >>> from cryptography.hazmat.backends import default_backend + >>> from cryptography.hazmat.primitives.asymmetric import ec + >>> private_key = ec.generate_private_key( + ... ec.SECP384R1(), default_backend() + ... ) + >>> peer_public_key = ec.generate_private_key( + ... ec.SECP384R1(), default_backend() + ... ).public_key() + >>> ecdh = ec.ECDH(private_key) + >>> sharedkey = ecdh.compute_key(peer_public_key) + + .. attribute:: private_key + + :type: :class:`EllipticCurvePrivateKey` + + The private key associated to this object + + .. method:: public_key() + + The public key associated to the object's private key. + + .. method:: compute_key(peer_public_key) + + :param peer_public_key: A :class:`EllipticCurvePublicKey` object. + + :returns: A ``bytes`` object containing the computed key. + + Elliptic Curves --------------- @@ -419,6 +461,8 @@ Key Interfaces .. _`FIPS 186-3`: http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf .. _`FIPS 186-4`: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf +.. _`800-56A`: http://csrc.nist.gov/publications/nistpubs/800-56A/SP800-56A_Revision1_Mar08-2007.pdf +.. _`800-56Ar2`: http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar2.pdf .. _`some concern`: https://crypto.stackexchange.com/questions/10263/should-we-trust-the-nist-recommended-ecc-parameters .. _`less than 224 bits`: http://www.ecrypt.eu.org/ecrypt2/documents/D.SPA.20.pdf .. _`elliptic curve diffie-hellman is faster than diffie-hellman`: http://digitalcommons.unl.edu/cgi/viewcontent.cgi?article=1100&context=cseconfwork diff --git a/src/cryptography/exceptions.py b/src/cryptography/exceptions.py index 29be22be..3bf8a75b 100644 --- a/src/cryptography/exceptions.py +++ b/src/cryptography/exceptions.py @@ -20,6 +20,7 @@ class _Reasons(Enum): UNSUPPORTED_ELLIPTIC_CURVE = 6 UNSUPPORTED_SERIALIZATION = 7 UNSUPPORTED_X509 = 8 + UNSUPPORTED_EXCHANGE_ALGORITHM = 9 class UnsupportedAlgorithm(Exception): diff --git a/src/cryptography/hazmat/backends/interfaces.py b/src/cryptography/hazmat/backends/interfaces.py index a43621a7..faa0b313 100644 --- a/src/cryptography/hazmat/backends/interfaces.py +++ b/src/cryptography/hazmat/backends/interfaces.py @@ -215,6 +215,12 @@ class EllipticCurveBackend(object): Return an EllipticCurvePublicKey provider using the given numbers. """ + @abc.abstractmethod + def elliptic_curve_exchange_algorithm_supported(self): + """ + Returns whether the exchange algorithm is supported by this backend. + """ + @six.add_metaclass(abc.ABCMeta) class PEMSerializationBackend(object): diff --git a/src/cryptography/hazmat/backends/multibackend.py b/src/cryptography/hazmat/backends/multibackend.py index 9db32aa5..77a45ccd 100644 --- a/src/cryptography/hazmat/backends/multibackend.py +++ b/src/cryptography/hazmat/backends/multibackend.py @@ -271,6 +271,12 @@ class MultiBackend(object): _Reasons.UNSUPPORTED_ELLIPTIC_CURVE ) + def elliptic_curve_exchange_algorithm_supported(self): + return any( + b.elliptic_curve_exchange_algorithm_supported() + for b in self._filtered_backends(EllipticCurveBackend) + ) + def load_pem_private_key(self, data, password): for b in self._filtered_backends(PEMSerializationBackend): return b.load_pem_private_key(data, password) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 0d3b3dd4..d82f3834 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -1671,6 +1671,26 @@ class Backend(object): return _EllipticCurvePublicKey(self, ec_cdata, evp_pkey) + def elliptic_curve_exchange_algorithm_supported(self): + return (self._lib.Cryptography_HAS_EC == 1 and + self._lib.Cryptography_HAS_ECDH == 1) + + def ecdh_compute_key(self, private_key, peer_public_key): + pri_key = private_key._ec_key + pub_key = peer_public_key._ec_key + + group = self._lib.EC_KEY_get0_group(pri_key) + z_len = (self._lib.EC_GROUP_get_degree(group) + 7) // 8 + self.openssl_assert(z_len > 0) + z_buf = self._ffi.new("uint8_t[]", z_len) + peer_key = self._lib.EC_KEY_get0_public_key(pub_key) + + r = self._lib.ECDH_compute_key(z_buf, z_len, + peer_key, pri_key, + self._ffi.NULL) + self.openssl_assert(r > 0) + return self._ffi.buffer(z_buf)[:z_len] + def _ec_cdata_to_evp_pkey(self, ec_cdata): evp_pkey = self._lib.EVP_PKEY_new() self.openssl_assert(evp_pkey != self._ffi.NULL) diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py index f1d39eed..978a7c41 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ec.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py @@ -8,6 +8,7 @@ import abc import six +from cryptography import exceptions from cryptography import utils @@ -302,3 +303,27 @@ class EllipticCurvePrivateNumbers(object): def __ne__(self, other): return not self == other + + +class ECDH(object): + def __init__(self, private_key): + if not isinstance(private_key, EllipticCurvePrivateKey): + raise TypeError("Private Key must be a EllipticCurvePrivateKey") + self._private_key = private_key + self._backend = private_key._backend + if not self._backend.elliptic_curve_exchange_algorithm_supported(): + raise exceptions.UnsupportedAlgorithm( + "This backend does not support the ECDH algorithm.", + exceptions._Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM + ) + + private_key = utils.read_only_property("_private_key") + + def public_key(self): + return self._private_key.public_key() + + def compute_key(self, peer_public_key): + if not isinstance(peer_public_key, EllipticCurvePublicKey): + raise TypeError("Peer Public Key must be a EllipticCurvePublicKey") + return self._backend.ecdh_compute_key(self._private_key, + peer_public_key) diff --git a/tests/hazmat/backends/test_multibackend.py b/tests/hazmat/backends/test_multibackend.py index 4d17cdb0..57aa7f44 100644 --- a/tests/hazmat/backends/test_multibackend.py +++ b/tests/hazmat/backends/test_multibackend.py @@ -138,8 +138,9 @@ class DummyCMACBackend(object): @utils.register_interface(EllipticCurveBackend) class DummyEllipticCurveBackend(object): - def __init__(self, supported_curves): + def __init__(self, supported_curves, exchange_supported): self._curves = supported_curves + self.exchange_supported = exchange_supported def elliptic_curve_supported(self, curve): return any( @@ -170,6 +171,9 @@ class DummyEllipticCurveBackend(object): if not self.elliptic_curve_supported(numbers.curve): raise UnsupportedAlgorithm(_Reasons.UNSUPPORTED_ELLIPTIC_CURVE) + def elliptic_curve_exchange_algorithm_supported(self): + return self.exchange_supported + @utils.register_interface(PEMSerializationBackend) class DummyPEMSerializationBackend(object): @@ -400,7 +404,7 @@ class TestMultiBackend(object): backend = MultiBackend([ DummyEllipticCurveBackend([ ec.SECT283K1 - ]) + ], True) ]) assert backend.elliptic_curve_supported(ec.SECT283K1()) is True @@ -462,6 +466,10 @@ class TestMultiBackend(object): ) ) + assert backend.elliptic_curve_exchange_algorithm_supported() is True + backend2 = MultiBackend([DummyEllipticCurveBackend([], False)]) + assert backend2.elliptic_curve_exchange_algorithm_supported() is False + def test_pem_serialization_backend(self): backend = MultiBackend([DummyPEMSerializationBackend()]) diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index 8fd0d711..13162046 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -534,6 +534,11 @@ class DummyLibrary(object): Cryptography_HAS_EC = 0 +class DummyLibraryECDH(object): + Cryptography_HAS_EC = 1 + Cryptography_HAS_ECDH = 0 + + class TestOpenSSLEllipticCurve(object): def test_elliptic_curve_supported(self, monkeypatch): monkeypatch.setattr(backend, "_lib", DummyLibrary()) @@ -551,6 +556,15 @@ class TestOpenSSLEllipticCurve(object): with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_ELLIPTIC_CURVE): _sn_to_elliptic_curve(backend, b"fake") + def test_elliptic_curve_exchange_algorithm_supported(self, monkeypatch): + monkeypatch.setattr(backend, "_lib", DummyLibrary()) + + assert backend.elliptic_curve_exchange_algorithm_supported() is False + + monkeypatch.setattr(backend, "_lib", DummyLibraryECDH()) + + assert backend.elliptic_curve_exchange_algorithm_supported() is False + @pytest.mark.requires_backend_interface(interface=RSABackend) class TestRSAPEMSerialization(object): diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py index 5467464a..c3a99e5d 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -7,6 +7,8 @@ from __future__ import absolute_import, division, print_function import itertools import os +from binascii import hexlify + import pytest from cryptography import exceptions, utils @@ -21,7 +23,8 @@ from cryptography.hazmat.primitives.asymmetric.utils import ( from ...utils import ( load_fips_ecdsa_key_pair_vectors, load_fips_ecdsa_signing_vectors, - load_vectors_from_file, raises_unsupported_algorithm + load_kasvs_ecdh_vectors, load_vectors_from_file, + raises_unsupported_algorithm ) _HASH_TYPES = { @@ -54,6 +57,15 @@ def _skip_curve_unsupported(backend, curve): ) +def _skip_exchange_algorithm_unsupported(backend): + if not backend.elliptic_curve_exchange_algorithm_supported(): + pytest.skip( + "Exchange algorithm is not supported by this backend {0}".format( + backend + ) + ) + + @utils.register_interface(ec.EllipticCurve) class DummyCurve(object): name = "dummy-curve" @@ -749,3 +761,83 @@ class TestECDSAVerification(object): public_key = key.public_key() with pytest.raises(TypeError): public_key.verifier(1234, ec.ECDSA(hashes.SHA256())) + + +class DummyECDHBackend(object): + @classmethod + def elliptic_curve_exchange_algorithm_supported(cls): + return False + + +@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) +class TestECDHVectors(object): + + def test_unsupported_ecdh_arguments(self, backend): + with pytest.raises(TypeError): + ec.ECDH(None) + curve = ec.SECP521R1 + _skip_curve_unsupported(backend, curve) + prikey = ec.generate_private_key(curve, backend) + ecdh = ec.ECDH(prikey) + ecdh.compute_key(ecdh.public_key()) + with pytest.raises(TypeError): + ecdh.compute_key(None) + with pytest.raises(exceptions.UnsupportedAlgorithm): + prikey._backend = DummyECDHBackend() + ecdh = ec.ECDH(prikey) + _skip_exchange_algorithm_unsupported(DummyECDHBackend()) + + def key_exchange(self, backend, vector): + key_numbers = vector['IUT'] + peer_numbers = vector['CAVS'] + + prikey = ec.EllipticCurvePrivateNumbers( + key_numbers['d'], + ec.EllipticCurvePublicNumbers( + key_numbers['x'], + key_numbers['y'], + ec._CURVE_TYPES[vector['curve']]() + ) + ).private_key(backend) + + peerkey = ec.EllipticCurvePrivateNumbers( + peer_numbers['d'], + ec.EllipticCurvePublicNumbers( + peer_numbers['x'], + peer_numbers['y'], + ec._CURVE_TYPES[vector['curve']]() + ) + ).private_key(backend) + peerpubkey = peerkey.public_key() + + ecdh = ec.ECDH(prikey) + z = ecdh.compute_key(peerpubkey) + + return int(hexlify(z).decode('ascii'), 16) + + @pytest.mark.parametrize( + "vector", + load_vectors_from_file( + os.path.join( + "asymmetric", "ECDH", + "KASValidityTest_ECCStaticUnified_NOKC_ZZOnly_init.fax"), + load_kasvs_ecdh_vectors + ) + ) + def test_key_exchange_with_vectors(self, backend, vector): + _skip_curve_unsupported(backend, ec._CURVE_TYPES[vector['curve']]) + _skip_exchange_algorithm_unsupported(backend) + + try: + z = self.key_exchange(backend, vector) + except ValueError: + assert vector['fail'] is True + + if vector['fail']: + # Errno 7 denotes a changed private key. Errno 8 denotes a changed + # shared key. Both these errors will not cause a failure in the + # exchange but should lead to a non-matching derived shared key. + if vector['errno'] in [7, 8]: + assert z != vector['Z'] + else: + assert z == vector['Z'] -- cgit v1.2.3 From 5cdfba5c8d06ed10510310de03e1df0265a89bcc Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 17 Oct 2015 16:33:04 -0400 Subject: a refactor to the API --- docs/hazmat/primitives/asymmetric/ec.rst | 27 +------ src/cryptography/hazmat/backends/interfaces.py | 2 +- src/cryptography/hazmat/backends/multibackend.py | 4 +- .../hazmat/backends/openssl/backend.py | 25 ++---- src/cryptography/hazmat/backends/openssl/ec.py | 25 ++++++ .../hazmat/primitives/asymmetric/ec.py | 22 +---- tests/hazmat/backends/test_multibackend.py | 27 ++++--- tests/hazmat/backends/test_openssl.py | 14 +--- tests/hazmat/primitives/test_ec.py | 94 ++++++++++------------ 9 files changed, 98 insertions(+), 142 deletions(-) diff --git a/docs/hazmat/primitives/asymmetric/ec.rst b/docs/hazmat/primitives/asymmetric/ec.rst index 910ce5d8..9b2e61fb 100644 --- a/docs/hazmat/primitives/asymmetric/ec.rst +++ b/docs/hazmat/primitives/asymmetric/ec.rst @@ -125,14 +125,12 @@ Elliptic Curve Signature Algorithms Elliptic Curve Key Exchange algorithm ------------------------------------- -.. class:: ECDH(private_key) +.. class:: ECDH() .. versionadded:: 1.1 - The ECDH Key Exchange algorithm first standardized in NIST publication - `800-56A`_, and later in `800-56Ar2`_. - - :param private_key: An instance of :class:`EllipticCurvePrivateKey`. + The Elliptic Curve Diffie-Hellman Key Exchange algorithm first standardized + in NIST publication `800-56A`_, and later in `800-56Ar2`_. .. doctest:: @@ -144,24 +142,7 @@ Elliptic Curve Key Exchange algorithm >>> peer_public_key = ec.generate_private_key( ... ec.SECP384R1(), default_backend() ... ).public_key() - >>> ecdh = ec.ECDH(private_key) - >>> sharedkey = ecdh.compute_key(peer_public_key) - - .. attribute:: private_key - - :type: :class:`EllipticCurvePrivateKey` - - The private key associated to this object - - .. method:: public_key() - - The public key associated to the object's private key. - - .. method:: compute_key(peer_public_key) - - :param peer_public_key: A :class:`EllipticCurvePublicKey` object. - - :returns: A ``bytes`` object containing the computed key. + >>> shared_key = private_key.exchange(ec.ECDH(), peer_public_key) Elliptic Curves diff --git a/src/cryptography/hazmat/backends/interfaces.py b/src/cryptography/hazmat/backends/interfaces.py index faa0b313..dbebc883 100644 --- a/src/cryptography/hazmat/backends/interfaces.py +++ b/src/cryptography/hazmat/backends/interfaces.py @@ -216,7 +216,7 @@ class EllipticCurveBackend(object): """ @abc.abstractmethod - def elliptic_curve_exchange_algorithm_supported(self): + def elliptic_curve_exchange_algorithm_supported(self, algorithm, curve): """ Returns whether the exchange algorithm is supported by this backend. """ diff --git a/src/cryptography/hazmat/backends/multibackend.py b/src/cryptography/hazmat/backends/multibackend.py index 77a45ccd..c4d2c133 100644 --- a/src/cryptography/hazmat/backends/multibackend.py +++ b/src/cryptography/hazmat/backends/multibackend.py @@ -271,9 +271,9 @@ class MultiBackend(object): _Reasons.UNSUPPORTED_ELLIPTIC_CURVE ) - def elliptic_curve_exchange_algorithm_supported(self): + def elliptic_curve_exchange_algorithm_supported(self, algorithm, curve): return any( - b.elliptic_curve_exchange_algorithm_supported() + b.elliptic_curve_exchange_algorithm_supported(algorithm, curve) for b in self._filtered_backends(EllipticCurveBackend) ) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index d82f3834..f86c3aa1 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -1671,25 +1671,12 @@ class Backend(object): return _EllipticCurvePublicKey(self, ec_cdata, evp_pkey) - def elliptic_curve_exchange_algorithm_supported(self): - return (self._lib.Cryptography_HAS_EC == 1 and - self._lib.Cryptography_HAS_ECDH == 1) - - def ecdh_compute_key(self, private_key, peer_public_key): - pri_key = private_key._ec_key - pub_key = peer_public_key._ec_key - - group = self._lib.EC_KEY_get0_group(pri_key) - z_len = (self._lib.EC_GROUP_get_degree(group) + 7) // 8 - self.openssl_assert(z_len > 0) - z_buf = self._ffi.new("uint8_t[]", z_len) - peer_key = self._lib.EC_KEY_get0_public_key(pub_key) - - r = self._lib.ECDH_compute_key(z_buf, z_len, - peer_key, pri_key, - self._ffi.NULL) - self.openssl_assert(r > 0) - return self._ffi.buffer(z_buf)[:z_len] + def elliptic_curve_exchange_algorithm_supported(self, algorithm, curve): + return ( + self.elliptic_curve_supported(curve) and + self._lib.Cryptography_HAS_ECDH == 1 and + isinstance(algorithm, ec.ECDH) + ) def _ec_cdata_to_evp_pkey(self, ec_cdata): evp_pkey = self._lib.EVP_PKEY_new() diff --git a/src/cryptography/hazmat/backends/openssl/ec.py b/src/cryptography/hazmat/backends/openssl/ec.py index 939a3f90..cfd559ae 100644 --- a/src/cryptography/hazmat/backends/openssl/ec.py +++ b/src/cryptography/hazmat/backends/openssl/ec.py @@ -171,6 +171,31 @@ class _EllipticCurvePrivateKey(object): "Unsupported elliptic curve signature algorithm.", _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM) + def exchange(self, algorithm, peer_public_key): + if not ( + self._backend.elliptic_curve_exchange_algorithm_supported( + algorithm, self.curve + ) + ): + raise UnsupportedAlgorithm( + "This backend does not support the ECDH algorithm.", + _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM + ) + + group = self._backend._lib.EC_KEY_get0_group(self._ec_key) + z_len = (self._backend._lib.EC_GROUP_get_degree(group) + 7) // 8 + self._backend.openssl_assert(z_len > 0) + z_buf = self._backend._ffi.new("uint8_t[]", z_len) + peer_key = self._backend._lib.EC_KEY_get0_public_key( + peer_public_key._ec_key + ) + + r = self._backend._lib.ECDH_compute_key( + z_buf, z_len, peer_key, self._ec_key, self._backend._ffi.NULL + ) + self._backend.openssl_assert(r > 0) + return self._backend._ffi.buffer(z_buf)[:z_len] + def public_key(self): group = self._backend._lib.EC_KEY_get0_group(self._ec_key) self._backend.openssl_assert(group != self._backend._ffi.NULL) diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py index 978a7c41..544894a9 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ec.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py @@ -306,24 +306,4 @@ class EllipticCurvePrivateNumbers(object): class ECDH(object): - def __init__(self, private_key): - if not isinstance(private_key, EllipticCurvePrivateKey): - raise TypeError("Private Key must be a EllipticCurvePrivateKey") - self._private_key = private_key - self._backend = private_key._backend - if not self._backend.elliptic_curve_exchange_algorithm_supported(): - raise exceptions.UnsupportedAlgorithm( - "This backend does not support the ECDH algorithm.", - exceptions._Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM - ) - - private_key = utils.read_only_property("_private_key") - - def public_key(self): - return self._private_key.public_key() - - def compute_key(self, peer_public_key): - if not isinstance(peer_public_key, EllipticCurvePublicKey): - raise TypeError("Peer Public Key must be a EllipticCurvePublicKey") - return self._backend.ecdh_compute_key(self._private_key, - peer_public_key) + pass diff --git a/tests/hazmat/backends/test_multibackend.py b/tests/hazmat/backends/test_multibackend.py index 57aa7f44..2a533750 100644 --- a/tests/hazmat/backends/test_multibackend.py +++ b/tests/hazmat/backends/test_multibackend.py @@ -138,9 +138,8 @@ class DummyCMACBackend(object): @utils.register_interface(EllipticCurveBackend) class DummyEllipticCurveBackend(object): - def __init__(self, supported_curves, exchange_supported): + def __init__(self, supported_curves): self._curves = supported_curves - self.exchange_supported = exchange_supported def elliptic_curve_supported(self, curve): return any( @@ -153,10 +152,7 @@ class DummyEllipticCurveBackend(object): ): return ( isinstance(signature_algorithm, ec.ECDSA) and - any( - isinstance(curve, curve_type) - for curve_type in self._curves - ) + self.elliptic_curve_supported(curve) ) def generate_elliptic_curve_private_key(self, curve): @@ -171,8 +167,11 @@ class DummyEllipticCurveBackend(object): if not self.elliptic_curve_supported(numbers.curve): raise UnsupportedAlgorithm(_Reasons.UNSUPPORTED_ELLIPTIC_CURVE) - def elliptic_curve_exchange_algorithm_supported(self): - return self.exchange_supported + def elliptic_curve_exchange_algorithm_supported(self, algorithm, curve): + return ( + isinstance(algorithm, ec.ECDH) and + self.elliptic_curve_supported(curve) + ) @utils.register_interface(PEMSerializationBackend) @@ -404,7 +403,7 @@ class TestMultiBackend(object): backend = MultiBackend([ DummyEllipticCurveBackend([ ec.SECT283K1 - ], True) + ]) ]) assert backend.elliptic_curve_supported(ec.SECT283K1()) is True @@ -466,9 +465,13 @@ class TestMultiBackend(object): ) ) - assert backend.elliptic_curve_exchange_algorithm_supported() is True - backend2 = MultiBackend([DummyEllipticCurveBackend([], False)]) - assert backend2.elliptic_curve_exchange_algorithm_supported() is False + assert backend.elliptic_curve_exchange_algorithm_supported( + ec.ECDH(), ec.SECT283K1() + ) + backend2 = MultiBackend([DummyEllipticCurveBackend([])]) + assert not backend2.elliptic_curve_exchange_algorithm_supported( + ec.ECDH(), ec.SECT163K1() + ) def test_pem_serialization_backend(self): backend = MultiBackend([DummyPEMSerializationBackend()]) diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index 13162046..85331595 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -534,11 +534,6 @@ class DummyLibrary(object): Cryptography_HAS_EC = 0 -class DummyLibraryECDH(object): - Cryptography_HAS_EC = 1 - Cryptography_HAS_ECDH = 0 - - class TestOpenSSLEllipticCurve(object): def test_elliptic_curve_supported(self, monkeypatch): monkeypatch.setattr(backend, "_lib", DummyLibrary()) @@ -558,12 +553,9 @@ class TestOpenSSLEllipticCurve(object): def test_elliptic_curve_exchange_algorithm_supported(self, monkeypatch): monkeypatch.setattr(backend, "_lib", DummyLibrary()) - - assert backend.elliptic_curve_exchange_algorithm_supported() is False - - monkeypatch.setattr(backend, "_lib", DummyLibraryECDH()) - - assert backend.elliptic_curve_exchange_algorithm_supported() is False + assert not backend.elliptic_curve_exchange_algorithm_supported( + ec.ECDH(), ec.SECP256R1() + ) @pytest.mark.requires_backend_interface(interface=RSABackend) diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py index c3a99e5d..2594d5db 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -57,8 +57,10 @@ def _skip_curve_unsupported(backend, curve): ) -def _skip_exchange_algorithm_unsupported(backend): - if not backend.elliptic_curve_exchange_algorithm_supported(): +def _skip_exchange_algorithm_unsupported(backend, algorithm, curve): + if not backend.elliptic_curve_exchange_algorithm_supported( + algorithm, curve + ): pytest.skip( "Exchange algorithm is not supported by this backend {0}".format( backend @@ -771,50 +773,6 @@ class DummyECDHBackend(object): @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) class TestECDHVectors(object): - - def test_unsupported_ecdh_arguments(self, backend): - with pytest.raises(TypeError): - ec.ECDH(None) - curve = ec.SECP521R1 - _skip_curve_unsupported(backend, curve) - prikey = ec.generate_private_key(curve, backend) - ecdh = ec.ECDH(prikey) - ecdh.compute_key(ecdh.public_key()) - with pytest.raises(TypeError): - ecdh.compute_key(None) - with pytest.raises(exceptions.UnsupportedAlgorithm): - prikey._backend = DummyECDHBackend() - ecdh = ec.ECDH(prikey) - _skip_exchange_algorithm_unsupported(DummyECDHBackend()) - - def key_exchange(self, backend, vector): - key_numbers = vector['IUT'] - peer_numbers = vector['CAVS'] - - prikey = ec.EllipticCurvePrivateNumbers( - key_numbers['d'], - ec.EllipticCurvePublicNumbers( - key_numbers['x'], - key_numbers['y'], - ec._CURVE_TYPES[vector['curve']]() - ) - ).private_key(backend) - - peerkey = ec.EllipticCurvePrivateNumbers( - peer_numbers['d'], - ec.EllipticCurvePublicNumbers( - peer_numbers['x'], - peer_numbers['y'], - ec._CURVE_TYPES[vector['curve']]() - ) - ).private_key(backend) - peerpubkey = peerkey.public_key() - - ecdh = ec.ECDH(prikey) - z = ecdh.compute_key(peerpubkey) - - return int(hexlify(z).decode('ascii'), 16) - @pytest.mark.parametrize( "vector", load_vectors_from_file( @@ -825,19 +783,49 @@ class TestECDHVectors(object): ) ) def test_key_exchange_with_vectors(self, backend, vector): - _skip_curve_unsupported(backend, ec._CURVE_TYPES[vector['curve']]) - _skip_exchange_algorithm_unsupported(backend) + _skip_exchange_algorithm_unsupported( + backend, ec.ECDH(), ec._CURVE_TYPES[vector['curve']] + ) + key_numbers = vector['IUT'] try: - z = self.key_exchange(backend, vector) + private_key = ec.EllipticCurvePrivateNumbers( + key_numbers['d'], + ec.EllipticCurvePublicNumbers( + key_numbers['x'], + key_numbers['y'], + ec._CURVE_TYPES[vector['curve']]() + ) + ).private_key(backend) except ValueError: - assert vector['fail'] is True + # Errno 5 and 6 indicates a bad public key, this doesn't test the + # ECDH code at all + assert vector['fail'] and vector['errno'] in [5, 6] + return - if vector['fail']: + peer_numbers = vector['CAVS'] + try: + peer_pubkey = ec.EllipticCurvePublicNumbers( + peer_numbers['x'], + peer_numbers['y'], + ec._CURVE_TYPES[vector['curve']]() + ).public_key(backend) + except ValueError: + # Errno 1 and 2 indicates a bad public key, this doesn't test the + # ECDH code at all + assert vector['fail'] and vector['errno'] in [1, 2] + return + + if vector['fail'] and vector['errno'] not in [7, 8]: + with pytest.raises(ValueError): + private_key.exchange(ec.ECDH(), peer_pubkey) + else: + z = private_key.exchange(ec.ECDH(), peer_pubkey) + z = int(hexlify(z).decode('ascii'), 16) # Errno 7 denotes a changed private key. Errno 8 denotes a changed # shared key. Both these errors will not cause a failure in the # exchange but should lead to a non-matching derived shared key. if vector['errno'] in [7, 8]: assert z != vector['Z'] - else: - assert z == vector['Z'] + else: + assert z == vector['Z'] -- cgit v1.2.3 From 2708323845ee4c51481a60ecda2334d83844b590 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 17 Oct 2015 16:33:57 -0400 Subject: changelog --- CHANGELOG.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index fdea8c35..34e3f9a7 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,8 @@ Changelog .. note:: This version is not yet released and is under active development. +* Added support for + :class:`cryptography.hazmat.primitives.asymmetric.ec.ECDH `. * Added :class:`~cryptography.hazmat.primitives.kdf.x963kdf.X963KDF`. 1.0.2 - 2015-09-27 -- cgit v1.2.3 From 4c081ad1fb54dae846a1ade2b15fe15e9ff31b0d Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 17 Oct 2015 16:34:33 -0400 Subject: unused --- tests/hazmat/primitives/test_ec.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py index 2594d5db..13bc11c9 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -765,12 +765,6 @@ class TestECDSAVerification(object): public_key.verifier(1234, ec.ECDSA(hashes.SHA256())) -class DummyECDHBackend(object): - @classmethod - def elliptic_curve_exchange_algorithm_supported(cls): - return False - - @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) class TestECDHVectors(object): @pytest.mark.parametrize( -- cgit v1.2.3 From 91113b9c37fbaeeb55a2486313d8314ecdc8dfbf Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 17 Oct 2015 16:35:05 -0400 Subject: unused import --- src/cryptography/hazmat/primitives/asymmetric/ec.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py index 544894a9..052ae742 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ec.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py @@ -8,7 +8,6 @@ import abc import six -from cryptography import exceptions from cryptography import utils -- cgit v1.2.3 From 7adb92cadaa46bfb23c8eabeb99091f5058bf244 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 17 Oct 2015 16:38:19 -0400 Subject: backwards syntax --- CHANGELOG.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 34e3f9a7..c1100a49 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -7,7 +7,7 @@ Changelog .. note:: This version is not yet released and is under active development. * Added support for - :class:`cryptography.hazmat.primitives.asymmetric.ec.ECDH `. + :class:`Elliptic Curve Diffie-Hellman`. * Added :class:`~cryptography.hazmat.primitives.kdf.x963kdf.X963KDF`. 1.0.2 - 2015-09-27 -- cgit v1.2.3 From 39d38b92e015e78269e5bbb248e30e14e22ea599 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 17 Oct 2015 16:44:15 -0400 Subject: clearer language --- CHANGELOG.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c1100a49..227a4404 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,8 +6,8 @@ Changelog .. note:: This version is not yet released and is under active development. -* Added support for - :class:`Elliptic Curve Diffie-Hellman`. +* Added support for Elliptic Curve Diffie-Hellman with + :class:`<~cryptography.hazmat.primitives.asymmetric.ec.ECDH>`. * Added :class:`~cryptography.hazmat.primitives.kdf.x963kdf.X963KDF`. 1.0.2 - 2015-09-27 -- cgit v1.2.3 From d29498902d40a446c65de1cafd567a79a4bbf84e Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 17 Oct 2015 16:45:55 -0400 Subject: one more --- CHANGELOG.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 227a4404..ec27596c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -7,7 +7,7 @@ Changelog .. note:: This version is not yet released and is under active development. * Added support for Elliptic Curve Diffie-Hellman with - :class:`<~cryptography.hazmat.primitives.asymmetric.ec.ECDH>`. + :class:`~cryptography.hazmat.primitives.asymmetric.ec.ECDH`. * Added :class:`~cryptography.hazmat.primitives.kdf.x963kdf.X963KDF`. 1.0.2 - 2015-09-27 -- cgit v1.2.3 From 68b3441d90fa4230b62d19a43c49dd2aa155db47 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 17 Oct 2015 18:09:03 -0400 Subject: better document hte iface --- docs/hazmat/primitives/asymmetric/ec.rst | 19 +++++++++++++++++++ src/cryptography/hazmat/primitives/asymmetric/ec.py | 7 +++++++ 2 files changed, 26 insertions(+) diff --git a/docs/hazmat/primitives/asymmetric/ec.rst b/docs/hazmat/primitives/asymmetric/ec.rst index 9b2e61fb..525bd6cb 100644 --- a/docs/hazmat/primitives/asymmetric/ec.rst +++ b/docs/hazmat/primitives/asymmetric/ec.rst @@ -132,6 +132,9 @@ Elliptic Curve Key Exchange algorithm The Elliptic Curve Diffie-Hellman Key Exchange algorithm first standardized in NIST publication `800-56A`_, and later in `800-56Ar2`_. + For most applications the ``shared_key`` should be passed to a key + derivation function. + .. doctest:: >>> from cryptography.hazmat.backends import default_backend @@ -337,6 +340,22 @@ Key Interfaces :returns: :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricSignatureContext` + .. method:: exchange(algorithm, peer_public_key) + + Perform's a key exchange operation using the provided algorithm with + the peer's public key. + + For most applications the result should be passed to a key derivation + function. + + :param algorithm: The key exchange algorithm, currently only + :class:`~cryptography.hazmat.primitives.asymmetric.ec.ECDH` is + supported. + :param EllipticCurvePublicKey peer_public_key: The public key for the + peer. + + :returns bytes: A shared key. + .. method:: public_key() :return: :class:`EllipticCurvePublicKey` diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py index 052ae742..c6f83667 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ec.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py @@ -43,6 +43,13 @@ class EllipticCurvePrivateKey(object): Returns an AsymmetricSignatureContext used for signing data. """ + @abc.abstractmethod + def exchange(self, algorithm, peer_public_key): + """ + Performs a key exchange operation using the provided algorithm with the + provided peer's public key. + """ + @abc.abstractmethod def public_key(self): """ -- cgit v1.2.3 From b5f1f7235f69dd56038ce8240bed6c08a5977b45 Mon Sep 17 00:00:00 2001 From: Terry Chia Date: Sun, 18 Oct 2015 10:12:13 +0800 Subject: Fix wrong mention of class in docstring. --- src/cryptography/hazmat/backends/interfaces.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptography/hazmat/backends/interfaces.py b/src/cryptography/hazmat/backends/interfaces.py index a43621a7..d93968cf 100644 --- a/src/cryptography/hazmat/backends/interfaces.py +++ b/src/cryptography/hazmat/backends/interfaces.py @@ -212,7 +212,7 @@ class EllipticCurveBackend(object): @abc.abstractmethod def load_elliptic_curve_private_numbers(self, numbers): """ - Return an EllipticCurvePublicKey provider using the given numbers. + Return an EllipticCurvePrivateKey provider using the given numbers. """ -- cgit v1.2.3 From 09d1b47823b6e2fec118a1d821a72babf5ce9916 Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Fri, 16 Oct 2015 08:14:42 +0100 Subject: Add --no-use-wheel when building static wheels. --- docs/installation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.rst b/docs/installation.rst index 5d629e9f..7847969f 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -166,7 +166,7 @@ dependencies. ./config no-shared no-ssl2 -fPIC --prefix=${CWD}/openssl make && make install cd .. - CFLAGS="-I${CWD}/openssl/include" LDFLAGS="-L${CWD}/openssl/lib" pip wheel cryptography + CFLAGS="-I${CWD}/openssl/include" LDFLAGS="-L${CWD}/openssl/lib" pip wheel --no-use-wheel cryptography Building cryptography on OS X ----------------------------- -- cgit v1.2.3 From cb87f62eed3dee7fcc903f545652623e41bda50a Mon Sep 17 00:00:00 2001 From: simo5 Date: Sat, 17 Oct 2015 16:49:40 -0400 Subject: Fix EC's generate_private_key param name The first parameter is curve, not backend Signed-off-by: Simo Sorce --- docs/hazmat/primitives/asymmetric/ec.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/hazmat/primitives/asymmetric/ec.rst b/docs/hazmat/primitives/asymmetric/ec.rst index 6356c278..7c67229c 100644 --- a/docs/hazmat/primitives/asymmetric/ec.rst +++ b/docs/hazmat/primitives/asymmetric/ec.rst @@ -12,7 +12,7 @@ Elliptic curve cryptography Generate a new private key on ``curve`` for use with ``backend``. - :param backend: A :class:`EllipticCurve` provider. + :param curve: A :class:`EllipticCurve` provider. :param backend: A :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend` -- cgit v1.2.3 From 799b33f69a8bfd1aaf7f90a81b6ee3fdebc777a1 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 18 Oct 2015 16:59:08 -0400 Subject: be more pro-active in handling invalid keys --- tests/hazmat/primitives/test_ec.py | 50 ++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py index 13bc11c9..a634afe8 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -782,33 +782,37 @@ class TestECDHVectors(object): ) key_numbers = vector['IUT'] - try: - private_key = ec.EllipticCurvePrivateNumbers( - key_numbers['d'], - ec.EllipticCurvePublicNumbers( - key_numbers['x'], - key_numbers['y'], - ec._CURVE_TYPES[vector['curve']]() - ) - ).private_key(backend) - except ValueError: - # Errno 5 and 6 indicates a bad public key, this doesn't test the - # ECDH code at all - assert vector['fail'] and vector['errno'] in [5, 6] + private_numbers = ec.EllipticCurvePrivateNumbers( + key_numbers['d'], + ec.EllipticCurvePublicNumbers( + key_numbers['x'], + key_numbers['y'], + ec._CURVE_TYPES[vector['curve']]() + ) + ) + # Errno 5 and 6 indicates a bad public key, this doesn't test the ECDH + # code at all + if vector['fail'] and vector['errno'] in [5, 6]: + with pytest.raises(ValueError): + private_numbers.private_key(backend) return + else: + private_key = private_numbers.private_key(backend) peer_numbers = vector['CAVS'] - try: - peer_pubkey = ec.EllipticCurvePublicNumbers( - peer_numbers['x'], - peer_numbers['y'], - ec._CURVE_TYPES[vector['curve']]() - ).public_key(backend) - except ValueError: - # Errno 1 and 2 indicates a bad public key, this doesn't test the - # ECDH code at all - assert vector['fail'] and vector['errno'] in [1, 2] + public_numbers = ec.EllipticCurvePublicNumbers( + peer_numbers['x'], + peer_numbers['y'], + ec._CURVE_TYPES[vector['curve']]() + ) + # Errno 1 and 2 indicates a bad public key, this doesn't test the ECDH + # code at all + if vector['fail'] and vector['errno'] in [1, 2]: + with pytest.raises(ValueError): + public_numbers.public_key(backend) return + else: + peer_pubkey = public_numbers.public_key(backend) if vector['fail'] and vector['errno'] not in [7, 8]: with pytest.raises(ValueError): -- cgit v1.2.3 From 7c60ffc621320349f88cf36b12cd087d8bd9b6a3 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 19 Oct 2015 08:04:17 -0400 Subject: removed unused code, and added a test --- tests/hazmat/primitives/test_ec.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py index a634afe8..6c184522 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -90,6 +90,12 @@ def test_skip_curve_unsupported(backend): _skip_curve_unsupported(backend, DummyCurve()) +@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) +def test_skip_exchange_algorithm_unsupported(backend): + with pytest.raises(pytest.skip.Exception): + _skip_exchange_algorithm_unsupported(backend, ec.ECDH(), DummyCurve()) + + def test_ec_numbers(): numbers = ec.EllipticCurvePrivateNumbers( 1, @@ -814,16 +820,11 @@ class TestECDHVectors(object): else: peer_pubkey = public_numbers.public_key(backend) - if vector['fail'] and vector['errno'] not in [7, 8]: - with pytest.raises(ValueError): - private_key.exchange(ec.ECDH(), peer_pubkey) + z = private_key.exchange(ec.ECDH(), peer_pubkey) + z = int(hexlify(z).decode('ascii'), 16) + # At this point fail indicates that one of the underlying keys was + # changed. This results in a non-matching derived key. + if vector['fail']: + assert z != vector['Z'] else: - z = private_key.exchange(ec.ECDH(), peer_pubkey) - z = int(hexlify(z).decode('ascii'), 16) - # Errno 7 denotes a changed private key. Errno 8 denotes a changed - # shared key. Both these errors will not cause a failure in the - # exchange but should lead to a non-matching derived shared key. - if vector['errno'] in [7, 8]: - assert z != vector['Z'] - else: - assert z == vector['Z'] + assert z == vector['Z'] -- cgit v1.2.3 From aaf4e8bccd9cac827b5f740371feaa7faeebcb93 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 19 Oct 2015 08:07:43 -0400 Subject: another test --- tests/hazmat/backends/test_openssl.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index 85331595..3ccc54c8 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -557,6 +557,13 @@ class TestOpenSSLEllipticCurve(object): ec.ECDH(), ec.SECP256R1() ) + def test_elliptic_curve_exchange_unsupported_algorithm(self): + key = ec.generate_private_key(ec.SECP256R1(), backend=backend) + with raises_unsupported_algorithm( + _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM + ): + key.exchange(None, key.public_key()) + @pytest.mark.requires_backend_interface(interface=RSABackend) class TestRSAPEMSerialization(object): -- cgit v1.2.3 From 7a40209a64c800be1b964a0eded2ab1f40accf50 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 19 Oct 2015 08:26:27 -0400 Subject: better place for this test --- tests/hazmat/backends/test_openssl.py | 7 ------- tests/hazmat/primitives/test_ec.py | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index 3ccc54c8..85331595 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -557,13 +557,6 @@ class TestOpenSSLEllipticCurve(object): ec.ECDH(), ec.SECP256R1() ) - def test_elliptic_curve_exchange_unsupported_algorithm(self): - key = ec.generate_private_key(ec.SECP256R1(), backend=backend) - with raises_unsupported_algorithm( - _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM - ): - key.exchange(None, key.public_key()) - @pytest.mark.requires_backend_interface(interface=RSABackend) class TestRSAPEMSerialization(object): diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py index 6c184522..4c4d5b90 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -828,3 +828,19 @@ class TestECDHVectors(object): assert z != vector['Z'] else: assert z == vector['Z'] + + def test_exchange_unsupported_algorithm(self, backend): + _skip_curve_unsupported(backend, ec.SECP256R1()) + + key = load_vectors_from_file( + os.path.join( + "asymmetric", "PKCS8", "ec_private_key.pem"), + lambda pemfile: serialization.load_pem_private_key( + pemfile.read().encode(), None, backend + ) + ) + + with raises_unsupported_algorithm( + exceptions._Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM + ): + key.exchange(None, key.public_key()) -- cgit v1.2.3 From afbe75bf4fb6c288a7e25b2c58a72ec7049f3f64 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 20 Oct 2015 08:08:43 -0500 Subject: add __repr__ to x509.Extensions fix #2434 --- src/cryptography/x509/extensions.py | 5 +++++ tests/test_x509_ext.py | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index cd75ecdc..46ba5a28 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -104,6 +104,11 @@ class Extensions(object): def __len__(self): return len(self._extensions) + def __repr__(self): + return ( + "".format(self._extensions) + ) + @utils.register_interface(ExtensionType) class AuthorityKeyIdentifier(object): diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py index 1bc14620..8f469366 100644 --- a/tests/test_x509_ext.py +++ b/tests/test_x509_ext.py @@ -857,6 +857,20 @@ class TestExtensions(object): assert ext is not None assert isinstance(ext.value, x509.BasicConstraints) + def test_repr(self, backend): + cert = _load_cert( + os.path.join( + "x509", "custom", "basic_constraints_not_critical.pem" + ), + x509.load_pem_x509_certificate, + backend + ) + assert repr(cert.extensions) == ( + ", critical=False, value=)>])>" + ) + @pytest.mark.requires_backend_interface(interface=RSABackend) @pytest.mark.requires_backend_interface(interface=X509Backend) -- cgit v1.2.3 -- cgit v1.2.3