X-Git-Url: http://www.git.cypherpunks.ru/?p=pyderasn.git;a=blobdiff_plain;f=pyderasn.py;h=acf0e469260588a921f20d5493546a86955e2a2b;hp=717c06cce42d63a15ed38356f71eb92cce217076;hb=4d56972efc2c9afe2edb27c4d91bf5c1d5ca4ede;hpb=63f01edc8b8f09f07fcc331f92242bbca1db40b7 diff --git a/pyderasn.py b/pyderasn.py index 717c06c..acf0e46 100755 --- a/pyderasn.py +++ b/pyderasn.py @@ -68,7 +68,7 @@ ____ Most types in ASN.1 has specific tag for them. ``Obj.tag_default`` is the default tag used during coding process. You can override it with either ``IMPLICIT`` (using ``impl`` keyword argument), or -``EXPLICIT`` one (using ``expl`` keyword argument). Both arguments takes +``EXPLICIT`` one (using ``expl`` keyword argument). Both arguments take raw binary string, containing that tag. You can **not** set implicit and explicit tags simultaneously. @@ -88,10 +88,10 @@ number. Pay attention that explicit tags always have *constructed* tag Implicit tag is not explicitly shown. -Two object of the same type, but with different implicit/explicit tags +Two objects of the same type, but with different implicit/explicit tags are **not** equal. -You can get objects effective tag (either default or implicited) through +You can get object's effective tag (either default or implicited) through ``tag`` property. You can decode it using :py:func:`pyderasn.tag_decode` function:: @@ -159,12 +159,12 @@ raised. Common methods ______________ -All objects have ``ready`` boolean property, that tells if it is ready -to be encoded. If that kind of action is performed on unready object, -then :py:exc:`pyderasn.ObjNotReady` exception will be raised. +All objects have ``ready`` boolean property, that tells if object is +ready to be encoded. If that kind of action is performed on unready +object, then :py:exc:`pyderasn.ObjNotReady` exception will be raised. -All objects have ``copy()`` method, returning its copy, that can be safely -mutated. +All objects have ``copy()`` method, that returns their copy, that can be +safely mutated. .. _decoding: @@ -251,16 +251,19 @@ done. Following types can be automatically decoded (DEFINED BY): * :py:class:`pyderasn.Any` +* :py:class:`pyderasn.BitString` (that is multiple of 8 bits) * :py:class:`pyderasn.OctetString` * :py:class:`pyderasn.SequenceOf`/:py:class:`pyderasn.SetOf` ``Any``/``OctetString``-s When any of those fields is automatically decoded, then ``.defined`` -attribute contains ``(OID, value)`` tuple. OID tell by which OID it was -defined, ``value`` contains corresponding decoded value. For example +attribute contains ``(OID, value)`` tuple. ``OID`` tells by which OID it +was defined, ``value`` contains corresponding decoded value. For example above, ``content_info["content"].defined == (id_signedData, signed_data)``. +.. _defines_by_path_kwarg: + defines_by_path kwarg _____________________ @@ -322,8 +325,8 @@ of ``PKIResponse``:: Pay attention for :py:func:`pyderasn.decode_path_defby` and ``any``. First function is useful for path construction when some automatic -decoding is already done. ``any`` is used for human readability and -means literally any value it meet -- useful for sequence and set of-s. +decoding is already done. ``any`` means literally any value it meet -- +useful for SEQUENCE/SET OF-s. Primitive types --------------- @@ -1679,7 +1682,7 @@ class BitString(Obj): >>> b.specs {'nonRepudiation': 1, 'digitalSignature': 0, 'keyEncipherment': 2} """ - __slots__ = ("specs",) + __slots__ = ("specs", "defined") tag_default = tag_encode(3) asn1_type_name = "BIT STRING" @@ -1716,6 +1719,7 @@ class BitString(Obj): ) if value is None: self._value = default + self.defined = None def _bits2octets(self, bits): if len(self.specs) > 0: @@ -1964,6 +1968,11 @@ class BitString(Obj): expl_llen=self.expl_llen if self.expled else None, expl_vlen=self.expl_vlen if self.expled else None, ) + defined_by, defined = self.defined or (None, None) + if defined_by is not None: + yield defined.pps( + decode_path=decode_path + (decode_path_defby(defined_by),) + ) class OctetString(Obj): @@ -4326,6 +4335,12 @@ def generic_decoder(): # pragma: no cover def main(): # pragma: no cover import argparse parser = argparse.ArgumentParser(description="PyDERASN ASN.1 DER decoder") + parser.add_argument( + "--skip", + type=int, + default=0, + help="Skip that number of bytes from the beginning", + ) parser.add_argument( "--oids", help="Python path to dictionary with OIDs", @@ -4334,12 +4349,17 @@ def main(): # pragma: no cover "--schema", help="Python path to schema definition to use", ) + parser.add_argument( + "--defines-by-path", + help="Python path to decoder's defines_by_path", + ) parser.add_argument( "DERFile", type=argparse.FileType("rb"), help="Path to DER file you want to decode", ) args = parser.parse_args() + args.DERFile.seek(args.skip) der = memoryview(args.DERFile.read()) args.DERFile.close() oids = obj_by_path(args.oids) if args.oids else {} @@ -4349,7 +4369,13 @@ def main(): # pragma: no cover pprinter = partial(pprint, big_blobs=True) else: schema, pprinter = generic_decoder() - obj, tail = schema().decode(der) + obj, tail = schema().decode( + der, + defines_by_path=( + None if args.defines_by_path is None + else obj_by_path(args.defines_by_path) + ), + ) print(pprinter(obj, oids=oids)) if tail != b"": print("\nTrailing data: %s" % hexenc(tail))