def _key(self): key = self.args.key if len(key) != 0x10: raise ValueError( F'Key length of {len(key)} bytes is invalid; XXTEA only supports 16 byte keys' ) return chunks.unpack(key, 4)
def _ripemd128_blocks(msg): N = len(msg) P = (56 - N) % 64 msg += b'\x80' + b'\x00' * (P - 1) + (N << 3).to_bytes(8, 'little') it = iter(chunks.unpack(msg, 4)) while True: block = list(itertools.islice(it, 16)) if not block: break assert len(block) == 16 yield block
def _checksum(self, data): from refinery.lib import chunks checksum = 0 it = chunks.unpack(data, 4) if len(data) % 4: import itertools it = itertools.chain(it, (int.from_bytes(data[-4:], 'little'), )) for chunk in it: checksum += chunk checksum ^= ((chunk & 0x7FFFFFFF) << 1) + (chunk >> 31) + 1 checksum &= 0xFFFFFFFF return checksum
def chunk(self, data, raw=False): if not raw: return chunks.unpack(data, self.args.blocksize, self.args.bigendian) def chunkraw(data, b: int): stop = len(data) stop = stop - stop % b for k in range(0, stop, b): yield data[k:k + b] return chunkraw(data, self.args.blocksize)
def block_encrypt(self, block) -> BufferType: u = self._u w = self._w g = self._g r = self._r M = self._m S = self._S A, B, C, D = chunks.unpack(block, u) B = B + S[0] & M D = D + S[1] & M for i in range(1, r + 1): t = rotl(w, B * (2 * B + 1) & M, g) v = rotl(w, D * (2 * D + 1) & M, g) A = rotl(w, A ^ t, v) + S[2 * i + 0] & M C = rotl(w, C ^ v, t) + S[2 * i + 1] & M A, B, C, D = B, C, D, A A = A + S[2 * r + 2] & M C = C + S[2 * r + 3] & M return chunks.pack((A, B, C, D), u)
def block_decrypt(self, block) -> BufferType: u = self._u w = self._w g = self._g r = self._r M = self._m S = self._S A, B, C, D = chunks.unpack(block, u) C = C - S[2 * r + 3] & M A = A - S[2 * r + 2] & M for i in range(r, 0, -1): A, B, C, D = D, A, B, C t = rotl(w, B * (2 * B + 1) & M, g) v = rotl(w, D * (2 * D + 1) & M, g) C = rotr(w, C - S[2 * i + 1] & M, t) ^ v A = rotr(w, A - S[2 * i + 0] & M, v) ^ t D = D - S[1] & M B = B - S[0] & M return chunks.pack((A, B, C, D), u)
def key(self, key): w = self._w # word size u = self._u # length of a word in bytes r = self._r # round count M = self._m # bit mask L = list(chunks.unpack(key + (-len(key) % u) * B'\0', u)) c = len(L) t = 2 * (r + 2) P, Q = rc5constants(w) S = [P] while len(S) < t: S.append(S[~0] + Q & M) i = j = 0 A = B = 0 for _ in range(3 * max(t, c)): A = S[i] = rotl(w, S[i] + A + B & M, 3) B = L[j] = rotl(w, L[j] + A + B & M, A + B) i = (i + 1) % t j = (j + 1) % c self._S = S
def keystream(self) -> Iterable[int]: key = self.args.key A: int = 0 B: int = 0 C: int = 0 S: List[int] = [0x9E3779B9] * 8 T: List[int] = [] K = list( chunks.unpack(key + bytearray(0x400 - len(key)), 4, bigendian=False)) U = 0xFFFFFFFF def _mix_state(): a, b, c, d, e, f, g, h = S a ^= (b << 0x0B) & U d = d + a & U b = b + c & U # noqa b ^= (c >> 0x02) & U e = e + b & U c = c + d & U # noqa c ^= (d << 0x08) & U f = f + c & U d = d + e & U # noqa d ^= (e >> 0x10) & U g = g + d & U e = e + f & U # noqa e ^= (f << 0x0A) & U h = h + e & U f = f + g & U # noqa f ^= (g >> 0x04) & U a = a + f & U g = g + h & U # noqa g ^= (h << 0x08) & U b = b + g & U h = h + a & U # noqa h ^= (a >> 0x09) & U c = c + h & U a = a + b & U # noqa S[:] = a, b, c, d, e, f, g, h return S def _initialize_with(R: List[int]): for i in range(0, 0x100, 8): S[:] = (x + R[j] & U for j, x in enumerate(S, i)) T[i:i + 8] = _mix_state() for _ in range(4): _mix_state() _initialize_with(K) _initialize_with(T) operations = [ (__lshift__, 0x0D), (__rshift__, 0x06), (__lshift__, 0x02), (__rshift__, 0x10), ] while True: C = (C + 1) & U B = (B + C) & U for i in range(0x100): X = T[i] shift, k = operations[i % 4] A = (A ^ shift(A, k)) & U A = (A + T[i ^ 0x80]) & U Y = T[+i] = T[X // 4 & 0xFF] + A + B & U B = K[~i] = X + T[Y // 1024 & 0xFF] & U yield from chunks.pack(K, 4, True)
def hexdump(data: ByteString, metrics: HexDumpMetrics, colorize=False) -> Iterable[str]: separator = metrics.hex_char_spacer hex_width = metrics.hex_column_width addr_width = metrics.address_width columns = metrics.hex_columns hexformat = metrics.hex_char_format printable = range(0x21, 0x7F) from colorama import Fore as FG, Style as S if columns <= 0: raise RuntimeError('Requested width is too small.') def pieces(data): view = memoryview(data) step = columns * metrics.block_size for lno, offset in enumerate(range(0, len(data), step)): if metrics.line_count and lno >= metrics.line_count: break yield lno, view[offset:offset + step] previous = None repetitions = 0 for last, (lno, chunk) in lookahead(pieces(data)): if not metrics.expand: if chunk == previous and not last: repetitions += 1 continue elif repetitions > 0: line = F' repeats {repetitions} times ' line = F'{line:/^{hex_width*columns-1}} {"":/<{columns}}' if colorize: line = F'{FG.LIGHTBLACK_EX}{line}{S.RESET_ALL}' if addr_width: line = F'{".":.>{addr_width}}{metrics.hex_addr_spacer}{line}' yield line repetitions = 0 blocks = chunks.unpack(chunk, metrics.block_size, metrics.big_endian) if not colorize: dump = separator.join(hexformat.format(b) for b in blocks) ascii_preview = re.sub(B'[^!-~]', B'.', chunk).decode('ascii') line = (F'{dump:<{hex_width*columns-len(separator)}}' F'{metrics.txt_separator}{ascii_preview:<{columns}}') else: def byte_color(value: int): if not value: return FG.LIGHTBLACK_EX elif value in B'\x20\t\n\r\v\f': return FG.LIGHTYELLOW_EX elif value not in printable: return FG.LIGHTRED_EX else: return S.RESET_ALL with io.StringIO() as _hex, io.StringIO() as _asc: current_color = S.RESET_ALL block_size = metrics.block_size prefix = metrics.hex_char_prefix remaining_hex_width = hex_width * columns - len(separator) for k, b in enumerate(chunk): if k % block_size == 0: if k != 0: _hex.write(separator) remaining_hex_width -= len(separator) if prefix: _hex.write(prefix) remaining_hex_width -= len(prefix) color = byte_color(b) if color != current_color: _hex.write(color) _asc.write(color) current_color = color _hex.write(F'{b:02X}') remaining_hex_width -= 2 _asc.write(chr(b) if b in printable else '.') _hex.write(S.RESET_ALL) _hex.write(' ' * remaining_hex_width) _asc.write(S.RESET_ALL) line = F'{_hex.getvalue()}{metrics.txt_separator}{_asc.getvalue():<{columns}}' if addr_width: line = F'{lno*columns:0{addr_width}X}: {line}' yield line if not metrics.expand: previous = chunk
def _unpack(self, data): if len(data) % 4: raise ValueError( 'The input data is not aligned to a multiple of 4 bytes.') return chunks.unpack(data, 4)