import struct from parse import records rs = records() oc = [r for r in rs if r['name'].startswith('OC')] assert len(oc)==8 L = set(len(r['blk']) for r in oc) print('lengths', L) b = [r['blk'] for r in oc] f = [r['field'] for r in oc] # show differing byte positions n = len(b[0]) diff = [i for i in range(n) if len(set(x[i] for x in b))>1] print('differing byte offsets:', [hex(i) for i in diff]) for i in diff: print(hex(i), [hex(x[i]) for x in b]) # GF(2) affine test: for equal-length messages, if h is affine over GF(2), # then h(A)^h(B)^h(C)^h(D) == 0 whenever A^B^C^D == 0. # Find quadruples among the 8 whose message-XOR is 0. import itertools def bx(x,y): return bytes(p^q for p,q in zip(x,y)) found=0 for c in itertools.combinations(range(8),4): m = bytes(n) for i in c: m = bx(m,b[i]) if m == bytes(n): v = 0 for i in c: v ^= f[i] print('quad', c, 'msgxor=0 fieldxor=%08x' % v) found+=1 print('quads with zero msg xor:', found) # Alternative affine test using the base-block trick: # Build a matrix over the differing bytes only.