source: trunk/lib/bletchley/chosen.py @ 130

Last change on this file since 130 was 92, checked in by tim, 8 years ago

.

File size: 2.8 KB
Line 
1'''
2A collection of tools to assist in analyzing encrypted blobs of data
3through chosen plaintext attacks.
4
5Copyright (C) 2011-2012 Virtual Security Research, LLC
6Copyright (C) 2014-2016 Blindspot Security LLC
7Author: Timothy D. Morgan
8
9 This program is free software: you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License, version 3,
11 as published by the Free Software Foundation.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program.  If not, see <http://www.gnu.org/licenses/>.
20'''
21
22import sys
23from buffertools import blockWiseDiff
24
25
26# Chosen plaintext attack on ECB encryption
27#
28# The encryptionOracle should accept a single string argument,
29# encrypt that argument as part of a larger (unknown) plaintext string,
30# and then return the ciphertext.
31#
32# This function will then return a dictionary with information about the
33# algorithm and chosen string attributes, including:
34#  block_size - the algorithm's block size
35#  chosen_offset - the chosen string's offset within the plaintext
36#  fragment_length - the length of a chosen from the chosen_offset to the
37#                    end of its current block
38#
39def ECB_FindChosenOffset(encryptionOracle):
40    ret_val = {}
41
42    # Guaranteed to have one block boundary on 128 bit block ciphers
43    chosen_length = 17
44    chosen = 'O'*chosen_length
45    base = encryptionOracle(chosen)
46
47    chosen = 'X' + 'O'*(chosen_length-1)
48    test_result = encryptionOracle(chosen)
49
50    different_blocks = blockWiseDiff(1, base, test_result)
51    block_size = len(different_blocks)
52    # Sanity check
53    different_blocks = blockWiseDiff(block_size, base, test_result)
54    if different_blocks == None:
55        sys.stderr.write("ERROR: Block size test yielded undiff-able ciphertexts.\n")
56        return None
57    if len(different_blocks) > 1:
58        sys.stderr.write("ERROR: Block size test yielded multiple altered blocks (not ECB mode?).\n")
59        return None
60
61    for i in range(2,chosen_length):
62        chosen = 'X'*i + 'O'*(chosen_length-i)
63        test_result = encryptionOracle(chosen)
64        different_blocks = blockWiseDiff(block_size, base, test_result)
65       
66        if different_blocks == None or len(different_blocks) == 0 or len(different_blocks) > 2:
67            sys.stderr.write("ERROR: Offset detection yielded inconsistent block diffs.\n")
68            return None
69        if len(different_blocks) == 2:
70            break
71
72    ret_val['block_size'] = block_size
73    ret_val['fragment_length'] = i-1
74    ret_val['chosen_offset'] = max(different_blocks)*block_size - ret_val['fragment_length']
75
76    return ret_val
Note: See TracBrowser for help on using the repository browser.