????JFIF??x?x????'
| Server IP : 172.67.174.47  /  Your IP : 216.73.216.83 Web Server : LiteSpeed System : Linux premium151.web-hosting.com 4.18.0-553.44.1.lve.el8.x86_64 #1 SMP Thu Mar 13 14:29:12 UTC 2025 x86_64 User : tempvsty ( 647) PHP Version : 8.0.30 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : OFF | Pkexec : OFF Directory : /proc/./thread-self/root/opt/imunify360/venv/lib/python3.11/site-packages/Crypto/Util/ | 
| Upload File : | 
# -*- coding: ascii -*-
#
#  Util/asn1.py : Minimal support for ASN.1 DER binary encoding.
#
# ===================================================================
# The contents of this file are dedicated to the public domain.  To
# the extent that dedication to the public domain is not available,
# everyone is granted a worldwide, perpetual, royalty-free,
# non-exclusive license to exercise all rights associated with the
# contents of this file for any purpose whatsoever.
# No rights are reserved.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# ===================================================================
import struct
from Crypto.Util.py3compat import byte_string, bchr, bord
from Crypto.Util.number import long_to_bytes, bytes_to_long
__all__ = ['DerObject', 'DerInteger', 'DerBoolean', 'DerOctetString',
           'DerNull', 'DerSequence', 'DerObjectId', 'DerBitString', 'DerSetOf']
# Useful references:
# - https://luca.ntop.org/Teaching/Appunti/asn1.html
# - https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/
# - https://www.zytrax.com/tech/survival/asn1.html
# - https://www.oss.com/asn1/resources/books-whitepapers-pubs/larmouth-asn1-book.pdf
# - https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
# - https://misc.daniel-marschall.de/asn.1/oid-converter/online.php
def _is_number(x, only_non_negative=False):
    test = 0
    try:
        test = x + test
    except TypeError:
        return False
    return not only_non_negative or x >= 0
class BytesIO_EOF(object):
    """This class differs from BytesIO in that a ValueError exception is
    raised whenever EOF is reached."""
    def __init__(self, initial_bytes):
        self._buffer = initial_bytes
        self._index = 0
        self._bookmark = None
    def set_bookmark(self):
        self._bookmark = self._index
    def data_since_bookmark(self):
        assert self._bookmark is not None
        return self._buffer[self._bookmark:self._index]
    def remaining_data(self):
        return len(self._buffer) - self._index
    def read(self, length):
        new_index = self._index + length
        if new_index > len(self._buffer):
            raise ValueError("Not enough data for DER decoding: expected %d bytes and found %d" % (new_index, len(self._buffer)))
        result = self._buffer[self._index:new_index]
        self._index = new_index
        return result
    def read_byte(self):
        return bord(self.read(1)[0])
class DerObject(object):
        """Base class for defining a single DER object.
        This class should never be directly instantiated.
        """
        def __init__(self, asn1Id=None, payload=b'', implicit=None,
                     constructed=False, explicit=None):
                """Initialize the DER object according to a specific ASN.1 type.
                :Parameters:
                  asn1Id : integer or byte
                    The universal DER tag number for this object
                    (e.g. 0x10 for a SEQUENCE).
                    If None, the tag is not known yet.
                  payload : byte string
                    The initial payload of the object (that it,
                    the content octets).
                    If not specified, the payload is empty.
                  implicit : integer or byte
                    The IMPLICIT tag number (< 0x1F) to use for the encoded object.
                    It overrides the universal tag *asn1Id*.
                    It cannot be combined with the ``explicit`` parameter.
                    By default, there is no IMPLICIT tag.
                  constructed : bool
                    True when the ASN.1 type is *constructed*.
                    False when it is *primitive* (default).
                  explicit : integer or byte
                    The EXPLICIT tag number (< 0x1F) to use for the encoded object.
                    It cannot be combined with the ``implicit`` parameter.
                    By default, there is no EXPLICIT tag.
                """
                if asn1Id is None:
                    # The tag octet will be read in with ``decode``
                    self._tag_octet = None
                    return
                asn1Id = self._convertTag(asn1Id)
                self.payload = payload
                # In a BER/DER identifier octet:
                # * bits 4-0 contain the tag value
                # * bit 5 is set if the type is 'constructed'
                #   and unset if 'primitive'
                # * bits 7-6 depend on the encoding class
                #
                # Class        | Bit 7, Bit 6
                # ----------------------------------
                # universal    |   0      0
                # application  |   0      1
                # context-spec |   1      0 (default for IMPLICIT/EXPLICIT)
                # private      |   1      1
                #
                constructed_bit = 0x20 if constructed else 0x00
                if None not in (explicit, implicit):
                    raise ValueError("Explicit and implicit tags are"
                                     " mutually exclusive")
                if implicit is not None:
                    # IMPLICIT tag overrides asn1Id
                    self._tag_octet = 0x80 | constructed_bit | self._convertTag(implicit)
                elif explicit is not None:
                    # 'constructed bit' is always asserted for an EXPLICIT tag
                    self._tag_octet = 0x80 | 0x20 | self._convertTag(explicit)
                    self._inner_tag_octet = constructed_bit | asn1Id
                else:
                    # Neither IMPLICIT nor EXPLICIT
                    self._tag_octet = constructed_bit | asn1Id
        def _convertTag(self, tag):
                """Check if *tag* is a real DER tag (5 bits).
                Convert it from a character to number if necessary.
                """
                if not _is_number(tag):
                    if len(tag) == 1:
                        tag = bord(tag[0])
                # Ensure that tag is a low tag
                if not (_is_number(tag) and 0 <= tag < 0x1F):
                    raise ValueError("Wrong DER tag")
                return tag
        @staticmethod
        def _definite_form(length):
                """Build length octets according to BER/DER
                definite form.
                """
                if length > 127:
                        encoding = long_to_bytes(length)
                        return bchr(len(encoding) + 128) + encoding
                return bchr(length)
        def encode(self):
                """Return this DER element, fully encoded as a binary byte string."""
                # Concatenate identifier octets, length octets,
                # and contents octets
                output_payload = self.payload
                # In case of an EXTERNAL tag, first encode the inner
                # element.
                if hasattr(self, "_inner_tag_octet"):
                    output_payload = (bchr(self._inner_tag_octet) +
                                      self._definite_form(len(self.payload)) +
                                      self.payload)
                return (bchr(self._tag_octet) +
                        self._definite_form(len(output_payload)) +
                        output_payload)
        def _decodeLen(self, s):
                """Decode DER length octets from a file."""
                length = s.read_byte()
                if length > 127:
                    encoded_length = s.read(length & 0x7F)
                    if bord(encoded_length[0]) == 0:
                        raise ValueError("Invalid DER: length has leading zero")
                    length = bytes_to_long(encoded_length)
                    if length <= 127:
                        raise ValueError("Invalid DER: length in long form but smaller than 128")
                return length
        def decode(self, der_encoded, strict=False):
                """Decode a complete DER element, and re-initializes this
                object with it.
                Args:
                  der_encoded (byte string): A complete DER element.
                Raises:
                  ValueError: in case of parsing errors.
                """
                if not byte_string(der_encoded):
                    raise ValueError("Input is not a byte string")
                s = BytesIO_EOF(der_encoded)
                self._decodeFromStream(s, strict)
                # There shouldn't be other bytes left
                if s.remaining_data() > 0:
                    raise ValueError("Unexpected extra data after the DER structure")
                return self
        def _decodeFromStream(self, s, strict):
                """Decode a complete DER element from a file."""
                idOctet = s.read_byte()
                if self._tag_octet is not None:
                    if idOctet != self._tag_octet:
                        raise ValueError("Unexpected DER tag")
                else:
                    self._tag_octet = idOctet
                length = self._decodeLen(s)
                self.payload = s.read(length)
                # In case of an EXTERNAL tag, further decode the inner
                # element.
                if hasattr(self, "_inner_tag_octet"):
                    p = BytesIO_EOF(self.payload)
                    inner_octet = p.read_byte()
                    if inner_octet != self._inner_tag_octet:
                        raise ValueError("Unexpected internal DER tag")
                    length = self._decodeLen(p)
                    self.payload = p.read(length)
                    # There shouldn't be other bytes left
                    if p.remaining_data() > 0:
                        raise ValueError("Unexpected extra data after the DER structure")
class DerInteger(DerObject):
        """Class to model a DER INTEGER.
        An example of encoding is::
          >>> from Crypto.Util.asn1 import DerInteger
          >>> from binascii import hexlify, unhexlify
          >>> int_der = DerInteger(9)
          >>> print hexlify(int_der.encode())
        which will show ``020109``, the DER encoding of 9.
        And for decoding::
          >>> s = unhexlify(b'020109')
          >>> try:
          >>>   int_der = DerInteger()
          >>>   int_der.decode(s)
          >>>   print int_der.value
          >>> except ValueError:
          >>>   print "Not a valid DER INTEGER"
        the output will be ``9``.
        :ivar value: The integer value
        :vartype value: integer
        """
        def __init__(self, value=0, implicit=None, explicit=None):
                """Initialize the DER object as an INTEGER.
                :Parameters:
                  value : integer
                    The value of the integer.
                  implicit : integer
                    The IMPLICIT tag to use for the encoded object.
                    It overrides the universal tag for INTEGER (2).
                """
                DerObject.__init__(self, 0x02, b'', implicit,
                                   False, explicit)
                self.value = value  # The integer value
        def encode(self):
                """Return the DER INTEGER, fully encoded as a
                binary string."""
                number = self.value
                self.payload = b''
                while True:
                    self.payload = bchr(int(number & 255)) + self.payload
                    if 128 <= number <= 255:
                        self.payload = bchr(0x00) + self.payload
                    if -128 <= number <= 255:
                        break
                    number >>= 8
                return DerObject.encode(self)
        def decode(self, der_encoded, strict=False):
                """Decode a DER-encoded INTEGER, and re-initializes this
                object with it.
                Args:
                  der_encoded (byte string): A complete INTEGER DER element.
                Raises:
                  ValueError: in case of parsing errors.
                """
                return DerObject.decode(self, der_encoded, strict=strict)
        def _decodeFromStream(self, s, strict):
                """Decode a complete DER INTEGER from a file."""
                # Fill up self.payload
                DerObject._decodeFromStream(self, s, strict)
                if strict:
                    if len(self.payload) == 0:
                        raise ValueError("Invalid encoding for DER INTEGER: empty payload")
                    if len(self.payload) >= 2 and struct.unpack('>H', self.payload[:2])[0] < 0x80:
                        raise ValueError("Invalid encoding for DER INTEGER: leading zero")
                # Derive self.value from self.payload
                self.value = 0
                bits = 1
                for i in self.payload:
                    self.value *= 256
                    self.value += bord(i)
                    bits <<= 8
                if self.payload and bord(self.payload[0]) & 0x80:
                    self.value -= bits
class DerBoolean(DerObject):
    """Class to model a DER-encoded BOOLEAN.
    An example of encoding is::
    >>> from Crypto.Util.asn1 import DerBoolean
    >>> bool_der = DerBoolean(True)
    >>> print(bool_der.encode().hex())
    which will show ``0101ff``, the DER encoding of True.
    And for decoding::
    >>> s = bytes.fromhex('0101ff')
    >>> try:
    >>>   bool_der = DerBoolean()
    >>>   bool_der.decode(s)
    >>>   print(bool_der.value)
    >>> except ValueError:
    >>>   print "Not a valid DER BOOLEAN"
    the output will be ``True``.
    :ivar value: The boolean value
    :vartype value: boolean
    """
    def __init__(self, value=False, implicit=None, explicit=None):
        """Initialize the DER object as a BOOLEAN.
        Args:
          value (boolean):
            The value of the boolean. Default is False.
          implicit (integer or byte):
            The IMPLICIT tag number (< 0x1F) to use for the encoded object.
            It overrides the universal tag for BOOLEAN (1).
            It cannot be combined with the ``explicit`` parameter.
            By default, there is no IMPLICIT tag.
          explicit (integer or byte):
            The EXPLICIT tag number (< 0x1F) to use for the encoded object.
            It cannot be combined with the ``implicit`` parameter.
            By default, there is no EXPLICIT tag.
        """
        DerObject.__init__(self, 0x01, b'', implicit, False, explicit)
        self.value = value  # The boolean value
    def encode(self):
        """Return the DER BOOLEAN, fully encoded as a binary string."""
        self.payload = b'\xFF' if self.value else b'\x00'
        return DerObject.encode(self)
    def decode(self, der_encoded, strict=False):
        """Decode a DER-encoded BOOLEAN, and re-initializes this object with it.
        Args:
            der_encoded (byte string): A DER-encoded BOOLEAN.
        Raises:
            ValueError: in case of parsing errors.
        """
        return DerObject.decode(self, der_encoded, strict)
    def _decodeFromStream(self, s, strict):
        """Decode a DER-encoded BOOLEAN from a file."""
        # Fill up self.payload
        DerObject._decodeFromStream(self, s, strict)
        if len(self.payload) != 1:
            raise ValueError("Invalid encoding for DER BOOLEAN: payload is not 1 byte")
        if bord(self.payload[0]) == 0:
            self.value = False
        elif bord(self.payload[0]) == 0xFF:
            self.value = True
        else:
            raise ValueError("Invalid payload for DER BOOLEAN")
class DerSequence(DerObject):
        """Class to model a DER SEQUENCE.
        This object behaves like a dynamic Python sequence.
        Sub-elements that are INTEGERs behave like Python integers.
        Any other sub-element is a binary string encoded as a complete DER
        sub-element (TLV).
        An example of encoding is:
          >>> from Crypto.Util.asn1 import DerSequence, DerInteger
          >>> from binascii import hexlify, unhexlify
          >>> obj_der = unhexlify('070102')
          >>> seq_der = DerSequence([4])
          >>> seq_der.append(9)
          >>> seq_der.append(obj_der.encode())
          >>> print hexlify(seq_der.encode())
        which will show ``3009020104020109070102``, the DER encoding of the
        sequence containing ``4``, ``9``, and the object with payload ``02``.
        For decoding:
          >>> s = unhexlify(b'3009020104020109070102')
          >>> try:
          >>>   seq_der = DerSequence()
          >>>   seq_der.decode(s)
          >>>   print len(seq_der)
          >>>   print seq_der[0]
          >>>   print seq_der[:]
          >>> except ValueError:
          >>>   print "Not a valid DER SEQUENCE"
        the output will be::
          3
          4
          [4, 9, b'\x07\x01\x02']
        """
        def __init__(self, startSeq=None, implicit=None, explicit=None):
                """Initialize the DER object as a SEQUENCE.
                :Parameters:
                  startSeq : Python sequence
                    A sequence whose element are either integers or
                    other DER objects.
                  implicit : integer or byte
                    The IMPLICIT tag number (< 0x1F) to use for the encoded object.
                    It overrides the universal tag for SEQUENCE (16).
                    It cannot be combined with the ``explicit`` parameter.
                    By default, there is no IMPLICIT tag.
                  explicit : integer or byte
                    The EXPLICIT tag number (< 0x1F) to use for the encoded object.
                    It cannot be combined with the ``implicit`` parameter.
                    By default, there is no EXPLICIT tag.
                """
                DerObject.__init__(self, 0x10, b'', implicit, True, explicit)
                if startSeq is None:
                    self._seq = []
                else:
                    self._seq = startSeq
        # A few methods to make it behave like a python sequence
        def __delitem__(self, n):
                del self._seq[n]
        def __getitem__(self, n):
                return self._seq[n]
        def __setitem__(self, key, value):
                self._seq[key] = value
        def __setslice__(self, i, j, sequence):
                self._seq[i:j] = sequence
        def __delslice__(self, i, j):
                del self._seq[i:j]
        def __getslice__(self, i, j):
                return self._seq[max(0, i):max(0, j)]
        def __len__(self):
                return len(self._seq)
        def __iadd__(self, item):
                self._seq.append(item)
                return self
        def append(self, item):
                self._seq.append(item)
                return self
        def insert(self, index, item):
                self._seq.insert(index, item)
                return self
        def hasInts(self, only_non_negative=True):
                """Return the number of items in this sequence that are
                integers.
                Args:
                  only_non_negative (boolean):
                    If ``True``, negative integers are not counted in.
                """
                items = [x for x in self._seq if _is_number(x, only_non_negative)]
                return len(items)
        def hasOnlyInts(self, only_non_negative=True):
                """Return ``True`` if all items in this sequence are integers
                or non-negative integers.
                This function returns False is the sequence is empty,
                or at least one member is not an integer.
                Args:
                  only_non_negative (boolean):
                    If ``True``, the presence of negative integers
                    causes the method to return ``False``."""
                return self._seq and self.hasInts(only_non_negative) == len(self._seq)
        def encode(self):
                """Return this DER SEQUENCE, fully encoded as a
                binary string.
                Raises:
                  ValueError: if some elements in the sequence are neither integers
                              nor byte strings.
                """
                self.payload = b''
                for item in self._seq:
                    if byte_string(item):
                        self.payload += item
                    elif _is_number(item):
                        self.payload += DerInteger(item).encode()
                    else:
                        self.payload += item.encode()
                return DerObject.encode(self)
        def decode(self, der_encoded, strict=False, nr_elements=None, only_ints_expected=False):
                """Decode a complete DER SEQUENCE, and re-initializes this
                object with it.
                Args:
                  der_encoded (byte string):
                    A complete SEQUENCE DER element.
                  nr_elements (None or integer or list of integers):
                    The number of members the SEQUENCE can have
                  only_ints_expected (boolean):
                    Whether the SEQUENCE is expected to contain only integers.
                  strict (boolean):
                    Whether decoding must check for strict DER compliancy.
                Raises:
                  ValueError: in case of parsing errors.
                DER INTEGERs are decoded into Python integers. Any other DER
                element is not decoded. Its validity is not checked.
                """
                self._nr_elements = nr_elements
                result = DerObject.decode(self, der_encoded, strict=strict)
                if only_ints_expected and not self.hasOnlyInts():
                    raise ValueError("Some members are not INTEGERs")
                return result
        def _decodeFromStream(self, s, strict):
                """Decode a complete DER SEQUENCE from a file."""
                self._seq = []
                # Fill up self.payload
                DerObject._decodeFromStream(self, s, strict)
                # Add one item at a time to self.seq, by scanning self.payload
                p = BytesIO_EOF(self.payload)
                while p.remaining_data() > 0:
                    p.set_bookmark()
                    der = DerObject()
                    der._decodeFromStream(p, strict)
                    # Parse INTEGERs differently
                    if der._tag_octet != 0x02:
                        self._seq.append(p.data_since_bookmark())
                    else:
                        derInt = DerInteger()
                        data = p.data_since_bookmark()
                        derInt.decode(data, strict=strict)
                        self._seq.append(derInt.value)
                ok = True
                if self._nr_elements is not None:
                    try:
                        ok = len(self._seq) in self._nr_elements
                    except TypeError:
                        ok = len(self._seq) == self._nr_elements
                if not ok:
                    raise ValueError("Unexpected number of members (%d)"
                                     " in the sequence" % len(self._seq))
class DerOctetString(DerObject):
    """Class to model a DER OCTET STRING.
    An example of encoding is:
    >>> from Crypto.Util.asn1 import DerOctetString
    >>> from binascii import hexlify, unhexlify
    >>> os_der = DerOctetString(b'\\xaa')
    >>> os_der.payload += b'\\xbb'
    >>> print hexlify(os_der.encode())
    which will show ``0402aabb``, the DER encoding for the byte string
    ``b'\\xAA\\xBB'``.
    For decoding:
    >>> s = unhexlify(b'0402aabb')
    >>> try:
    >>>   os_der = DerOctetString()
    >>>   os_der.decode(s)
    >>>   print hexlify(os_der.payload)
    >>> except ValueError:
    >>>   print "Not a valid DER OCTET STRING"
    the output will be ``aabb``.
    :ivar payload: The content of the string
    :vartype payload: byte string
    """
    def __init__(self, value=b'', implicit=None):
        """Initialize the DER object as an OCTET STRING.
        :Parameters:
          value : byte string
            The initial payload of the object.
            If not specified, the payload is empty.
          implicit : integer
            The IMPLICIT tag to use for the encoded object.
            It overrides the universal tag for OCTET STRING (4).
        """
        DerObject.__init__(self, 0x04, value, implicit, False)
class DerNull(DerObject):
    """Class to model a DER NULL element."""
    def __init__(self):
        """Initialize the DER object as a NULL."""
        DerObject.__init__(self, 0x05, b'', None, False)
class DerObjectId(DerObject):
    """Class to model a DER OBJECT ID.
    An example of encoding is:
    >>> from Crypto.Util.asn1 import DerObjectId
    >>> from binascii import hexlify, unhexlify
    >>> oid_der = DerObjectId("1.2")
    >>> oid_der.value += ".840.113549.1.1.1"
    >>> print hexlify(oid_der.encode())
    which will show ``06092a864886f70d010101``, the DER encoding for the
    RSA Object Identifier ``1.2.840.113549.1.1.1``.
    For decoding:
    >>> s = unhexlify(b'06092a864886f70d010101')
    >>> try:
    >>>   oid_der = DerObjectId()
    >>>   oid_der.decode(s)
    >>>   print oid_der.value
    >>> except ValueError:
    >>>   print "Not a valid DER OBJECT ID"
    the output will be ``1.2.840.113549.1.1.1``.
    :ivar value: The Object ID (OID), a dot separated list of integers
    :vartype value: string
    """
    def __init__(self, value='', implicit=None, explicit=None):
        """Initialize the DER object as an OBJECT ID.
        :Parameters:
          value : string
            The initial Object Identifier (e.g. "1.2.0.0.6.2").
          implicit : integer
            The IMPLICIT tag to use for the encoded object.
            It overrides the universal tag for OBJECT ID (6).
          explicit : integer
            The EXPLICIT tag to use for the encoded object.
        """
        DerObject.__init__(self, 0x06, b'', implicit, False, explicit)
        self.value = value
    def encode(self):
        """Return the DER OBJECT ID, fully encoded as a
        binary string."""
        comps = [int(x) for x in self.value.split(".")]
        if len(comps) < 2:
            raise ValueError("Not a valid Object Identifier string")
        if comps[0] > 2:
            raise ValueError("First component must be 0, 1 or 2")
        if comps[0] < 2 and comps[1] > 39:
            raise ValueError("Second component must be 39 at most")
        subcomps = [40 * comps[0] + comps[1]] + comps[2:]
        encoding = []
        for v in reversed(subcomps):
            encoding.append(v & 0x7F)
            v >>= 7
            while v:
                encoding.append((v & 0x7F) | 0x80)
                v >>= 7
        self.payload = b''.join([bchr(x) for x in reversed(encoding)])
        return DerObject.encode(self)
    def decode(self, der_encoded, strict=False):
        """Decode a complete DER OBJECT ID, and re-initializes this
        object with it.
        Args:
            der_encoded (byte string):
                A complete DER OBJECT ID.
            strict (boolean):
                Whether decoding must check for strict DER compliancy.
        Raises:
            ValueError: in case of parsing errors.
        """
        return DerObject.decode(self, der_encoded, strict)
    def _decodeFromStream(self, s, strict):
        """Decode a complete DER OBJECT ID from a file."""
        # Fill up self.payload
        DerObject._decodeFromStream(self, s, strict)
        # Derive self.value from self.payload
        p = BytesIO_EOF(self.payload)
        subcomps = []
        v = 0
        while p.remaining_data():
            c = p.read_byte()
            v = (v << 7) + (c & 0x7F)
            if not (c & 0x80):
                subcomps.append(v)
                v = 0
        if len(subcomps) == 0:
            raise ValueError("Empty payload")
        if subcomps[0] < 40:
            subcomps[:1] = [0, subcomps[0]]
        elif subcomps[0] < 80:
            subcomps[:1] = [1, subcomps[0] - 40]
        else:
            subcomps[:1] = [2, subcomps[0] - 80]
        self.value = ".".join([str(x) for x in subcomps])
class DerBitString(DerObject):
    """Class to model a DER BIT STRING.
    An example of encoding is:
    >>> from Crypto.Util.asn1 import DerBitString
    >>> bs_der = DerBitString(b'\\xAA')
    >>> bs_der.value += b'\\xBB'
    >>> print(bs_der.encode().hex())
    which will show ``030300aabb``, the DER encoding for the bit string
    ``b'\\xAA\\xBB'``.
    For decoding:
    >>> s = bytes.fromhex('030300aabb')
    >>> try:
    >>>   bs_der = DerBitString()
    >>>   bs_der.decode(s)
    >>>   print(bs_der.value.hex())
    >>> except ValueError:
    >>>   print "Not a valid DER BIT STRING"
    the output will be ``aabb``.
    :ivar value: The content of the string
    :vartype value: byte string
    """
    def __init__(self, value=b'', implicit=None, explicit=None):
        """Initialize the DER object as a BIT STRING.
        :Parameters:
          value : byte string or DER object
            The initial, packed bit string.
            If not specified, the bit string is empty.
          implicit : integer
            The IMPLICIT tag to use for the encoded object.
            It overrides the universal tag for BIT STRING (3).
          explicit : integer
            The EXPLICIT tag to use for the encoded object.
        """
        DerObject.__init__(self, 0x03, b'', implicit, False, explicit)
        # The bitstring value (packed)
        if isinstance(value, DerObject):
            self.value = value.encode()
        else:
            self.value = value
    def encode(self):
        """Return the DER BIT STRING, fully encoded as a
        byte string."""
        # Add padding count byte
        self.payload = b'\x00' + self.value
        return DerObject.encode(self)
    def decode(self, der_encoded, strict=False):
        """Decode a complete DER BIT STRING, and re-initializes this
        object with it.
        Args:
            der_encoded (byte string): a complete DER BIT STRING.
            strict (boolean):
                Whether decoding must check for strict DER compliancy.
        Raises:
            ValueError: in case of parsing errors.
        """
        return DerObject.decode(self, der_encoded, strict)
    def _decodeFromStream(self, s, strict):
        """Decode a complete DER BIT STRING DER from a file."""
        # Fill-up self.payload
        DerObject._decodeFromStream(self, s, strict)
        if self.payload and bord(self.payload[0]) != 0:
            raise ValueError("Not a valid BIT STRING")
        # Fill-up self.value
        self.value = b''
        # Remove padding count byte
        if self.payload:
            self.value = self.payload[1:]
class DerSetOf(DerObject):
    """Class to model a DER SET OF.
    An example of encoding is:
    >>> from Crypto.Util.asn1 import DerBitString
    >>> from binascii import hexlify, unhexlify
    >>> so_der = DerSetOf([4,5])
    >>> so_der.add(6)
    >>> print hexlify(so_der.encode())
    which will show ``3109020104020105020106``, the DER encoding
    of a SET OF with items 4,5, and 6.
    For decoding:
    >>> s = unhexlify(b'3109020104020105020106')
    >>> try:
    >>>   so_der = DerSetOf()
    >>>   so_der.decode(s)
    >>>   print [x for x in so_der]
    >>> except ValueError:
    >>>   print "Not a valid DER SET OF"
    the output will be ``[4, 5, 6]``.
    """
    def __init__(self, startSet=None, implicit=None):
        """Initialize the DER object as a SET OF.
        :Parameters:
          startSet : container
            The initial set of integers or DER encoded objects.
          implicit : integer
            The IMPLICIT tag to use for the encoded object.
            It overrides the universal tag for SET OF (17).
        """
        DerObject.__init__(self, 0x11, b'', implicit, True)
        self._seq = []
        # All elements must be of the same type (and therefore have the
        # same leading octet)
        self._elemOctet = None
        if startSet:
            for e in startSet:
                self.add(e)
    def __getitem__(self, n):
        return self._seq[n]
    def __iter__(self):
        return iter(self._seq)
    def __len__(self):
        return len(self._seq)
    def add(self, elem):
        """Add an element to the set.
        Args:
            elem (byte string or integer):
              An element of the same type of objects already in the set.
              It can be an integer or a DER encoded object.
        """
        if _is_number(elem):
            eo = 0x02
        elif isinstance(elem, DerObject):
            eo = self._tag_octet
        else:
            eo = bord(elem[0])
        if self._elemOctet != eo:
            if self._elemOctet is not None:
                raise ValueError("New element does not belong to the set")
            self._elemOctet = eo
        if elem not in self._seq:
            self._seq.append(elem)
    def decode(self, der_encoded, strict=False):
        """Decode a complete SET OF DER element, and re-initializes this
        object with it.
        DER INTEGERs are decoded into Python integers. Any other DER
        element is left undecoded; its validity is not checked.
        Args:
            der_encoded (byte string): a complete DER BIT SET OF.
            strict (boolean):
                Whether decoding must check for strict DER compliancy.
        Raises:
            ValueError: in case of parsing errors.
        """
        return DerObject.decode(self, der_encoded, strict)
    def _decodeFromStream(self, s, strict):
        """Decode a complete DER SET OF from a file."""
        self._seq = []
        # Fill up self.payload
        DerObject._decodeFromStream(self, s, strict)
        # Add one item at a time to self.seq, by scanning self.payload
        p = BytesIO_EOF(self.payload)
        setIdOctet = -1
        while p.remaining_data() > 0:
            p.set_bookmark()
            der = DerObject()
            der._decodeFromStream(p, strict)
            # Verify that all members are of the same type
            if setIdOctet < 0:
                setIdOctet = der._tag_octet
            else:
                if setIdOctet != der._tag_octet:
                    raise ValueError("Not all elements are of the same DER type")
            # Parse INTEGERs differently
            if setIdOctet != 0x02:
                self._seq.append(p.data_since_bookmark())
            else:
                derInt = DerInteger()
                derInt.decode(p.data_since_bookmark(), strict)
                self._seq.append(derInt.value)
        # end
    def encode(self):
        """Return this SET OF DER element, fully encoded as a
        binary string.
        """
        # Elements in the set must be ordered in lexicographic order
        ordered = []
        for item in self._seq:
            if _is_number(item):
                bys = DerInteger(item).encode()
            elif isinstance(item, DerObject):
                bys = item.encode()
            else:
                bys = item
            ordered.append(bys)
        ordered.sort()
        self.payload = b''.join(ordered)
        return DerObject.encode(self)