aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS.rst1
-rw-r--r--CHANGELOG.rst6
-rw-r--r--dev-requirements.txt1
-rw-r--r--docs/community.rst2
-rw-r--r--docs/conf.py2
-rw-r--r--docs/development/c-bindings.rst2
-rw-r--r--docs/development/submitting-patches.rst3
-rw-r--r--docs/development/test-vectors.rst63
-rw-r--r--docs/hazmat/backends/openssl.rst2
-rw-r--r--docs/hazmat/bindings/openssl.rst2
-rw-r--r--docs/hazmat/primitives/asymmetric/dsa.rst3
-rw-r--r--docs/hazmat/primitives/asymmetric/ec.rst4
-rw-r--r--docs/hazmat/primitives/asymmetric/index.rst1
-rw-r--r--docs/hazmat/primitives/asymmetric/rsa.rst2
-rw-r--r--docs/hazmat/primitives/asymmetric/serialization.rst39
-rw-r--r--docs/hazmat/primitives/asymmetric/utils.rst26
-rw-r--r--docs/hazmat/primitives/interfaces.rst6
-rw-r--r--docs/hazmat/primitives/symmetric-encryption.rst2
-rw-r--r--docs/spelling_wordlist.txt1
-rw-r--r--pytest.ini5
-rw-r--r--setup.py2
-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
-rw-r--r--tasks.py3
-rw-r--r--tests/hazmat/primitives/test_asym_utils.py65
-rw-r--r--tests/hazmat/primitives/test_dsa.py73
-rw-r--r--tests/hazmat/primitives/test_ec.py55
-rw-r--r--tests/hazmat/primitives/test_rsa.py53
-rw-r--r--tests/hazmat/primitives/test_serialization.py122
-rw-r--r--tests/test_utils.py22
-rw-r--r--tests/utils.py17
-rw-r--r--tox.ini7
-rw-r--r--vectors/cryptography_vectors/x509/custom/dsa_selfsigned_ca.pem31
-rw-r--r--vectors/cryptography_vectors/x509/custom/ec_no_named_curve.pem16
-rw-r--r--vectors/cryptography_vectors/x509/custom/invalid_version.pem22
-rw-r--r--vectors/cryptography_vectors/x509/custom/post2000utctime.pem24
-rw-r--r--vectors/cryptography_vectors/x509/ecdsa_root.pem15
-rw-r--r--vectors/cryptography_vectors/x509/v1_cert.pem10
47 files changed, 909 insertions, 122 deletions
diff --git a/AUTHORS.rst b/AUTHORS.rst
index 250b717b..c233bc86 100644
--- a/AUTHORS.rst
+++ b/AUTHORS.rst
@@ -18,3 +18,4 @@ PGP key fingerprints are enclosed in parentheses.
* Matthew Iversen <matt@notevencode.com> (2F04 3DCC D6E6 D5AC D262 2E0B C046 E8A8 7452 2973)
* Mohammed Attia <skeuomorf@gmail.com> (854A F9C5 9FF5 6E38 B17D 9587 2D70 E1ED 5290 D357)
* Michael Hart <michael.hart1994@gmail.com>
+* Mark Adams <mark@markadams.me> (A18A 7DD3 283C CF2A B0CE FE0E C7A0 5E3F C972 098C)
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index a0d8150d..cf6d2252 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -16,6 +16,12 @@ Changelog
* Added :class:`~cryptography.hazmat.primitives.interfaces.MACContext` as a
common interface for CMAC and HMAC and deprecated
:class:`~cryptography.hazmat.primitives.interfaces.CMACContext`.
+* Added support for encoding and decoding :rfc:`6979` signatures in
+ :doc:`/hazmat/primitives/asymmetric/utils`.
+* Added
+ :func:`~cryptography.hazmat.primitives.serialization.load_ssh_public_key` to
+ support the loading of OpenSSH public keys (:rfc:`4253`). Currently, only RSA
+ keys are supported.
0.6.1 - 2014-10-15
~~~~~~~~~~~~~~~~~~
diff --git a/dev-requirements.txt b/dev-requirements.txt
index 4fff76b5..092b9914 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -5,7 +5,6 @@ invoke
iso8601
pep8-naming
pretend
-pyasn1
pytest
requests
sphinx
diff --git a/docs/community.rst b/docs/community.rst
index bf1cd1c7..2b7cdc60 100644
--- a/docs/community.rst
+++ b/docs/community.rst
@@ -17,4 +17,4 @@ Conduct`_.
.. _`Source code`: https://github.com/pyca/cryptography
.. _`Issue tracker`: https://github.com/pyca/cryptography/issues
.. _`Documentation`: https://cryptography.io/
-.. _`Python Community Code of Conduct`: http://www.python.org/psf/codeofconduct/
+.. _`Python Community Code of Conduct`: https://www.python.org/psf/codeofconduct/
diff --git a/docs/conf.py b/docs/conf.py
index b70114d8..fc16b38a 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -268,6 +268,6 @@ texinfo_documents = [
# texinfo_show_urls = 'footnote'
# Example configuration for intersphinx: refer to the Python standard library.
-intersphinx_mapping = {'http://docs.python.org/': None}
+intersphinx_mapping = {'https://docs.python.org/': None}
epub_theme = 'epub'
diff --git a/docs/development/c-bindings.rst b/docs/development/c-bindings.rst
index 10d5fc10..993a4ab2 100644
--- a/docs/development/c-bindings.rst
+++ b/docs/development/c-bindings.rst
@@ -3,7 +3,7 @@ C bindings
C bindings are bindings to C libraries, using cffi_ whenever possible.
-.. _cffi: http://cffi.readthedocs.org
+.. _cffi: https://cffi.readthedocs.org
Bindings live in :py:mod:`cryptography.hazmat.bindings`.
diff --git a/docs/development/submitting-patches.rst b/docs/development/submitting-patches.rst
index ff650c4f..810b8748 100644
--- a/docs/development/submitting-patches.rst
+++ b/docs/development/submitting-patches.rst
@@ -25,6 +25,9 @@ configuration. You can also run the ``tox`` job with ``tox -e pep8``.
`Write comments as complete sentences.`_
+Class names which contains acronyms or initialisms should always be
+capitalized. A class should be named ``HTTPClient``, not ``HttpClient``.
+
Every code file must start with the boilerplate licensing notice:
.. code-block:: python
diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst
index 8c2d1361..10c20dba 100644
--- a/docs/development/test-vectors.rst
+++ b/docs/development/test-vectors.rst
@@ -34,10 +34,48 @@ Asymmetric ciphers
`enc2-rsa-pkcs8.pem`_ was re-encrypted using a stronger PKCS#8 cipher.
* `Botan's ECC private keys`_.
+Custom Asymmetric Vectors
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* ``ec_private_key.pem`` - Contains an Elliptic Curve key generated by OpenSSL
+ from the curve ``secp256r1``.
+* ``ec_private_key_encrypted.pem`` - Contains the same Elliptic Curve key as
+ ``ec_private_key.pem``, except that it is encrypted with AES-128 with the
+ password "123456".
+* ``ec_public_key.pem`` - Contains the public key corresponding to
+ ``ec_private_key.pem``, generated using OpenSSL.
+* ``rsa_private_key.pem`` - Contains an RSA 2048 bit key generated using
+ OpenSSL, protected by the secret "123456" with DES3 encryption.
+* ``rsa_public_key.pem`` - Contains an RSA 2048 bit public generated using
+ OpenSSL from ``rsa_private_key.pem``.
+* ``dsaparam.pem`` - Contains 2048-bit DSA parameters generated using OpenSSL;
+ contains no keys.
+* ``dsa_private_key.pem`` - Contains a DSA 2048 bit key generated using
+ OpenSSL from the parameters in ``dsaparam.pem``, protected by the secret
+ "123456" with DES3 encryption.
+* ``dsa_public_key.pem`` - Contains a DSA 2048 bit key generated using OpenSSL
+ from ``dsa_private_key.pem``.
+
+
X.509
~~~~~
* PKITS test suite from `NIST PKI Testing`_.
+* ``v1_cert.pem`` from the OpenSSL source tree (`testx509.pem`_).
+* ``ecdsa_root.pem`` - `DigiCert Global Root G3`_, a ``secp384r1`` ECDSA root
+ certificate.
+
+Custom X.509 Vectors
+~~~~~~~~~~~~~~~~~~~~
+
+* ``invalid_version.pem`` - Contains an RSA 2048 bit certificate with the
+ X.509 version field set to ``0x7``.
+* ``post2000utctime.pem`` - Contains an RSA 2048 bit certificate with the
+ ``notBefore`` and ``notAfter`` fields encoded as post-2000 ``UTCTime``.
+* ``dsa_selfsigned_ca.pem`` - Contains a DSA self-signed CA certificate
+ generated using OpenSSL.
+* ``ec_no_named_curve.pem`` - Contains an ECDSA certificate that does not have
+ an embedded OID defining the curve.
Hashes
~~~~~~
@@ -107,27 +145,8 @@ Creating test vectors
When official vectors are unavailable ``cryptography`` may choose to build
its own using existing vectors as source material.
-Current custom vectors
-~~~~~~~~~~~~~~~~~~~~~~
-
-* ``ec_private_key.pem`` - Contains an Elliptic Curve key generated by OpenSSL
- from the curve ``secp256r1``.
-* ``ec_private_key_encrypted.pem`` - Contains the same Elliptic Curve key as
- ``ec_private_key.pem``, except that it is encrypted with AES-128 with the
- password "123456".
-* ``ec_public_key.pem`` - Contains the public key corresponding to
- ``ec_private_key.pem``, generated using OpenSSL.
-* ``rsa_private_key.pem`` - Contains an RSA 2048 bit key generated using
- OpenSSL, protected by the secret "123456" with DES3 encryption.
-* ``rsa_public_key.pem`` - Contains an RSA 2048 bit public generated using
- OpenSSL from ``rsa_private_key.pem``.
-* ``dsaparam.pem`` - Contains 2048-bit DSA parameters generated using OpenSSL;
- contains no keys.
-* ``dsa_private_key.pem`` - Contains a DSA 2048 bit key generated using
- OpenSSL from the parameters in ``dsaparam.pem``, protected by the secret
- "123456" with DES3 encryption.
-* ``dsa_public_key.pem`` - Contains a DSA 2048 bit key generated using OpenSSL
- from ``dsa_private_key.pem``.
+Custom Symmetric Vectors
+~~~~~~~~~~~~~~~~~~~~~~~~
.. toctree::
:maxdepth: 1
@@ -174,3 +193,5 @@ header format (substituting the correct information):
.. _`Ed25519 website`: http://ed25519.cr.yp.to/software.html
.. _`NIST SP-800-38B`: http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
.. _`NIST PKI Testing`: http://csrc.nist.gov/groups/ST/crypto_apps_infra/pki/pkitesting.html
+.. _`testx509.pem`: https://github.com/openssl/openssl/blob/master/test/testx509.pem
+.. _`DigiCert Global Root G3`: http://cacerts.digicert.com/DigiCertGlobalRootG3.crt
diff --git a/docs/hazmat/backends/openssl.rst b/docs/hazmat/backends/openssl.rst
index e829798a..b48e502d 100644
--- a/docs/hazmat/backends/openssl.rst
+++ b/docs/hazmat/backends/openssl.rst
@@ -78,5 +78,5 @@ seeded from the same pool as ``/dev/random``.
.. _`OpenSSL`: https://www.openssl.org/
.. _`initializing the RNG`: https://en.wikipedia.org/wiki/OpenSSL#Predictable_keys_.28Debian-specific.29
-.. _`Yarrow`: http://en.wikipedia.org/wiki/Yarrow_algorithm
+.. _`Yarrow`: https://en.wikipedia.org/wiki/Yarrow_algorithm
.. _`Microsoft documentation`: http://msdn.microsoft.com/en-us/library/windows/desktop/aa379942(v=vs.85).aspx
diff --git a/docs/hazmat/bindings/openssl.rst b/docs/hazmat/bindings/openssl.rst
index a6d1c484..36255b52 100644
--- a/docs/hazmat/bindings/openssl.rst
+++ b/docs/hazmat/bindings/openssl.rst
@@ -46,4 +46,4 @@ OpenSSL.
.. _`CFFI`: https://cffi.readthedocs.org/
.. _`OpenSSL`: https://www.openssl.org/
-.. _`thread safety facilities`: http://www.openssl.org/docs/crypto/threads.html
+.. _`thread safety facilities`: https://www.openssl.org/docs/crypto/threads.html
diff --git a/docs/hazmat/primitives/asymmetric/dsa.rst b/docs/hazmat/primitives/asymmetric/dsa.rst
index 43741ede..df3c99fc 100644
--- a/docs/hazmat/primitives/asymmetric/dsa.rst
+++ b/docs/hazmat/primitives/asymmetric/dsa.rst
@@ -80,7 +80,8 @@ provider.
>>> signature = signer.finalize()
The ``signature`` is a ``bytes`` object, whose contents is DER encoded as
-described in :rfc:`6979`.
+described in :rfc:`6979`. This can be decoded using
+:func:`~cryptography.hazmat.primitives.asymmetric.utils.decode_rfc6979_signature`.
Verification
~~~~~~~~~~~~
diff --git a/docs/hazmat/primitives/asymmetric/ec.rst b/docs/hazmat/primitives/asymmetric/ec.rst
index fd20cbb2..13ab7c11 100644
--- a/docs/hazmat/primitives/asymmetric/ec.rst
+++ b/docs/hazmat/primitives/asymmetric/ec.rst
@@ -53,7 +53,9 @@ Elliptic Curve Signature Algorithms
>>> signature = signer.finalize()
The ``signature`` is a ``bytes`` object, whose contents is DER encoded as
- described in :rfc:`6979`.
+ described in :rfc:`6979`. This can be decoded using
+ :func:`~cryptography.hazmat.primitives.asymmetric.utils.decode_rfc6979_signature`.
+
.. class:: EllipticCurvePrivateNumbers(private_value, public_numbers)
diff --git a/docs/hazmat/primitives/asymmetric/index.rst b/docs/hazmat/primitives/asymmetric/index.rst
index 6a5228ba..24f0f5b1 100644
--- a/docs/hazmat/primitives/asymmetric/index.rst
+++ b/docs/hazmat/primitives/asymmetric/index.rst
@@ -11,3 +11,4 @@ Asymmetric algorithms
rsa
padding
serialization
+ utils
diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst
index a5cebb1d..6c96090a 100644
--- a/docs/hazmat/primitives/asymmetric/rsa.rst
+++ b/docs/hazmat/primitives/asymmetric/rsa.rst
@@ -271,4 +271,4 @@ this without having to do the math themselves.
.. _`use 65537`: http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html
.. _`at least 2048`: http://www.ecrypt.eu.org/documents/D.SPA.20.pdf
.. _`OpenPGP`: https://en.wikipedia.org/wiki/Pretty_Good_Privacy
-.. _`Chinese Remainder Theorem`: http://en.wikipedia.org/wiki/RSA_%28cryptosystem%29#Using_the_Chinese_remainder_algorithm
+.. _`Chinese Remainder Theorem`: https://en.wikipedia.org/wiki/RSA_%28cryptosystem%29#Using_the_Chinese_remainder_algorithm
diff --git a/docs/hazmat/primitives/asymmetric/serialization.rst b/docs/hazmat/primitives/asymmetric/serialization.rst
index b0b37b80..a9392c7b 100644
--- a/docs/hazmat/primitives/asymmetric/serialization.rst
+++ b/docs/hazmat/primitives/asymmetric/serialization.rst
@@ -195,3 +195,42 @@ KEY-----`` or ``-----BEGIN DSA PRIVATE KEY-----``.
:raises UnsupportedAlgorithm: If the serialized key is of a type that
is not supported by the backend or if the key is encrypted with a
symmetric cipher that is not supported by the backend.
+
+OpenSSH Public Key
+~~~~~~~~~~~~~~~~~~
+
+The format used by OpenSSH to store public keys, as specified in :rfc:`4253`.
+
+Currently, only RSA public keys are supported. Any other type of key will
+result in an exception being thrown.
+
+An example RSA key in OpenSSH format (line breaks added for formatting
+purposes)::
+
+ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDu/XRP1kyK6Cgt36gts9XAk
+ FiiuJLW6RU0j3KKVZSs1I7Z3UmU9/9aVh/rZV43WQG8jaR6kkcP4stOR0DEtll
+ PDA7ZRBnrfiHpSQYQ874AZaAoIjgkv7DBfsE6gcDQLub0PFjWyrYQUJhtOLQEK
+ vY/G0vt2iRL3juawWmCFdTK3W3XvwAdgGk71i6lHt+deOPNEPN2H58E4odrZ2f
+ sxn/adpDqfb2sM0kPwQs0aWvrrKGvUaustkivQE4XWiSFnB0oJB/lKK/CKVKuy
+ ///ImSCGHQRvhwariN2tvZ6CBNSLh3iQgeB0AkyJlng7MXB2qYq/Ci2FUOryCX
+ 2MzHvnbv testkey@localhost
+
+.. function:: load_ssh_public_key(data, backend)
+
+ .. versionadded:: 0.7
+
+ Deserialize a public key from OpenSSH (:rfc:`4253`) encoded data to an
+ instance of the public key type for the specified backend.
+
+ :param bytes data: The OpenSSH encoded key data.
+
+ :param backend: An
+ :class:`~cryptography.hazmat.backends.interfaces.RSABackend` provider.
+
+ :returns: A new instance of a public key type.
+
+ :raises ValueError: If the OpenSSH data could not be properly decoded or
+ if the key is not in the proper format.
+
+ :raises UnsupportedAlgorithm: If the serialized key is of a type that is
+ not supported.
diff --git a/docs/hazmat/primitives/asymmetric/utils.rst b/docs/hazmat/primitives/asymmetric/utils.rst
new file mode 100644
index 00000000..6b348801
--- /dev/null
+++ b/docs/hazmat/primitives/asymmetric/utils.rst
@@ -0,0 +1,26 @@
+.. hazmat::
+
+Asymmetric Utilities
+====================
+
+.. currentmodule:: cryptography.hazmat.primitives.asymmetric.utils
+
+
+.. function:: decode_rfc6979_signature(signature)
+
+ Takes in :rfc:`6979` signatures generated by the DSA/ECDSA signers and
+ returns a tuple ``(r, s)``.
+
+ :param bytes signature: The signature to decode.
+
+ :returns: The decoded tuple ``(r, s)``.
+
+.. function:: encode_rfc6979_signature(r, s)
+
+ Creates an :rfc:`6979` byte string from raw signature values.
+
+ :param int r: The raw signature value ``r``.
+
+ :param int s: The raw signature value ``s``.
+
+ :return bytes: The encoded signature.
diff --git a/docs/hazmat/primitives/interfaces.rst b/docs/hazmat/primitives/interfaces.rst
index d964f25c..d87e8d66 100644
--- a/docs/hazmat/primitives/interfaces.rst
+++ b/docs/hazmat/primitives/interfaces.rst
@@ -9,7 +9,7 @@ properties and methods of most primitive constructs. Backends may also use
this information to influence their operation. Interfaces should also be used
to document argument and return types.
-.. _`Abstract Base Classes`: http://docs.python.org/3.2/library/abc.html
+.. _`Abstract Base Classes`: https://docs.python.org/3/library/abc.html
Symmetric ciphers
@@ -752,5 +752,5 @@ X509
.. _`Chinese remainder theorem`: https://en.wikipedia.org/wiki/Chinese_remainder_theorem
.. _`DSA`: https://en.wikipedia.org/wiki/Digital_Signature_Algorithm
.. _`CMAC`: https://en.wikipedia.org/wiki/CMAC
-.. _`ECDSA`: http://en.wikipedia.org/wiki/ECDSA
-.. _`EdDSA`: http://en.wikipedia.org/wiki/EdDSA
+.. _`ECDSA`: https://en.wikipedia.org/wiki/ECDSA
+.. _`EdDSA`: https://en.wikipedia.org/wiki/EdDSA
diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst
index 586285b7..b21ef612 100644
--- a/docs/hazmat/primitives/symmetric-encryption.rst
+++ b/docs/hazmat/primitives/symmetric-encryption.rst
@@ -510,6 +510,6 @@ Interfaces
.. _`Communications Security Establishment`: http://www.cse-cst.gc.ca
.. _`encrypt`: https://ssd.eff.org/tech/encryption
.. _`CRYPTREC`: http://www.cryptrec.go.jp/english/
-.. _`significant patterns in the output`: http://en.wikipedia.org/wiki/Cipher_block_chaining#Electronic_codebook_.28ECB.29
+.. _`significant patterns in the output`: https://en.wikipedia.org/wiki/Cipher_block_chaining#Electronic_codebook_.28ECB.29
.. _`International Data Encryption Algorithm`: https://en.wikipedia.org/wiki/International_Data_Encryption_Algorithm
.. _`OpenPGP`: http://www.openpgp.org
diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt
index b7b33436..003e37d5 100644
--- a/docs/spelling_wordlist.txt
+++ b/docs/spelling_wordlist.txt
@@ -24,6 +24,7 @@ fernet
Fernet
hazmat
indistinguishability
+initialisms
interoperable
introspectability
invariants
diff --git a/pytest.ini b/pytest.ini
deleted file mode 100644
index 0567f800..00000000
--- a/pytest.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[pytest]
-addopts = -r s
-markers =
- requires_backend_interface: this test requires a specific backend interface
- supported: parametrized test requiring only_if and skip_message
diff --git a/setup.py b/setup.py
index 7a76909b..3e2ab3eb 100644
--- a/setup.py
+++ b/setup.py
@@ -36,6 +36,7 @@ VECTORS_DEPENDENCY = "cryptography_vectors=={0}".format(about['__version__'])
requirements = [
CFFI_DEPENDENCY,
+ "pyasn1",
SIX_DEPENDENCY,
SETUPTOOLS_DEPENDENCY
]
@@ -43,7 +44,6 @@ requirements = [
# If you add a new dep here you probably need to add it in the tox.ini as well
test_requirements = [
"pytest",
- "pyasn1",
"pretend",
"iso8601",
]
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))
diff --git a/tasks.py b/tasks.py
index 2dd005ba..c109f149 100644
--- a/tasks.py
+++ b/tasks.py
@@ -17,6 +17,9 @@ JENKINS_URL = "https://jenkins.cryptography.io/job/cryptography-wheel-builder"
def wait_for_build_completed(session):
+ # Wait 3 seconds before actually checking if the build is complete, to
+ # ensure that it had time to really start.
+ time.sleep(3)
while True:
response = session.get(
"{0}/lastBuild/api/json/".format(JENKINS_URL),
diff --git a/tests/hazmat/primitives/test_asym_utils.py b/tests/hazmat/primitives/test_asym_utils.py
new file mode 100644
index 00000000..bf55bad8
--- /dev/null
+++ b/tests/hazmat/primitives/test_asym_utils.py
@@ -0,0 +1,65 @@
+# 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 pytest
+
+from cryptography.hazmat.primitives.asymmetric.utils import (
+ decode_rfc6979_signature, encode_rfc6979_signature
+)
+
+
+def test_rfc6979_signature():
+ sig = encode_rfc6979_signature(1, 1)
+ assert sig == b"0\x06\x02\x01\x01\x02\x01\x01"
+ assert decode_rfc6979_signature(sig) == (1, 1)
+
+ r_s1 = (
+ 1037234182290683143945502320610861668562885151617,
+ 559776156650501990899426031439030258256861634312
+ )
+ sig2 = encode_rfc6979_signature(*r_s1)
+ assert sig2 == (
+ b'0-\x02\x15\x00\xb5\xaf0xg\xfb\x8bT9\x00\x13\xccg\x02\r\xdf\x1f,\x0b'
+ b'\x81\x02\x14b\r;"\xabP1D\x0c>5\xea\xb6\xf4\x81)\x8f\x9e\x9f\x08'
+ )
+ assert decode_rfc6979_signature(sig2) == r_s1
+
+ sig3 = encode_rfc6979_signature(0, 0)
+ assert sig3 == b"0\x06\x02\x01\x00\x02\x01\x00"
+ assert decode_rfc6979_signature(sig3) == (0, 0)
+
+ sig4 = encode_rfc6979_signature(-1, 0)
+ assert sig4 == b"0\x06\x02\x01\xFF\x02\x01\x00"
+ assert decode_rfc6979_signature(sig4) == (-1, 0)
+
+
+def test_encode_rfc6979_non_integer():
+ with pytest.raises(ValueError):
+ encode_rfc6979_signature("h", 3)
+
+ with pytest.raises(ValueError):
+ encode_rfc6979_signature("3", "2")
+
+ with pytest.raises(ValueError):
+ encode_rfc6979_signature(3, "h")
+
+ with pytest.raises(ValueError):
+ encode_rfc6979_signature(3.3, 1.2)
+
+ with pytest.raises(ValueError):
+ encode_rfc6979_signature("hello", "world")
+
+
+def test_decode_rfc6979_trailing_bytes():
+ with pytest.raises(ValueError):
+ decode_rfc6979_signature(b"0\x06\x02\x01\x01\x02\x01\x01\x00\x00\x00")
+
+
+def test_decode_rfc6979_invalid_asn1():
+ with pytest.raises(ValueError):
+ # This byte sequence has an invalid ASN.1 sequence length as well as
+ # an invalid integer length for the second integer.
+ decode_rfc6979_signature(b"0\x07\x02\x01\x01\x02\x02\x01")
diff --git a/tests/hazmat/primitives/test_dsa.py b/tests/hazmat/primitives/test_dsa.py
index 6411b7f9..8c0fb80c 100644
--- a/tests/hazmat/primitives/test_dsa.py
+++ b/tests/hazmat/primitives/test_dsa.py
@@ -12,14 +12,17 @@ from cryptography.exceptions import AlreadyFinalized, InvalidSignature
from cryptography.hazmat.backends.interfaces import DSABackend
from cryptography.hazmat.primitives import hashes, interfaces
from cryptography.hazmat.primitives.asymmetric import dsa
+from cryptography.hazmat.primitives.asymmetric.utils import (
+ encode_rfc6979_signature
+)
from cryptography.utils import bit_length
from .fixtures_dsa import (
DSA_KEY_1024, DSA_KEY_2048, DSA_KEY_3072
)
from ...utils import (
- der_encode_dsa_signature, load_fips_dsa_key_pair_vectors,
- load_fips_dsa_sig_vectors, load_vectors_from_file,
+ load_fips_dsa_key_pair_vectors, load_fips_dsa_sig_vectors,
+ load_vectors_from_file,
)
@@ -557,7 +560,7 @@ class TestDSAVerification(object):
),
y=vector['y']
).public_key(backend)
- sig = der_encode_dsa_signature(vector['r'], vector['s'])
+ sig = encode_rfc6979_signature(vector['r'], vector['s'])
verifier = public_key.verifier(sig, algorithm())
verifier.update(vector['msg'])
if vector['result'] == "F":
@@ -702,3 +705,67 @@ class TestDSANumbers(object):
with pytest.raises(TypeError):
dsa.DSAPrivateNumbers(x=None, public_numbers=public_numbers)
+
+
+class TestDSANumberEquality(object):
+ def test_parameter_numbers_eq(self):
+ param = dsa.DSAParameterNumbers(1, 2, 3)
+ assert param == dsa.DSAParameterNumbers(1, 2, 3)
+
+ def test_parameter_numbers_ne(self):
+ param = dsa.DSAParameterNumbers(1, 2, 3)
+ assert param != dsa.DSAParameterNumbers(1, 2, 4)
+ assert param != dsa.DSAParameterNumbers(1, 1, 3)
+ assert param != dsa.DSAParameterNumbers(2, 2, 3)
+ assert param != object()
+
+ def test_public_numbers_eq(self):
+ pub = dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 3))
+ assert pub == dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 3))
+
+ def test_public_numbers_ne(self):
+ pub = dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 3))
+ assert pub != dsa.DSAPublicNumbers(2, dsa.DSAParameterNumbers(1, 2, 3))
+ assert pub != dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(2, 2, 3))
+ assert pub != dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 3, 3))
+ assert pub != dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 4))
+ assert pub != object()
+
+ def test_private_numbers_eq(self):
+ pub = dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 3))
+ priv = dsa.DSAPrivateNumbers(1, pub)
+ assert priv == dsa.DSAPrivateNumbers(
+ 1, dsa.DSAPublicNumbers(
+ 1, dsa.DSAParameterNumbers(1, 2, 3)
+ )
+ )
+
+ def test_private_numbers_ne(self):
+ pub = dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 3))
+ priv = dsa.DSAPrivateNumbers(1, pub)
+ assert priv != dsa.DSAPrivateNumbers(
+ 2, dsa.DSAPublicNumbers(
+ 1, dsa.DSAParameterNumbers(1, 2, 3)
+ )
+ )
+ assert priv != dsa.DSAPrivateNumbers(
+ 1, dsa.DSAPublicNumbers(
+ 2, dsa.DSAParameterNumbers(1, 2, 3)
+ )
+ )
+ assert priv != dsa.DSAPrivateNumbers(
+ 1, dsa.DSAPublicNumbers(
+ 1, dsa.DSAParameterNumbers(2, 2, 3)
+ )
+ )
+ assert priv != dsa.DSAPrivateNumbers(
+ 1, dsa.DSAPublicNumbers(
+ 1, dsa.DSAParameterNumbers(1, 3, 3)
+ )
+ )
+ assert priv != dsa.DSAPrivateNumbers(
+ 1, dsa.DSAPublicNumbers(
+ 1, dsa.DSAParameterNumbers(1, 2, 4)
+ )
+ )
+ assert priv != object()
diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py
index 3080a6c2..84c447c1 100644
--- a/tests/hazmat/primitives/test_ec.py
+++ b/tests/hazmat/primitives/test_ec.py
@@ -13,11 +13,13 @@ from cryptography import exceptions, utils
from cryptography.hazmat.backends.interfaces import EllipticCurveBackend
from cryptography.hazmat.primitives import hashes, interfaces
from cryptography.hazmat.primitives.asymmetric import ec
+from cryptography.hazmat.primitives.asymmetric.utils import (
+ encode_rfc6979_signature
+)
from ...utils import (
- der_encode_dsa_signature, load_fips_ecdsa_key_pair_vectors,
- load_fips_ecdsa_signing_vectors, load_vectors_from_file,
- raises_unsupported_algorithm
+ load_fips_ecdsa_key_pair_vectors, load_fips_ecdsa_signing_vectors,
+ load_vectors_from_file, raises_unsupported_algorithm
)
_HASH_TYPES = {
@@ -305,10 +307,7 @@ class TestECDSAVectors(object):
curve_type()
).public_key(backend)
- signature = der_encode_dsa_signature(
- vector['r'],
- vector['s']
- )
+ signature = encode_rfc6979_signature(vector['r'], vector['s'])
verifier = key.verifier(
signature,
@@ -337,10 +336,7 @@ class TestECDSAVectors(object):
curve_type()
).public_key(backend)
- signature = der_encode_dsa_signature(
- vector['r'],
- vector['s']
- )
+ signature = encode_rfc6979_signature(vector['r'], vector['s'])
verifier = key.verifier(
signature,
@@ -364,3 +360,40 @@ class TestECDSAVectors(object):
numbers = ec.EllipticCurvePrivateNumbers(1, pub_numbers)
assert numbers.private_key(b) == b"private_key"
assert pub_numbers.public_key(b) == b"public_key"
+
+
+class TestECNumbersEquality(object):
+ def test_public_numbers_eq(self):
+ pub = ec.EllipticCurvePublicNumbers(1, 2, ec.SECP192R1())
+ assert pub == ec.EllipticCurvePublicNumbers(1, 2, ec.SECP192R1())
+
+ def test_public_numbers_ne(self):
+ pub = ec.EllipticCurvePublicNumbers(1, 2, ec.SECP192R1())
+ assert pub != ec.EllipticCurvePublicNumbers(1, 2, ec.SECP384R1())
+ assert pub != ec.EllipticCurvePublicNumbers(1, 3, ec.SECP192R1())
+ assert pub != ec.EllipticCurvePublicNumbers(2, 2, ec.SECP192R1())
+ assert pub != object()
+
+ def test_private_numbers_eq(self):
+ pub = ec.EllipticCurvePublicNumbers(1, 2, ec.SECP192R1())
+ priv = ec.EllipticCurvePrivateNumbers(1, pub)
+ assert priv == ec.EllipticCurvePrivateNumbers(
+ 1, ec.EllipticCurvePublicNumbers(1, 2, ec.SECP192R1())
+ )
+
+ def test_private_numbers_ne(self):
+ pub = ec.EllipticCurvePublicNumbers(1, 2, ec.SECP192R1())
+ priv = ec.EllipticCurvePrivateNumbers(1, pub)
+ assert priv != ec.EllipticCurvePrivateNumbers(
+ 2, ec.EllipticCurvePublicNumbers(1, 2, ec.SECP192R1())
+ )
+ assert priv != ec.EllipticCurvePrivateNumbers(
+ 1, ec.EllipticCurvePublicNumbers(2, 2, ec.SECP192R1())
+ )
+ assert priv != ec.EllipticCurvePrivateNumbers(
+ 1, ec.EllipticCurvePublicNumbers(1, 3, ec.SECP192R1())
+ )
+ assert priv != ec.EllipticCurvePrivateNumbers(
+ 1, ec.EllipticCurvePublicNumbers(1, 2, ec.SECP521R1())
+ )
+ assert priv != object()
diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py
index 581976ae..095ed037 100644
--- a/tests/hazmat/primitives/test_rsa.py
+++ b/tests/hazmat/primitives/test_rsa.py
@@ -18,7 +18,9 @@ from cryptography.exceptions import (
from cryptography.hazmat.backends.interfaces import RSABackend
from cryptography.hazmat.primitives import hashes, interfaces
from cryptography.hazmat.primitives.asymmetric import padding, rsa
-from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicNumbers
+from cryptography.hazmat.primitives.asymmetric.rsa import (
+ RSAPrivateNumbers, RSAPublicNumbers
+)
from .fixtures_rsa import (
RSA_KEY_1024, RSA_KEY_1025, RSA_KEY_1026, RSA_KEY_1027, RSA_KEY_1028,
@@ -1647,3 +1649,52 @@ class TestRSANumbers(object):
def test_public_number_repr(self):
num = RSAPublicNumbers(1, 1)
assert repr(num) == "<RSAPublicNumbers(e=1, n=1)>"
+
+
+class TestRSANumbersEquality(object):
+ def test_public_numbers_eq(self):
+ num = RSAPublicNumbers(1, 2)
+ num2 = RSAPublicNumbers(1, 2)
+ assert num == num2
+
+ def test_public_numbers_ne(self):
+ num = RSAPublicNumbers(1, 2)
+ assert num != RSAPublicNumbers(2, 2)
+ assert num != RSAPublicNumbers(1, 3)
+ assert num != object()
+
+ def test_private_numbers_eq(self):
+ pub = RSAPublicNumbers(1, 2)
+ num = RSAPrivateNumbers(1, 2, 3, 4, 5, 6, pub)
+ pub2 = RSAPublicNumbers(1, 2)
+ num2 = RSAPrivateNumbers(1, 2, 3, 4, 5, 6, pub2)
+ assert num == num2
+
+ def test_private_numbers_ne(self):
+ pub = RSAPublicNumbers(1, 2)
+ num = RSAPrivateNumbers(1, 2, 3, 4, 5, 6, pub)
+ assert num != RSAPrivateNumbers(
+ 1, 2, 3, 4, 5, 7, RSAPublicNumbers(1, 2)
+ )
+ assert num != RSAPrivateNumbers(
+ 1, 2, 3, 4, 4, 6, RSAPublicNumbers(1, 2)
+ )
+ assert num != RSAPrivateNumbers(
+ 1, 2, 3, 5, 5, 6, RSAPublicNumbers(1, 2)
+ )
+ assert num != RSAPrivateNumbers(
+ 1, 2, 4, 4, 5, 6, RSAPublicNumbers(1, 2)
+ )
+ assert num != RSAPrivateNumbers(
+ 1, 3, 3, 4, 5, 6, RSAPublicNumbers(1, 2)
+ )
+ assert num != RSAPrivateNumbers(
+ 2, 2, 3, 4, 5, 6, RSAPublicNumbers(1, 2)
+ )
+ assert num != RSAPrivateNumbers(
+ 1, 2, 3, 4, 5, 6, RSAPublicNumbers(2, 2)
+ )
+ assert num != RSAPrivateNumbers(
+ 1, 2, 3, 4, 5, 6, RSAPublicNumbers(1, 3)
+ )
+ assert num != object()
diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py
index 726e73dd..abb55751 100644
--- a/tests/hazmat/primitives/test_serialization.py
+++ b/tests/hazmat/primitives/test_serialization.py
@@ -9,16 +9,17 @@ import textwrap
import pytest
-from cryptography.exceptions import _Reasons
+from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
from cryptography.hazmat.backends.interfaces import (
EllipticCurveBackend, PEMSerializationBackend, PKCS8SerializationBackend,
- TraditionalOpenSSLSerializationBackend
+ RSABackend, TraditionalOpenSSLSerializationBackend
)
from cryptography.hazmat.primitives import interfaces
from cryptography.hazmat.primitives.asymmetric import ec
+from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicNumbers
from cryptography.hazmat.primitives.serialization import (
load_pem_pkcs8_private_key, load_pem_private_key, load_pem_public_key,
- load_pem_traditional_openssl_private_key
+ load_pem_traditional_openssl_private_key, load_ssh_public_key
)
@@ -680,3 +681,118 @@ class TestPKCS8Serialization(object):
pemfile.read().encode(), password, backend
)
)
+
+
+@pytest.mark.requires_backend_interface(interface=RSABackend)
+class TestSSHSerialization(object):
+ def test_load_ssh_public_key_unsupported(self, backend):
+ ssh_key = b'ssh-dss AAAAB3NzaC1kc3MAAACBAO7q0a7VsQZcdRTCqFentQt...'
+
+ with pytest.raises(UnsupportedAlgorithm):
+ load_ssh_public_key(ssh_key, backend)
+
+ def test_load_ssh_public_key_bad_format(self, backend):
+ ssh_key = b'not-a-real-key text'
+
+ with pytest.raises(ValueError):
+ load_ssh_public_key(ssh_key, backend)
+
+ def test_load_ssh_public_key_rsa_too_short(self, backend):
+ ssh_key = b'ssh-rsa'
+
+ with pytest.raises(ValueError):
+ load_ssh_public_key(ssh_key, backend)
+
+ def test_load_ssh_public_key_rsa_key_types_dont_match(self, backend):
+ ssh_key = (
+ b"ssh-bad AAAAB3NzaC1yc2EAAAADAQABAAABAQDDu/XRP1kyK6Cgt36gts9XAk"
+ b"FiiuJLW6RU0j3KKVZSs1I7Z3UmU9/9aVh/rZV43WQG8jaR6kkcP4stOR0DEtll"
+ b"PDA7ZRBnrfiHpSQYQ874AZaAoIjgkv7DBfsE6gcDQLub0PFjWyrYQUJhtOLQEK"
+ b"vY/G0vt2iRL3juawWmCFdTK3W3XvwAdgGk71i6lHt+deOPNEPN2H58E4odrZ2f"
+ b"sxn/adpDqfb2sM0kPwQs0aWvrrKGvUaustkivQE4XWiSFnB0oJB/lKK/CKVKuy"
+ b"///ImSCGHQRvhwariN2tvZ6CBNSLh3iQgeB0AkyJlng7MXB2qYq/Ci2FUOryCX"
+ b"2MzHvnbv testkey@localhost extra"
+ )
+
+ with pytest.raises(ValueError):
+ load_ssh_public_key(ssh_key, backend)
+
+ def test_load_ssh_public_key_rsa_extra_string_after_comment(self, backend):
+ ssh_key = (
+ b"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDu/XRP1kyK6Cgt36gts9XAk"
+ b"FiiuJLW6RU0j3KKVZSs1I7Z3UmU9/9aVh/rZV43WQG8jaR6kkcP4stOR0DEtll"
+ b"PDA7ZRBnrfiHpSQYQ874AZaAoIjgkv7DBfsE6gcDQLub0PFjWyrYQUJhtOLQEK"
+ b"vY/G0vt2iRL3juawWmCFdTK3W3XvwAdgGk71i6lHt+deOPNEPN2H58E4odrZ2f"
+ b"sxn/adpDqfb2sM0kPwQs0aWvrrKGvUaustkivQE4XWiSFnB0oJB/lKK/CKVKuy"
+ b"///ImSCGHQRvhwariN2tvZ6CBNSLh3iQgeB0AkyJlng7MXB2qYq/Ci2FUOryCX"
+ # Extra section appended
+ b"2MzHvnbv testkey@localhost extra"
+ )
+
+ with pytest.raises(ValueError):
+ load_ssh_public_key(ssh_key, backend)
+
+ def test_load_ssh_public_key_rsa_extra_data_after_modulo(self, backend):
+ ssh_key = (
+ b"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDu/XRP1kyK6Cgt36gts9XAk"
+ b"FiiuJLW6RU0j3KKVZSs1I7Z3UmU9/9aVh/rZV43WQG8jaR6kkcP4stOR0DEtll"
+ b"PDA7ZRBnrfiHpSQYQ874AZaAoIjgkv7DBfsE6gcDQLub0PFjWyrYQUJhtOLQEK"
+ b"vY/G0vt2iRL3juawWmCFdTK3W3XvwAdgGk71i6lHt+deOPNEPN2H58E4odrZ2f"
+ b"sxn/adpDqfb2sM0kPwQs0aWvrrKGvUaustkivQE4XWiSFnB0oJB/lKK/CKVKuy"
+ b"///ImSCGHQRvhwariN2tvZ6CBNSLh3iQgeB0AkyJlng7MXB2qYq/Ci2FUOryCX"
+ b"2MzHvnbvAQ== testkey@localhost"
+ )
+
+ with pytest.raises(ValueError):
+ load_ssh_public_key(ssh_key, backend)
+
+ def test_load_ssh_public_key_rsa_different_string(self, backend):
+ ssh_key = (
+ # "AAAAB3NzA" the final A is capitalized here to cause the string
+ # ssh-rsa inside the base64 encoded blob to be incorrect. It should
+ # be a lower case 'a'.
+ b"ssh-rsa AAAAB3NzAC1yc2EAAAADAQABAAABAQDDu/XRP1kyK6Cgt36gts9XAk"
+ b"FiiuJLW6RU0j3KKVZSs1I7Z3UmU9/9aVh/rZV43WQG8jaR6kkcP4stOR0DEtll"
+ b"PDA7ZRBnrfiHpSQYQ874AZaAoIjgkv7DBfsE6gcDQLub0PFjWyrYQUJhtOLQEK"
+ b"vY/G0vt2iRL3juawWmCFdTK3W3XvwAdgGk71i6lHt+deOPNEPN2H58E4odrZ2f"
+ b"sxn/adpDqfb2sM0kPwQs0aWvrrKGvUaustkivQE4XWiSFnB0oJB/lKK/CKVKuy"
+ b"///ImSCGHQRvhwariN2tvZ6CBNSLh3iQgeB0AkyJlng7MXB2qYq/Ci2FUOryCX"
+ b"2MzHvnbvAQ== testkey@localhost"
+ )
+ with pytest.raises(ValueError):
+ load_ssh_public_key(ssh_key, backend)
+
+ def test_load_ssh_public_key_rsa(self, backend):
+ ssh_key = (
+ b"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDu/XRP1kyK6Cgt36gts9XAk"
+ b"FiiuJLW6RU0j3KKVZSs1I7Z3UmU9/9aVh/rZV43WQG8jaR6kkcP4stOR0DEtll"
+ b"PDA7ZRBnrfiHpSQYQ874AZaAoIjgkv7DBfsE6gcDQLub0PFjWyrYQUJhtOLQEK"
+ b"vY/G0vt2iRL3juawWmCFdTK3W3XvwAdgGk71i6lHt+deOPNEPN2H58E4odrZ2f"
+ b"sxn/adpDqfb2sM0kPwQs0aWvrrKGvUaustkivQE4XWiSFnB0oJB/lKK/CKVKuy"
+ b"///ImSCGHQRvhwariN2tvZ6CBNSLh3iQgeB0AkyJlng7MXB2qYq/Ci2FUOryCX"
+ b"2MzHvnbv testkey@localhost"
+ )
+
+ key = load_ssh_public_key(ssh_key, backend)
+
+ assert key is not None
+ assert isinstance(key, interfaces.RSAPublicKey)
+
+ numbers = key.public_numbers()
+
+ expected_e = 0x10001
+ expected_n = int(
+ '00C3BBF5D13F59322BA0A0B77EA0B6CF570241628AE24B5BA454D'
+ '23DCA295652B3523B67752653DFFD69587FAD9578DD6406F23691'
+ 'EA491C3F8B2D391D0312D9653C303B651067ADF887A5241843CEF'
+ '8019680A088E092FEC305FB04EA070340BB9BD0F1635B2AD84142'
+ '61B4E2D010ABD8FC6D2FB768912F78EE6B05A60857532B75B75EF'
+ 'C007601A4EF58BA947B7E75E38F3443CDD87E7C138A1DAD9D9FB3'
+ '19FF69DA43A9F6F6B0CD243F042CD1A5AFAEB286BD46AEB2D922B'
+ 'D01385D6892167074A0907F94A2BF08A54ABB2FFFFC89920861D0'
+ '46F8706AB88DDADBD9E8204D48B87789081E074024C8996783B31'
+ '7076A98ABF0A2D8550EAF2097D8CCC7BE76EF', 16)
+
+ expected = RSAPublicNumbers(expected_e, expected_n)
+
+ assert numbers == expected
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 637c42bc..bc5f2e14 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -18,7 +18,7 @@ from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
import cryptography_vectors
from .utils import (
- check_backend_support, der_encode_dsa_signature, load_cryptrec_vectors,
+ check_backend_support, load_cryptrec_vectors,
load_fips_dsa_key_pair_vectors, load_fips_dsa_sig_vectors,
load_fips_ecdsa_key_pair_vectors, load_fips_ecdsa_signing_vectors,
load_hash_vectors, load_kasvs_dh_vectors, load_nist_vectors,
@@ -110,26 +110,6 @@ def test_check_backend_support_no_backend():
check_backend_support(item)
-def test_der_encode_dsa_signature_values():
- sig = der_encode_dsa_signature(1, 1)
- assert sig == b"0\x06\x02\x01\x01\x02\x01\x01"
-
- sig2 = der_encode_dsa_signature(
- 1037234182290683143945502320610861668562885151617,
- 559776156650501990899426031439030258256861634312
- )
- assert sig2 == (
- b'0-\x02\x15\x00\xb5\xaf0xg\xfb\x8bT9\x00\x13\xccg\x02\r\xdf\x1f,\x0b'
- b'\x81\x02\x14b\r;"\xabP1D\x0c>5\xea\xb6\xf4\x81)\x8f\x9e\x9f\x08'
- )
-
- sig3 = der_encode_dsa_signature(0, 0)
- assert sig3 == b"0\x06\x02\x01\x00\x02\x01\x00"
-
- sig4 = der_encode_dsa_signature(-1, 0)
- assert sig4 == b"0\x06\x02\x01\xFF\x02\x01\x00"
-
-
def test_load_nist_vectors():
vector_data = textwrap.dedent("""
# CAVS 11.1
diff --git a/tests/utils.py b/tests/utils.py
index 01ab4e6f..37efc580 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -9,9 +9,6 @@ import collections
import re
from contextlib import contextmanager
-from pyasn1.codec.der import encoder
-from pyasn1.type import namedtype, univ
-
import pytest
import six
@@ -73,20 +70,6 @@ def raises_unsupported_algorithm(reason):
assert exc_info.value._reason is reason
-class _DSSSigValue(univ.Sequence):
- componentType = namedtype.NamedTypes(
- namedtype.NamedType('r', univ.Integer()),
- namedtype.NamedType('s', univ.Integer())
- )
-
-
-def der_encode_dsa_signature(r, s):
- sig = _DSSSigValue()
- sig.setComponentByName('r', r)
- sig.setComponentByName('s', s)
- return encoder.encode(sig)
-
-
def load_vectors_from_file(filename, loader, mode="r"):
with cryptography_vectors.open_vector_file(filename, mode) as vector_file:
return loader(vector_file)
diff --git a/tox.ini b/tox.ini
index 151b5530..677df7e4 100644
--- a/tox.ini
+++ b/tox.ini
@@ -7,7 +7,6 @@ deps =
coverage
iso8601
pretend
- pyasn1
pytest
./vectors
commands =
@@ -77,3 +76,9 @@ application-import-names = cryptography,cryptography_vectors,tests
[doc8]
extensions = rst
+
+[pytest]
+addopts = -r s
+markers =
+ requires_backend_interface: this test requires a specific backend interface
+ supported: parametrized test requiring only_if and skip_message
diff --git a/vectors/cryptography_vectors/x509/custom/dsa_selfsigned_ca.pem b/vectors/cryptography_vectors/x509/custom/dsa_selfsigned_ca.pem
new file mode 100644
index 00000000..4348ce81
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/custom/dsa_selfsigned_ca.pem
@@ -0,0 +1,31 @@
+-----BEGIN CERTIFICATE-----
+MIIFWjCCBRqgAwIBAgIJAKNzUuCyFC+GMAkGByqGSM44BAMwZzELMAkGA1UEBhMC
+VVMxDjAMBgNVBAgTBVRleGFzMQ8wDQYDVQQHEwZBdXN0aW4xITAfBgNVBAoTGElu
+dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEUMBIGA1UEAxMLUHlDQSBEU0EgQ0EwHhcN
+MTQxMTI3MDUxNDE3WhcNMTQxMjI3MDUxNDE3WjBnMQswCQYDVQQGEwJVUzEOMAwG
+A1UECBMFVGV4YXMxDzANBgNVBAcTBkF1c3RpbjEhMB8GA1UEChMYSW50ZXJuZXQg
+V2lkZ2l0cyBQdHkgTHRkMRQwEgYDVQQDEwtQeUNBIERTQSBDQTCCAzowggItBgcq
+hkjOOAQBMIICIAKCAQEAv63mBI43PNTki2d+h4yOWwjAIQKuBOsstcRqUjo68cc9
+FrJPNKSWR4GuflBQDiF3d1SmcL0Zp0INYzCE5VVuM8osDn1UfqX0agegG/hmmuO9
+7AQtmyrl5uz0nwC6nayZq27/FA0s7fci7mLC+XNoV5cURMJdCjPSAX3DbWgqEFT+
+KpQo3aNVqFHObm1h4D5Bn9TKTnAzE3Q9hsqohZMPYu1b80LYFlYnaB6cwyRLpyqi
+IUhACmu+gBVOhV0ELJ3Co0BfHlF76d6lBWL1bak/YIX4RKfnBcHwQ+ZXUcWDuA0p
+ED5ZDMsm79qgiT2DPjZGjzkHz8p4ijy3kPA0HIoxvwIVAIIv9dI04HO5Ac9ZQfWO
+H1OOcdQNAoIBAEt87XHcNTll7MENRBqaBvwklDoy1mQp3V70TUPmfXidmXcK7DLA
+QV3JKXCICHLaRf743R4RWj5IATh7ptdVhh8GL9O26eqOJkEVIzm4KDFbFSjubHt5
+RY0h89uXP2/DA/k5cXTCeZ3SNRKCqi2IQsNXpzSVu6rEkyeGQUxV5g1zFp9XYQNv
+uinp7r+wSfijsbfO5vP7+hNiBfEwvuLPW5w43BCV1ABvLnMzXAc1LGQTChqyuJ8T
+tI9ijTzDhovuzpu3vq3p+DDqzG+iQUJcCz/MDfQWoMife/NWaNdl7JXNz76cr/Sc
+/BVsZox2+mJHZ2ptOslFhEoINQnGobQ2usoDggEFAAKCAQBMCL/l8tdmScgKz31D
+H2riEksheryMn2rKd23fqUU7ZlbxPlQ2hM1fZDGjFDd9Kr+gaLcIDLjdwGWvwt6l
+WfC1hMl6KyNbm2m0a8beGu1CKm80GDJhi8quIZiro4gJna+wX/C17+yzsK4WmmLh
+xyAir1CuaK87AzwY5u7B999GksRWzK+3nMfgjaCleG6YFs7aZR1htLt7gcJ4Pal8
+6mLfZ69ehZkf3BOv8Q/GDgZYY4a5a7eNZXUPVC+GlR4FptgbqtvNNaLlytQRmSOu
+aiACCRo9FwF/k8UpcBE83BGZcLkHTKUG6skcPdN2Ml30r2s5Ee8mfSZiOlocXfSm
+0T8co4HMMIHJMB0GA1UdDgQWBBSk+4h6E/zeswO7rpod7KcvElpUGzCBmQYDVR0j
+BIGRMIGOgBSk+4h6E/zeswO7rpod7KcvElpUG6FrpGkwZzELMAkGA1UEBhMCVVMx
+DjAMBgNVBAgTBVRleGFzMQ8wDQYDVQQHEwZBdXN0aW4xITAfBgNVBAoTGEludGVy
+bmV0IFdpZGdpdHMgUHR5IEx0ZDEUMBIGA1UEAxMLUHlDQSBEU0EgQ0GCCQCjc1Lg
+shQvhjAMBgNVHRMEBTADAQH/MAkGByqGSM44BAMDLwAwLAIUJcSoSpNqsxHuAX08
+vZo8ZQuzrkoCFF0wxktDJoa9+SVxa07QWRhDlrzO
+-----END CERTIFICATE-----
diff --git a/vectors/cryptography_vectors/x509/custom/ec_no_named_curve.pem b/vectors/cryptography_vectors/x509/custom/ec_no_named_curve.pem
new file mode 100644
index 00000000..4edeaa1c
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/custom/ec_no_named_curve.pem
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIICbTCCAhOgAwIBAgIBADAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztYWUxJOlpC
+M0w6NUpINjpFVVZYOldVS0o6S0w2WTpSSENPOlRFU1k6SVNYTToyWVZFOkZOSFU6
+Wkk2UTAeFw0xNDEyMTIwODAyMTdaFw0xNDEyMTMwODAyMTdaMEYxRDBCBgNVBAMT
+O1hZTEk6WkIzTDo1Skg2OkVVVlg6V1VLSjpLTDZZOlJIQ086VEVTWTpJU1hNOjJZ
+VkU6Rk5IVTpaSTZRMIIBSzCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIh
+AP////8AAAABAAAAAAAAAAAAAAAA////////////////MFsEIP////8AAAABAAAA
+AAAAAAAAAAAA///////////////8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7
+zjw+J9JgSwMVAMSdNgiG5wSTamZ44ROdJreBn36QBEEEaxfR8uEsQkf4vOblY6RA
+8ncDfYEt6zOg9KE5RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R
+9QIhAP////8AAAAA//////////+85vqtpxeehPO5ysL8YyVRAgEBA0IABO5cqNMX
+U4PWD9x2ffa/B9xvpw3poTOAQYpRHSlGV7JTYuubeZEm2vRRLXA9n1l7+JBffxZC
+r+yjS2JHNuq+0kgwCgYIKoZIzj0EAwIDSAAwRQIhAKYoc7Azt/GwTeLFBlhaLpSD
+seB3qsN1kdZH4bzylonjAiA9/nVi7fbYydpym5jnW4DpHnenoZcZdWeDVnhE0J4c
+WA==
+-----END CERTIFICATE-----
diff --git a/vectors/cryptography_vectors/x509/custom/invalid_version.pem b/vectors/cryptography_vectors/x509/custom/invalid_version.pem
new file mode 100644
index 00000000..84a55626
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/custom/invalid_version.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDjjCCAnagAwIBBwITBlqtEggCEIn2HtsUzORK3EHP0zANBgkqhkiG9w0BAQUF
+ADBXMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxDzANBgNVBAcMBkF1c3Rp
+bjENMAsGA1UECgwEUHlDQTEYMBYGA1UEAwwPQ3J5cHRvZ3JhcGh5IENBMB4XDTE0
+MTEyNjE0NDQ1N1oXDTM0MTEyMTIwNDQ1N1owVzELMAkGA1UEBhMCVVMxDjAMBgNV
+BAgMBVRleGFzMQ8wDQYDVQQHDAZBdXN0aW4xDTALBgNVBAoMBFB5Q0ExGDAWBgNV
+BAMMD0NyeXB0b2dyYXBoeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAJZPCfKbFZQ5G5gYdXbxPq7o1DFaYzeWOqBzR4M1iE1gnDTw/ZQXExVVIZga
+QU3aiiL1hZ+9NdWvmViDKlj4Qa7+8FxHhuq/Weri/itFhMcEuGs+iTclWc/H1M5J
+3OChClzKcugeOPP/ZevZXiKSB4pGd+b6esw40WSmIWBqwKpQOu8DxXX1LCP+xS9j
+ZlARDS2VqD/LP6ZbTd5odOX6kMi4dm9mVnfREUL79hMShTPt2BB7muKm2yNWmJuh
+npUWTyl0P7r+lgr1y1E+u+3YbThWe7hk2Ra21J1Xpba4v1j5WR0+IfwjbJIJA7up
+eeqB3rrZBJmPyKGVX6m8gXiYtR8CAwEAAaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAd
+BgNVHQ4EFgQUrc6wKzvf3ST5Tk+Idr37QF9pIjMwHwYDVR0jBBgwFoAUrc6wKzvf
+3ST5Tk+Idr37QF9pIjMwDQYJKoZIhvcNAQEFBQADggEBACZusajSqo9wL+Rjn0EA
+kM92FglKgZ7K3Bp1O9MPp740ytnueY7lWduiPuEjcUQUeI2nBfQYJRoucPLi/2dD
+jJgxK6BoYwvm5VJH3g65G39EYnz3L8IUCYGKJ75nffVYvlqcJkfNO+lxt11hGXMA
+w/QOdv4TsfjVVbLMcbhKtrMh5iaB5+QbcoBx21i8opg1qi3pwJ8Tgj6JxsKTjlc0
+xoZWDjPao8/dpvbfMsJwlHazZFAPdknZN8/oo0M5DWBQuxiFNoXllDsHrZNN8TAk
+Xvr/2XumAxgJJmxDqSbRBDXnwAzj9Jq3ITl4bJ8Nw9sPpS920Owv0xKtQILbo+RR
+tcA=
+-----END CERTIFICATE-----
diff --git a/vectors/cryptography_vectors/x509/custom/post2000utctime.pem b/vectors/cryptography_vectors/x509/custom/post2000utctime.pem
new file mode 100644
index 00000000..ce5c058b
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/custom/post2000utctime.pem
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIID8DCCAtigAwIBAgIJAKBstLlV9/TbMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQxETAPBgNVBAMTCEhlbGxvIENBMB4XDTE0MTEyNjIxNDEy
+MFoXDTE0MTIyNjIxNDEyMFowWDELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUt
+U3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDERMA8GA1UE
+AxMISGVsbG8gQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCwOvcC
+BZ4n8eIoS1a7smwDkVO/gfKVtzpJEymQZF7eTS2gqRPELn0401iaANOUDRlPbm2H
+fC74EtoionXoPYvnhkZ0i05/I9EOhz/XL1ehPexzL8VqsTixuzCDmbtBLNc5IU73
+FOGXbglgNAXiVWKZoFUiUQrEV0216css9fmej0jBaWqz6i1tLdq31OGzFxiLdqVy
+l39uzgpK05bwFQ59ixqZhsDLkFJ+wmylbikUwnDSoZi2MvqKL9pVB509OYZLb7lt
+2+Mxyss8uHg6hJTMzNiGo1JQeIR8oByl+APokhRAPopLVJlTnAuG96DapFsgSo4H
+nYpbA9t7obo9cBGnAgMBAAGjgbwwgbkwHQYDVR0OBBYEFNjoncd35EcmVvGGRpWp
+9mt7BACuMIGJBgNVHSMEgYEwf4AU2Oidx3fkRyZW8YZGlan2a3sEAK6hXKRaMFgx
+CzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRl
+cm5ldCBXaWRnaXRzIFB0eSBMdGQxETAPBgNVBAMTCEhlbGxvIENBggkAoGy0uVX3
+9NswDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAjg9y/L6+R1Wryvds
+jOC64XzeTbFikWOOGxzgSpPNtMRKNIYHCYbFqIDBT9+El+fSibJjDMsh0ko9GqGy
+2HSCB/Oh4WzN+Nqop+oaM9SXdPUT7fCScL2OZltjAKEPADZqWQdpBetjzxCoGgyn
+im7zEn9ssvb7f5R/ziKjDYAEjCQ7osGlTEJf4SMQ6Kc3Y49JIDVNTM4ly9neol5q
+L+DYV5pcjZKbknW+Ihl1R58/dQdbys8JUmUjtf1n92g/PNpCD6ux6eb8JrwGSc9h
+uwUdaTL6w3Bmuxb1WQPf54U9xeUF4qEPu6T56ToNO1O3+jSwXXum7vhpv8NLjlFP
+1UGfdQ==
+-----END CERTIFICATE-----
diff --git a/vectors/cryptography_vectors/x509/ecdsa_root.pem b/vectors/cryptography_vectors/x509/ecdsa_root.pem
new file mode 100644
index 00000000..bc20c1e1
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/ecdsa_root.pem
@@ -0,0 +1,15 @@
+-----BEGIN CERTIFICATE-----
+MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw
+CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
+ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe
+Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw
+EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x
+IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF
+K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG
+fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO
+Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd
+BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx
+AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/
+oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8
+sycX
+-----END CERTIFICATE-----
diff --git a/vectors/cryptography_vectors/x509/v1_cert.pem b/vectors/cryptography_vectors/x509/v1_cert.pem
new file mode 100644
index 00000000..8a85d149
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/v1_cert.pem
@@ -0,0 +1,10 @@
+-----BEGIN CERTIFICATE-----
+MIIBWzCCAQYCARgwDQYJKoZIhvcNAQEEBQAwODELMAkGA1UEBhMCQVUxDDAKBgNV
+BAgTA1FMRDEbMBkGA1UEAxMSU1NMZWF5L3JzYSB0ZXN0IENBMB4XDTk1MDYxOTIz
+MzMxMloXDTk1MDcxNzIzMzMxMlowOjELMAkGA1UEBhMCQVUxDDAKBgNVBAgTA1FM
+RDEdMBsGA1UEAxMUU1NMZWF5L3JzYSB0ZXN0IGNlcnQwXDANBgkqhkiG9w0BAQEF
+AANLADBIAkEAqtt6qS5GTxVxGZYWa0/4u+IwHf7p2LNZbcPBp9/OfIcYAXBQn8hO
+/Re1uwLKXdCjIoaGs4DLdG88rkzfyK5dPQIDAQABMAwGCCqGSIb3DQIFBQADQQAE
+Wc7EcF8po2/ZO6kNCwK/ICH6DobgLekA5lSLr5EvuioZniZp5lFzAw4+YzPQ7XKJ
+zl9HYIMxATFyqSiD9jsx
+-----END CERTIFICATE-----