Skip to content

Commit 7c7e4ad

Browse files
authored
Add support for RFC 8769 (etingof#136)
1 parent 13ca0da commit 7c7e4ad

File tree

4 files changed

+158
-1
lines changed

4 files changed

+158
-1
lines changed

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Revision 0.3.0, released XX-03-2020
4040
- Add RFC8702 providing SHAKE One-way Hash Functions in the CMS
4141
- Add RFC8708 providing HSS/LMS Hash-based Signature Algorithm for CMS
4242
- Advance copyright statement to year 2020
43+
- Add RFC8769 providing CBOR and CBOR Sequence content types for CMS
4344

4445
Revision 0.2.8, released 16-11-2019
4546
-----------------------------------

pyasn1_modules/rfc8769.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#
2+
# This file is part of pyasn1-modules software.
3+
#
4+
# Created by Russ Housley.
5+
#
6+
# Copyright (c) 2020, Vigil Security, LLC
7+
# License: http://snmplabs.com/pyasn1/license.html
8+
#
9+
# CBOR Content for CMS
10+
#
11+
# ASN.1 source from:
12+
# https://www.rfc-editor.org/rfc/rfc8769.txt
13+
#
14+
15+
from pyasn1.type import univ
16+
17+
18+
id_ct_cbor = univ.ObjectIdentifier('1.2.840.113549.1.9.16.1.44')
19+
20+
21+
id_ct_cborSequence = univ.ObjectIdentifier('1.2.840.113549.1.9.16.1.45')

tests/__main__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@
126126
'tests.test_rfc8692.suite',
127127
'tests.test_rfc8696.suite',
128128
'tests.test_rfc8702.suite',
129-
'tests.test_rfc8708.suite']
129+
'tests.test_rfc8708.suite',
130+
'tests.test_rfc8769.suite']
130131
)
131132

132133

tests/test_rfc8769.py

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#
2+
# This file is part of pyasn1-modules software.
3+
#
4+
# Copyright (c) 2020, Vigil Security, LLC
5+
# License: http://snmplabs.com/pyasn1/license.html
6+
#
7+
import sys
8+
import unittest
9+
10+
from pyasn1.codec.der.decoder import decode as der_decoder
11+
from pyasn1.codec.der.encoder import encode as der_encoder
12+
13+
from pyasn1_modules import pem
14+
from pyasn1_modules import rfc5652
15+
from pyasn1_modules import rfc8769
16+
17+
18+
class CBORContentTestCase(unittest.TestCase):
19+
pem_text = """\
20+
MIIEHwYJKoZIhvcNAQcCoIIEEDCCBAwCAQMxDTALBglghkgBZQMEAgIwIQYLKoZIhvcNAQkQ
21+
ASygEgQQgw9kUnVzc/tADzMzMzMzM6CCAnwwggJ4MIIB/qADAgECAgkApbNUKBuwbjswCgYI
22+
KoZIzj0EAwMwPzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMRAwDgYDVQQHDAdIZXJuZG9u
23+
MREwDwYDVQQKDAhCb2d1cyBDQTAeFw0xOTA1MjkxNDQ1NDFaFw0yMDA1MjgxNDQ1NDFaMHAx
24+
CzAJBgNVBAYTAlVTMQswCQYDVQQIEwJWQTEQMA4GA1UEBxMHSGVybmRvbjEQMA4GA1UEChMH
25+
RXhhbXBsZTEOMAwGA1UEAxMFQWxpY2UxIDAeBgkqhkiG9w0BCQEWEWFsaWNlQGV4YW1wbGUu
26+
Y29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE+M2fBy/sRA6V1pKFqecRTE8+LuAHtZxes1wm
27+
JZrBBg+bz7uYZfYQxI3dVB0YCSD6Mt3yXFlnmfBRwoqyArbjIBYrDbHBv2k8Csg2DhQ7qs/w
28+
to8hMKoFgkcscqIbiV7Zo4GUMIGRMAsGA1UdDwQEAwIHgDBCBglghkgBhvhCAQ0ENRYzVGhp
29+
cyBjZXJ0aWZpY2F0ZSBjYW5ub3QgYmUgdHJ1c3RlZCBmb3IgYW55IHB1cnBvc2UuMB0GA1Ud
30+
DgQWBBTEuloOPnrjPIGw9AKqaLsW4JYONTAfBgNVHSMEGDAWgBTyNds0BNqlVfK9aQOZsGLs
31+
4hUIwTAKBggqhkjOPQQDAwNoADBlAjBjuR/RNbgL3kRhmn+PJTeKaL9sh/oQgHOYTgLmSnv3
32+
+NDCkhfKuMNoo/tHrkmihYgCMQC94MaerDIrQpi0IDh+v0QSAv9rMife8tClafXWtDwwL8MS
33+
7oAh0ymT446Uizxx3PUxggFTMIIBTwIBATBMMD8xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJW
34+
QTEQMA4GA1UEBwwHSGVybmRvbjERMA8GA1UECgwIQm9ndXMgQ0ECCQCls1QoG7BuOzALBglg
35+
hkgBZQMEAgKgezAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQASwwHAYJKoZIhvcNAQkFMQ8X
36+
DTIwMDExNDIyMjIxNVowPwYJKoZIhvcNAQkEMTIEMADSWdHn4vsesm9XnjJq1WxkoV6EtD+f
37+
qDAs1JEpZMZ+n8AtUxvC5SFobYpGCl+fsDAKBggqhkjOPQQDAwRmMGQCMGclPwvZLwVJqgON
38+
mOfnxSF8Cqn3AC+ZFBg7VplspiuhKPNIyu3IofqZjCxw0TzSpAIwEK0JxNlY28KDb5te0iN6
39+
I2hw+am26W+PRyltVVGUAISHM2kA4tG39HcxEQi+6HJx
40+
"""
41+
42+
def testDerCodec(self):
43+
substrate = pem.readBase64fromText(self.pem_text)
44+
45+
layers = { }
46+
layers.update(rfc5652.cmsContentTypesMap)
47+
48+
getNextLayer = {
49+
rfc5652.id_ct_contentInfo: lambda x: x['contentType'],
50+
rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContentType'],
51+
}
52+
53+
getNextSubstrate = {
54+
rfc5652.id_ct_contentInfo: lambda x: x['content'],
55+
rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContent'],
56+
}
57+
58+
next_layer = rfc5652.id_ct_contentInfo
59+
while next_layer in layers:
60+
asn1Object, rest = der_decoder(
61+
substrate, asn1Spec=layers[next_layer])
62+
63+
self.assertFalse(rest)
64+
self.assertTrue(asn1Object.prettyPrint())
65+
self.assertEqual(substrate, der_encoder(asn1Object))
66+
67+
substrate = getNextSubstrate[next_layer](asn1Object)
68+
next_layer = getNextLayer[next_layer](asn1Object)
69+
70+
self.assertEqual(rfc8769.id_ct_cbor, next_layer)
71+
72+
73+
class CBORSequenceContentTestCase(unittest.TestCase):
74+
pem_text = """\
75+
MIIEKQYJKoZIhvcNAQcCoIIEGjCCBBYCAQMxDTALBglghkgBZQMEAgIwKgYLKoZIhvcNAQkQ
76+
AS2gGwQZgw9kUnVzc/tADzMzMzMzM6MDCSD1YWFhYqCCAnwwggJ4MIIB/qADAgECAgkApbNU
77+
KBuwbjswCgYIKoZIzj0EAwMwPzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMRAwDgYDVQQH
78+
DAdIZXJuZG9uMREwDwYDVQQKDAhCb2d1cyBDQTAeFw0xOTA1MjkxNDQ1NDFaFw0yMDA1Mjgx
79+
NDQ1NDFaMHAxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJWQTEQMA4GA1UEBxMHSGVybmRvbjEQ
80+
MA4GA1UEChMHRXhhbXBsZTEOMAwGA1UEAxMFQWxpY2UxIDAeBgkqhkiG9w0BCQEWEWFsaWNl
81+
QGV4YW1wbGUuY29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE+M2fBy/sRA6V1pKFqecRTE8+
82+
LuAHtZxes1wmJZrBBg+bz7uYZfYQxI3dVB0YCSD6Mt3yXFlnmfBRwoqyArbjIBYrDbHBv2k8
83+
Csg2DhQ7qs/wto8hMKoFgkcscqIbiV7Zo4GUMIGRMAsGA1UdDwQEAwIHgDBCBglghkgBhvhC
84+
AQ0ENRYzVGhpcyBjZXJ0aWZpY2F0ZSBjYW5ub3QgYmUgdHJ1c3RlZCBmb3IgYW55IHB1cnBv
85+
c2UuMB0GA1UdDgQWBBTEuloOPnrjPIGw9AKqaLsW4JYONTAfBgNVHSMEGDAWgBTyNds0BNql
86+
VfK9aQOZsGLs4hUIwTAKBggqhkjOPQQDAwNoADBlAjBjuR/RNbgL3kRhmn+PJTeKaL9sh/oQ
87+
gHOYTgLmSnv3+NDCkhfKuMNoo/tHrkmihYgCMQC94MaerDIrQpi0IDh+v0QSAv9rMife8tCl
88+
afXWtDwwL8MS7oAh0ymT446Uizxx3PUxggFUMIIBUAIBATBMMD8xCzAJBgNVBAYTAlVTMQsw
89+
CQYDVQQIDAJWQTEQMA4GA1UEBwwHSGVybmRvbjERMA8GA1UECgwIQm9ndXMgQ0ECCQCls1Qo
90+
G7BuOzALBglghkgBZQMEAgKgezAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAS0wHAYJKoZI
91+
hvcNAQkFMQ8XDTIwMDExNDIyMjIxNVowPwYJKoZIhvcNAQkEMTIEMOsEu3dGU5j6fKZbsZPL
92+
LDA8QWxpP36CPDZWr3BVJ3R5mMCKCSmoWtVRnB7XASQcjTAKBggqhkjOPQQDAwRnMGUCMBLW
93+
PyYw4c11nrH97KHnEmx3BSDX/SfepFNM6PoPR5HCI+OR/v/wlIIByuhyrIl8xAIxAK8dEwOe
94+
I06um+ATKQzUcbgq0PCKA7T31pAq46fsWc5tA+mMARTrxZjSXsDneeAWpw==
95+
"""
96+
97+
def testDerCodec(self):
98+
substrate = pem.readBase64fromText(self.pem_text)
99+
100+
layers = { }
101+
layers.update(rfc5652.cmsContentTypesMap)
102+
103+
getNextLayer = {
104+
rfc5652.id_ct_contentInfo: lambda x: x['contentType'],
105+
rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContentType'],
106+
}
107+
108+
getNextSubstrate = {
109+
rfc5652.id_ct_contentInfo: lambda x: x['content'],
110+
rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContent'],
111+
}
112+
113+
next_layer = rfc5652.id_ct_contentInfo
114+
while next_layer in layers:
115+
asn1Object, rest = der_decoder(
116+
substrate, asn1Spec=layers[next_layer])
117+
118+
self.assertFalse(rest)
119+
self.assertTrue(asn1Object.prettyPrint())
120+
self.assertEqual(substrate, der_encoder(asn1Object))
121+
122+
substrate = getNextSubstrate[next_layer](asn1Object)
123+
next_layer = getNextLayer[next_layer](asn1Object)
124+
125+
self.assertEqual(rfc8769.id_ct_cborSequence, next_layer)
126+
127+
128+
suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])
129+
130+
if __name__ == '__main__':
131+
import sys
132+
133+
result = unittest.TextTestRunner(verbosity=2).run(suite)
134+
sys.exit(not result.wasSuccessful())

0 commit comments

Comments
 (0)