def _export_register(self, register_name: str, compute_inverses: bool) -> bytes: """Generate binary output for single register.""" register = BitArray(length=32) user_config = self.user_config.get(register_name, dict()) inverse_present = False for field in self._get_bitfields(register_name, exclude_computed=False): name = field.attrib["name"] offset = parse_int(field.attrib["offset"]) width = parse_int(field.attrib["width"]) # chcek whether there's a need to calculate inverse values inverse_present |= name == "INVERSE_VALUE" # The configuration allows to configure the whole register with single value if isinstance(user_config, str): temp_value = user_config else: temp_value = user_config.get(name) or field.attrib["reset_value"] value = parse_int(temp_value) # due to endianess we fill the bits from the end, therefore there's '-' in position # pos = 0 means offset = 0, means end of the BitArray register.overwrite(bs=BitArray(f"uint:{width}={value}"), pos=-(offset + width)) if compute_inverses and inverse_present: # NOTE: For now we'll assume the INVERSES are 16b long and inverts bits[15:0] # should this change in the future a data model change is necessary # NOTE: invert method changes bits in-place, thus we need to call it on separate object # calling invert() after slicing doesn't work for BitArray b_lower = register[16:] b_lower.invert() register.overwrite(b_lower, 0) # swapping bytes from big endian into little register.byteswap() return register.bytes
def validate_checksum_xrb(cls, address: str) -> bool: """Given an xrb/nano/ban address validate the checksum. Return true if valid, false otherwise""" if len(address) == 64 and address[:4] == 'ban_': # Populate 32-char account index account_map = "13456789abcdefghijkmnopqrstuwxyz" account_lookup = {} for i in range(0, 32): account_lookup[account_map[i]] = BitArray(uint=i, length=5) # Extract key from address (everything after prefix) acrop_key = address[4:-8] # Extract checksum from address acrop_check = address[-8:] # Convert base-32 (5-bit) values to byte string by appending each 5-bit value to the bitstring, essentially bitshifting << 5 and then adding the 5-bit value. number_l = BitArray() for x in range(0, len(acrop_key)): number_l.append(account_lookup[acrop_key[x]]) number_l = number_l[ 4:] # reduce from 260 to 256 bit (upper 4 bits are never used as account is a uint256) check_l = BitArray() for x in range(0, len(acrop_check)): if acrop_check[x] not in account_lookup: return False check_l.append(account_lookup[acrop_check[x]]) check_l.byteswap() # reverse byte order to match hashing format # verify checksum h = blake2b(digest_size=5) h.update(number_l.bytes) return h.hexdigest() == check_l.hex return False
def _parse_register(self, register_name: str, data: bytes) -> Union[str, dict]: """Parse individual register, returns wither one 32b value or dict of bitfields.""" register = {} bits = BitArray(data) # data is stored in little endian, but processed in big endian bits.byteswap() for field in self._get_bitfields(register_name, exclude_computed=False): width = parse_int(field.attrib["width"]) # exit early if we found a single 32b field if width == 32: return format_value(bits.uint, width) name = field.attrib["name"] offset = parse_int(field.attrib["offset"]) # OK, what the hell is that slicing about?! # offset is marked from the end of the bitarray not the begging like in a list # e.g.: ba = BitArray('0b00001100'), we want to extract bitfields of width=2 and offset=2 ('11') # again offset=2 means 2 bits from the end # BitArray supports negative indexing like an regular python list does: last bit has index -1 # that means we want to extract bits with indecies -4,-3 => [-4:-2] # HOWEVER: if we would want to extract 2 bits in the end (offset=0) # we would need to use [-offset:] slice or [-offset:None] slice_end = None if offset == 0 else -offset filed_bits = bits[-(offset + width): slice_end] register[name] = format_value(filed_bits.uint, width) return register
def getBinBitArray(self, val, endian, numBase, binFormat): # [0b|0x|0o]1234 try: val = str(val) binSize = numBase.value["mod"]*len(val) bArr = BitArray(numBase.value["prefix"]+val) if endian == Endian.LITTLE: bArr.byteswap() binData = bArr.bin if binFormat == BinFormat.C2 or binFormat == BinFormat.C1: bArr = BitArray(NumBase.BIN.value["prefix"] + binData[0] * (self.mem.value["size"] - binSize) + binData) elif binFormat == BinFormat.MS: sign = binData[0] binSize += 1 bArr = BitArray(bin=binData[1:]) binData = bArr.bin bArr = BitArray(NumBase.BIN.value["prefix"] + sign + binData[0] * (self.mem.value["size"] - binSize) + binData) if endian == Endian.LITTLE: bArr.byteswap() return bArr except CreationError as e: raise ConvertionException(str(e))
def xvcShift(TMS, TDI): numBits = TMS.len print("TMS: ", TMS) print("TDI: ", TDI) ## Pad to nearest byte alignment TMS += BitArray((8 - numBits) % 8) TDI += BitArray((8 - numBits) % 8) ## Make "little-endian" essentially where bit 0 of first byte is ## the first bit out. TMS.reverse() TMS.byteswap() TDI.reverse() TDI.byteswap() msg = numBits.to_bytes(4, byteorder='little') + TMS.bytes + TDI.bytes resp = xvcdSend('shift:', msg, TMS.len // 8) TDO = BitArray(resp) TDO.byteswap() TDO.reverse() TDO = TDO[0:numBits] #print("< 0x{} == ".format(resp.hex()), TDO) print("< 0x{}".format(resp.hex())) print("TDO: ", TDO) print() return TDO
def xrb_account(address): # Given a string containing an XRB address, confirm validity and provide resulting hex address if len(address) == 64 and (address[:4] == 'xrb_'): account_map = "13456789abcdefghijkmnopqrstuwxyz" # each index = binary value, account_lookup[0] == '1' account_lookup = {} for i in range( 0, 32 ): # populate lookup index with prebuilt bitarrays ready to append account_lookup[account_map[i]] = BitArray(uint=i, length=5) acrop_key = address[ 4: -8] # we want everything after 'xrb_' but before the 8-char checksum acrop_check = address[-8:] # extract checksum # convert base-32 (5-bit) values to byte string by appending each 5-bit value to the bitstring, essentially bitshifting << 5 and then adding the 5-bit value. number_l = BitArray() for x in range(0, len(acrop_key)): number_l.append(account_lookup[acrop_key[x]]) number_l = number_l[ 4:] # reduce from 260 to 256 bit (upper 4 bits are never used as account is a uint256) check_l = BitArray() for x in range(0, len(acrop_check)): check_l.append(account_lookup[acrop_check[x]]) check_l.byteswap() # reverse byte order to match hashing format result = number_l.hex.upper() # verify checksum h = blake2b(digest_size=5) h.update(number_l.bytes) if (h.hexdigest() == check_l.hex): return result return False return False
def emit_int_16_bits(self, int_string): parsed_int = self.parse_int(int_string) if parsed_int < 32768: b = BitArray(int=parsed_int, length=16) else: b = BitArray(uint=parsed_int, length=16) b.byteswap() return b.bin
def emit_int_32_bits(self, int_string): parsed_int = self.parse_int(int_string) if parsed_int < 2147483648: b = BitArray(int=parsed_int, length=32) else: b = BitArray(uint=parsed_int, length=32) b.byteswap() return b.bin
def write_serial(data, header): #Process header #Open serial port portName = header["port"] baudrate = header["baudrate"] waitTime = 0.1 response = {"msg": "", "err": False, "data": ""} try: ser = serial.Serial(portName, baudrate, timeout=waitTime) #ser.open() except serial.SerialException: # print("Unable to open",portName,". Exiting...") response["msg"] = "Unable to open %s." % portName response["err"] = True return response #Flush buffer ser.flushInput() ser.flushOutput() #Write data x = ser.write(data) if header["mode"] == "read": #Read data time.sleep(waitTime) try: tmp = ser.read(4) if not tmp: print("No data received") response[ "msg"] = "Waited for data, but no response from %s." % portName response["err"] = True response["data"] = "" else: tmp2 = BitArray(tmp) tmp2.byteswap() response["data"] = [tmp2.hex] except Exception: print( "main: error: exception for\n", "{}".format(traceback.format_exc()), ) response["msg"] = "Unable to read from %s." % portName # response["msg"] = "Exception when reading:\n" + f"{traceback.format_exc()}" response["err"] = True #Close serial port ser.close() return response
def from_data(cls, databytes): values = dict.fromkeys(MdatStateMessage.fields) # accept either the full frame payload or just the data after the CCL type identifier if (len(databytes) > 31): databytes = databytes[1:] d = BitStream(bytes=databytes) values['mode'] = 'MDAT_STATE' lat_bits = BitArray(d.read('bits:24')) values['latitude'] = decode_latlon(lat_bits) lon_bits = BitArray(d.read('bits:24')) values['longitude'] = decode_latlon(lon_bits) values['fix_age'] = d.read('uint:8') * 4 values['time_date'] = decode_time_date(d.read('bits:24')) values['heading'] = d.read('uint:8') * (360.0 / 255.0) mission_mode_depth_bits = d.read('bits:16') (values['mission_mode'], values['depth']) = decode_mission_mode_and_depth(mission_mode_depth_bits) values['faults_bits'] = d.read('bits:40') values['mission_leg'] = d.read('uint:8') values['estimated_velocity'] = d.read('uint:8') / 25.0 values['objective_index'] = d.read('uint:8') values['power_watts'] = d.read('uint:8') * 4.0 goal_lat_bits = BitArray(d.read('bits:24')) values['goal_latitude'] = decode_latlon(goal_lat_bits) goal_lon_bits = BitArray(d.read('bits:24')) values['goal_longitude'] = decode_latlon(goal_lon_bits) values['battery_percent'] = d.read('uint:8') gfi_pitch_oil_encoded = BitArray(d.read('bits:16')) gfi_pitch_oil_encoded.byteswap() values['gfi_percent'] = gfi_pitch_oil_encoded[11:].uint * 100.0 / 31.0 values['oil'] = gfi_pitch_oil_encoded[6:11].uint * 100.0 / 31.0 values['pitch'] = gfi_pitch_oil_encoded[0:6].int * 180.0 / 63.0 # Make a message mdat_state = cls(values) return mdat_state
def hex_to_account(hex_acc: str) -> (str, str): """ Given a string containing a hex address, encode to public address. :return string public account address as xrb_(...) :param hex_acc: string encoded address # TODO consider nano_(...) addresses """ # format with checksum # each index = binary value, account_lookup['00001'] == '3' account_map = "13456789abcdefghijkmnopqrstuwxyz" account_lookup = {} # populate lookup index for binary string to base-32 string character for i in range(32): account_lookup[BitArray(uint=i, length=5).bin] = account_map[i] # hex string > binary account = BitArray(hex=hex_acc) # get checksum h = blake2b(digest_size=5) h.update(account.bytes) checksum = BitArray(hex=h.hexdigest()) # encode checksum # swap bytes for compatibility with original implementation checksum.byteswap() encode_check = '' for x in range(0, int(len(checksum.bin) / 5)): # each 5-bit sequence = a base-32 character from account_map encode_check += account_lookup[checksum.bin[x * 5:x * 5 + 5]] # encode account encode_account = '' while len(account.bin) < 260: # pad our binary value so it is 260 bits long before conversion # (first value can only be 00000 '1' or 00001 '3') account = '0b0' + account for x in range(0, int(len(account.bin) / 5)): # each 5-bit sequence = a base-32 character from account_map encode_account += account_lookup[account.bin[x * 5:x * 5 + 5]] # build the full address return 'xrb_{}{}'.format(encode_account, encode_check)
def encrypt(self, msg): all_chiper = [] for i in range(len(msg)): hex_plain = hex(ord(msg[i])) keystream = self.keystream(8) keystream = '0b' + ''.join(str(i) for i in keystream[::-1]) keystream = BitArray(keystream) keystream.byteswap() plain = BitArray(hex_plain) plain.byteswap() cipher = [ x ^ y for x, y in zip(map(int, list(plain)), map(int, list(keystream))) ] all_chiper += cipher cipher = '0b' + ''.join(str(i) for i in cipher) cipher = BitArray(cipher) cipher.byteswap() print '{: ^15}{: ^15}{: ^15}{: ^15}{:^15}'.format( hex_plain, plain.bin, keystream.bin, cipher.bin, '0x' + cipher.hex.upper()) return all_chiper
def encode(data: bytes): root = build_tree(data) translation_list = build_character_translation(root, []) # print(f'translation list {translation_list}') translation = merge_dictionaries(translation_list) # print(f'translation {translation}') translated = list(itertools.chain(*[translation.get(byte) for byte in data])) # print(f'l translated {len(translated)}') additional_bytes = len(translated) % 8 # print(f'additional bytes {additional_bytes}') x = BitArray(translated) + BitArray([0] * (8 - additional_bytes)) x.reverse() x.byteswap() # print (f'x {x.bin}') encoded_bytes = x.tobytes() # print(f'encoded bytes: {encoded_bytes}') root.additional_bytes = additional_bytes serialised_tree = DefaultEncoder().encode(root) output = bytes(serialised_tree, 'ascii') + encoded_bytes return output
def account_xrb(account): # Given a string containing a hex address, encode to public address format with checksum account_map = "13456789abcdefghijkmnopqrstuwxyz" # each index = binary value, account_lookup['00001'] == '3' account_lookup = {} for i in range( 0, 32 ): # populate lookup index for binary string to base-32 string character account_lookup[BitArray(uint=i, length=5).bin] = account_map[i] account = BitArray(hex=account) # hex string > binary # get checksum h = blake2b(digest_size=5) h.update(account.bytes) checksum = BitArray(hex=h.hexdigest()) # encode checksum checksum.byteswap( ) # swap bytes for compatibility with original implementation encode_check = '' for x in range(0, int(len(checksum.bin) / 5)): encode_check += account_lookup[checksum.bin[ x * 5:x * 5 + 5]] # each 5-bit sequence = a base-32 character from account_map # encode account encode_account = '' while len( account.bin ) < 260: # pad our binary value so it is 260 bits long before conversion (first value can only be 00000 '1' or 00001 '3') account = '0b0' + account for x in range(0, int(len(account.bin) / 5)): encode_account += account_lookup[account.bin[ x * 5:x * 5 + 5]] # each 5-bit sequence = a base-32 character from account_map return 'xrb_' + encode_account + encode_check # build final address string
def main(): print "Test vectors -- set 1" print "=====================" KEY = BitArray("0x80000000000000000000") print "Key : ", KEY.hex KEY.byteswap() KEY = map(int, KEY.bin) IV = BitArray("0x00000000000000000000") print "IV : ", IV.hex IV.byteswap() IV = map(int, IV.bin) trivium = Trivium(KEY, IV) generete_keystream = trivium.keystream(128) hex_keystream = '0b' + ''.join(str(i) for i in generete_keystream[::-1]) hex_keystream = BitArray(hex_keystream) hex_keystream.byteswap() print "Keystream : ", hex_keystream.hex.upper() assert hex_keystream.hex.upper() == '38EB86FF730D7A9CAF8DF13A4420540D' print "OK"
def test_byteswap(): ba = BitArray(f"uint:32={0x1234_5678}") ba.byteswap() assert ba.hex == '78563412'
class Trivium: def __init__(self, key, iv): self.key = plain_text_to_hexa(key) self.iv = plain_text_to_hexa(iv) self.key = BitArray(self.key) self.key.byteswap() self.key = map(int, self.key.bin) self.iv = BitArray(self.iv) self.iv.byteswap() self.iv = map(int, self.iv.bin) self.state = None # Initialize state # (s1; s2; : : : ; s93) (K1; : : : ; K80; 0; : : : ; 0) init_state = list(self.key) init_state += list(repeat(0, 13)) # (s94; s95; : : : ; s177) (IV1; : : : ; IV80; 0; : : : ; 0) init_state += self.iv init_state += list(repeat(0, 4)) # (s178; s279; : : : ; s288) (0; : : : ; 0; 1; 1; 1) init_state += list(repeat(0, 108)) init_state += [1, 1, 1] if (len(init_state) < 300): for i in range(len(init_state), 300): init_state += [0] self.state = deque(init_state) # Do 4 Full cycle clock for i in range(4 * 288): self.gen_keystream() def gen_keystream(self): t_1 = self.state[65] ^ self.state[92] t_2 = self.state[161] ^ self.state[176] t_3 = self.state[242] ^ self.state[287] z = t_1 ^ t_2 ^ t_3 t_1 = t_1 ^ self.state[90] & self.state[91] ^ self.state[170] t_2 = t_2 ^ self.state[174] & self.state[175] ^ self.state[263] t_3 = t_3 ^ self.state[285] & self.state[286] ^ self.state[68] self.state.rotate() self.state[0] = t_3 self.state[93] = t_1 self.state[177] = t_2 return z def keystream(self, msglen): # Generete keystream counter = 0 keystream = [] while counter < msglen: keystream.append(self.gen_keystream()) counter += 1 return keystream def encrypt(self, msg, b64): result = "" if b64: msg = base64.b64decode(msg).hex() result = "" for i in range(0, len(msg), 2): hex_plain = "0x" + msg[i] + msg[i + 1] result += chr(int(str(self.general(hex_plain)), 16)) return result else: for i in range(len(msg)): hex_plain = hex(ord(msg[i])) result += self.general(hex_plain) return codecs.encode(codecs.decode(str(result)[2:], 'hex'), 'base64').decode().replace("\n", "") def general(self, hex_plain): keystream = self.keystream(8) keystream = '0b' + ''.join(str(i) for i in keystream[::-1]) keystream = BitArray(keystream) plain = BitArray(hex_plain) cipher = [ x ^ y for x, y in zip(map(int, list(plain)), map(int, list(keystream))) ] cipher = '0b' + ''.join(str(i) for i in cipher) return BitArray(cipher)
def encrypt(self, msg): keystream = self.keystream_bytes(len(msg)) cipher = [x ^ y for x, y in zip(msg, keystream)] return cipher def decrypt(self, msg): keystream = self.keystream_bytes(len(msg)) plain = [x ^ y for x, y in zip(msg, keystream)] return plain key = "0x80000000000000000000" # Initiate grain KEY = BitArray(key) #print "Key : ", KEY.hex KEY.byteswap() KEY = map(int, KEY.bin) iv = "0x0000000000000000" IV = BitArray(iv) #print "IV : ", IV.hex IV.byteswap() IV = map(int, IV.bin) g = Grain(KEY, IV) print str(g.keystream_bytes(1)[0]).format("02x")
def main(): """ KEY = BitArray("0x80000000000000000000") print "Key : ", KEY.hex KEY.byteswap() KEY = map(int, KEY.bin) IV = BitArray("0x00000000000000000000") print "IV : ", IV.hex IV.byteswap() IV = map(int, IV.bin) trivium = Trivium(KEY, IV) keystream = trivium.keystream(128) hex_keystream = '0b' + ''.join(str(i) for i in keystream[::-1]) hex_keystream = BitArray(hex_keystream) hex_keystream.byteswap() print "Keystream : ", hex_keystream.hex.upper() """ parser = argparse.ArgumentParser( description='Decryption or encryption using Trivium stream cipher.', epilog= "trivium.py -m e -k 0x80000000000000000000 -iv 0x00000000000000000000 ABCD" ) parser.add_argument( '-m', '--mode', type=str, choices=['e', 'd'], help='Choose mode, e for encryption or d for decryption') parser.add_argument('-k, --key', action='store', dest='key', type=str, help='An 80 bit key e.g.: 0x0000000000000000') parser.add_argument( '-iv', action='store', dest='iv', type=str, help='An 80 bit initialization vector e.g.: 0x0000000000000000') parser.add_argument('M', help='Cipher text or plain text') args = parser.parse_args() # Initialize Trivium KEY = BitArray(args.key) print '{:<15}{:<2}{:<10}'.format('KEY', '=', KEY.hex) KEY.byteswap() KEY = map(int, KEY.bin) IV = BitArray(args.iv) print '{:<15}{:<2}{:<10}'.format('IV', '=', IV.hex) IV.byteswap() IV = map(int, IV.bin) trivium = Trivium(KEY, IV) # Encryption mode if args.mode == 'e': print '{:<15}{:<2}{:<10}\n'.format('PLAIN TEXT', '=', args.M) print '{: ^15}{: ^15}{: ^15}{: ^15}{: ^15}'.format( 'INPUT', 'PLAIN TEXT', 'KEYSTREAM', 'CIPHER TEXT', 'OUTPUT') print '{:->75}'.format(' ') cipher = trivium.encrypt(args.M) cipher = '0b' + ''.join(str(i) for i in cipher) cipher = BitArray(cipher) else: print '{:<15}{:<2}{:<10}\n'.format('CIPHER TEXT', '=', args.M) print '{: ^15}{: ^15}{: ^15}{: ^15}{: ^15}'.format( 'INPUT', 'CIPHER TEXT', 'KEYSTREAM', 'PLAIN TEXT', 'OUTPUT') print '{:->75}'.format(' ') print 'Not yet implemented' pass
def calc_label_x86_imm_32_bits(self, source_instruction_address, label_address): b = BitArray(int=label_address, length=32) b.byteswap() return b.bin
def test_byteswap(): """Test of BitArray - Byte swap.""" bit_array = BitArray(f"uint:32={0x1234_5678}") bit_array.byteswap() assert bit_array.hex == "78563412"
def calc_label_x86_rel_32_bit_cond_branch(self, source_instruction_address, label_address): rel = label_address - source_instruction_address - 6 b = BitArray(int=rel, length=32) b.byteswap() return b.bin
def testByteSwap(self): a = BitArray('0xff00ff00ff00') n = a.byteswap(2, end=32, repeat=True) self.assertEqual(n, 2) self.assertEqual(a, '0xff0000ff00ff')