aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.rst4
-rw-r--r--docs/development/test-vectors.rst18
-rw-r--r--docs/glossary.rst8
-rw-r--r--docs/hazmat/primitives/symmetric-encryption.rst13
-rw-r--r--docs/hazmat/primitives/twofactor.rst47
-rw-r--r--docs/spelling_wordlist.txt1
-rw-r--r--docs/x509.rst114
-rw-r--r--src/cryptography/__about__.py2
-rw-r--r--src/cryptography/hazmat/backends/openssl/x509.py27
-rw-r--r--src/cryptography/hazmat/bindings/openssl/asn1.py1
-rw-r--r--src/cryptography/hazmat/bindings/openssl/ssl.py10
-rw-r--r--src/cryptography/hazmat/bindings/openssl/x509.py19
-rw-r--r--src/cryptography/hazmat/bindings/openssl/x509name.py2
-rw-r--r--src/cryptography/hazmat/primitives/twofactor/hotp.py6
-rw-r--r--src/cryptography/hazmat/primitives/twofactor/totp.py6
-rw-r--r--src/cryptography/hazmat/primitives/twofactor/utils.py30
-rw-r--r--src/cryptography/x509.py146
-rw-r--r--tasks.py9
-rw-r--r--tests/hazmat/primitives/test_dh.py15
-rw-r--r--tests/hazmat/primitives/twofactor/test_hotp.py13
-rw-r--r--tests/hazmat/primitives/twofactor/test_totp.py13
-rw-r--r--tests/test_utils.py69
-rw-r--r--tests/test_x509.py84
-rw-r--r--tests/test_x509_ext.py83
-rw-r--r--tests/utils.py4
-rw-r--r--tox.ini3
-rw-r--r--vectors/cryptography_vectors/__about__.py2
-rw-r--r--vectors/cryptography_vectors/x509/custom/crl_all_reasons.pem37
-rw-r--r--vectors/cryptography_vectors/x509/custom/crl_dup_entry_ext.pem11
-rw-r--r--vectors/cryptography_vectors/x509/custom/crl_md2_unknown_crit_entry_ext.pem11
-rw-r--r--vectors/cryptography_vectors/x509/custom/crl_unsupported_reason.pem11
31 files changed, 772 insertions, 47 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 4d7a9a82..88ff1962 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,7 +1,7 @@
Changelog
=========
-0.10 - `master`_
+1.0 - `master`_
~~~~~~~~~~~~~~~~
.. note:: This version is not yet released and is under active development.
@@ -9,6 +9,8 @@ Changelog
* Support serialization of certificate signing requests using the
``public_bytes`` method of
:class:`~cryptography.x509.CertificateSigningRequest`.
+* Support serialization of certificates using the ``public_bytes`` method of
+ :class:`~cryptography.x509.Certificate`.
0.9 - 2015-05-13
~~~~~~~~~~~~~~~~
diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst
index b4f23eda..0bd1f69e 100644
--- a/docs/development/test-vectors.rst
+++ b/docs/development/test-vectors.rst
@@ -22,7 +22,7 @@ Asymmetric ciphers
* RSA FIPS 186-2 and PKCS1 v1.5 vulnerability test vectors from `NIST CAVP`_.
* FIPS 186-2 and FIPS 186-3 DSA test vectors from `NIST CAVP`_.
* FIPS 186-2 and FIPS 186-3 ECDSA test vectors from `NIST CAVP`_.
-* DH and ECDH test vectors from `NIST CAVP`_.
+* DH and ECDH and ECDH+KDF(17.4) test vectors from `NIST CAVP`_.
* Ed25519 test vectors from the `Ed25519 website_`.
* OpenSSL PEM RSA serialization vectors from the `OpenSSL example key`_ and
`GnuTLS key parsing tests`_.
@@ -234,6 +234,22 @@ Custom X.509 Request Vectors
2048 bit key containing a basic constraints extension marked as
critical.
+Custom X.509 Certificate Revocation List Vectors
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* ``crl_all_reasons.pem`` - Contains a CRL with 12 revoked certificates, whose
+ serials match their list position. It includes one revocation without
+ any entry extensions, 10 revocations with every supported reason code and one
+ revocation with an unsupported, non-critical entry extension with the OID
+ value set to "1.2.3.4".
+* ``crl_dup_entry_ext.pem`` - Contains a CRL with one revocation which has a
+ duplicate entry extension.
+* ``crl_md2_unknown_crit_entry_ext.pem`` - Contains a CRL with one revocation
+ which contains an unsupported critical entry extension with the OID value set
+ 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.
+
Hashes
~~~~~~
diff --git a/docs/glossary.rst b/docs/glossary.rst
index dc6f3ebf..202fa2de 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -64,3 +64,11 @@ Glossary
text
This type corresponds to ``unicode`` on Python 2 and ``str`` on Python
3. This is equivalent to ``six.text_type``.
+
+ nonce
+ A nonce is a **n**\ umber used **once**. Nonces are used in many
+ cryptographic protocols. Generally, a nonce does not have to be secret
+ or unpredictable, but it must be unique. A nonce is often a random
+ or pseudo-random number (see :doc:`Random number generation
+ </random-numbers>`). Since a nonce does not have to be unpredictable,
+ it can also take a form of a counter.
diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst
index 47486895..309c6fd0 100644
--- a/docs/hazmat/primitives/symmetric-encryption.rst
+++ b/docs/hazmat/primitives/symmetric-encryption.rst
@@ -240,7 +240,7 @@ Modes
**This mode does not require padding.**
- :param bytes nonce: Should be :doc:`random bytes </random-numbers>`. It is
+ :param bytes nonce: Should be unique, a :term:`nonce`. It is
critical to never reuse a ``nonce`` with a given key. Any reuse of a
nonce with the same key compromises the security of every message
encrypted with that key. Must be the same number of bytes as the
@@ -305,12 +305,11 @@ Modes
**This mode does not require padding.**
- :param bytes initialization_vector: Must be :doc:`random bytes
- </random-numbers>`. They do not need to be kept secret and they can be
- included in a transmitted message. NIST `recommends a 96-bit IV
- length`_ for performance critical situations but it can be up to
- 2\ :sup:`64` - 1 bits. Do not reuse an ``initialization_vector`` with a
- given ``key``.
+ :param bytes initialization_vector: Must be unique, a :term:`nonce`.
+ They do not need to be kept secret and they can be included in a
+ transmitted message. NIST `recommends a 96-bit IV length`_ for
+ performance critical situations but it can be up to 2\ :sup:`64` - 1
+ bits. Do not reuse an ``initialization_vector`` with a given ``key``.
.. note::
diff --git a/docs/hazmat/primitives/twofactor.rst b/docs/hazmat/primitives/twofactor.rst
index dd3e0250..df70a58a 100644
--- a/docs/hazmat/primitives/twofactor.rst
+++ b/docs/hazmat/primitives/twofactor.rst
@@ -74,6 +74,18 @@ codes (HMAC).
:raises cryptography.hazmat.primitives.twofactor.InvalidToken: This
is raised when the supplied HOTP does not match the expected HOTP.
+ .. method:: get_provisioning_uri(account_name, counter, issuer)
+
+ :param account_name: The display name of account, such as
+ ``'Alice Smith'`` or ``'alice@example.com'``.
+ :type account_name: :term:`text`
+ :param issuer: The optional display name of issuer. This is typically
+ the provider or service the user wants to access using the OTP
+ token.
+ :type issuer: :term:`text` or `None`
+ :param int counter: The current value of counter.
+ :return: A URI string.
+
Throttling
~~~~~~~~~~
@@ -171,3 +183,38 @@ similar to the following code.
:param int time: The time value to validate against.
:raises cryptography.hazmat.primitives.twofactor.InvalidToken: This
is raised when the supplied TOTP does not match the expected TOTP.
+
+ .. method:: get_provisioning_uri(account_name, issuer)
+
+ :param account_name: The display name of account, such as
+ ``'Alice Smith'`` or ``'alice@example.com'``.
+ :type: :term:`text`
+ :param issuer: The optional display name of issuer. This is typically
+ the provider or service the user wants to access using the OTP
+ token.
+ :type issuer: :term:`text` or `None`
+ :return: A URI string.
+
+Provisioning URI
+~~~~~~~~~~~~~~~~
+
+The provisioning URI of HOTP and TOTP is not actual the part of RFC 4226 and
+RFC 6238, but a `spec of Google Authenticator`_. It is widely supported by web
+sites and mobile applications which are using Two-Factor authentication.
+
+For generating a provisioning URI, you could use the ``get_provisioning_uri``
+method of HOTP/TOTP instances.
+
+.. code-block:: python
+
+ counter = 5
+ account_name = 'alice@example.com'
+ issuer_name = 'Example Inc'
+
+ hotp_uri = hotp.get_provisioning_uri(account_name, counter, issuer_name)
+ totp_uri = totp.get_provisioning_uri(account_name, issuer_name)
+
+A common usage is encoding the provisioning URI into QR code and guiding users
+to scan it with Two-Factor authentication applications in their mobile devices.
+
+.. _`spec of Google Authenticator`: https://github.com/google/google-authenticator/wiki/Key-Uri-Format
diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt
index badb500c..81510134 100644
--- a/docs/spelling_wordlist.txt
+++ b/docs/spelling_wordlist.txt
@@ -40,6 +40,7 @@ multi
naïve
namespace
namespaces
+Nonces
online
paddings
pickleable
diff --git a/docs/x509.rst b/docs/x509.rst
index c570f196..bdcd60b1 100644
--- a/docs/x509.rst
+++ b/docs/x509.rst
@@ -208,7 +208,7 @@ X.509 Certificate Object
:class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
that will be used to generate the fingerprint.
- :return bytes: The fingerprint using the supplied hash algorithm as
+ :return bytes: The fingerprint using the supplied hash algorithm, as
bytes.
.. doctest::
@@ -326,6 +326,70 @@ X.509 Certificate Object
<Extension(oid=<ObjectIdentifier(oid=2.5.29.32, name=certificatePolicies)>, critical=False, value=<CertificatePolicies([<PolicyInformation(policy_identifier=<ObjectIdentifier(oid=2.16.840.1.101.3.2.1.48.1, name=Unknown OID)>, policy_qualifiers=None)>])>)>
<Extension(oid=<ObjectIdentifier(oid=2.5.29.19, name=basicConstraints)>, critical=True, value=<BasicConstraints(ca=True, path_length=None)>)>
+ .. method:: public_bytes(encoding)
+
+ :param encoding: The
+ :class:`~cryptography.hazmat.primitives.serialization.Encoding`
+ that will be used to serialize the certificate.
+
+ :return bytes: The data that can be written to a file or sent
+ over the network to be verified by clients.
+
+X.509 CRL (Certificate Revocation List) Object
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. class:: CertificateRevocationList
+
+ .. versionadded:: 1.0
+
+ .. method:: fingerprint(algorithm)
+
+ :param algorithm: The
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+ that will be used to generate the fingerprint.
+
+ :return bytes: The fingerprint using the supplied hash algorithm, as
+ bytes.
+
+ .. attribute:: signature_hash_algorithm
+
+ :type: :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+
+ Returns the
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` which
+ was used in signing this CRL.
+
+ .. attribute:: issuer
+
+ :type: :class:`Name`
+
+ The :class:`Name` of the issuer.
+
+ .. attribute:: next_update
+
+ :type: :class:`datetime.datetime`
+
+ A naïve datetime representing when the next update to this CRL is
+ expected.
+
+ .. attribute:: last_update
+
+ :type: :class:`datetime.datetime`
+
+ A naïve datetime representing when the this CRL was last updated.
+
+ .. attribute:: revoked_certificates
+
+ :type: list of :class:`RevokedCertificate`
+
+ The revoked certificates listed in this CRL.
+
+ .. attribute:: extensions
+
+ :type: :class:`Extensions`
+
+ The extensions encoded in the CRL.
+
X.509 CSR (Certificate Signing Request) Object
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -379,6 +443,30 @@ X.509 CSR (Certificate Signing Request) Object
over the network to be signed by the certificate
authority.
+X.509 Revoked Certificate Object
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. class:: RevokedCertificate
+
+ .. versionadded:: 1.0
+
+ .. attribute:: serial_number
+
+ :type: :class:`int`
+
+ An integer representing the serial number of the revoked certificate.
+
+ .. attribute:: revocation_date
+
+ :type: :class:`datetime.datetime`
+
+ A naïve datetime representing the date this certificates was revoked.
+
+ .. attribute:: extensions
+
+ :type: :class:`Extensions`
+
+ The extensions encoded in the revoked certificate.
.. class:: Name
@@ -715,7 +803,7 @@ X.509 Extensions
.. class:: OCSPNoCheck
- .. versionadded:: 0.10
+ .. versionadded:: 1.0
This presence of this extension indicates that an OCSP client can trust a
responder for the lifetime of the responder's certificate. CAs issuing
@@ -921,6 +1009,24 @@ X.509 Extensions
removed from the CRL. This reason cannot be used as a reason flag
in a :class:`DistributionPoint`.
+.. class:: InhibitAnyPolicy
+
+ .. versionadded:: 1.0
+
+ The inhibit ``anyPolicy`` extension indicates that the special OID
+ :data:`OID_ANY_POLICY`, is not considered an explicit match for other
+ :class:`CertificatePolicies` except when it appears in an intermediate
+ self-issued CA certificate. The value indicates the number of additional
+ non-self-issued certificates that may appear in the path before
+ :data:`OID_ANY_POLICY` is no longer permitted. For example, a value
+ of one indicates that :data:`OID_ANY_POLICY` may be processed in
+ certificates issued by the subject of this certificate, but not in
+ additional certificates in the path.
+
+ .. attribute:: skip_certs
+
+ :type: int
+
.. class:: CertificatePolicies
.. versionadded:: 0.9
@@ -1212,6 +1318,10 @@ Policy Qualifier OIDs
Corresponds to the dotted string ``"1.3.6.1.5.5.7.2.2"``.
+.. data:: OID_ANY_POLICY
+
+ Corresponds to the dotted string ``"2.5.29.32.0"``.
+
.. _extension_oids:
Extension OIDs
diff --git a/src/cryptography/__about__.py b/src/cryptography/__about__.py
index 359cd819..9c28be2e 100644
--- a/src/cryptography/__about__.py
+++ b/src/cryptography/__about__.py
@@ -14,7 +14,7 @@ __summary__ = ("cryptography is a package which provides cryptographic recipes"
" and primitives to Python developers.")
__uri__ = "https://github.com/pyca/cryptography"
-__version__ = "0.10.dev1"
+__version__ = "1.0.dev1"
__author__ = "The cryptography developers"
__email__ = "cryptography-dev@python.org"
diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py
index 72041366..f46dd1b7 100644
--- a/src/cryptography/hazmat/backends/openssl/x509.py
+++ b/src/cryptography/hazmat/backends/openssl/x509.py
@@ -1,15 +1,6 @@
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+# 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
@@ -311,6 +302,18 @@ class _Certificate(object):
return x509.Extensions(extensions)
+ def public_bytes(self, encoding):
+ if not isinstance(encoding, serialization.Encoding):
+ raise TypeError("encoding must be an item from the Encoding enum")
+
+ bio = self._backend._create_mem_bio()
+ if encoding is serialization.Encoding.PEM:
+ res = self._backend._lib.PEM_write_bio_X509(bio, self._x509)
+ elif encoding is serialization.Encoding.DER:
+ res = self._backend._lib.i2d_X509_bio(bio, self._x509)
+ assert res == 1
+ return self._backend._read_mem_bio(bio)
+
def _decode_certificate_policies(backend, ext):
cp = backend._ffi.cast(
diff --git a/src/cryptography/hazmat/bindings/openssl/asn1.py b/src/cryptography/hazmat/bindings/openssl/asn1.py
index 711c30b2..c18708c5 100644
--- a/src/cryptography/hazmat/bindings/openssl/asn1.py
+++ b/src/cryptography/hazmat/bindings/openssl/asn1.py
@@ -114,6 +114,7 @@ void ASN1_GENERALIZEDTIME_free(ASN1_GENERALIZEDTIME *);
ASN1_ENUMERATED *ASN1_ENUMERATED_new(void);
void ASN1_ENUMERATED_free(ASN1_ENUMERATED *);
int ASN1_ENUMERATED_set(ASN1_ENUMERATED *, long);
+long ASN1_ENUMERATED_get(ASN1_ENUMERATED *);
ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **, const unsigned char **, long,
const ASN1_ITEM *);
diff --git a/src/cryptography/hazmat/bindings/openssl/ssl.py b/src/cryptography/hazmat/bindings/openssl/ssl.py
index dd71375e..fa0aefc8 100644
--- a/src/cryptography/hazmat/bindings/openssl/ssl.py
+++ b/src/cryptography/hazmat/bindings/openssl/ssl.py
@@ -125,12 +125,9 @@ static const long SSL_MODE_ENABLE_PARTIAL_WRITE;
static const long SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
static const long SSL_MODE_AUTO_RETRY;
static const long SSL3_RANDOM_SIZE;
+
typedef ... SSL_METHOD;
-typedef struct ssl_st {
- int version;
- int type;
- ...;
-} SSL_CTX;
+typedef ... SSL_CTX;
typedef struct {
int master_key_length;
@@ -145,9 +142,10 @@ typedef struct {
} SSL3_STATE;
typedef struct {
+ int version;
+ int type;
SSL3_STATE *s3;
SSL_SESSION *session;
- int type;
...;
} SSL;
diff --git a/src/cryptography/hazmat/bindings/openssl/x509.py b/src/cryptography/hazmat/bindings/openssl/x509.py
index caa33969..534f5b08 100644
--- a/src/cryptography/hazmat/bindings/openssl/x509.py
+++ b/src/cryptography/hazmat/bindings/openssl/x509.py
@@ -194,6 +194,7 @@ int X509_CRL_verify(X509_CRL *, EVP_PKEY *);
int X509_CRL_get_ext_count(X509_CRL *);
X509_EXTENSION *X509_CRL_get_ext(X509_CRL *, int);
int X509_CRL_add_ext(X509_CRL *, X509_EXTENSION *, int);
+int X509_CRL_cmp(const X509_CRL *, const X509_CRL *);
int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *, EVP_PKEY *);
int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *, EVP_PKEY *, const EVP_MD *);
@@ -298,8 +299,8 @@ Cryptography_STACK_OF_X509_REVOKED *X509_CRL_get_REVOKED(X509_CRL *);
/* These aren't macros these arguments are all const X on openssl > 1.0.x */
int X509_CRL_set_lastUpdate(X509_CRL *, ASN1_TIME *);
int X509_CRL_set_nextUpdate(X509_CRL *, ASN1_TIME *);
-int X509_set_notBefore(X509 *, ASN1_UTCTIME *);
-int X509_set_notAfter(X509 *, ASN1_UTCTIME *);
+int X509_set_notBefore(X509 *, ASN1_TIME *);
+int X509_set_notAfter(X509 *, ASN1_TIME *);
/* These use STACK_OF(X509_EXTENSION) in 0.9.8e. Once we drop support for
RHEL/CentOS 5 we should move these back to FUNCTIONS. */
@@ -310,9 +311,14 @@ int i2d_EC_PUBKEY(EC_KEY *, unsigned char **);
EC_KEY *d2i_EC_PUBKEY(EC_KEY **, const unsigned char **, long);
EC_KEY *d2i_EC_PUBKEY_bio(BIO *, EC_KEY **);
int i2d_EC_PUBKEY_bio(BIO *, EC_KEY *);
+EC_KEY *d2i_ECPrivateKey(EC_KEY **, const unsigned char **, long);
EC_KEY *d2i_ECPrivateKey_bio(BIO *, EC_KEY **);
+int i2d_ECPrivateKey(EC_KEY *, unsigned char **);
int i2d_ECPrivateKey_bio(BIO *, EC_KEY *);
+EC_KEY *o2i_ECPublicKey(EC_KEY **, const unsigned char **, long);
+int i2o_ECPublicKey(EC_KEY *, unsigned char **);
+
// declared in safestack
int sk_ASN1_OBJECT_num(Cryptography_STACK_OF_ASN1_OBJECT *);
ASN1_OBJECT *sk_ASN1_OBJECT_value(Cryptography_STACK_OF_ASN1_OBJECT *, int);
@@ -329,8 +335,13 @@ int (*i2d_EC_PUBKEY)(EC_KEY *, unsigned char **) = NULL;
EC_KEY *(*d2i_EC_PUBKEY)(EC_KEY **, const unsigned char **, long) = NULL;
EC_KEY *(*d2i_EC_PUBKEY_bio)(BIO *, EC_KEY **) = NULL;
int (*i2d_EC_PUBKEY_bio)(BIO *, EC_KEY *) = NULL;
+EC_KEY *(*d2i_ECPrivateKey)(EC_KEY **, const unsigned char **, long) = NULL;
EC_KEY *(*d2i_ECPrivateKey_bio)(BIO *, EC_KEY **) = NULL;
+int (*i2d_ECPrivateKey)(EC_KEY *, unsigned char **) = NULL;
int (*i2d_ECPrivateKey_bio)(BIO *, EC_KEY *) = NULL;
+
+EC_KEY *(*o2i_ECPublicKey)(EC_KEY **, const unsigned char **, long) = NULL;
+int (*i2o_ECPublicKey)(EC_KEY *, unsigned char **) = NULL;
#endif
"""
@@ -340,7 +351,11 @@ CONDITIONAL_NAMES = {
"d2i_EC_PUBKEY",
"d2i_EC_PUBKEY_bio",
"i2d_EC_PUBKEY_bio",
+ "d2i_ECPrivateKey",
"d2i_ECPrivateKey_bio",
+ "i2d_ECPrivateKey",
"i2d_ECPrivateKey_bio",
+ "i2o_ECPublicKey",
+ "o2i_ECPublicKey",
]
}
diff --git a/src/cryptography/hazmat/bindings/openssl/x509name.py b/src/cryptography/hazmat/bindings/openssl/x509name.py
index a7dde87c..be5b3a75 100644
--- a/src/cryptography/hazmat/bindings/openssl/x509name.py
+++ b/src/cryptography/hazmat/bindings/openssl/x509name.py
@@ -34,6 +34,8 @@ unsigned long X509_NAME_hash(X509_NAME *);
int i2d_X509_NAME(X509_NAME *, unsigned char **);
int X509_NAME_add_entry_by_txt(X509_NAME *, const char *, int,
const unsigned char *, int, int, int);
+int X509_NAME_add_entry_by_OBJ(X509_NAME *, ASN1_OBJECT *, int,
+ unsigned char *, int, int, int);
int X509_NAME_add_entry_by_NID(X509_NAME *, int, int, unsigned char *,
int, int, int);
X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *, int);
diff --git a/src/cryptography/hazmat/primitives/twofactor/hotp.py b/src/cryptography/hazmat/primitives/twofactor/hotp.py
index ba228b40..8c0cec14 100644
--- a/src/cryptography/hazmat/primitives/twofactor/hotp.py
+++ b/src/cryptography/hazmat/primitives/twofactor/hotp.py
@@ -15,6 +15,7 @@ from cryptography.hazmat.backends.interfaces import HMACBackend
from cryptography.hazmat.primitives import constant_time, hmac
from cryptography.hazmat.primitives.hashes import SHA1, SHA256, SHA512
from cryptography.hazmat.primitives.twofactor import InvalidToken
+from cryptography.hazmat.primitives.twofactor.utils import _generate_uri
class HOTP(object):
@@ -59,3 +60,8 @@ class HOTP(object):
offset = six.indexbytes(hmac_value, len(hmac_value) - 1) & 0b1111
p = hmac_value[offset:offset + 4]
return struct.unpack(">I", p)[0] & 0x7fffffff
+
+ def get_provisioning_uri(self, account_name, counter, issuer):
+ return _generate_uri(self, 'hotp', account_name, issuer, [
+ ('counter', int(counter)),
+ ])
diff --git a/src/cryptography/hazmat/primitives/twofactor/totp.py b/src/cryptography/hazmat/primitives/twofactor/totp.py
index 03df9292..98493b6d 100644
--- a/src/cryptography/hazmat/primitives/twofactor/totp.py
+++ b/src/cryptography/hazmat/primitives/twofactor/totp.py
@@ -11,6 +11,7 @@ from cryptography.hazmat.backends.interfaces import HMACBackend
from cryptography.hazmat.primitives import constant_time
from cryptography.hazmat.primitives.twofactor import InvalidToken
from cryptography.hazmat.primitives.twofactor.hotp import HOTP
+from cryptography.hazmat.primitives.twofactor.utils import _generate_uri
class TOTP(object):
@@ -31,3 +32,8 @@ class TOTP(object):
def verify(self, totp, time):
if not constant_time.bytes_eq(self.generate(time), totp):
raise InvalidToken("Supplied TOTP value does not match.")
+
+ def get_provisioning_uri(self, account_name, issuer):
+ return _generate_uri(self._hotp, 'totp', account_name, issuer, [
+ ('period', int(self._time_step)),
+ ])
diff --git a/src/cryptography/hazmat/primitives/twofactor/utils.py b/src/cryptography/hazmat/primitives/twofactor/utils.py
new file mode 100644
index 00000000..91d2e148
--- /dev/null
+++ b/src/cryptography/hazmat/primitives/twofactor/utils.py
@@ -0,0 +1,30 @@
+# 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 base64
+
+from six.moves.urllib.parse import quote, urlencode
+
+
+def _generate_uri(hotp, type_name, account_name, issuer, extra_parameters):
+ parameters = [
+ ('digits', hotp._length),
+ ('secret', base64.b32encode(hotp._key)),
+ ('algorithm', hotp._algorithm.name.upper()),
+ ]
+
+ if issuer is not None:
+ parameters.append(('issuer', issuer))
+
+ parameters.extend(extra_parameters)
+
+ uriparts = {
+ 'type': type_name,
+ 'label': ('%s:%s' % (quote(issuer), quote(account_name)) if issuer
+ else quote(account_name)),
+ 'parameters': urlencode(parameters),
+ }
+ return 'otpauth://{type}/{label}?{parameters}'.format(**uriparts)
diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py
index 9a3295ce..6592684b 100644
--- a/src/cryptography/x509.py
+++ b/src/cryptography/x509.py
@@ -55,6 +55,9 @@ _OID_NAMES = {
"2.5.29.17": "subjectAltName",
"2.5.29.18": "issuerAltName",
"2.5.29.19": "basicConstraints",
+ "2.5.29.21": "cRLReason",
+ "2.5.29.24": "invalidityDate",
+ "2.5.29.29": "certificateIssuer",
"2.5.29.30": "nameConstraints",
"2.5.29.31": "cRLDistributionPoints",
"2.5.29.32": "certificatePolicies",
@@ -224,6 +227,9 @@ OID_KEY_USAGE = ObjectIdentifier("2.5.29.15")
OID_SUBJECT_ALTERNATIVE_NAME = ObjectIdentifier("2.5.29.17")
OID_ISSUER_ALTERNATIVE_NAME = ObjectIdentifier("2.5.29.18")
OID_BASIC_CONSTRAINTS = ObjectIdentifier("2.5.29.19")
+OID_CRL_REASON = ObjectIdentifier("2.5.29.21")
+OID_INVALIDITY_DATE = ObjectIdentifier("2.5.29.24")
+OID_CERTIFICATE_ISSUER = ObjectIdentifier("2.5.29.29")
OID_NAME_CONSTRAINTS = ObjectIdentifier("2.5.29.30")
OID_CRL_DISTRIBUTION_POINTS = ObjectIdentifier("2.5.29.31")
OID_CERTIFICATE_POLICIES = ObjectIdentifier("2.5.29.32")
@@ -785,6 +791,31 @@ class ReasonFlags(Enum):
remove_from_crl = "removeFromCRL"
+class InhibitAnyPolicy(object):
+ def __init__(self, skip_certs):
+ if not isinstance(skip_certs, six.integer_types):
+ raise TypeError("skip_certs must be an integer")
+
+ if skip_certs < 0:
+ raise ValueError("skip_certs must be a non-negative integer")
+
+ self._skip_certs = skip_certs
+
+ def __repr__(self):
+ return "<InhibitAnyPolicy(skip_certs={0.skip_certs})>".format(self)
+
+ def __eq__(self, other):
+ if not isinstance(other, InhibitAnyPolicy):
+ return NotImplemented
+
+ return self.skip_certs == other.skip_certs
+
+ def __ne__(self, other):
+ return not self == other
+
+ skip_certs = utils.read_only_property("_skip_certs")
+
+
@six.add_metaclass(abc.ABCMeta)
class GeneralName(object):
@abc.abstractproperty
@@ -944,7 +975,7 @@ class IPAddress(object):
return not self == other
-class SubjectAlternativeName(object):
+class GeneralNames(object):
def __init__(self, general_names):
if not all(isinstance(x, GeneralName) for x in general_names):
raise TypeError(
@@ -964,6 +995,32 @@ class SubjectAlternativeName(object):
return [i.value for i in self if isinstance(i, type)]
def __repr__(self):
+ return "<GeneralNames({0})>".format(self._general_names)
+
+ def __eq__(self, other):
+ if not isinstance(other, GeneralNames):
+ return NotImplemented
+
+ return self._general_names == other._general_names
+
+ def __ne__(self, other):
+ return not self == other
+
+
+class SubjectAlternativeName(object):
+ def __init__(self, general_names):
+ self._general_names = GeneralNames(general_names)
+
+ def __iter__(self):
+ return iter(self._general_names)
+
+ def __len__(self):
+ return len(self._general_names)
+
+ def get_values_for_type(self, type):
+ return self._general_names.get_values_for_type(type)
+
+ def __repr__(self):
return "<SubjectAlternativeName({0})>".format(self._general_names)
def __eq__(self, other):
@@ -1090,6 +1147,7 @@ OID_OCSP = ObjectIdentifier("1.3.6.1.5.5.7.48.1")
OID_CPS_QUALIFIER = ObjectIdentifier("1.3.6.1.5.5.7.2.1")
OID_CPS_USER_NOTICE = ObjectIdentifier("1.3.6.1.5.5.7.2.2")
+OID_ANY_POLICY = ObjectIdentifier("2.5.29.32.0")
@six.add_metaclass(abc.ABCMeta)
@@ -1167,6 +1225,71 @@ class Certificate(object):
Checks not equal.
"""
+ @abc.abstractmethod
+ def public_bytes(self, encoding):
+ """
+ Serializes the certificate to PEM or DER format.
+ """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class CertificateRevocationList(object):
+
+ @abc.abstractmethod
+ def fingerprint(self, algorithm):
+ """
+ Returns bytes using digest passed.
+ """
+
+ @abc.abstractproperty
+ def signature_hash_algorithm(self):
+ """
+ Returns a HashAlgorithm corresponding to the type of the digest signed
+ in the certificate.
+ """
+
+ @abc.abstractproperty
+ def issuer(self):
+ """
+ Returns the X509Name with the issuer of this CRL.
+ """
+
+ @abc.abstractproperty
+ def next_update(self):
+ """
+ Returns the date of next update for this CRL.
+ """
+
+ @abc.abstractproperty
+ def last_update(self):
+ """
+ Returns the date of last update for this CRL.
+ """
+
+ @abc.abstractproperty
+ def revoked_certificates(self):
+ """
+ Returns a list of RevokedCertificate objects for this CRL.
+ """
+
+ @abc.abstractproperty
+ def extensions(self):
+ """
+ Returns an Extensions object containing a list of CRL extensions.
+ """
+
+ @abc.abstractmethod
+ def __eq__(self, other):
+ """
+ Checks equality.
+ """
+
+ @abc.abstractmethod
+ def __ne__(self, other):
+ """
+ Checks not equal.
+ """
+
@six.add_metaclass(abc.ABCMeta)
class CertificateSigningRequest(object):
@@ -1200,3 +1323,24 @@ class CertificateSigningRequest(object):
"""
Encodes the request to PEM or DER format.
"""
+
+
+@six.add_metaclass(abc.ABCMeta)
+class RevokedCertificate(object):
+ @abc.abstractproperty
+ def serial_number(self):
+ """
+ Returns the serial number of the revoked certificate.
+ """
+
+ @abc.abstractproperty
+ def revocation_date(self):
+ """
+ Returns the date of when this certificate was revoked.
+ """
+
+ @abc.abstractproperty
+ def extensions(self):
+ """
+ Returns an Extensions object containing a list of Revoked extensions.
+ """
diff --git a/tasks.py b/tasks.py
index 74ff6b19..76d0d029 100644
--- a/tasks.py
+++ b/tasks.py
@@ -47,7 +47,16 @@ def download_artifacts(session):
paths = []
+ last_build_number = response.json()["number"]
for run in response.json()["runs"]:
+ if run["number"] != last_build_number:
+ print(
+ "Skipping {0} as it is not from the latest build ({1})".format(
+ run["url"], last_build_number
+ )
+ )
+ continue
+
response = session.get(
run["url"] + "api/json/",
headers={
diff --git a/tests/hazmat/primitives/test_dh.py b/tests/hazmat/primitives/test_dh.py
index 115f3d8c..d8869de9 100644
--- a/tests/hazmat/primitives/test_dh.py
+++ b/tests/hazmat/primitives/test_dh.py
@@ -1,15 +1,6 @@
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+# 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
diff --git a/tests/hazmat/primitives/twofactor/test_hotp.py b/tests/hazmat/primitives/twofactor/test_hotp.py
index a5d1c284..ab5f93c5 100644
--- a/tests/hazmat/primitives/twofactor/test_hotp.py
+++ b/tests/hazmat/primitives/twofactor/test_hotp.py
@@ -92,6 +92,19 @@ class TestHOTP(object):
with pytest.raises(TypeError):
HOTP(secret, b"foo", SHA1(), backend)
+ def test_get_provisioning_uri(self, backend):
+ secret = b"12345678901234567890"
+ hotp = HOTP(secret, 6, SHA1(), backend)
+
+ assert hotp.get_provisioning_uri("Alice Smith", 1, None) == (
+ "otpauth://hotp/Alice%20Smith?digits=6&secret=GEZDGNBV"
+ "GY3TQOJQGEZDGNBVGY3TQOJQ&algorithm=SHA1&counter=1")
+
+ assert hotp.get_provisioning_uri("Alice Smith", 1, 'Foo') == (
+ "otpauth://hotp/Foo:Alice%20Smith?digits=6&secret=GEZD"
+ "GNBVGY3TQOJQGEZDGNBVGY3TQOJQ&algorithm=SHA1&issuer=Foo"
+ "&counter=1")
+
def test_invalid_backend():
secret = b"12345678901234567890"
diff --git a/tests/hazmat/primitives/twofactor/test_totp.py b/tests/hazmat/primitives/twofactor/test_totp.py
index 6039983e..95829713 100644
--- a/tests/hazmat/primitives/twofactor/test_totp.py
+++ b/tests/hazmat/primitives/twofactor/test_totp.py
@@ -126,6 +126,19 @@ class TestTOTP(object):
assert totp.generate(time) == b"94287082"
+ def test_get_provisioning_uri(self, backend):
+ secret = b"12345678901234567890"
+ totp = TOTP(secret, 6, hashes.SHA1(), 30, backend=backend)
+
+ assert totp.get_provisioning_uri("Alice Smith", None) == (
+ "otpauth://totp/Alice%20Smith?digits=6&secret=GEZDGNBVG"
+ "Y3TQOJQGEZDGNBVGY3TQOJQ&algorithm=SHA1&period=30")
+
+ assert totp.get_provisioning_uri("Alice Smith", 'World') == (
+ "otpauth://totp/World:Alice%20Smith?digits=6&secret=GEZ"
+ "DGNBVGY3TQOJQGEZDGNBVGY3TQOJQ&algorithm=SHA1&issuer=World"
+ "&period=30")
+
def test_invalid_backend():
secret = b"12345678901234567890"
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 61efb10c..8601d11d 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -3336,6 +3336,75 @@ f47021022a6c9b45ed791d09d9540eb81ea065fc1959eca365001ee39928c343d75
assert expected == load_kasvs_ecdh_vectors(vector_data)
+def test_load_kasvs_ecdh_kdf_vectors():
+ vector_data = textwrap.dedent("""
+ # Parameter set(s) supported: EB EC ED EE
+ # CAVSid: CAVSid (in hex: 434156536964)
+ # IUTid: In hex: a1b2c3d4e5
+ [EB]
+
+ [Curve selected: P-224]
+ [SHA(s) supported (Used in the KDF function): SHA224 SHA256 SHA384 SHA512]
+ [MAC algorithm supported: HMAC]
+ [HMAC SHAs supported: SHA512]
+ [HMACKeySize(in bits): 112]
+ [HMAC Tag length(in bits): 64]
+
+ # Generated on Mon Dec 22 11:45:18 2014
+
+
+
+ [EB - SHA224]
+
+
+ COUNT = 0
+ dsCAVS = 540904b67b3716823dd621ed72ad3dbc615887b4f56f910b78a57199
+ QsCAVSx = 28e5f3a72d8f6b8499dd1bcdfceafcecec68a0d715789bcf4b55fe15
+ QsCAVSy = 8c8006a7da7c1a19f5328d7e865522b0c0dfb9a29b2c46dc96590d2a
+ Nonce = 4eefb2a29a0e89c3898a7affdfa60dd7
+ dsIUT = 5e717ae889fc8d67be11c2ebe1a7d3550051448d68a040b2dee8e327
+ QsIUTx = ae7f3db340b647d61713f5374c019f1be2b28573cb6219bb7b747223
+ QsIUTy = 800e6bffcf97c15864ec6e5673fb83359b45f89b8a26a27f6f3dfbff
+ NonceDKMIUT = bb7f1b40d14ebd70443393990b57
+ OI = a1b2c3d4e5bb7f1b40d14ebd70443393990b574341565369645b1582daab9cc6c30d6\
+1fdcf1cdfc7e9a304651e0fdb
+ CAVSTag = 84de198c3a958c62
+ Z = 43f23b2c760d686fc99cc008b63aea92f866e224265af60d2d8ae540
+ MacData = 5374616e646172642054657374204d6573736167654eefb2a29a0e89c3898a7a\
+ffdfa60dd7
+ DKM = ad65fa2d12541c3a21f3cd223efb
+ Result = F (12 - Tag changed )
+ """).splitlines()
+
+ expected = [
+ {'errno': 12,
+ 'fail': True,
+ 'COUNT': 0,
+ 'CAVS': {
+ 'd': int("540904b67b3716823dd621ed72ad3dbc615887b4f56f910b"
+ "78a57199", 16),
+ 'x': int("28e5f3a72d8f6b8499dd1bcdfceafcecec68a0d715789bcf"
+ "4b55fe15", 16),
+ 'y': int("8c8006a7da7c1a19f5328d7e865522b0c0dfb9a29b2c46dc"
+ "96590d2a", 16)},
+ 'IUT': {
+ 'd': int("5e717ae889fc8d67be11c2ebe1a7d3550051448d68a040b2"
+ "dee8e327", 16),
+ 'x': int("ae7f3db340b647d61713f5374c019f1be2b28573cb6219bb"
+ "7b747223", 16),
+ 'y': int("800e6bffcf97c15864ec6e5673fb83359b45f89b8a26a27f"
+ "6f3dfbff", 16)},
+ 'OI': int("a1b2c3d4e5bb7f1b40d14ebd70443393990b574341565369"
+ "645b1582daab9cc6c30d61fdcf1cdfc7e9a304651e0fdb", 16),
+ 'Z': int("43f23b2c760d686fc99cc008b63aea92f866e224265af60d"
+ "2d8ae540", 16),
+ 'DKM': int("ad65fa2d12541c3a21f3cd223efb", 16),
+ 'curve': 'secp224r1'}
+ ]
+
+ assert expected == load_kasvs_ecdh_vectors(vector_data)
+
+
def test_vector_version():
assert cryptography.__version__ == cryptography_vectors.__version__
diff --git a/tests/test_x509.py b/tests/test_x509.py
index 72fc9d40..a3bed85f 100644
--- a/tests/test_x509.py
+++ b/tests/test_x509.py
@@ -368,6 +368,90 @@ class TestRSACertificate(object):
with pytest.raises(UnsupportedAlgorithm):
cert.signature_hash_algorithm
+ def test_public_bytes_pem(self, backend):
+ # Load an existing certificate.
+ cert = _load_cert(
+ os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
+ x509.load_der_x509_certificate,
+ backend
+ )
+
+ # Encode it to PEM and load it back.
+ cert = x509.load_pem_x509_certificate(cert.public_bytes(
+ encoding=serialization.Encoding.PEM,
+ ), backend)
+
+ # We should recover what we had to start with.
+ assert cert.not_valid_before == datetime.datetime(2010, 1, 1, 8, 30)
+ assert cert.not_valid_after == datetime.datetime(2030, 12, 31, 8, 30)
+ assert cert.serial == 2
+ public_key = cert.public_key()
+ assert isinstance(public_key, rsa.RSAPublicKey)
+ assert cert.version is x509.Version.v3
+ fingerprint = binascii.hexlify(cert.fingerprint(hashes.SHA1()))
+ assert fingerprint == b"6f49779533d565e8b7c1062503eab41492c38e4d"
+
+ def test_public_bytes_der(self, backend):
+ # Load an existing certificate.
+ cert = _load_cert(
+ os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
+ x509.load_der_x509_certificate,
+ backend
+ )
+
+ # Encode it to DER and load it back.
+ cert = x509.load_der_x509_certificate(cert.public_bytes(
+ encoding=serialization.Encoding.DER,
+ ), backend)
+
+ # We should recover what we had to start with.
+ assert cert.not_valid_before == datetime.datetime(2010, 1, 1, 8, 30)
+ assert cert.not_valid_after == datetime.datetime(2030, 12, 31, 8, 30)
+ assert cert.serial == 2
+ public_key = cert.public_key()
+ assert isinstance(public_key, rsa.RSAPublicKey)
+ assert cert.version is x509.Version.v3
+ fingerprint = binascii.hexlify(cert.fingerprint(hashes.SHA1()))
+ assert fingerprint == b"6f49779533d565e8b7c1062503eab41492c38e4d"
+
+ def test_public_bytes_invalid_encoding(self, backend):
+ cert = _load_cert(
+ os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
+ x509.load_der_x509_certificate,
+ backend
+ )
+
+ with pytest.raises(TypeError):
+ cert.public_bytes('NotAnEncoding')
+
+ @pytest.mark.parametrize(
+ ("cert_path", "loader_func", "encoding"),
+ [
+ (
+ os.path.join("x509", "v1_cert.pem"),
+ x509.load_pem_x509_certificate,
+ serialization.Encoding.PEM,
+ ),
+ (
+ os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
+ x509.load_der_x509_certificate,
+ serialization.Encoding.DER,
+ ),
+ ]
+ )
+ def test_public_bytes_match(self, cert_path, loader_func, encoding,
+ backend):
+ cert_bytes = load_vectors_from_file(
+ cert_path, lambda pemfile: pemfile.read(), mode="rb"
+ )
+ cert = loader_func(cert_bytes, backend)
+ serialized = cert.public_bytes(encoding)
+ assert serialized == cert_bytes
+
+
+@pytest.mark.requires_backend_interface(interface=RSABackend)
+@pytest.mark.requires_backend_interface(interface=X509Backend)
+class TestRSACertificateRequest(object):
@pytest.mark.parametrize(
("path", "loader_func"),
[
diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py
index 20a016b6..f16db337 100644
--- a/tests/test_x509_ext.py
+++ b/tests/test_x509_ext.py
@@ -1139,6 +1139,61 @@ class TestIPAddress(object):
assert gn != object()
+class TestGeneralNames(object):
+ def test_get_values_for_type(self):
+ gns = x509.GeneralNames(
+ [x509.DNSName(u"cryptography.io")]
+ )
+ names = gns.get_values_for_type(x509.DNSName)
+ assert names == [u"cryptography.io"]
+
+ def test_iter_names(self):
+ gns = x509.GeneralNames([
+ x509.DNSName(u"cryptography.io"),
+ x509.DNSName(u"crypto.local"),
+ ])
+ assert len(gns) == 2
+ assert list(gns) == [
+ x509.DNSName(u"cryptography.io"),
+ x509.DNSName(u"crypto.local"),
+ ]
+
+ def test_invalid_general_names(self):
+ with pytest.raises(TypeError):
+ x509.GeneralNames(
+ [x509.DNSName(u"cryptography.io"), "invalid"]
+ )
+
+ def test_repr(self):
+ gns = x509.GeneralNames(
+ [
+ x509.DNSName(u"cryptography.io")
+ ]
+ )
+ assert repr(gns) == (
+ "<GeneralNames([<DNSName(value=cryptography.io)>])>"
+ )
+
+ def test_eq(self):
+ gns = x509.GeneralNames(
+ [x509.DNSName(u"cryptography.io")]
+ )
+ gns2 = x509.GeneralNames(
+ [x509.DNSName(u"cryptography.io")]
+ )
+ assert gns == gns2
+
+ def test_ne(self):
+ gns = x509.GeneralNames(
+ [x509.DNSName(u"cryptography.io")]
+ )
+ gns2 = x509.GeneralNames(
+ [x509.RFC822Name(u"admin@cryptography.io")]
+ )
+ assert gns != gns2
+ assert gns != object()
+
+
class TestSubjectAlternativeName(object):
def test_get_values_for_type(self):
san = x509.SubjectAlternativeName(
@@ -1171,7 +1226,8 @@ class TestSubjectAlternativeName(object):
]
)
assert repr(san) == (
- "<SubjectAlternativeName([<DNSName(value=cryptography.io)>])>"
+ "<SubjectAlternativeName("
+ "<GeneralNames([<DNSName(value=cryptography.io)>])>)>"
)
def test_eq(self):
@@ -2271,3 +2327,28 @@ class TestCRLDistributionPointsExtension(object):
)],
)
])
+
+
+class TestInhibitAnyPolicy(object):
+ def test_not_int(self):
+ with pytest.raises(TypeError):
+ x509.InhibitAnyPolicy("notint")
+
+ def test_negative_int(self):
+ with pytest.raises(ValueError):
+ x509.InhibitAnyPolicy(-1)
+
+ def test_repr(self):
+ iap = x509.InhibitAnyPolicy(0)
+ assert repr(iap) == "<InhibitAnyPolicy(skip_certs=0)>"
+
+ def test_eq(self):
+ iap = x509.InhibitAnyPolicy(1)
+ iap2 = x509.InhibitAnyPolicy(1)
+ assert iap == iap2
+
+ def test_ne(self):
+ iap = x509.InhibitAnyPolicy(1)
+ iap2 = x509.InhibitAnyPolicy(4)
+ assert iap != iap2
+ assert iap != object()
diff --git a/tests/utils.py b/tests/utils.py
index ab922c94..46d93646 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -739,8 +739,12 @@ def load_kasvs_ecdh_vectors(vector_data):
data["IUT"]["x"] = int(line.split("=")[1], 16)
elif line.startswith("QsIUTy = "):
data["IUT"]["y"] = int(line.split("=")[1], 16)
+ elif line.startswith("OI = "):
+ data["OI"] = int(line.split("=")[1], 16)
elif line.startswith("Z = "):
data["Z"] = int(line.split("=")[1], 16)
+ elif line.startswith("DKM = "):
+ data["DKM"] = int(line.split("=")[1], 16)
elif line.startswith("Result = "):
result_str = line.split("=")[1].strip()
match = result_rx.match(result_str)
diff --git a/tox.ini b/tox.ini
index 77382ebe..6d6bb120 100644
--- a/tox.ini
+++ b/tox.ini
@@ -11,6 +11,7 @@ deps =
./vectors
passenv = ARCHFLAGS LDFLAGS CFLAGS INCLUDE LIB LD_LIBRARY_PATH
commands =
+ python -c "from cryptography.hazmat.backends.openssl.backend import backend; print(backend.openssl_version_text())"
# We use parallel mode and then combine here so that coverage.py will take
# the paths like .tox/py34/lib/python3.4/site-packages/cryptography/__init__.py
# and collapse them into src/cryptography/__init__.py.
@@ -46,12 +47,14 @@ commands =
# coverage.py on pypy.
[testenv:pypy]
commands =
+ python -c "from cryptography.hazmat.backends.openssl.backend import backend; print(backend.openssl_version_text())"
py.test --capture=no --strict {posargs}
# Temporarily disable coverage on pypy3 because of performance problems with
# coverage.py on pypy3.
[testenv:pypy3]
commands =
+ python -c "from cryptography.hazmat.backends.openssl.backend import backend; print(backend.openssl_version_text())"
py.test --capture=no --strict {posargs}
[testenv:pep8]
diff --git a/vectors/cryptography_vectors/__about__.py b/vectors/cryptography_vectors/__about__.py
index f796fc37..a8199ced 100644
--- a/vectors/cryptography_vectors/__about__.py
+++ b/vectors/cryptography_vectors/__about__.py
@@ -14,7 +14,7 @@ __summary__ = "Test vectors for the cryptography package."
__uri__ = "https://github.com/pyca/cryptography"
-__version__ = "0.10.dev1"
+__version__ = "1.0.dev1"
__author__ = "The cryptography developers"
__email__ = "cryptography-dev@python.org"
diff --git a/vectors/cryptography_vectors/x509/custom/crl_all_reasons.pem b/vectors/cryptography_vectors/x509/custom/crl_all_reasons.pem
new file mode 100644
index 00000000..960363d0
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/custom/crl_all_reasons.pem
@@ -0,0 +1,37 @@
+-----BEGIN X509 CRL-----
+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
+EO3JcHNjZRmW
+-----END X509 CRL-----
diff --git a/vectors/cryptography_vectors/x509/custom/crl_dup_entry_ext.pem b/vectors/cryptography_vectors/x509/custom/crl_dup_entry_ext.pem
new file mode 100644
index 00000000..1b1d313c
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/custom/crl_dup_entry_ext.pem
@@ -0,0 +1,11 @@
+-----BEGIN X509 CRL-----
+MIIBpjCBjwIBAjANBgkqhkiG9w0BAQsFADAnMQswCQYDVQQGEwJVUzEYMBYGA1UE
+AwwPY3J5cHRvZ3JhcGh5LmlvGA8yMDE1MDEwMTAwMDAwMFoYDzIwMTYwMTAxMDAw
+MDAwWjAwMC4CAQAYDzIwMTUwMTAxMDAwMDAwWjAYMAoGA1UdFQQDCgEBMAoGA1Ud
+FQQDCgEBMA0GCSqGSIb3DQEBCwUAA4IBAQAse9C8f10JNCBNgE9nyAU1mlkKHubL
+jc6Svs/X5r6NVRN/VxZXSQt7UYN0klh+vZueGhiXb1ZAjixrRnjkM9o/KWrmXAc2
+Uq83EOFHsy+vBYbUwwDAK+qxhn0UV8iUbUYWBDonPAc7MzIz+VdwEFRZgn0oTz3k
+HCNri16GgPl30KA7eMbTLtxAKhMvLYFN0isEUGLRsCWxW/TX7zpZ5ciAfm6dkllt
+8D97KxcxWbWhA/6aifLfxLuaMQxTQyJq6lZhPNgYJdgD4hvzVPjKBf0G16zY1UuX
+VUcfTK7TX+zIC8R5AFQb6j9NtwOvAUgVpstXkZ3j7wuKAHJ3pN+KJP8T
+-----END X509 CRL-----
diff --git a/vectors/cryptography_vectors/x509/custom/crl_md2_unknown_crit_entry_ext.pem b/vectors/cryptography_vectors/x509/custom/crl_md2_unknown_crit_entry_ext.pem
new file mode 100644
index 00000000..c6b378cd
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/custom/crl_md2_unknown_crit_entry_ext.pem
@@ -0,0 +1,11 @@
+-----BEGIN X509 CRL-----
+MIIBnTCBhgIBAjANBgkqhkiG9w0BAQIFADAnMQswCQYDVQQGEwJVUzEYMBYGA1UE
+AwwPY3J5cHRvZ3JhcGh5LmlvGA8yMDE1MDEwMTAwMDAwMFoYDzIwMTYwMTAxMDAw
+MDAwWjAnMCUCAQAYDzIwMTUwMTAxMDAwMDAwWjAPMA0GAyoDBAEB/wQDCgEAMA0G
+CSqGSIb3DQEBAgUAA4IBAQAx/z+KEN+qCjT1nxyKH4QpCyGc4Yo3m0SSdjszfLMc
+fXTgf7040DxiHwa4EpLtUR0eVjcRTCGPAvm5uEmsOMF41gsqqeVWhBrqIXvt5XG5
+BxmcGIY2Pl1CwWYEXfRw5woHQRAe71dgtg6tOEyh/RRMzlDgWPcxd+M4DxN0CbBt
+xNJHkeROg2f1j892V8UG6d6CU+EZ15EJ8z5csrlIEcXO+Tk5ZgaZnEvaYC1qNnbn
+hw5Zrc2N9ewRaOIK/sV/nv4z5u1wU9+VENc+dxiage0Lod+aZbf8owJAWtE/eqOt
+GlduyWgnWUyR8hENOnuiWa8VpgFeaTGxDLQtTrZRlwzP
+-----END X509 CRL-----
diff --git a/vectors/cryptography_vectors/x509/custom/crl_unsupported_reason.pem b/vectors/cryptography_vectors/x509/custom/crl_unsupported_reason.pem
new file mode 100644
index 00000000..3d12675b
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/custom/crl_unsupported_reason.pem
@@ -0,0 +1,11 @@
+-----BEGIN X509 CRL-----
+MIIBmjCBgwIBAjANBgkqhkiG9w0BAQsFADAnMQswCQYDVQQGEwJVUzEYMBYGA1UE
+AwwPY3J5cHRvZ3JhcGh5LmlvGA8yMDE1MDEwMTAwMDAwMFoYDzIwMTYwMTAxMDAw
+MDAwWjAkMCICAQAYDzIwMTUwMTAxMDAwMDAwWjAMMAoGA1UdFQQDCgEMMA0GCSqG
+SIb3DQEBCwUAA4IBAQDGXlEYOwcEcTjGqvU4JVdGyDkj+5kzJlVOZiHLQ8v4O5qe
++Pxsc14umZwLQfQgqtbtfzWFcluHPn6fQiJjqdmxIzVFvS38yiGFOnufweGALRpJ
+5qsogHCjNTW4L5O3YJv4Z253I7FEcY3evHUgYLUHNcM6O5kDxfZoNKv0x9L4gADo
+3YUDXRsJaTecCHOO8GOpHSFin+ppB1lW85R+T2jpIsL/0FySaVQFaRYS1s2PWG69
+atJksNX95GgjgmTeSTiV3lc50UZDy5pUx6C3Y2jmJFeRD7/nvo3gnM9NUhTqZcNk
+Fqg77pbHlRMLwxyQzE02lon6XSw5Osg/3Gs6R1Y6
+-----END X509 CRL-----