【问题标题】:Java bruteforce for loop with confusing resultJava bruteforce for 循环结果令人困惑
【发布时间】:2016-06-02 17:57:13
【问题描述】:

我创建了一个小程序,试图从 AES-CBC 密钥中找到 20 个丢失的位。其结构如下:

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class Ex02 {
    private static final byte[] firstPart = {0x43, 0x72, 0x1a, 0x5b,
            (byte) 0x8e, (byte) 0xde, 0x5f, 0x57,
            (byte) 0x89, (byte) 0xf0, (byte) 0xdd, 0x28,
            0x68, (byte) 0x80};
    private static final byte[] SOLUTION = {0x43, 0x72, 0x1a, 0x5b,
            (byte) 0x8e, (byte) 0xde, 0x5f, 0x57,
            (byte) 0x89, (byte) 0xf0, (byte) 0xdd, 0x28,
            0x68, (byte) 0x8d, 0x63, (byte) 0xc5};
    private static final byte[] IV = {(byte) 0x80, (byte) 0x81, (byte) 0x82, (byte) 0x83,
            (byte) 0x84, (byte) 0x85, (byte) 0x86, (byte) 0x87,
            (byte) 0x88, (byte) 0x89, (byte) 0x8a, (byte) 0x8b,
            (byte) 0x8c, (byte) 0x8d, (byte) 0x8e, (byte) 0x8f};
    private static byte[] currentKey = new byte[IV.length];
    private static final byte[] chiffrat = Chiffrat.getAsHex();

    // For debugging purposes, this is set as class-variable
    private static int i;

    public static void main(String[] args) {
        Cipher c;

        // 20 Bits are missing, so 20 Bits to test
        int rounds = (int) Math.pow(2, 20);
        try {
            c = Cipher.getInstance("AES/CBC/NoPadding");

            // Test every possible key
            for (i = 0xd63c3; i < rounds; i++) {
                // For tracking progress
                if (i%100000==0 && i > 1) System.out.println(i + "/" + rounds);

                // Create Key out of first and second part
                // First convert i to a six digit hex number
                String tmp = Integer.toHexString(i);
                while (tmp.length() < 6) {
                    tmp = "0" + tmp;
                }

                // Convert String into byte array
                byte[] secondPart = new byte[tmp.length() / 2];
                for (int j = 0; j < tmp.length(); j+=2) {
                    secondPart[j / 2] = (byte) Integer.parseInt(tmp.substring(j, j + 2), 16);
                }

                // Copy first key part into the final key array
                System.arraycopy(firstPart, 0, currentKey, 0, firstPart.length);

                // Attach second part to the final key
                for (int j = 0; j < secondPart.length; j++) {
                    currentKey[currentKey.length - secondPart.length + j] |= secondPart[j];
                }

                // Decrypt
                SecretKeySpec secretKeySpec = new SecretKeySpec(currentKey, "AES");
                c.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(IV));
                byte[] result = c.doFinal(chiffrat);

                // Check if decrypted text is useful
                if (checkEnglish(result)) {
                    System.out.println("Key found!");
                    System.out.println("Counter: " + i);
                    System.out.println("Generated String: " + tmp);
                    System.out.println("First Part: 0x" + byteArrayToString(firstPart));
                    System.out.println("Second Part: 0x" + byteArrayToString(secondPart));
                    System.out.println("Used Key: 0x" + byteArrayToString(currentKey));
                    System.out.println("Result: " + new String(result));
                    break;
                }
            }
        } catch (Exception e) {
            System.out.print("ERROR: ");
            e.printStackTrace();
        }
    }

    private static boolean checkEnglish(byte[] b) {
        String tmp = new String(b).toLowerCase();
        return (tmp.contains("the") && tmp.contains("to") && tmp.contains("in") && tmp.contains("and"));
    }

    private static String byteArrayToString(byte[] bArr) {
        String result = "";
        for (byte b : bArr) {
            result += Integer.toHexString(Byte.toUnsignedInt(b));
        }
        return result;
    }
}

所以问题来了: 如果我从 0 开始,我不会得到任何结果。用于跟踪目的的字符串总是打印,直到我达到 2^20。但是,如果我将 i 设置为所需的解决方案 0xd63c5 或 0xd63c4,我会得到解密的文本。即使使用 0xd63c3 也没有“功能”。 也许我只见树木不见森林,但我已经尝试了很长时间了。

任何帮助表示赞赏,在此先感谢。

【问题讨论】:

  • 您问题中的代码已损坏。请在您的问题中添加可编译代码(它应该在问题本身中,而不是在外部资源中)。
  • 好的,添加完整的代码sn-p。
  • 如果您使用 Eclipse(或其他合适的 IDE),请在循环中设置条件断点并在 i == 0xd63c4 的情况下单步执行
  • 此外,我猜 currentKey 不应该是一个字段,而是一个局部变量。它可能包含循环上一次迭代的剩余部分。
  • 非常感谢 - 将 currentKey 更改为局部变量。如此愚蠢的缺陷。

标签: java for-loop aes cbc-mode


【解决方案1】:

正如 JF Meier 所说,将 byte[] currentKey 更改为局部变量并在 for 循环中对其进行初始化可以解决问题。
因为 currentKey 在循环时不会重新初始化,所以每个可能的键都是 OR-concatenated i1 | i2 | ... | in 并且永远不会达到所需的值 (0xd63c5)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-11
    • 1970-01-01
    • 1970-01-01
    • 2018-07-30
    • 1970-01-01
    相关资源
    最近更新 更多