]> Cypherpunks.ru repositories - pyderasn.git/blobdiff - pyderasn.py
BitString ''H notation support
[pyderasn.git] / pyderasn.py
index c8e29e3d767249c9de62be911540c9c3cf9e7992..b3ee318ae7f03cecbe120f8173e4de1a580e8eb6 100755 (executable)
@@ -608,7 +608,7 @@ class NotEnoughData(DecodeError):
     pass
 
 
-class LenIndefiniteForm(DecodeError):
+class LenIndefForm(DecodeError):
     pass
 
 
@@ -803,6 +803,11 @@ def len_encode(l):
 
 
 def len_decode(data):
+    """Decode length
+
+    :returns: (decoded length, length's length, remaining data)
+    :raises LenIndefForm: if indefinite form encoding is met
+    """
     if len(data) == 0:
         raise NotEnoughData("no data at all")
     first_octet = byte2int(data)
@@ -812,7 +817,7 @@ def len_decode(data):
     if octets_num + 1 > len(data):
         raise NotEnoughData("encoded length is longer than data")
     if octets_num == 0:
-        raise LenIndefiniteForm()
+        raise LenIndefForm()
     if byte2int(data[1:]) == 0:
         raise DecodeError("leading zeros")
     l = 0
@@ -986,7 +991,7 @@ class Obj(object):
                 )
             try:
                 l, llen, v = len_decode(lv)
-            except LenIndefiniteForm as err:
+            except LenIndefForm as err:
                 if not ctx.get("bered", False):
                     raise err.__class__(
                         msg=err.msg,
@@ -1826,6 +1831,8 @@ class BitString(Obj):
     >>> b.bit_len
     88
 
+    >>> BitString("'0A3B5F291CD'H")
+    BIT STRING 44 bits 0a3b5f291cd0
     >>> b = BitString("'010110000000'B")
     BIT STRING 12 bits 5800
     >>> b.bit_len
@@ -1914,21 +1921,25 @@ class BitString(Obj):
         if isinstance(value, (string_types, binary_type)):
             if (
                     isinstance(value, string_types) and
-                    value.startswith("'") and
-                    value.endswith("'B")
+                    value.startswith("'")
             ):
-                value = value[1:-2]
-                if not set(value) <= set(("0", "1")):
-                    raise ValueError("B's coding contains unacceptable chars")
-                return self._bits2octets(value)
+                if value.endswith("'B"):
+                    value = value[1:-2]
+                    if not set(value) <= set(("0", "1")):
+                        raise ValueError("B's coding contains unacceptable chars")
+                    return self._bits2octets(value)
+                elif value.endswith("'H"):
+                    value = value[1:-2]
+                    return (
+                        len(value) * 4,
+                        hexdec(value + ("" if len(value) % 2 == 0 else "0")),
+                    )
+                else:
+                    raise InvalidValueType((self.__class__, string_types, binary_type))
             elif isinstance(value, binary_type):
                 return (len(value) * 8, value)
             else:
-                raise InvalidValueType((
-                    self.__class__,
-                    string_types,
-                    binary_type,
-                ))
+                raise InvalidValueType((self.__class__, string_types, binary_type))
         if isinstance(value, tuple):
             if (
                     len(value) == 2 and
@@ -2126,7 +2137,7 @@ class BitString(Obj):
             lenindef = False
             try:
                 l, llen, v = len_decode(lv)
-            except LenIndefiniteForm:
+            except LenIndefForm:
                 llen, l, v = 1, 0, lv[1:]
                 lenindef = True
             except DecodeError as err:
@@ -2478,7 +2489,7 @@ class OctetString(Obj):
             lenindef = False
             try:
                 l, llen, v = len_decode(lv)
-            except LenIndefiniteForm:
+            except LenIndefForm:
                 llen, l, v = 1, 0, lv[1:]
                 lenindef = True
             except DecodeError as err:
@@ -3240,6 +3251,10 @@ class CommonString(OctetString):
             tlen=self.tlen,
             llen=self.llen,
             vlen=self.vlen,
+            expl_offset=self.expl_offset if self.expled else None,
+            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,
         )
 
 
@@ -3428,6 +3443,10 @@ class UTCTime(CommonString):
             tlen=self.tlen,
             llen=self.llen,
             vlen=self.vlen,
+            expl_offset=self.expl_offset if self.expled else None,
+            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,
         )
 
 
@@ -3899,7 +3918,7 @@ class Any(Obj):
             )
         try:
             l, llen, v = len_decode(lv)
-        except LenIndefiniteForm as err:
+        except LenIndefForm as err:
             if not ctx.get("bered", False):
                 raise err.__class__(
                     msg=err.msg,
@@ -4282,7 +4301,7 @@ class Sequence(Obj):
         lenindef = False
         try:
             l, llen, v = len_decode(lv)
-        except LenIndefiniteForm as err:
+        except LenIndefForm as err:
             if not ctx.get("bered", False):
                 raise err.__class__(
                     msg=err.msg,
@@ -4313,8 +4332,8 @@ class Sequence(Obj):
         values = {}
         for name, spec in self.specs.items():
             if spec.optional and (
-                (lenindef and v[:EOC_LEN].tobytes() == EOC) or
-                len(v) == 0
+                    (lenindef and v[:EOC_LEN].tobytes() == EOC) or
+                    len(v) == 0
             ):
                 continue
             sub_decode_path = decode_path + (name,)
@@ -4507,7 +4526,7 @@ class Set(Sequence):
         lenindef = False
         try:
             l, llen, v = len_decode(lv)
-        except LenIndefiniteForm as err:
+        except LenIndefForm as err:
             if not ctx.get("bered", False):
                 raise err.__class__(
                     msg=err.msg,
@@ -4794,7 +4813,7 @@ class SequenceOf(Obj):
         lenindef = False
         try:
             l, llen, v = len_decode(lv)
-        except LenIndefiniteForm as err:
+        except LenIndefForm as err:
             if not ctx.get("bered", False):
                 raise err.__class__(
                     msg=err.msg,