Ejemplo n.º 1
0
def lnencode(addr: 'LnAddr', privkey) -> str:
    if addr.amount:
        amount = addr.currency + shorten_amount(addr.amount)
    else:
        amount = addr.currency if addr.currency else ''

    hrp = 'ln' + amount

    # Start with the timestamp
    data = bitstring.pack('uint:35', addr.date)

    tags_set = set()

    # Payment hash
    data += tagged_bytes('p', addr.paymenthash)
    tags_set.add('p')

    if addr.payment_secret is not None:
        data += tagged_bytes('s', addr.payment_secret)
        tags_set.add('s')

    for k, v in addr.tags:

        # BOLT #11:
        #
        # A writer MUST NOT include more than one `d`, `h`, `n` or `x` fields,
        if k in ('d', 'h', 'n', 'x', 'p', 's'):
            if k in tags_set:
                raise ValueError("Duplicate '{}' tag".format(k))

        if k == 'r':
            route = bitstring.BitArray()
            for step in v:
                pubkey, channel, feebase, feerate, cltv = step
                route.append(
                    bitstring.BitArray(pubkey) + bitstring.BitArray(channel) +
                    bitstring.pack('intbe:32', feebase) +
                    bitstring.pack('intbe:32', feerate) +
                    bitstring.pack('intbe:16', cltv))
            data += tagged('r', route)
        elif k == 't':
            pubkey, feebase, feerate, cltv = v
            route = bitstring.BitArray(pubkey) + bitstring.pack(
                'intbe:32', feebase) + bitstring.pack(
                    'intbe:32', feerate) + bitstring.pack('intbe:16', cltv)
            data += tagged('t', route)
        elif k == 'f':
            data += encode_fallback(v, addr.currency)
        elif k == 'd':
            # truncate to max length: 1024*5 bits = 639 bytes
            data += tagged_bytes('d', v.encode()[0:639])
        elif k == 'x':
            expirybits = bitstring.pack('intbe:64', v)
            expirybits = trim_to_min_length(expirybits)
            data += tagged('x', expirybits)
        elif k == 'h':
            data += tagged_bytes('h', sha256(v.encode('utf-8')).digest())
        elif k == 'n':
            data += tagged_bytes('n', v)
        elif k == 'c':
            finalcltvbits = bitstring.pack('intbe:64', v)
            finalcltvbits = trim_to_min_length(finalcltvbits)
            data += tagged('c', finalcltvbits)
        elif k == '9':
            if v == 0:
                continue
            feature_bits = bitstring.BitArray(uint=v, length=v.bit_length())
            feature_bits = trim_to_min_length(feature_bits)
            data += tagged('9', feature_bits)
        else:
            # FIXME: Support unknown tags?
            raise ValueError("Unknown tag {}".format(k))

        tags_set.add(k)

    # BOLT #11:
    #
    # A writer MUST include either a `d` or `h` field, and MUST NOT include
    # both.
    if 'd' in tags_set and 'h' in tags_set:
        raise ValueError("Cannot include both 'd' and 'h'")
    if not 'd' in tags_set and not 'h' in tags_set:
        raise ValueError("Must include either 'd' or 'h'")

    # We actually sign the hrp, then data (padded to 8 bits with zeroes).
    msg = hrp.encode("ascii") + data.tobytes()
    privkey = ecc.ECPrivkey(privkey)
    sig = privkey.sign_message(msg,
                               is_compressed=False,
                               algo=lambda x: sha256(x).digest())
    recovery_flag = bytes([sig[0] - 27])
    sig = bytes(sig[1:]) + recovery_flag
    data += sig

    return bech32_encode(segwit_addr.Encoding.BECH32, hrp,
                         bitarray_to_u5(data))
Ejemplo n.º 2
0
def u5_to_bitarray(arr):
    b = ''.join(_INT_TO_BINSTR[a] for a in arr)
    return bitstring.BitArray(bin=b)
Ejemplo n.º 3
0
#!/usr/bin/env python
Ejemplo n.º 4
0
 def getPeHash(self, exe):
     try:
         #image characteristics
         img_chars = bitstring.BitArray(hex(exe.FILE_HEADER.Characteristics))
         #pad to 16 bits
         img_chars = bitstring.BitArray(bytes=img_chars.tobytes())
         img_chars_xor = img_chars[0:7] ^ img_chars[8:15]
      
         #start to build pehash
         pehash_bin = bitstring.BitArray(img_chars_xor)
      
         #subsystem -
         sub_chars = bitstring.BitArray(hex(exe.FILE_HEADER.Machine))
         #pad to 16 bits
         sub_chars = bitstring.BitArray(bytes=sub_chars.tobytes())
         sub_chars_xor = sub_chars[0:7] ^ sub_chars[8:15]
         pehash_bin.append(sub_chars_xor)
      
         #Stack Commit Size
         stk_size = bitstring.BitArray(hex(exe.OPTIONAL_HEADER.SizeOfStackCommit))
         stk_size_bits = string.zfill(stk_size.bin, 32)
         #now xor the bits
         stk_size = bitstring.BitArray(bin=stk_size_bits)
         stk_size_xor = stk_size[8:15] ^ stk_size[16:23] ^ stk_size[24:31]
         #pad to 8 bits
         stk_size_xor = bitstring.BitArray(bytes=stk_size_xor.tobytes())
         pehash_bin.append(stk_size_xor)
      
         #Heap Commit Size
         hp_size = bitstring.BitArray(hex(exe.OPTIONAL_HEADER.SizeOfHeapCommit))
         hp_size_bits = string.zfill(hp_size.bin, 32)
         #now xor the bits
         hp_size = bitstring.BitArray(bin=hp_size_bits)
         hp_size_xor = hp_size[8:15] ^ hp_size[16:23] ^ hp_size[24:31]
         #pad to 8 bits
         hp_size_xor = bitstring.BitArray(bytes=hp_size_xor.tobytes())
         pehash_bin.append(hp_size_xor)
      
         #Section chars
         for section in exe.sections:
             #virutal address
             sect_va =  bitstring.BitArray(hex(section.VirtualAddress))
             sect_va = bitstring.BitArray(bytes=sect_va.tobytes())
             pehash_bin.append(sect_va)    
      
             #rawsize
             sect_rs =  bitstring.BitArray(hex(section.SizeOfRawData))
             sect_rs = bitstring.BitArray(bytes=sect_rs.tobytes())
             sect_rs_bits = string.zfill(sect_rs.bin, 32)
             sect_rs = bitstring.BitArray(bin=sect_rs_bits)
             sect_rs = bitstring.BitArray(bytes=sect_rs.tobytes())
             sect_rs_bits = sect_rs[8:31]
             pehash_bin.append(sect_rs_bits)
      
             #section chars
             sect_chars =  bitstring.BitArray(hex(section.Characteristics))
             sect_chars = bitstring.BitArray(bytes=sect_chars.tobytes())
             sect_chars_xor = sect_chars[16:23] ^ sect_chars[24:31]
             pehash_bin.append(sect_chars_xor)
      
             #entropy calulation
             address = section.VirtualAddress
             size = section.SizeOfRawData
             raw = exe.write()[address+size:]
             if size == 0:
                 kolmog = bitstring.BitArray(float=1, length=32)
                 pehash_bin.append(kolmog[0:7])
                 continue
             bz2_raw = bz2.compress(raw)
             bz2_size = len(bz2_raw)
             #k = round(bz2_size / size, 5)
             k = bz2_size / size
             kolmog = bitstring.BitArray(float=k, length=32)
             pehash_bin.append(kolmog[0:7])
      
         m = hashlib.sha1()
         m.update(pehash_bin.tobytes())
         return m.hexdigest()
     except Exception, e:
         log.error("Error calculate PeHash: %s" % e)
Ejemplo n.º 5
0
def decode_pdu(data: bytearray):
    # result = GSM.decode(data.decode())
    # logging.info('result:', result)
    # return result
    result = dict()
    result['type'] = data[0]
    p = 1
    while p < len(data):
        record = data[p]
        length = data[p + 1]
        payload = data[p + 2:p + 2 + length]

        # teleservice_identifier
        if record == 0x00:
            result['teleservice_identifier'] = payload
        # service_category
        elif record == 0x01:
            result['service_category'] = payload
        # originating_address
        elif record == 0x02:
            bits = bitstring.BitArray(bytes=payload)
            number_length = bits[2:10].uint
            number = ''
            for i in range(0, number_length):
                number += str(bits[i * 4 + 10:i * 4 + 14].uint % 10)
            result['source'] = number
        # originating_subaddress
        elif record == 0x03:
            result['originating_subaddress'] = payload
        # destination_address
        elif record == 0x04:
            result['destination_address'] = payload
        # destination_subaddress
        elif record == 0x05:
            result['destination_subaddress'] = payload
        # bearer_reply_option
        elif record == 0x06:
            result['bearer_reply_option'] = payload
        # cause_codes
        elif record == 0x07:
            result['cause_codes'] = payload
        # bearer_data
        elif record == 0x08:
            q = 0
            while q < length:
                bearer_record = payload[q]
                bearer_length = payload[q + 1]
                bearer_payload = payload[q + 2:q + 2 + bearer_length]

                # message_id
                if bearer_record == 0x00:
                    result['message_id'] = bearer_payload
                    result['long_message'] = (bearer_payload[2] & 0b1000 > 0)
                # content
                elif bearer_record == 0x01:
                    bits = bitstring.BitArray(bytes=bearer_payload)

                    content_encoding = bits[:5].uint
                    content_length = bits[5:13].uint
                    logging.info(
                        "SMS content length = {}".format(content_length))

                    if result['long_message']:
                        udh_length = bits[13:21].uint
                        udh = bits[21:21 + udh_length * 8].bytes

                        r = 0
                        while r < udh_length:
                            udh_record = udh[r]
                            udh_record_length = udh[r + 1]
                            if udh_record == 0:
                                assert (udh_record_length == 3)
                                result['long_message_ref'] = udh[r + 2]
                                result['long_message_total'] = udh[r + 3]
                                result['long_message_index'] = udh[r + 4]
                            else:
                                logging.warning(
                                    'Advanced UDH is currently not implemented'
                                )
                            r += udh_record_length + 2

                        del bits[13:21 + udh_length * 8]

                    # utf-16
                    if content_encoding == 0x04:
                        content = bits[13:-3].bytes.decode('utf-16-be')
                    # ascii
                    elif content_encoding == 0x02:
                        content = bits[13:13 + content_length * 7]

                        for i in range(0, content_length):
                            content.insert('0b0', i * 8)
                        content = content.bytes.decode('ascii')
                    else:
                        raise Exception('Unexpected encoding')

                    result['content'] = content
                    # TODO
                # timestamp
                elif bearer_record == 0x03:
                    assert (bearer_length == 6)
                    timestamp = list()
                    for i in range(0, 6):
                        timestamp.append(bearer_payload[i] // 16 * 10 +
                                         bearer_payload[i] % 16)
                    timestamp[0] += 2000
                    result['timestamp'] = datetime.datetime(
                        timestamp[0], timestamp[1], timestamp[2], timestamp[3],
                        timestamp[4], timestamp[5])
                # reply_option
                elif bearer_record == 0x0a:
                    result['reply_option'] = bearer_payload
                elif bearer_record == 0x0e:
                    bits = bitstring.BitArray(bytes=bearer_payload)
                    number_length = bits[1:9].uint
                    number = ''
                    for i in range(0, number_length):
                        number += str(bits[i * 4 + 9:i * 4 + 13].uint % 10)

                    result['callback_number'] = number

                q += bearer_length + 2
        else:
            raise Exception('Unexpected PDU data')

        p += length + 2
    return result
def test_resume(tmpdir):
    tmpdir.join('a').write('zz')
    lp = upload.LocalPath(pathlib.Path(str(tmpdir)), pathlib.Path('a'))

    opts = mock.MagicMock()
    opts.chunk_size_bytes = 0
    opts.one_shot_bytes = 0
    opts.store_file_properties.md5 = True
    opts.rsa_public_key = None

    ase = azmodels.StorageEntity('cont')
    ase._mode = azmodels.StorageModes.Block
    ase._name = 'name'
    ase._encryption = None

    # test no resume
    ud = upload.Descriptor(lp, ase, 'uid', opts, mock.MagicMock(), None)
    assert ud._resume() is None

    # check if path exists in resume db
    resume = mock.MagicMock()
    resume.get_record.return_value = None
    ud = upload.Descriptor(lp, ase, 'uid', opts, mock.MagicMock(), resume)
    assert ud._resume() is None

    # check same lengths
    bad = mock.MagicMock()
    bad.length = 0
    resume.get_record.return_value = bad
    assert ud._resume() is None

    # check completed resume
    comp = mock.MagicMock()
    comp.length = 2
    comp.completed = True
    comp.total_chunks = 1
    comp.chunk_size = 2
    comp.completed_chunks = 1
    resume.get_record.return_value = comp
    ud._completed_chunks = mock.MagicMock()
    ud._src_ase = ase
    assert ud._resume() == 2

    ase.replica_targets = [ase]
    ud = upload.Descriptor(lp, ase, 'uid', opts, mock.MagicMock(), resume)
    ud._completed_chunks = mock.MagicMock()
    ud._src_ase = ase
    assert ud._resume() == 4

    # check no encryption
    ase = azmodels.StorageEntity('cont')
    ase._mode = azmodels.StorageModes.Block
    ase._name = 'name'
    opts.rsa_public_key = 'abc'

    nc = mock.MagicMock()
    nc.length = 16
    nc.completed = False
    nc.total_chunks = 2
    nc.chunk_size = 1
    nc.completed_chunks = 1

    resume.get_record.return_value = nc
    ud = upload.Descriptor(lp, ase, 'uid', opts, mock.MagicMock(), resume)
    assert ud._resume() is None

    # check rr path exists
    ase = azmodels.StorageEntity('cont')
    ase._mode = azmodels.StorageModes.Block
    ase._name = 'name'

    nc.length = 2
    nc.local_path = pathlib.Path('yyy')
    opts.rsa_public_key = None

    resume.get_record.return_value = nc
    ud = upload.Descriptor(lp, ase, 'uid', opts, mock.MagicMock(), resume)
    assert ud._resume() is None

    # check resume no md5
    opts.store_file_properties.md5 = False

    ase = azmodels.StorageEntity('cont')
    ase._mode = azmodels.StorageModes.Block
    ase._name = 'name'

    nc = mock.MagicMock()
    nc.length = 2
    nc.completed = False
    nc.total_chunks = 2
    nc.chunk_size = 1
    cc = bitstring.BitArray(length=nc.total_chunks)
    cc.set(True, 0)
    nc.completed_chunks = cc.int
    nc.local_path = lp.absolute_path

    resume.get_record.return_value = nc
    ud = upload.Descriptor(lp, ase, 'uid', opts, mock.MagicMock(), resume)
    assert ud._resume() == 1

    # check resume with md5 mismatch
    opts.store_file_properties.md5 = True

    ase = azmodels.StorageEntity('cont')
    ase._mode = azmodels.StorageModes.Block
    ase._name = 'name'

    nc = mock.MagicMock()
    nc.length = 2
    nc.completed = False
    nc.total_chunks = 2
    nc.chunk_size = 1
    cc = bitstring.BitArray(length=nc.total_chunks)
    cc.set(True, 0)
    nc.completed_chunks = cc.int
    nc.local_path = lp.absolute_path

    resume.get_record.return_value = nc
    ud = upload.Descriptor(lp, ase, 'uid', opts, mock.MagicMock(), resume)
    assert ud._resume() is None

    # check resume with md5 match
    ase = azmodels.StorageEntity('cont')
    ase._mode = azmodels.StorageModes.Block
    ase._name = 'name'

    nc = mock.MagicMock()
    nc.length = 2
    nc.completed = False
    nc.total_chunks = 2
    nc.chunk_size = 1
    cc = bitstring.BitArray(length=nc.total_chunks)
    cc.set(True, 0)
    nc.completed_chunks = cc.int
    nc.local_path = lp.absolute_path
    md5 = hashlib.md5()
    md5.update(b'z')
    nc.md5hexdigest = md5.hexdigest()

    resume.get_record.return_value = nc
    ud = upload.Descriptor(lp, ase, 'uid', opts, mock.MagicMock(), resume)
    assert ud._resume() == 1
Ejemplo n.º 7
0
def resolve_host_name(host_name_to):
    """
  Queries the DNS A record for the given host name and returns the result.
  """

    host_name_to = host_name_to.split(".")

    # Construct the DNS packet consisting of header + QNAME + QTYPE + QCLASS.

    DNS_QUERY_FORMAT = [
        "hex=id", "bin=flags", "uintbe:16=qdcount", "uintbe:16=ancount",
        "uintbe:16=nscount", "uintbe:16=arcount"
    ]

    DNS_QUERY = {
        "id": "0x1a2b",
        "flags": "0b0000000100000000"  # Standard query. Ask for recursion.
        ,
        "qdcount": 1  # One question.
        ,
        "ancount": 0,
        "nscount": 0,
        "arcount": 0
    }

    # Construct the QNAME:
    # size|label|size|label|size|...|label|0x00

    j = 0

    for i, _ in enumerate(host_name_to):

        host_name_to[i] = host_name_to[i].strip()

        DNS_QUERY_FORMAT.append("hex=" + "qname" + str(j))

        DNS_QUERY["qname" + str(j)] = to_hex_string(len(host_name_to[i]))

        j += 1

        DNS_QUERY_FORMAT.append("hex=" + "qname" + str(j))

        DNS_QUERY["qname" + str(j)] = to_hex_string(host_name_to[i])

        j += 1

    # Add a terminating byte.

    DNS_QUERY_FORMAT.append("hex=qname" + str(j))

    DNS_QUERY["qname" + str(j)] = to_hex_string(0)

    # End QNAME.

    # Set the type and class now.

    DNS_QUERY_FORMAT.append("uintbe:16=qtype")

    DNS_QUERY["qtype"] = 1  # For the A record.

    DNS_QUERY_FORMAT.append("hex=qclass")

    DNS_QUERY["qclass"] = "0x0001"  # For IN or Internet.

    # Convert the struct to a bit string.

    data = bitstring.pack(",".join(DNS_QUERY_FORMAT), **DNS_QUERY)

    # Send the packet off to the server.

    # DNS_IP = "141.226.242.178" # Google public DNS server IP.
    # DNS_PORT = 5053 # DNS server port for queries.
    DNS_IP = "8.8.8.8"  # Google public DNS server IP.
    DNS_PORT = 53

    READ_BUFFER = 1024  # The size of the buffer to read in the received UDP packet.

    address = (DNS_IP, DNS_PORT)  # Tuple needed by sendto.

    client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # Internet, UDP.

    print(data.tobytes)
    client.sendto(data.tobytes(),
                  address)  # Send the DNS packet to the server using the port.

    # Get the response DNS packet back, decode, and print out the IP.

    # Get the response and put it in data. Get the responding server address and put it in address.

    data, address = client.recvfrom(READ_BUFFER)

    # Convert data to bit string.

    data = bitstring.BitArray(bytes=data)

    # Unpack the receive DNS packet and extract the IP the host name resolved to.

    # Get the host name from the QNAME located just past the received header.

    host_name_from = []

    # First size of the QNAME labels starts at bit 96 and goes up to bit 104.
    # size|label|size|label|size|...|label|0x00

    x = 96
    y = x + 8

    for i, _ in enumerate(host_name_to):

        # Based on the size of the very next label indicated by
        # the 1 octet/byte before the label, read in that many
        # bits past the octet/byte indicating the very next
        # label size.

        # Get the label size in hex. Convert to an integer and times it
        # by 8 to get the number of bits.

        increment = (int(str(data[x:y].hex), 16) * 8)

        x = y
        y = x + increment

        # Read in the label, converting to ASCII.

        host_name_from.append(
            codecs.decode(data[x:y].hex, "hex_codec").decode())

        # Set up the next iteration to get the next label size.
        # Assuming here that any label size is no bigger than
        # one byte.

        x = y
        y = x + 8  # Eight bits to a byte.

    # Get the response code.
    # This is located in the received DNS packet header at
    # bit 28 ending at bit 32.

    response_code = str(data[28:32].hex)

    result = {'host_name': None, 'ip_address': None}

    # Check for errors.

    if (response_code == "0"):

        result['host_name'] = ".".join(host_name_from)

        # Assemble the IP address the host name resolved to.
        # It is usually the last four octets of the DNS
        # packet--at least for A records.

        result['ip_address'] = ".".join([
            str(data[-32:-24].uintbe),
            str(data[-24:-16].uintbe),
            str(data[-16:-8].uintbe),
            str(data[-8:].uintbe)
        ])

    elif (response_code == "1"):

        print("\nFormat error. Unable to interpret query.\n")

    elif (response_code == "2"):

        print("\nServer failure. Unable to process query.\n")

    elif (response_code == "3"):

        print("\nName error. Domain name does not exist.\n")

    elif (response_code == "4"):

        print("\nQuery request type not supported.\n")

    elif (response_code == "5"):

        print("\nServer refused query.\n")

    return result
Ejemplo n.º 8
0
def replay(device):
    for code in codes:
        codeb = bitstring.BitArray(hex=code).tobytes()
        print str(codeb)
        device.RFxmit(codeb)
        time.sleep(1)
Ejemplo n.º 9
0
def u5_to_bitarray(arr):
    ret = bitstring.BitArray()
    for a in arr:
        ret += bitstring.pack("uint:5", a)
    return ret
Ejemplo n.º 10
0
 def __init__(self, data):
     self.bitfield = bitstring.BitArray(bytes=data)
Ejemplo n.º 11
0
 def testBitArrayCopy(self):
     ba = bitstring.BitArray(100)
     ba_copy = copy.copy(ba)
     self.assertFalse(ba is ba_copy)
     self.assertFalse(ba._datastore is ba_copy._datastore)
     self.assertTrue(ba == ba_copy)
Ejemplo n.º 12
0
    def to_bytes(self):
        response = bitstring.BitArray()

        milliseconds = int(self.microseconds / 1000)
        thedata = bitstring.BitArray(
            bytearray([milliseconds >> 8, milliseconds & 0xFF]))
        response = response + thedata[-1:-11:-1]
        thedata = bitstring.BitArray(bytearray([self.seconds]))
        response = response + thedata[-1:-7:-1]
        thedata = bitstring.BitArray(bytearray([self.minute]))
        response = response + thedata[-1:-7:-1]
        thedata = bitstring.BitArray(bytearray([self.TIS]))
        response = response + thedata[-1:]
        thedata = bitstring.BitArray(bytearray([self.IV]))
        response = response + thedata[-1:]
        thedata = bitstring.BitArray(bytearray([self.hour]))
        response = response + thedata[-1:-6:-1]
        thedata = bitstring.BitArray(bytearray([self.RES1]))
        response = response + thedata[-1:-3:-1]
        thedata = bitstring.BitArray(bytearray([self.SU]))
        response = response + thedata[-1:]
        thedata = bitstring.BitArray(bytearray([self.dayofmonth]))
        response = response + thedata[-1:-6:-1]
        thedata = bitstring.BitArray(bytearray([self.dayofweek]))
        response = response + thedata[-1:-4:-1]
        thedata = bitstring.BitArray(bytearray([self.month]))
        response = response + thedata[-1:-5:-1]
        thedata = bitstring.BitArray(bytearray([self.ETI]))
        response = response + thedata[-1:-3:-1]
        thedata = bitstring.BitArray(bytearray([self.PTI]))
        response = response + thedata[-1:-3:-1]
        thedata = bitstring.BitArray(bytearray([self.year]))
        response = response + thedata[-1:-8:-1]
        thedata = bitstring.BitArray(bytearray([self.RES2]))
        response = response + thedata[-1:]
        response = response[::-1]
        inbytes = response.tobytes()[::-1]
        return inbytes
Ejemplo n.º 13
0
    def from_hex(self, data):
        reversed_bytes = bitstring.BitArray(bytearray(reversed(data)))
        reversed_bits = bitstring.BitStream(reversed(reversed_bytes))

        milliseconds = bitstring.BitArray(reversed(
            reversed_bits.read(10))).uint
        self.microseconds = milliseconds * 1000
        self.seconds = bitstring.BitArray(reversed(reversed_bits.read(6))).uint
        self.minute = bitstring.BitArray(reversed(reversed_bits.read(6))).uint
        self.TIS = reversed_bits.read(1).uint
        self.IV = reversed_bits.read(1).uint
        self.hour = bitstring.BitArray(reversed(reversed_bits.read(5))).uint
        self.RES1 = bitstring.BitArray(reversed(reversed_bits.read(2))).uint
        self.SU = reversed_bits.read(1).uint
        self.dayofmonth = bitstring.BitArray(reversed(
            reversed_bits.read(5))).uint or 1
        self.dayofweek = bitstring.BitArray(reversed(
            reversed_bits.read(3))).uint
        self.month = bitstring.BitArray(reversed(
            reversed_bits.read(4))).uint or 1
        self.ETI = bitstring.BitArray(reversed(reversed_bits.read(2))).uint
        self.PTI = bitstring.BitArray(reversed(reversed_bits.read(2))).uint
        self.year = bitstring.BitArray(reversed(reversed_bits.read(7))).uint
        self.RES2 = reversed_bits.read(1).uint