Skip to content

Commit

Permalink
Use pyasn1 to get extensions in x509 certificates
Browse files Browse the repository at this point in the history
This change
 - Merges branch 'test-ext-by-oid' into cryptography
 - Reintroduces the dependence on pyasn1
 - Adds tests for get_ext_by_oid()

See Yubico@72f7e00#diff-1595778f95f527cab74dfcd7ec0e70c0R58
  • Loading branch information
moreati committed Oct 1, 2015
1 parent 926d521 commit ef597bf
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 8 deletions.
1 change: 0 additions & 1 deletion NEWS
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
* Version 4.0.0 (not yet released)
** Major release: Changed backend from M2Crypto to cryptography
** Added: dependency on cryptography 1.0 or higher
** Removed: dependency on PyASN and PyASN-modules
** For now M2Crypto is still needed for verifying issuer certificates
** utils.rand_bytes() now sources bytes from os.urandom()

Expand Down
2 changes: 2 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
install_requires=[
'cryptography>=1.0',
'M2Crypto',
'pyasn1>=0.1.7',
'pyasn1-modules',
],
test_suite='test',
tests_require=[],
Expand Down
47 changes: 47 additions & 0 deletions test/test_matchers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import unittest

from cryptography import x509
from cryptography.hazmat.backends import default_backend

from u2flib_server.attestation.matchers import get_ext_by_oid

YUBICO_ATTESTATION_CERT_SERIAL_544338083 = '''-----BEGIN CERTIFICATE-----
MIICIjCCAQygAwIBAgIEIHHwozALBgkqhkiG9w0BAQswDzENMAsGA1UEAxMEdGVz
dDAeFw0xNTA4MTEwOTAwMzNaFw0xNjA4MTAwOTAwMzNaMCkxJzAlBgNVBAMTHll1
YmljbyBVMkYgRUUgU2VyaWFsIDU0NDMzODA4MzBZMBMGByqGSM49AgEGCCqGSM49
AwEHA0IABPdFG1pBjBBQVhLrD39Qg1vKjuR2kRdBZnwLI/zgzztQpf4ffpkrkB/3
E0TXj5zg8gN9sgMkX48geBe+tBEpvMmjOzA5MCIGCSsGAQQBgsQKAgQVMS4zLjYu
MS40LjEuNDE0ODIuMS4yMBMGCysGAQQBguUcAgEBBAQDAgQwMAsGCSqGSIb3DQEB
CwOCAQEAb3YpnmHHduNuWEXlLqlnww9034ZeZaojhPAYSLR8d5NPk9gc0hkjQKmI
aaBM7DsaHbcHMKpXoMGTQSC++NCZTcKvZ0Lt12mp5HRnM1NNBPol8Hte5fLmvW4t
Q9EzLl4gkz7LSlORxTuwTbae1eQqNdxdeB+0ilMFCEUc+3NGCNM0RWd+sP5+gzMX
BDQAI1Sc9XaPIg8t3du5JChAl1ifpu/uERZ2WQgtxeBDO6z1Xoa5qz4svf5oURjP
ZjxS0WUKht48Z2rIjk5lZzERSaY3RrX3UtrnZEIzCmInXOrcRPeAD4ZutpiwuHe6
2ABsjuMRnKbATbOUiLdknNyPYYQz2g==
-----END CERTIFICATE-----'''

# From https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers
# Regsitered number Enterprise
# 1.3.6.1.4.1.41482 Yubico
# 1.3.6.1.4.1.45724 FIDO Alliance, Inc.


class X509ExtensionsTest(unittest.TestCase):

attestation_cert = x509.load_pem_x509_certificate(
YUBICO_ATTESTATION_CERT_SERIAL_544338083,
default_backend(),
)

def test_get_ext_by_oid_yubico(self):
self.assertEqual(
b'1.3.6.1.4.1.41482.1.2',
get_ext_by_oid(self.attestation_cert, '1.3.6.1.4.1.41482.2'),
)

def test_get_ext_by_oid_fido_alliance(self):
self.assertEqual(
b'\x03\x02\x040',
get_ext_by_oid(self.attestation_cert, '1.3.6.1.4.1.45724.2.1.1'),
)

19 changes: 12 additions & 7 deletions u2flib_server/attestation/matchers.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@
# POSSIBILITY OF SUCH DAMAGE.

from cryptography import x509
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives import hashes, serialization

from pyasn1.codec.der import decoder
from pyasn1_modules import rfc2459

__all__ = [
'DeviceMatcher',
Expand All @@ -53,12 +56,14 @@ def matches(self, certificate, parameters=[]):


def get_ext_by_oid(cert, oid):
oid = x509.ObjectIdentifier(oid)
try:
ext = cert.extensions.get_extension_for_oid(oid)
except x509.ExtensionNotFound:
return None
return ext.value
# This is needed until cryptography supports reading custom extensions,
# see https://github.com/pyca/cryptography/issues/2288
cert_der = cert.public_bytes(serialization.Encoding.DER)
cert, _ = decoder.decode(cert_der, asn1Spec=rfc2459.Certificate())
for ext in cert['tbsCertificate']['extensions']:
if ext['extnID'].prettyPrint() == oid:
return decoder.decode(ext['extnValue'])[0].asOctets()
return None


class ExtensionMatcher(DeviceMatcher):
Expand Down

0 comments on commit ef597bf

Please sign in to comment.