-
-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for RFC 4043 and RFC 7585 (#104)
- Loading branch information
1 parent
b61bbfa
commit bab198c
Showing
6 changed files
with
342 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# | ||
# This file is part of pyasn1-modules software. | ||
# | ||
# Created by Russ Housley with assistance from asn1ate v.0.6.0. | ||
# | ||
# Copyright (c) 2019, Vigil Security, LLC | ||
# License: http://snmplabs.com/pyasn1/license.html | ||
# | ||
# Internet X.509 Public Key Infrastructure Permanent Identifier | ||
# | ||
# ASN.1 source from: | ||
# https://www.rfc-editor.org/rfc/rfc4043.txt | ||
# | ||
|
||
from pyasn1.type import char | ||
from pyasn1.type import namedtype | ||
from pyasn1.type import univ | ||
|
||
from pyasn1_modules import rfc5280 | ||
|
||
|
||
id_pkix = univ.ObjectIdentifier((1, 3, 6, 1, 5, 5, 7, )) | ||
|
||
id_on = id_pkix + (8, ) | ||
|
||
id_on_permanentIdentifier = id_on + (3, ) | ||
|
||
|
||
class PermanentIdentifier(univ.Sequence): | ||
componentType = namedtype.NamedTypes( | ||
namedtype.OptionalNamedType('identifierValue', char.UTF8String()), | ||
namedtype.OptionalNamedType('assigner', univ.ObjectIdentifier()) | ||
) | ||
|
||
|
||
# Map of Other Name OIDs to Other Name is added to the | ||
# ones that are in rfc5280.py | ||
|
||
_anotherNameMapUpdate = { | ||
id_on_permanentIdentifier: PermanentIdentifier(), | ||
} | ||
|
||
rfc5280.anotherNameMap.update(_anotherNameMapUpdate) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# | ||
# This file is part of pyasn1-modules software. | ||
# | ||
# Created by Russ Housley with some assistance from asn1ate v.0.6.0. | ||
# | ||
# Copyright (c) 2019, Vigil Security, LLC | ||
# License: http://snmplabs.com/pyasn1/license.html | ||
# | ||
# Network Access Identifier (NAI) Realm Name for Certificates | ||
# | ||
# ASN.1 source from: | ||
# https://www.rfc-editor.org/rfc/rfc7585.txt | ||
# | ||
|
||
from pyasn1.type import char | ||
from pyasn1.type import constraint | ||
from pyasn1.type import univ | ||
|
||
from pyasn1_modules import rfc5280 | ||
|
||
|
||
# NAI Realm Name for Certificates | ||
|
||
id_pkix = univ.ObjectIdentifier('1.3.6.1.5.5.7') | ||
|
||
id_on = id_pkix + (8, ) | ||
|
||
id_on_naiRealm = id_on + (8, ) | ||
|
||
|
||
ub_naiRealm_length = univ.Integer(255) | ||
|
||
|
||
class NAIRealm(char.UTF8String): | ||
subtypeSpec = constraint.ValueSizeConstraint(1, ub_naiRealm_length) | ||
|
||
|
||
naiRealm = rfc5280.AnotherName() | ||
naiRealm['type-id'] = id_on_naiRealm | ||
naiRealm['value'] = NAIRealm() | ||
|
||
|
||
# Map of Other Name OIDs to Other Name is added to the | ||
# ones that are in rfc5280.py | ||
|
||
_anotherNameMapUpdate = { | ||
id_on_naiRealm: NAIRealm(), | ||
} | ||
|
||
rfc5280.anotherNameMap.update(_anotherNameMapUpdate) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
# | ||
# This file is part of pyasn1-modules software. | ||
# | ||
# Created by Russ Housley | ||
# Copyright (c) 2019, Vigil Security, LLC | ||
# License: http://snmplabs.com/pyasn1/license.html | ||
# | ||
|
||
import sys | ||
|
||
from pyasn1.codec.der.decoder import decode as der_decode | ||
from pyasn1.codec.der.encoder import encode as der_encode | ||
|
||
from pyasn1.type import univ | ||
|
||
from pyasn1_modules import pem | ||
from pyasn1_modules import rfc5280 | ||
from pyasn1_modules import rfc4043 | ||
|
||
try: | ||
import unittest2 as unittest | ||
except ImportError: | ||
import unittest | ||
|
||
|
||
class PermIdCertTestCase(unittest.TestCase): | ||
cert_pem_text = """\ | ||
MIIDDTCCApOgAwIBAgIJAKWzVCgbsG5HMAoGCCqGSM49BAMDMD8xCzAJBgNVBAYT | ||
AlVTMQswCQYDVQQIDAJWQTEQMA4GA1UEBwwHSGVybmRvbjERMA8GA1UECgwIQm9n | ||
dXMgQ0EwHhcNMTkxMTEwMDA0MDIyWhcNMjAxMTA5MDA0MDIyWjBNMQswCQYDVQQG | ||
EwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24xEDAOBgNVBAoTB0V4 | ||
YW1wbGUxDTALBgNVBAMTBEdhaWwwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQBoktg | ||
/68xL+uEQaWBoHyOjw8EMLeMEng3R2H7yiEzTGoaMJgPOKvSfzB2P0paHYPL+B5y | ||
Gc0CK5EHRujMl9ljH+Wydpk57rKBLo1ZzpWUS6anLGIkWs1sOakcgGGr7hGjggFL | ||
MIIBRzAdBgNVHQ4EFgQU1pCNZuMzfEaJ9GGhH7RKy6Mvz+cwbwYDVR0jBGgwZoAU | ||
8jXbNATapVXyvWkDmbBi7OIVCMGhQ6RBMD8xCzAJBgNVBAYTAlVTMQswCQYDVQQI | ||
DAJWQTEQMA4GA1UEBwwHSGVybmRvbjERMA8GA1UECgwIQm9ndXMgQ0GCCQDokdYG | ||
kU/O8jAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBhjBCBglghkgBhvhCAQ0E | ||
NRYzVGhpcyBjZXJ0aWZpY2F0ZSBjYW5ub3QgYmUgdHJ1c3RlZCBmb3IgYW55IHB1 | ||
cnBvc2UuMFMGA1UdEQRMMEqgNgYIKwYBBQUHCAOgKjAoDBs4MjYyMDgtNDE3MDI4 | ||
LTU0ODE5NS0yMTUyMzMGCSsGAQQBgaxgMIEQZ2FpbEBleGFtcGxlLmNvbTAKBggq | ||
hkjOPQQDAwNoADBlAjBT+36Y/LPaGSu+61P7kR97M8jAjtH5DtUwrWR02ChshvYJ | ||
x0bpZq3PJaO0WlBgFicCMQCf+67wSvjxxtjI/OAg4t8NQIJW1LcehSXizlPDc772 | ||
/FC5OiUAxO+iFaSVMeDFsCo= | ||
""" | ||
|
||
def setUp(self): | ||
self.asn1Spec = rfc5280.Certificate() | ||
|
||
def testDerCodec(self): | ||
substrate = pem.readBase64fromText(self.cert_pem_text) | ||
asn1Object, rest = der_decode(substrate, asn1Spec=self.asn1Spec) | ||
assert not rest | ||
assert asn1Object.prettyPrint() | ||
assert der_encode(asn1Object) == substrate | ||
|
||
perm_id_oid = rfc4043.id_on_permanentIdentifier | ||
assigner_oid = univ.ObjectIdentifier('1.3.6.1.4.1.22112.48') | ||
permanent_identifier_found = False | ||
|
||
for extn in asn1Object['tbsCertificate']['extensions']: | ||
if extn['extnID'] == rfc5280.id_ce_subjectAltName: | ||
extnValue, rest = der_decode(extn['extnValue'], | ||
asn1Spec=rfc5280.SubjectAltName()) | ||
assert not rest | ||
assert extnValue.prettyPrint() | ||
assert der_encode(extnValue) == extn['extnValue'] | ||
|
||
for gn in extnValue: | ||
if gn['otherName'].hasValue(): | ||
assert gn['otherName']['type-id'] == perm_id_oid | ||
onValue, rest = der_decode(gn['otherName']['value'], | ||
asn1Spec=rfc4043.PermanentIdentifier()) | ||
assert not rest | ||
assert onValue.prettyPrint() | ||
assert der_encode(onValue) == gn['otherName']['value'] | ||
assert onValue['assigner'] == assigner_oid | ||
permanent_identifier_found = True | ||
|
||
assert permanent_identifier_found | ||
|
||
def testOpenTypes(self): | ||
substrate = pem.readBase64fromText(self.cert_pem_text) | ||
asn1Object, rest = der_decode(substrate, | ||
asn1Spec=self.asn1Spec, | ||
decodeOpenTypes=True) | ||
assert not rest | ||
assert asn1Object.prettyPrint() | ||
assert der_encode(asn1Object) == substrate | ||
|
||
perm_id_oid = rfc4043.id_on_permanentIdentifier | ||
assigner_oid = univ.ObjectIdentifier('1.3.6.1.4.1.22112.48') | ||
permanent_identifier_found = False | ||
|
||
for extn in asn1Object['tbsCertificate']['extensions']: | ||
if extn['extnID'] == rfc5280.id_ce_subjectAltName: | ||
extnValue, rest = der_decode(extn['extnValue'], | ||
asn1Spec=rfc5280.SubjectAltName(), | ||
decodeOpenTypes=True) | ||
assert not rest | ||
assert extnValue.prettyPrint() | ||
assert der_encode(extnValue) == extn['extnValue'] | ||
|
||
for gn in extnValue: | ||
if gn['otherName'].hasValue(): | ||
on = gn['otherName'] | ||
assert on['type-id'] == perm_id_oid | ||
assert on['value']['assigner'] == assigner_oid | ||
permanent_identifier_found = True | ||
|
||
assert permanent_identifier_found | ||
|
||
|
||
suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) | ||
|
||
if __name__ == '__main__': | ||
import sys | ||
|
||
result = unittest.TextTestRunner(verbosity=2).run(suite) | ||
sys.exit(not result.wasSuccessful()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
# | ||
# This file is part of pyasn1-modules software. | ||
# | ||
# Created by Russ Housley | ||
# Copyright (c) 2019, Vigil Security, LLC | ||
# License: http://snmplabs.com/pyasn1/license.html | ||
# | ||
|
||
import sys | ||
|
||
from pyasn1.codec.der.decoder import decode as der_decode | ||
from pyasn1.codec.der.encoder import encode as der_encode | ||
|
||
from pyasn1.type import univ | ||
|
||
from pyasn1_modules import pem | ||
from pyasn1_modules import rfc5280 | ||
from pyasn1_modules import rfc7585 | ||
|
||
try: | ||
import unittest2 as unittest | ||
except ImportError: | ||
import unittest | ||
|
||
|
||
class NAIRealmCertTestCase(unittest.TestCase): | ||
cert_pem_text = """\ | ||
MIIEZzCCA0+gAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBkjELMAkGA1UEBhMCRlIx | ||
DzANBgNVBAgMBlJhZGl1czESMBAGA1UEBwwJU29tZXdoZXJlMRQwEgYDVQQKDAtF | ||
eGFtcGxlIEluYzEgMB4GCSqGSIb3DQEJARYRYWRtaW5AZXhhbXBsZS5vcmcxJjAk | ||
BgNVBAMMHUV4YW1wbGUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTE5MTExMTE4 | ||
MDQyMVoXDTIwMDExMDE4MDQyMVowezELMAkGA1UEBhMCRlIxDzANBgNVBAgMBlJh | ||
ZGl1czEUMBIGA1UECgwLRXhhbXBsZSBJbmMxIzAhBgNVBAMMGkV4YW1wbGUgU2Vy | ||
dmVyIENlcnRpZmljYXRlMSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFtcGxlLm9y | ||
ZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM9HqbuyWpsTMKo739Dm | ||
DwmQo2HUkNdQYbvsB+e7ILsw8fWa2qnsF1CoRr/1bcZqXUR1To/QbHse7xSMZH9t | ||
F7rdlDMc7QtgdwVfn8TiL3hCg5LSE8iaBzfJUjrts/V5WOByP1DwJVM7W3Va/5dN | ||
oOiceVeC7ThghMlwIx/wN5cy78a8fPYV2FvPR6e+U2HG35zaIv2PizYcliF/QmZG | ||
gnw4Q9dYC1Lw/ogVBZBALlv+/MuGheb/xIuL8lu1PFZ0YbW65WLD9Cx4wvytAke7 | ||
tKlhL/Kd4OBSeOY3OYmpxbc1gEUmFoLTlZesY2NP9Jyl5mGsIHtPdvVkh/tSBy8o | ||
VLUCAwEAAaOB3TCB2jAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DATBgNVHSUEDDAK | ||
BggrBgEFBQcDATA2BgNVHR8ELzAtMCugKaAnhiVodHRwOi8vd3d3LmV4YW1wbGUu | ||
Y29tL2V4YW1wbGVfY2EuY3JsMDcGCCsGAQUFBwEBBCswKTAnBggrBgEFBQcwAYYb | ||
aHR0cDovL3d3dy5leGFtcGxlLm9yZy9vY3NwMDoGA1UdEQQzMDGCEnJhZGl1cy5l | ||
eGFtcGxlLm9yZ6AbBggrBgEFBQcICKAPDA0qLmV4YW1wbGUuY29tMA0GCSqGSIb3 | ||
DQEBCwUAA4IBAQBOhtH2Jpi0b0MZ8FBKTqDl44rIHL1rHG2mW/YYmRI4jZo8kFhA | ||
yWm/T8ZpdaotJgRqbQbeXvTXIg4/JNFheyLG4yLOzS1esdMAYDD5EN9/dXE++jND | ||
/wrfPU+QtTgzAjkgFDKuqO7gr1/vSizxLYTWLKBPRHhiQo7GGlEC6/CPb38x4mfQ | ||
5Y9DsKCp6BEZu+LByCho/HMDzcIPCdtXRX7Fs8rtX4/zRpVIdm6D+vebuo6CwRKp | ||
mIljfssCvZjb9YIxSVDmA/6Lapqsfsfo922kb+MTXvPrq2ynPx8LrPDrxKc8maYc | ||
Jiw8B0yjkokwojxyRGftMT8uxNjWQVsMDbxl | ||
""" | ||
|
||
def setUp(self): | ||
self.asn1Spec = rfc5280.Certificate() | ||
|
||
def testDerCodec(self): | ||
substrate = pem.readBase64fromText(self.cert_pem_text) | ||
asn1Object, rest = der_decode(substrate, asn1Spec=self.asn1Spec) | ||
assert not rest | ||
assert asn1Object.prettyPrint() | ||
assert der_encode(asn1Object) == substrate | ||
|
||
nai_realm_oid = rfc7585.id_on_naiRealm | ||
nai_realm_found = False | ||
|
||
for extn in asn1Object['tbsCertificate']['extensions']: | ||
if extn['extnID'] == rfc5280.id_ce_subjectAltName: | ||
extnValue, rest = der_decode(extn['extnValue'], | ||
asn1Spec=rfc5280.SubjectAltName()) | ||
assert not rest | ||
assert extnValue.prettyPrint() | ||
assert der_encode(extnValue) == extn['extnValue'] | ||
|
||
for gn in extnValue: | ||
if gn['otherName'].hasValue(): | ||
assert gn['otherName']['type-id'] == nai_realm_oid | ||
onValue, rest = der_decode(gn['otherName']['value'], | ||
asn1Spec=rfc7585.NAIRealm()) | ||
assert not rest | ||
assert onValue.prettyPrint() | ||
assert der_encode(onValue) == gn['otherName']['value'] | ||
assert 'example' in onValue | ||
nai_realm_found = True | ||
|
||
assert nai_realm_found | ||
|
||
def testOpenTypes(self): | ||
substrate = pem.readBase64fromText(self.cert_pem_text) | ||
asn1Object, rest = der_decode(substrate, | ||
asn1Spec=self.asn1Spec, | ||
decodeOpenTypes=True) | ||
assert not rest | ||
assert asn1Object.prettyPrint() | ||
assert der_encode(asn1Object) == substrate | ||
|
||
nai_realm_oid = rfc7585.id_on_naiRealm | ||
nai_realm_found = False | ||
|
||
for extn in asn1Object['tbsCertificate']['extensions']: | ||
if extn['extnID'] == rfc5280.id_ce_subjectAltName: | ||
extnValue, rest = der_decode(extn['extnValue'], | ||
asn1Spec=rfc5280.SubjectAltName(), | ||
decodeOpenTypes=True) | ||
assert not rest | ||
assert extnValue.prettyPrint() | ||
assert der_encode(extnValue) == extn['extnValue'] | ||
|
||
for gn in extnValue: | ||
if gn['otherName'].hasValue(): | ||
assert gn['otherName']['type-id'] == nai_realm_oid | ||
assert 'example' in gn['otherName']['value'] | ||
nai_realm_found = True | ||
|
||
assert nai_realm_found | ||
|
||
|
||
suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) | ||
|
||
if __name__ == '__main__': | ||
import sys | ||
|
||
result = unittest.TextTestRunner(verbosity=2).run(suite) | ||
sys.exit(not result.wasSuccessful()) |