Пример #1
0
def report(cand_single):
    most_probable = []

    for i in range(nblock):
        top_cands = sorted(enumerate(cand_single[i]),
                           key=lambda x: abs(x[1]))[::-1][:5]
        # color_str = '\033[01;33m' if i in sboxs_pats else '\033[01m'
        color_str = '\033[01;33m' if 0 else '\033[01m'
        print(f'{color_str}#{i:2d}\033[0m:   ', end='')

        if not top_cands or top_cands[0][1] == 0:
            print('N/A')
            continue
        else:
            best_cand, _ = top_cands[0]
            most_probable.append(int2bits(best_cand, sbits))

        for char, cnt in top_cands:
            print(f'[\033[01;34m{hex(char)[2:]}\033[0m {cnt:6d}]   ', end='')
        print()

    if not is_revealing_last_round and len(most_probable) == nblock:
        result = ''.join(most_probable)
        result = cipher.permute(result, cipher.pbox)
        result = hex(int(result, 2))[2:]

        print(f'Most probable result: \033[01;32m{result}\033[01;0m')
Пример #2
0
def simulate(path_spec):
    counters_single = __utils.counters_single

    fins, fouts, bias = path_spec

    sboxs_o_pats = group_by_sboxs(fouts)
    output_sboxs = sboxs_o_pats.items()

    sboxs_a_pats = sboxs_o_pats
    affected_sboxs = output_sboxs

    if len(affected_sboxs) > 2:
        return

    print('Simulating', fins, '->', fouts, 'affecting sbox',
          ','.join(map(str, sboxs_a_pats.keys())), 'bias', bias)

    # itertools.product(*[range(16) for _ in affected_sboxs])
    for target_subkeys in itertools.product(
            *[range(N) for _ in affected_sboxs]):
        cnt = 0

        for xx, yy in data:
            xored = 0

            # xor fan-ins
            for i in fins:
                xored ^= int(xx[i], 2)

            # construct masked key

            blocked_key = ['0' * sbits] * nblock
            for (blkid, _), subkey in zip(affected_sboxs, target_subkeys):
                blocked_key[blkid] = int2bits(subkey, sbits)

            key = ''.join(blocked_key)

            # if not is_revealing_last_round:
            #     key = cipher.substitute(key, cipher.sbox)

            # partial decrypts affected sboxs
            yy_rev = yy
            #   add round key
            yy_rev = cipher.add_round_key(yy_rev, key)
            #   inverse S-box
            yy_rev = cipher.substitute(yy_rev, cipher.isbox)

            for (blkid, pat) in output_sboxs:
                blk_base = blkid * sbits

                blk_rev = yy_rev[blk_base:(blk_base + sbits)]

                # xor fan-outs
                for offs, bit in enumerate(int2bits(pat, sbits)):
                    if int(bit, 2):
                        xored ^= int(blk_rev[offs], 2)

            # (0, 1) -> (-1, 1)
            cnt += ((xored << 1) - 1)

        # makes biases add-able by converting them positive

        if len(affected_sboxs) == 1:
            ia, = sboxs_a_pats.keys()
            ka, = target_subkeys
            counters_single[ia][ka] += abs(cnt)
            # cand_single[ia].increment(ka, abs(cnt))

        elif len(affected_sboxs) == 2:
            ia, ib = sboxs_a_pats.keys()
            ka, kb = target_subkeys
            counters_single[ia][ka] += abs(cnt)
            counters_single[ib][kb] += abs(cnt)
            # __utils.counters_double[(ia, ib)].increment((ka << 4) + kb, abs(cnt))
            # cand_single[ia].increment(ka, abs(cnt))
            # cand_single[ib].increment(kb, abs(cnt))

        else:
            break
Пример #3
0
        y = cipher.permute(y, cipher.ipbox)

        if i != nround - 1:
            y = cipher.permute(y, cipher.ipbox)

    # if nround == 0:
    #     print('the key is', int(cipher.add_round_key(x, y), 2).to_bytes(nbits // 8, 'little'))

    return y


nblock = cipher.nblock

round_keys_inv = list(
    map(
        lambda x: int2bits(x, nbits),
        [
            # placeholders...
            # 0x4dbf_cb9c_3d81_ff1b,
            # 0x0000_0000_0000_0000,
            # 0x1111_1111_1111_1111,
            # 0x2222_2222_2222_2222,
            # 0x3333_3333_3333_3333,
        ]))

is_revealing_last_round = False
nlevels = 3

assert (nlevels == nround - 1) == (is_revealing_last_round)
assert len(round_keys_inv) + nlevels == nround - 1
Пример #4
0
def transform_input_hex(x, nbits):
    x = bytes.fromhex(x)
    x = int.from_bytes(x, 'little')
    x = int2bits(x, nbits)
    return x
Пример #5
0
def pat_to_pins(pat, base):
    l = int2bits(pat, 4)
    return [(base * 4 + i) for i, v in enumerate(l) if v == '1']
Пример #6
0
        pa for pa in paths if (pa.bias == paths[0].bias and pa.bias != 0)
    ]
    best_paths.extend(round_best_paths)

best_paths.sort(key=attrgetter('abs_bias'), reverse=True)
for pa in best_paths:
    print(pa)
exit()

counts = np.load('round5_7_10.npy')
counts -= 500
counts = np.abs(counts)
counts /= 1000
max_idx = np.argmax(counts)
print(counts[max_idx])
print(int2bits(max_idx, 12))
# counts = np.sort(counts)
for i in range(len(counts)):
    if (counts[i] > 0.05):
        print(i)
        print(counts[i])
        print(int2bits(i, 12))
exit()
# -- Start Attack -- #
# last round key
candidate = best_paths[1]
n = len(candidate.u)
print(candidate)
counts = np.zeros(1 << (sbits * n))
for k in range(1 << (sbits * n)):
    keys = [
Пример #7
0
# # counts = np.sort(counts)
# for i in range(len(counts)):
#     if(counts[i] > 0.05):
#         print(i)
#         print(counts[i])
#         print(int2bits(i, 12))
# exit()
# -- Start Attack -- #
# last round key
candidate = best_paths[0]
n = len(candidate.u)
print(candidate)
counts = np.zeros(1 << (sbits * n))
for k in range(1 << (sbits * n)):
    keys = [
        int2bits(k, sbits * n)[i:i + sbits]
        for i in range(0, sbits * n, sbits)
    ]
    idx = list(candidate.u.keys())
    test_key = key2int(keys, idx, sbits, nbits)

    # all known plaintext pairs
    for x, y in data:
        xx = int.from_bytes(x, "little")
        yy = int.from_bytes(y, "little")

        result = 0
        # plaintext bits needed
        for p in candidate.p:
            result ^= int(int2bits(xx, nbits)[p], 2)