From f8f92c66af855c581d4b6e8b824da63f6987cc33 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Sun, 20 May 2018 13:05:02 +0300 Subject: [PATCH] BER pprinting --- doc/examples.rst | 37 +++++++++++++++++++++++++++--------- pyderasn.py | 49 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 73 insertions(+), 13 deletions(-) diff --git a/doc/examples.rst b/doc/examples.rst index bdc8faf..e95369c 100644 --- a/doc/examples.rst +++ b/doc/examples.rst @@ -218,21 +218,27 @@ There is huge output. Let's pretty print it:: Let's parse that output, human:: - 10-2 [1,1, 1] . . version: [0] EXPLICIT Version INTEGER v3 OPTIONAL - ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ - 0 1 2 3 4 5 6 7 8 9 10 11 + 10-2 [1,1, 1] . . version: [0] EXPLICIT Version INTEGER v3 OPTIONAL + ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ + 0 1 2 3 4 5 6 7 8 9 10 11 :: - 20 [1,1, 9] . . . algorithm: OBJECT IDENTIFIER 1.2.840.113549.1.1.5 - ^ ^ ^ ^ ^ ^ ^ ^ - 0 2 3 4 5 6 9 10 + 20 [1,1, 9] . . . algorithm: OBJECT IDENTIFIER 1.2.840.113549.1.1.5 + ^ ^ ^ ^ ^ ^ ^ ^ + 0 2 3 4 5 6 9 10 :: - 33 [0,0, 278] . . issuer: Name CHOICE rdnSequence - ^ ^ ^ ^ ^ ^ ^ ^ ^ - 0 2 3 4 5 6 8 9 10 + 33 [0,0, 278] . . issuer: Name CHOICE rdnSequence + ^ ^ ^ ^ ^ ^ ^ ^ ^ + 0 2 3 4 5 6 8 9 10 + +:: + + 52-2 [1,1,1054]-4 . . . . eContent: [0] EXPLICIT BER OCTET STRING 1046 bytes + ^ ^ ^ ^ + 12 13 9 10 :0: Offset of the object, where its DER encoding begins. @@ -265,6 +271,19 @@ Let's parse that output, human:: :11: Possible other flags like OPTIONAL and DEFAULT, if value equals to the default one, specified in the schema. +:12: + Only applicable to BER encoded data. If object has indefinite length + encoding, then subtract 2 bytes EOC from its length. If object has + explicit tag with indefinite length, then subtract another EOC bytes. + In example above, ``eContent`` field has both indefinite field encoding + and indefinite length explicit tag. ``BIT STRING``, ``OCTET STRING`` + (and its derivatives), ``SEQUENCE``, ``SET``, ``SEQUENCE OF``, ``SET + OF``, ``ANY`` could have indefinite length coding. +:13: + Only applicable to BER encoded data. If object has BER-specific + encoding, then ``BER`` will be shown. It does not depend on indefinite + length encoding. ``BOOLEAN``, ``BIT STRING``, ``OCTET STRING`` (and its + derivatives) could be BERed. As command line utility ----------------------- diff --git a/pyderasn.py b/pyderasn.py index b3ee318..ac74adc 100755 --- a/pyderasn.py +++ b/pyderasn.py @@ -854,8 +854,8 @@ class Obj(object): "offset", "llen", "vlen", - "lenindef", "expl_lenindef", + "lenindef", "bered", ) @@ -878,8 +878,8 @@ class Obj(object): self.optional = optional self.offset, self.llen, self.vlen = _decoded self.default = None - self.lenindef = False self.expl_lenindef = False + self.lenindef = False self.bered = False @property @@ -1123,6 +1123,9 @@ PP = namedtuple("PP", ( "expl_tlen", "expl_llen", "expl_vlen", + "expl_lenindef", + "lenindef", + "bered", )) @@ -1144,6 +1147,9 @@ def _pp( expl_tlen=None, expl_llen=None, expl_vlen=None, + expl_lenindef=False, + lenindef=False, + bered=False, ): return PP( asn1_type_name, @@ -1163,6 +1169,9 @@ def _pp( expl_tlen, expl_llen, expl_vlen, + expl_lenindef, + lenindef, + bered, ) @@ -1188,7 +1197,17 @@ def pp_console_row( ) cols.append(_colorize(col, "red", with_colours, ())) col = "[%d,%d,%4d]" % (pp.tlen, pp.llen, pp.vlen) - cols.append(_colorize(col, "green", with_colours, ())) + col = _colorize(col, "green", with_colours, ()) + ber_deoffset = 0 + if pp.expl_lenindef: + ber_deoffset += 2 + if pp.lenindef: + ber_deoffset += 2 + col += ( + " " if ber_deoffset == 0 else + _colorize(("-%d" % ber_deoffset), "red", with_colours) + ) + cols.append(col) if len(pp.decode_path) > 0: cols.append(" ." * (len(pp.decode_path))) ent = pp.decode_path[-1] @@ -1216,6 +1235,8 @@ def pp_console_row( cols.append(_colorize(col, "blue", with_colours)) if pp.asn1_type_name.replace(" ", "") != pp.obj_name.upper(): cols.append(_colorize(pp.obj_name, "magenta", with_colours)) + if pp.bered: + cols.append(_colorize("BER", "red", with_colours)) cols.append(_colorize(pp.asn1_type_name, "cyan", with_colours)) if pp.value is not None: value = pp.value @@ -1239,7 +1260,7 @@ def pp_console_row( def pp_console_blob(pp): - cols = [" " * len("XXXXXYY [X,X,XXXX]")] + cols = [" " * len("XXXXXYY [X,X,XXXX]YY")] if len(pp.decode_path) > 0: cols.append(" ." * (len(pp.decode_path) + 1)) if isinstance(pp.blob, binary_type): @@ -1494,6 +1515,8 @@ class Boolean(Obj): expl_tlen=self.expl_tlen if self.expled else None, expl_llen=self.expl_llen if self.expled else None, expl_vlen=self.expl_vlen if self.expled else None, + expl_lenindef=self.expl_lenindef, + bered=self.bered, ) @@ -1816,6 +1839,7 @@ class Integer(Obj): expl_tlen=self.expl_tlen if self.expled else None, expl_llen=self.expl_llen if self.expled else None, expl_vlen=self.expl_vlen if self.expled else None, + expl_lenindef=self.expl_lenindef, ) @@ -2263,6 +2287,9 @@ class BitString(Obj): expl_tlen=self.expl_tlen if self.expled else None, expl_llen=self.expl_llen if self.expled else None, expl_vlen=self.expl_vlen if self.expled else None, + expl_lenindef=self.expl_lenindef, + lenindef=self.lenindef, + bered=self.bered, ) defined_by, defined = self.defined or (None, None) if defined_by is not None: @@ -2609,6 +2636,9 @@ class OctetString(Obj): expl_tlen=self.expl_tlen if self.expled else None, expl_llen=self.expl_llen if self.expled else None, expl_vlen=self.expl_vlen if self.expled else None, + expl_lenindef=self.expl_lenindef, + lenindef=self.lenindef, + bered=self.bered, ) defined_by, defined = self.defined or (None, None) if defined_by is not None: @@ -2745,6 +2775,7 @@ class Null(Obj): expl_tlen=self.expl_tlen if self.expled else None, expl_llen=self.expl_llen if self.expled else None, expl_vlen=self.expl_vlen if self.expled else None, + expl_lenindef=self.expl_lenindef, ) @@ -3033,6 +3064,7 @@ class ObjectIdentifier(Obj): expl_tlen=self.expl_tlen if self.expled else None, expl_llen=self.expl_llen if self.expled else None, expl_vlen=self.expl_vlen if self.expled else None, + expl_lenindef=self.expl_lenindef, ) @@ -3255,6 +3287,7 @@ class CommonString(OctetString): expl_tlen=self.expl_tlen if self.expled else None, expl_llen=self.expl_llen if self.expled else None, expl_vlen=self.expl_vlen if self.expled else None, + expl_lenindef=self.expl_lenindef, ) @@ -3447,6 +3480,7 @@ class UTCTime(CommonString): expl_tlen=self.expl_tlen if self.expled else None, expl_llen=self.expl_llen if self.expled else None, expl_vlen=self.expl_vlen if self.expled else None, + expl_lenindef=self.expl_lenindef, ) @@ -3778,6 +3812,7 @@ class Choice(Obj): tlen=self.tlen, llen=self.llen, vlen=self.vlen, + expl_lenindef=self.expl_lenindef, ) if self.ready: yield self.value.pps(decode_path=decode_path + (self.choice,)) @@ -3998,6 +4033,8 @@ class Any(Obj): expl_tlen=self.expl_tlen if self.expled else None, expl_llen=self.expl_llen if self.expled else None, expl_vlen=self.expl_vlen if self.expled else None, + expl_lenindef=self.expl_lenindef, + lenindef=self.lenindef, ) defined_by, defined = self.defined or (None, None) if defined_by is not None: @@ -4482,6 +4519,8 @@ class Sequence(Obj): expl_tlen=self.expl_tlen if self.expled else None, expl_llen=self.expl_llen if self.expled else None, expl_vlen=self.expl_vlen if self.expled else None, + expl_lenindef=self.expl_lenindef, + lenindef=self.lenindef, ) for name in self.specs: value = self._value.get(name) @@ -4894,6 +4933,8 @@ class SequenceOf(Obj): expl_tlen=self.expl_tlen if self.expled else None, expl_llen=self.expl_llen if self.expled else None, expl_vlen=self.expl_vlen if self.expled else None, + expl_lenindef=self.expl_lenindef, + lenindef=self.lenindef, ) for i, value in enumerate(self._value): yield value.pps(decode_path=decode_path + (str(i),)) -- 2.44.0