diff options
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. + """ @@ -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) @@ -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----- |