aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOfek Lev <ofekmeister@gmail.com>2017-02-08 00:09:41 -0500
committerPaul Kehrer <paul.l.kehrer@gmail.com>2017-02-08 13:09:41 +0800
commit0e6a129724b707ebf79149376251e85fad550414 (patch)
tree4dde35c726fa6e611d46ef84823c77050b9cb83c
parent1c7bd66eef4075888a5a2c2d80ec9a67f62fec08 (diff)
downloadcryptography-0e6a129724b707ebf79149376251e85fad550414.tar.gz
cryptography-0e6a129724b707ebf79149376251e85fad550414.tar.bz2
cryptography-0e6a129724b707ebf79149376251e85fad550414.zip
replace pyasn1 with asn1crypto (#3361)
* replace pyasn1 with asn1crypto * allow trailing bytes * fix x509 test * update CHANGELOG.rst * fix assert * make asn1crypto code more idiomatic * find tag * final clean-up * leave trailing byte logic unchanged * document dependency change * spelling * fix spelling
-rw-r--r--CHANGELOG.rst3
-rw-r--r--setup.py3
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/utils.py31
-rw-r--r--src/cryptography/x509/extensions.py24
-rw-r--r--tests/hazmat/primitives/test_asym_utils.py3
-rw-r--r--tests/test_x509.py21
6 files changed, 19 insertions, 66 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 744ec205..ee0a3455 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -7,6 +7,9 @@ Changelog
.. note:: This version is not yet released and is under active development.
* Added support for Python 3.6.
+* Changed ASN.1 dependency from ``pyasn1`` to ``asn1crypto`` resulting in a
+ general performance increase when encoding/decoding ASN.1 structures. Also,
+ the ``pyasn1_modules`` test dependency is no longer required.
* Added
:meth:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKeyWithSerialization.private_bytes`
diff --git a/setup.py b/setup.py
index 8419e6a7..1b1ff608 100644
--- a/setup.py
+++ b/setup.py
@@ -35,7 +35,7 @@ VECTORS_DEPENDENCY = "cryptography_vectors=={0}".format(about['__version__'])
requirements = [
"idna>=2.0",
- "pyasn1>=0.1.8",
+ "asn1crypto>=0.21.0",
"six>=1.4.1",
"setuptools>=11.3",
]
@@ -61,7 +61,6 @@ test_requirements = [
"pytest>=2.9.0",
"pretend",
"iso8601",
- "pyasn1_modules",
"pytz",
]
if sys.version_info[:2] > (2, 6):
diff --git a/src/cryptography/hazmat/primitives/asymmetric/utils.py b/src/cryptography/hazmat/primitives/asymmetric/utils.py
index 44bf59d1..4c2337bf 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/utils.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/utils.py
@@ -6,9 +6,7 @@ from __future__ import absolute_import, division, print_function
import warnings
-from pyasn1.codec.der import decoder, encoder
-from pyasn1.error import PyAsn1Error
-from pyasn1.type import namedtype, univ
+from asn1crypto.algos import DSASignature
import six
@@ -16,13 +14,6 @@ from cryptography import utils
from cryptography.hazmat.primitives import hashes
-class _DSSSigValue(univ.Sequence):
- componentType = namedtype.NamedTypes(
- namedtype.NamedType('r', univ.Integer()),
- namedtype.NamedType('s', univ.Integer())
- )
-
-
def decode_rfc6979_signature(signature):
warnings.warn(
"decode_rfc6979_signature is deprecated and will "
@@ -34,19 +25,8 @@ def decode_rfc6979_signature(signature):
def decode_dss_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)
+ data = DSASignature.load(signature, strict=True).native
+ return data['r'], data['s']
def encode_rfc6979_signature(r, s):
@@ -66,10 +46,7 @@ def encode_dss_signature(r, s):
):
raise ValueError("Both r and s must be integers")
- sig = _DSSSigValue()
- sig.setComponentByName('r', r)
- sig.setComponentByName('s', s)
- return encoder.encode(sig)
+ return DSASignature({'r': r, 's': s}).dump()
class Prehashed(object):
diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py
index f7f6fcd3..1a3ced7d 100644
--- a/src/cryptography/x509/extensions.py
+++ b/src/cryptography/x509/extensions.py
@@ -11,8 +11,7 @@ import ipaddress
import warnings
from enum import Enum
-from pyasn1.codec.der import decoder
-from pyasn1.type import namedtype, univ
+from asn1crypto.keys import PublicKeyInfo
import six
@@ -27,13 +26,6 @@ from cryptography.x509.oid import (
)
-class _SubjectPublicKeyInfo(univ.Sequence):
- componentType = namedtype.NamedTypes(
- namedtype.NamedType('algorithm', univ.Sequence()),
- namedtype.NamedType('subjectPublicKey', univ.BitString())
- )
-
-
def _key_identifier_from_public_key(public_key):
if isinstance(public_key, RSAPublicKey):
data = public_key.public_bytes(
@@ -48,18 +40,8 @@ def _key_identifier_from_public_key(public_key):
serialization.Encoding.DER,
serialization.PublicFormat.SubjectPublicKeyInfo
)
- spki, remaining = decoder.decode(
- serialized, asn1Spec=_SubjectPublicKeyInfo()
- )
- assert not remaining
- # the univ.BitString object is a tuple of bits. We need bytes and
- # pyasn1 really doesn't want to give them to us. To get it we'll
- # build an integer and convert that to bytes.
- bits = 0
- for bit in spki.getComponentByName("subjectPublicKey"):
- bits = bits << 1 | bit
-
- data = utils.int_to_bytes(bits)
+
+ data = six.binary_type(PublicKeyInfo.load(serialized)['public_key'])
return hashlib.sha1(data).digest()
diff --git a/tests/hazmat/primitives/test_asym_utils.py b/tests/hazmat/primitives/test_asym_utils.py
index bd1fa35e..4835f091 100644
--- a/tests/hazmat/primitives/test_asym_utils.py
+++ b/tests/hazmat/primitives/test_asym_utils.py
@@ -73,8 +73,7 @@ def test_decode_dss_invalid_asn1():
decode_dss_signature(b"0\x07\x02\x01\x01\x02\x02\x01")
with pytest.raises(ValueError):
- # This is the BER "end-of-contents octets," which older versions of
- # pyasn1 are wrongly willing to return from top-level DER decoding.
+ # This is the BER "end-of-contents octets".
decode_dss_signature(b"\x00\x00")
diff --git a/tests/test_x509.py b/tests/test_x509.py
index 1ecf6b6a..db26f563 100644
--- a/tests/test_x509.py
+++ b/tests/test_x509.py
@@ -11,9 +11,7 @@ import os
import sys
import warnings
-from pyasn1.codec.der import decoder
-
-from pyasn1_modules import rfc2459
+from asn1crypto.x509 import Certificate
import pytest
@@ -1458,17 +1456,12 @@ class TestRSACertificateRequest(object):
cert = builder.sign(issuer_private_key, hashes.SHA256(), backend)
- parsed, _ = decoder.decode(
- cert.public_bytes(serialization.Encoding.DER),
- asn1Spec=rfc2459.Certificate()
- )
- tbs_cert = parsed.getComponentByName('tbsCertificate')
- subject = tbs_cert.getComponentByName('subject')
- issuer = tbs_cert.getComponentByName('issuer')
- # \x13 is printable string. The first byte of the value of the
- # node corresponds to the ASN.1 string type.
- assert subject[0][0][0][1][0] == b"\x13"[0]
- assert issuer[0][0][0][1][0] == b"\x13"[0]
+ parsed = Certificate.load(
+ cert.public_bytes(serialization.Encoding.DER))
+
+ # Check that each value was encoded as an ASN.1 PRINTABLESTRING.
+ assert parsed.subject.chosen[0][0]['value'].chosen.tag == 19
+ assert parsed.issuer.chosen[0][0]['value'].chosen.tag == 19
class TestCertificateBuilder(object):