aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Housley <housley@vigilsec.com>2019-05-29 16:30:45 -0400
committerIlya Etingof <etingof@gmail.com>2019-05-29 22:30:45 +0200
commit9901a7f012fb77aa406921c9e423b2c0cb8e37e4 (patch)
tree2427cc34f91f2b9dcae97dc8f788d75d3bdf9822
parent2cd40241c3c152256d98637ecc887f990780525f (diff)
downloadpyasn1-modules-9901a7f012fb77aa406921c9e423b2c0cb8e37e4.tar.gz
Add support for RFC 2634 (#38)
-rw-r--r--CHANGES.txt4
-rw-r--r--pyasn1_modules/rfc2634.py322
-rw-r--r--tests/__main__.py1
-rwxr-xr-xtests/test_rfc2634.py151
4 files changed, 476 insertions, 2 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index d586875..eab86ba 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -14,8 +14,8 @@ Revision 0.2.6, released XX-05-2019
- Added RFC3161 providing Time-Stamp Protocol support
- Added RFC3709 providing Logotypes in X.509 Certificates
- Added RFC3274 providing CMS Compressed Data Content Type
-- Added RFC4073 providing Multiple Contents protection
- with CMS
+- Added RFC4073 providing Multiple Contents protection with CMS
+- Added RFC2634 providing Enhanced Security Services for S/MIME
Revision 0.2.5, released 24-04-2019
-----------------------------------
diff --git a/pyasn1_modules/rfc2634.py b/pyasn1_modules/rfc2634.py
new file mode 100644
index 0000000..c9e387d
--- /dev/null
+++ b/pyasn1_modules/rfc2634.py
@@ -0,0 +1,322 @@
+#
+# 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
+#
+# Enhanced Security Services for S/MIME
+#
+# ASN.1 source from:
+# https://www.rfc-editor.org/rfc/rfc2634.txt
+#
+
+from pyasn1.type import char
+from pyasn1.type import constraint
+from pyasn1.type import namedval
+from pyasn1.type import namedtype
+from pyasn1.type import tag
+from pyasn1.type import univ
+from pyasn1.type import useful
+
+from pyasn1_modules import rfc5652
+from pyasn1_modules import rfc5280
+
+MAX = float('inf')
+
+ContentType = rfc5652.ContentType
+
+IssuerAndSerialNumber = rfc5652.IssuerAndSerialNumber
+
+SubjectKeyIdentifier = rfc5652.SubjectKeyIdentifier
+
+PolicyInformation = rfc5280.PolicyInformation
+
+GeneralNames = rfc5280.GeneralNames
+
+CertificateSerialNumber = rfc5280.CertificateSerialNumber
+
+
+# Signing Certificate Attribute
+# Warning: It is better to use SigningCertificateV2 from RFC 5035
+
+id_aa_signingCertificate = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.12')
+
+class Hash(univ.OctetString):
+ pass # SHA-1 hash of entire certificate; RFC 5035 supports other hash algorithms
+
+
+class IssuerSerial(univ.Sequence):
+ pass
+
+IssuerSerial.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('issuer', GeneralNames()),
+ namedtype.NamedType('serialNumber', CertificateSerialNumber())
+)
+
+
+class ESSCertID(univ.Sequence):
+ pass
+
+ESSCertID.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('certHash', Hash()),
+ namedtype.OptionalNamedType('issuerSerial', IssuerSerial())
+)
+
+
+class SigningCertificate(univ.Sequence):
+ pass
+
+SigningCertificate.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('certs', univ.SequenceOf(
+ componentType=ESSCertID())),
+ namedtype.OptionalNamedType('policies', univ.SequenceOf(
+ componentType=PolicyInformation()))
+)
+
+
+# Mail List Expansion History Attribute
+
+id_aa_mlExpandHistory = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.3')
+
+ub_ml_expansion_history = univ.Integer(64)
+
+
+class EntityIdentifier(univ.Choice):
+ pass
+
+EntityIdentifier.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('issuerAndSerialNumber', IssuerAndSerialNumber()),
+ namedtype.NamedType('subjectKeyIdentifier', SubjectKeyIdentifier())
+)
+
+
+class MLReceiptPolicy(univ.Choice):
+ pass
+
+MLReceiptPolicy.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('none', univ.Null().subtype(implicitTag=tag.Tag(
+ tag.tagClassContext, tag.tagFormatSimple, 0))),
+ namedtype.NamedType('insteadOf', univ.SequenceOf(
+ componentType=GeneralNames()).subtype(
+ subtypeSpec=constraint.ValueSizeConstraint(1, MAX)).subtype(
+ implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))),
+ namedtype.NamedType('inAdditionTo', univ.SequenceOf(
+ componentType=GeneralNames()).subtype(
+ subtypeSpec=constraint.ValueSizeConstraint(1, MAX)).subtype(
+ implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2)))
+)
+
+
+class MLData(univ.Sequence):
+ pass
+
+MLData.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('mailListIdentifier', EntityIdentifier()),
+ namedtype.NamedType('expansionTime', useful.GeneralizedTime()),
+ namedtype.OptionalNamedType('mlReceiptPolicy', MLReceiptPolicy())
+)
+
+class MLExpansionHistory(univ.SequenceOf):
+ pass
+
+MLExpansionHistory.componentType = MLData()
+MLExpansionHistory.subtypeSpec=constraint.ValueSizeConstraint(1, ub_ml_expansion_history)
+
+
+# ESS Security Label Attribute
+
+id_aa_securityLabel = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.2')
+
+ub_privacy_mark_length = univ.Integer(128)
+
+ub_security_categories = univ.Integer(64)
+
+ub_integer_options = univ.Integer(256)
+
+
+class ESSPrivacyMark(univ.Choice):
+ pass
+
+ESSPrivacyMark.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('pString', char.PrintableString().subtype(
+ subtypeSpec=constraint.ValueSizeConstraint(1, ub_privacy_mark_length))),
+ namedtype.NamedType('utf8String', char.UTF8String().subtype(
+ subtypeSpec=constraint.ValueSizeConstraint(1, MAX)))
+)
+
+
+class SecurityClassification(univ.Integer):
+ pass
+
+SecurityClassification.subtypeSpec=constraint.ValueRangeConstraint(0, ub_integer_options)
+
+SecurityClassification.namedValues = namedval.NamedValues(
+ ('unmarked', 0),
+ ('unclassified', 1),
+ ('restricted', 2),
+ ('confidential', 3),
+ ('secret', 4),
+ ('top-secret', 5)
+)
+
+
+class SecurityPolicyIdentifier(univ.ObjectIdentifier):
+ pass
+
+
+class SecurityCategory(univ.Sequence):
+ pass
+
+SecurityCategory.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('type', univ.ObjectIdentifier().subtype(
+ implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))),
+ namedtype.NamedType('value', univ.Any().subtype(implicitTag=tag.Tag(
+ tag.tagClassContext, tag.tagFormatSimple, 1)))
+)
+
+
+class SecurityCategories(univ.SetOf):
+ pass
+
+SecurityCategories.componentType = SecurityCategory()
+SecurityCategories.subtypeSpec=constraint.ValueSizeConstraint(1, ub_security_categories)
+
+
+class ESSSecurityLabel(univ.Set):
+ pass
+
+ESSSecurityLabel.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('security-policy-identifier', SecurityPolicyIdentifier()),
+ namedtype.OptionalNamedType('security-classification', SecurityClassification()),
+ namedtype.OptionalNamedType('privacy-mark', ESSPrivacyMark()),
+ namedtype.OptionalNamedType('security-categories', SecurityCategories())
+)
+
+
+# Equivalent Labels Attribute
+
+id_aa_equivalentLabels = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.9')
+
+class EquivalentLabels(univ.SequenceOf):
+ pass
+
+EquivalentLabels.componentType = ESSSecurityLabel()
+
+
+# Content Identifier Attribute
+
+id_aa_contentIdentifier = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.7')
+
+class ContentIdentifier(univ.OctetString):
+ pass
+
+
+# Content Reference Attribute
+
+id_aa_contentReference = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.10')
+
+class ContentReference(univ.Sequence):
+ pass
+
+ContentReference.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('contentType', ContentType()),
+ namedtype.NamedType('signedContentIdentifier', ContentIdentifier()),
+ namedtype.NamedType('originatorSignatureValue', univ.OctetString())
+)
+
+
+# Message Signature Digest Attribute
+
+id_aa_msgSigDigest = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.5')
+
+class MsgSigDigest(univ.OctetString):
+ pass
+
+
+# Content Hints Attribute
+
+id_aa_contentHint = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.4')
+
+class ContentHints(univ.Sequence):
+ pass
+
+ContentHints.componentType = namedtype.NamedTypes(
+ namedtype.OptionalNamedType('contentDescription', char.UTF8String().subtype(subtypeSpec=constraint.ValueSizeConstraint(1, MAX))),
+ namedtype.NamedType('contentType', ContentType())
+)
+
+
+# Receipt Request Attribute
+
+class AllOrFirstTier(univ.Integer):
+ pass
+
+AllOrFirstTier.namedValues = namedval.NamedValues(
+ ('allReceipts', 0),
+ ('firstTierRecipients', 1)
+)
+
+
+class ReceiptsFrom(univ.Choice):
+ pass
+
+ReceiptsFrom.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('allOrFirstTier', AllOrFirstTier().subtype(
+ implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))),
+ namedtype.NamedType('receiptList', univ.SequenceOf(
+ componentType=GeneralNames()).subtype(implicitTag=tag.Tag(
+ tag.tagClassContext, tag.tagFormatSimple, 1)))
+)
+
+
+id_aa_receiptRequest = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.1')
+
+ub_receiptsTo = univ.Integer(16)
+
+class ReceiptRequest(univ.Sequence):
+ pass
+
+ReceiptRequest.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('signedContentIdentifier', ContentIdentifier()),
+ namedtype.NamedType('receiptsFrom', ReceiptsFrom()),
+ namedtype.NamedType('receiptsTo', univ.SequenceOf(componentType=GeneralNames()).subtype(subtypeSpec=constraint.ValueSizeConstraint(1, ub_receiptsTo)))
+)
+
+# Receipt Content Type
+
+class ESSVersion(univ.Integer):
+ pass
+
+ESSVersion.namedValues = namedval.NamedValues(
+ ('v1', 1)
+)
+
+
+id_ct_receipt = univ.ObjectIdentifier('1.2.840.113549.1.9.16.1.1')
+
+class Receipt(univ.Sequence):
+ pass
+
+Receipt.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('version', ESSVersion()),
+ namedtype.NamedType('contentType', ContentType()),
+ namedtype.NamedType('signedContentIdentifier', ContentIdentifier()),
+ namedtype.NamedType('originatorSignatureValue', univ.OctetString())
+)
+
+
+# Map of Attribute Type to the Attribute structure
+
+ESSAttributeMap = {
+ id_aa_signingCertificate: SigningCertificate(),
+ id_aa_mlExpandHistory: MLExpansionHistory(),
+ id_aa_securityLabel: ESSSecurityLabel(),
+ id_aa_equivalentLabels: EquivalentLabels(),
+ id_aa_contentIdentifier: ContentIdentifier(),
+ id_aa_contentReference: ContentReference(),
+ id_aa_msgSigDigest: MsgSigDigest(),
+ id_aa_contentHint: ContentHints(),
+ id_aa_receiptRequest: ReceiptRequest(),
+}
diff --git a/tests/__main__.py b/tests/__main__.py
index c46d1d4..360f4d8 100644
--- a/tests/__main__.py
+++ b/tests/__main__.py
@@ -17,6 +17,7 @@ suite = unittest.TestLoader().loadTestsFromNames(
'tests.test_rfc2459.suite',
'tests.test_rfc2511.suite',
'tests.test_rfc2560.suite',
+ 'tests.test_rfc2634.suite',
'tests.test_rfc2986.suite',
'tests.test_rfc3161.suite',
'tests.test_rfc3274.suite',
diff --git a/tests/test_rfc2634.py b/tests/test_rfc2634.py
new file mode 100755
index 0000000..9b52f99
--- /dev/null
+++ b/tests/test_rfc2634.py
@@ -0,0 +1,151 @@
+#
+# 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_modules import pem
+from pyasn1_modules import rfc5652
+from pyasn1_modules import rfc2634
+
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
+
+
+class SignedMessageTestCase(unittest.TestCase):
+ signed_message_pem_text = """\
+MIIFLgYJKoZIhvcNAQcCoIIFHzCCBRsCAQExDTALBglghkgBZQMEAgIwUQYJKoZI
+hvcNAQcBoEQEQkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbg0KDQpXYXRzb24sIGNv
+bWUgaGVyZSAtIEkgd2FudCB0byBzZWUgeW91LqCCAnwwggJ4MIIB/qADAgECAgkA
+pbNUKBuwbjswCgYIKoZIzj0EAwMwPzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZB
+MRAwDgYDVQQHDAdIZXJuZG9uMREwDwYDVQQKDAhCb2d1cyBDQTAeFw0xOTA1Mjkx
+NDQ1NDFaFw0yMDA1MjgxNDQ1NDFaMHAxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJW
+QTEQMA4GA1UEBxMHSGVybmRvbjEQMA4GA1UEChMHRXhhbXBsZTEOMAwGA1UEAxMF
+QWxpY2UxIDAeBgkqhkiG9w0BCQEWEWFsaWNlQGV4YW1wbGUuY29tMHYwEAYHKoZI
+zj0CAQYFK4EEACIDYgAE+M2fBy/sRA6V1pKFqecRTE8+LuAHtZxes1wmJZrBBg+b
+z7uYZfYQxI3dVB0YCSD6Mt3yXFlnmfBRwoqyArbjIBYrDbHBv2k8Csg2DhQ7qs/w
+to8hMKoFgkcscqIbiV7Zo4GUMIGRMAsGA1UdDwQEAwIHgDBCBglghkgBhvhCAQ0E
+NRYzVGhpcyBjZXJ0aWZpY2F0ZSBjYW5ub3QgYmUgdHJ1c3RlZCBmb3IgYW55IHB1
+cnBvc2UuMB0GA1UdDgQWBBTEuloOPnrjPIGw9AKqaLsW4JYONTAfBgNVHSMEGDAW
+gBTyNds0BNqlVfK9aQOZsGLs4hUIwTAKBggqhkjOPQQDAwNoADBlAjBjuR/RNbgL
+3kRhmn+PJTeKaL9sh/oQgHOYTgLmSnv3+NDCkhfKuMNoo/tHrkmihYgCMQC94Mae
+rDIrQpi0IDh+v0QSAv9rMife8tClafXWtDwwL8MS7oAh0ymT446Uizxx3PUxggIy
+MIICLgIBATBMMD8xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJWQTEQMA4GA1UEBwwH
+SGVybmRvbjERMA8GA1UECgwIQm9ndXMgQ0ECCQCls1QoG7BuOzALBglghkgBZQME
+AgKgggFXMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8X
+DTE5MDUyOTE4MjMxOVowJQYLKoZIhvcNAQkQAgcxFgQUAbWZQYhLO5wtUgsOCGtT
+4V3aNhUwLwYLKoZIhvcNAQkQAgQxIDAeDBFXYXRzb24sIGNvbWUgaGVyZQYJKoZI
+hvcNAQcBMDUGCyqGSIb3DQEJEAICMSYxJAIBAQYKKwYBBAGBrGABARMTQm9hZ3Vz
+IFByaXZhY3kgTWFyazA/BgkqhkiG9w0BCQQxMgQwtuQipP2CZx7U96rGbUT06LC5
+jVFYccZW5/CaNvpcrOPiChDm2vI3m4k300z5mSZsME0GCyqGSIb3DQEJEAIBMT4w
+PAQgx08hD2QnVwj1DoeRELNtdZ0PffW4BQIvcwwVc/goU6OAAQEwFTATgRFhbGlj
+ZUBleGFtcGxlLmNvbTAKBggqhkjOPQQDAwRnMGUCMAFFVP2gYFLTbaxvV5J2ICNM
+Nk/K4pXbj5Zvj3dcCeC4+OUYyG3ZW5lOtKqaabEAXAIxALDg1WOouhkDfwuQdgBi
+mNTr0mjYeUWRe/15IsWNx+kuFcLDr71DFHvMFY5M3sdfMA==
+"""
+
+ def setUp(self):
+ self.asn1Spec = rfc5652.ContentInfo()
+
+ def testDerCodec(self):
+ substrate = pem.readBase64fromText(self.signed_message_pem_text)
+ asn1Object, rest = der_decode (substrate, asn1Spec=self.asn1Spec)
+ assert not rest
+ assert asn1Object.prettyPrint()
+ assert der_encode(asn1Object) == substrate
+
+ assert asn1Object['contentType'] == rfc5652.id_signedData
+ sd, rest = der_decode(asn1Object['content'], asn1Spec=rfc5652.SignedData())
+ assert not rest
+ assert sd.prettyPrint()
+ assert der_encode(sd) == asn1Object['content']
+
+ for sa in sd['signerInfos'][0]['signedAttrs']:
+ sat = sa['attrType']
+ sav0 = sa['attrValues'][0]
+
+ if sat in rfc2634.ESSAttributeMap.keys():
+ sav, rest = der_decode(sav0, asn1Spec=rfc2634.ESSAttributeMap[sat])
+ assert not rest
+ assert sav.prettyPrint()
+ assert der_encode(sav) == sav0
+
+
+class SignedReceiptTestCase(unittest.TestCase):
+ signed_receipt_pem_text = """\
+MIIE3gYJKoZIhvcNAQcCoIIEzzCCBMsCAQMxDTALBglghkgBZQMEAgEwga4GCyqG
+SIb3DQEJ EAEBoIGeBIGbMIGYAgEBBgkqhkiG9w0BBwEEIMdPIQ9kJ1cI9Q6HkRC
+zbXWdD331uAUCL3MM FXP4KFOjBGYwZAIwOLV5WCbYjy5HLHE69IqXQQHVDJQzmo
+18WwkFrEYH3EMsvpXEIGqsFTFN 6NV4VBe9AjA5fGOCP5IhI32YqmGfs+zDlqZyb
+2xSX6Gr/IfCIm0angfOI39g7lAZDyivjh5H /oSgggJ3MIICczCCAfqgAwIBAgIJ
+AKWzVCgbsG48MAoGCCqGSM49BAMDMD8xCzAJBgNVBAYT AlVTMQswCQYDVQQIDAJ
+WQTEQMA4GA1UEBwwHSGVybmRvbjERMA8GA1UECgwIQm9ndXMgQ0Ew HhcNMTkwNT
+I5MTkyMDEzWhcNMjAwNTI4MTkyMDEzWjBsMQswCQYDVQQGEwJVUzELMAkGA1UE C
+BMCVkExEDAOBgNVBAcTB0hlcm5kb24xEDAOBgNVBAoTB0V4YW1wbGUxDDAKBgNVB
+AMTA0Jv YjEeMBwGCSqGSIb3DQEJARYPYm9iQGV4YW1wbGUuY29tMHYwEAYHKoZI
+zj0CAQYFK4EEACID YgAEMaRiVS8WvN8Ycmpfq75jBbOMUukNfXAg6AL0JJBXtIF
+AuIJcZVlkLn/xbywkcMLHK/O+ w9RWUQa2Cjw+h8b/1Cl+gIpqLtE558bD5PfM2a
+YpJ/YE6yZ9nBfTQs7z1TH5o4GUMIGRMAsG A1UdDwQEAwIHgDBCBglghkgBhvhCA
+Q0ENRYzVGhpcyBjZXJ0aWZpY2F0ZSBjYW5ub3QgYmUg dHJ1c3RlZCBmb3IgYW55
+IHB1cnBvc2UuMB0GA1UdDgQWBBTKa2Zy3iybV3+YjuLDKtNmjsIa pTAfBgNVHSM
+EGDAWgBTyNds0BNqlVfK9aQOZsGLs4hUIwTAKBggqhkjOPQQDAwNnADBkAjAV bo
+S6OfEYQomLDi2RUkd71hzwwiQZztbxNbosahIzjR8ZQaHhjdjJlrP/T6aXBwsCMD
+fRweYz 3Ce4E4wPfoqQnvqpM7ZlfhstjQQGOsWAtIIfqW/l+TgCO8ux3XLV6fj36
+zGCAYkwggGFAgEB MEwwPzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMRAwDgYD
+VQQHDAdIZXJuZG9uMREwDwYD VQQKDAhCb2d1cyBDQQIJAKWzVCgbsG48MAsGCWC
+GSAFlAwQCAaCBrjAaBgkqhkiG9w0BCQMx DQYLKoZIhvcNAQkQAQEwHAYJKoZIhv
+cNAQkFMQ8XDTE5MDUyOTE5MzU1NVowLwYJKoZIhvcN AQkEMSIEIGb9Hm2kCnM0C
+YNpZU4Uj7dN0AzOieIn9sDqZMcIcZrEMEEGCyqGSIb3DQEJEAIF MTIEMBZzeHVj
+a7fQ62ywyh8rtKzBP1WJooMdZ+8c6pRqfIESYIU5bQnH99OPA51QCwdOdjAK Bgg
+qhkjOPQQDAgRoMGYCMQDZiT22xgab6RFMAPvN4fhWwzx017EzttD4VaYrpbolrop
+BdPJ6 jIXiZQgCwxbGTCwCMQClaQ9K+L5LTeuW50ZKSIbmBZQ5dxjtnK3OlS7hYR
+i6U0JKZmWbbuS8 vFIgX7eIkd8=
+"""
+
+ def setUp(self):
+ self.asn1Spec = rfc5652.ContentInfo()
+
+ def testDerCodec(self):
+ substrate = pem.readBase64fromText(self.signed_receipt_pem_text)
+ asn1Object, rest = der_decode(substrate, asn1Spec=self.asn1Spec)
+ assert not rest
+ assert asn1Object.prettyPrint()
+ assert der_encode(asn1Object) == substrate
+
+ assert asn1Object['contentType'] == rfc5652.id_signedData
+ sd, rest = der_decode (asn1Object['content'], asn1Spec=rfc5652.SignedData())
+ assert not rest
+ assert sd.prettyPrint()
+ assert der_encode(sd) == asn1Object['content']
+
+ assert sd['encapContentInfo']['eContentType'] == rfc2634.id_ct_receipt
+ receipt, rest = der_decode(sd['encapContentInfo']['eContent'],
+ asn1Spec=rfc2634.Receipt())
+ assert not rest
+ assert receipt.prettyPrint()
+ assert der_encode(receipt) == sd['encapContentInfo']['eContent']
+
+ for sa in sd['signerInfos'][0]['signedAttrs']:
+ sat = sa['attrType']
+ sav0 = sa['attrValues'][0]
+
+ if sat in rfc2634.ESSAttributeMap.keys():
+ sav, rest = der_decode(sav0, asn1Spec=rfc2634.ESSAttributeMap[sat])
+ assert not rest
+ assert sav.prettyPrint()
+ assert der_encode(sav) == sav0
+
+
+suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])
+
+if __name__ == '__main__':
+ unittest.TextTestRunner(verbosity=2).run(suite)