Skip to content

Commit 346ed69

Browse files
author
Sébastien Andrivet
committed
Translate example, convert big switches to dictionaries, add common OIDs.
1 parent 2736885 commit 346ed69

File tree

1 file changed

+122
-82
lines changed

1 file changed

+122
-82
lines changed

examples/dump.py

Lines changed: 122 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,27 @@
1+
# -*- coding: utf-8 -*-
12
#
23
# This file is part of Python-ASN1. Python-ASN1 is free software that is
34
# made available under the MIT license. Consult the file "LICENSE" that
45
# is distributed together with this file for the exact licensing terms.
56
#
6-
# Python-ASN1 is copyright (c) 2007-2008 by the Python-ASN1 authors. See
7+
# Python-ASN1 is copyright (c) 2007-2016 by the Python-ASN1 authors. See
78
# the file "AUTHORS" for a complete overview.
89

10+
from __future__ import absolute_import, division, print_function, unicode_literals
11+
from builtins import open, bytes, str
912
import sys
10-
import os.path
13+
import base64
14+
import binascii
1115

1216
import asn1
1317
import optparse
1418

15-
def read_pem(input):
19+
20+
def read_pem(input_file):
1621
"""Read PEM formatted input."""
1722
data = []
1823
state = 0
19-
for line in input:
24+
for line in input_file:
2025
if state == 0:
2126
if line.startswith('-----BEGIN'):
2227
state = 1
@@ -28,104 +33,139 @@ def read_pem(input):
2833
elif state == 2:
2934
break
3035
if state != 2:
31-
raise ValueError, 'No PEM encoded input found'
36+
raise ValueError('No PEM encoded input found')
3237
data = ''.join(data)
33-
data = data.decode('base64')
34-
return data
38+
return base64.b64decode(data)
39+
40+
41+
tag_id_to_string_map = {
42+
asn1.Boolean: "BOOLEAN",
43+
asn1.Integer: "INTEGER",
44+
asn1.BitString: "BIT STRING",
45+
asn1.OctetString: "OCTET STRING",
46+
asn1.Null: "NULL",
47+
asn1.ObjectIdentifier: "OBJECT",
48+
asn1.PrintableString: "PRINTABLESTRING",
49+
asn1.IA5String: "IA5STRING",
50+
asn1.UTCTime: "UTCTIME",
51+
asn1.Enumerated: "ENUMERATED",
52+
asn1.Sequence: "SEQUENCE",
53+
asn1.Set: "SET"
54+
}
55+
56+
class_id_to_string_map = {
57+
asn1.ClassUniversal: "U",
58+
asn1.ClassApplication: "A",
59+
asn1.ClassContext: "C",
60+
asn1.ClassPrivate: "P"
61+
}
62+
63+
object_id_to_string_map = {
64+
"1.2.840.113549.1.1.1": "rsaEncryption",
65+
"1.2.840.113549.1.1.5": "sha1WithRSAEncryption",
66+
67+
"1.3.6.1.5.5.7.1.1": "authorityInfoAccess",
68+
69+
"2.5.4.3": "commonName",
70+
"2.5.4.4": "surname",
71+
"2.5.4.5": "serialNumber",
72+
"2.5.4.6": "countryName",
73+
"2.5.4.7": "localityName",
74+
"2.5.4.8": "stateOrProvinceName",
75+
"2.5.4.9": "streetAddress",
76+
"2.5.4.10": "organizationName",
77+
"2.5.4.11": "organizationalUnitName",
78+
"2.5.4.12": "title",
79+
"2.5.4.13": "description",
80+
"2.5.4.42": "givenName",
81+
82+
"1.2.840.113549.1.9.1": "emailAddress",
83+
84+
"2.5.29.14": "X509v3 Subject Key Identifier",
85+
"2.5.29.15": "X509v3 Key Usage",
86+
"2.5.29.16": "X509v3 Private Key Usage Period",
87+
"2.5.29.17": "X509v3 Subject Alternative Name",
88+
"2.5.29.18": "X509v3 Issuer Alternative Name",
89+
"2.5.29.19": "X509v3 Basic Constraints",
90+
"2.5.29.30": "X509v3 Name Constraints",
91+
"2.5.29.31": "X509v3 CRL Distribution Points",
92+
"2.5.29.32": "X509v3 Certificate Policies Extension",
93+
"2.5.29.33": "X509v3 Policy Mappings",
94+
"2.5.29.35": "X509v3 Authority Key Identifier",
95+
"2.5.29.36": "X509v3 Policy Constraints",
96+
"2.5.29.37": "X509v3 Extended Key Usage"
97+
}
98+
3599

36-
def strid(id):
100+
def tag_id_to_string(identifier):
37101
"""Return a string representation of a ASN.1 id."""
38-
if id == asn1.Boolean:
39-
s = 'BOOLEAN'
40-
elif id == asn1.Integer:
41-
s = 'INTEGER'
42-
elif id == asn1.OctetString:
43-
s = 'OCTET STRING'
44-
elif id == asn1.Null:
45-
s = 'NULL'
46-
elif id == asn1.ObjectIdentifier:
47-
s = 'OBJECT IDENTIFIER'
48-
elif id == asn1.Enumerated:
49-
s = 'ENUMERATED'
50-
elif id == asn1.Sequence:
51-
s = 'SEQUENCE'
52-
elif id == asn1.Set:
53-
s = 'SET'
54-
elif id == asn1.Null:
55-
s = 'NULL'
56-
else:
57-
s = '%#02x' % id
58-
return s
59-
60-
def strclass(id):
102+
if identifier in tag_id_to_string_map:
103+
return tag_id_to_string_map[identifier]
104+
return '{:#02x}'.format(identifier)
105+
106+
107+
def class_id_to_string(identifier):
61108
"""Return a string representation of an ASN.1 class."""
62-
if id == asn1.ClassUniversal:
63-
s = 'UNIVERSAL'
64-
elif id == asn1.ClassApplication:
65-
s = 'APPLICATION'
66-
elif id == asn1.ClassContext:
67-
s = 'CONTEXT'
68-
elif id == san1.ClassPrivate:
69-
s = 'PRIVATE'
109+
if identifier in class_id_to_string_map:
110+
return class_id_to_string_map[identifier]
111+
raise ValueError('Illegal class: {:#02x}'.format(identifier))
112+
113+
114+
def object_identifier_to_string(identifier):
115+
if identifier in object_id_to_string_map:
116+
return object_id_to_string_map[identifier]
117+
return identifier
118+
119+
120+
def value_to_string(tag_number, value):
121+
if isinstance(value, bytes):
122+
return '0x' + str(binascii.hexlify(value).upper())
123+
elif isinstance(value, str):
124+
return value
125+
elif tag_number == asn1.ObjectIdentifier:
126+
return object_identifier_to_string(value)
70127
else:
71-
raise ValueError, 'Illegal class: %#02x' % id
72-
return s
128+
return repr(value)
73129

74-
def strtag(tag):
75-
"""Return a string represenation of an ASN.1 tag."""
76-
return '[%s] %s' % (strid(tag[0]), strclass(tag[2]))
77130

78-
def prettyprint(input, output, indent=0):
131+
def pretty_print(input_stream, output_stream, indent=0):
79132
"""Pretty print ASN.1 data."""
80-
while not input.eof():
81-
tag = input.peek()
82-
if tag[1] == asn1.TypePrimitive:
83-
tag, value = input.read()
84-
output.write(' ' * indent)
85-
output.write('[%s] %s (value %s)' %
86-
(strclass(tag[2]), strid(tag[0]), repr(value)))
87-
output.write('\n')
88-
elif tag[1] == asn1.TypeConstructed:
89-
output.write(' ' * indent)
90-
output.write('[%s] %s:\n' % (strclass(tag[2]), strid(tag[0])))
91-
input.enter()
92-
prettyprint(input, output, indent+2)
93-
input.leave()
133+
while not input_stream.eof():
134+
tag = input_stream.peek()
135+
if tag.typ == asn1.TypePrimitive:
136+
tag, value = input_stream.read()
137+
output_stream.write(' ' * indent)
138+
output_stream.write('[{}] {}: {}\n'.format(class_id_to_string(tag.cls), tag_id_to_string(tag.nr), value_to_string(tag.nr, value)))
139+
elif tag.typ == asn1.TypeConstructed:
140+
output_stream.write(' ' * indent)
141+
output_stream.write('[{}] {}\n'.format(class_id_to_string(tag.cls), tag_id_to_string(tag.nr)))
142+
input_stream.enter()
143+
pretty_print(input_stream, output_stream, indent + 2)
144+
input_stream.leave()
94145

95146

96147
# Main script
97148

98149
parser = optparse.OptionParser()
99-
parser.add_option('-p', '--pem', dest='mode', action='store_const',
100-
const='pem', help='PEM encoded input')
101-
parser.add_option('-r', '--raw', dest='mode', action='store_const',
102-
const='raw', help='raw input')
103-
parser.add_option('-o', '--output', dest='output',
104-
help='output to FILE instead', metavar='FILE')
150+
parser.add_option('-p', '--pem', dest='mode', action='store_const', const='pem', help='PEM encoded input')
151+
parser.add_option('-r', '--raw', dest='mode', action='store_const', const='raw', help='raw input')
152+
parser.add_option('-o', '--output', dest='output', help='output to FILE instead', metavar='FILE')
105153
parser.set_default('mode', 'pem')
106154
(opts, args) = parser.parse_args()
107155

108-
if len(args) == 1:
109-
input = file(sys.argv[1])
110-
else:
111-
input = sys.stdin
112-
113156
if opts.mode == 'pem':
114-
input = read_pem(input)
157+
input_file = open(sys.argv[1], 'r')
158+
input_data = read_pem(input_file)
115159
else:
116-
input = input.read()
160+
input_file = open(sys.argv[1], 'rb')
161+
input_data = input_file.read()
117162

118163
if opts.output:
119-
output = file(opts.output, 'w')
164+
output_file = open(opts.output, 'w')
120165
else:
121-
output = sys.stdout
122-
123-
data = []
124-
for line in input:
125-
data.append(line)
126-
data = ''.join(data)
166+
output_file = sys.stdout
127167

128-
dec = asn1.Decoder()
129-
dec.start(data)
168+
decoder = asn1.Decoder()
169+
decoder.start(input_data)
130170

131-
prettyprint(dec, output)
171+
pretty_print(decoder, output_file)

0 commit comments

Comments
 (0)