Расшифровка Java CBC работает, но CTR не работает

Я установил программу для класса, который я беру на крипто. Я буду следовать этому с моим кодом и другим разделом для моих различий переменных. Моя цель - расшифровать текст для нашей домашней работы. Я не хочу, чтобы кто-то расшифровывал это для меня, но хотел бы получить некоторую помощь относительно того, что вызывает это в моем коде. Когда я расшифровываю CBC, я получаю правильный вывод без проблем, хотя в нем есть некоторые дополнительные символы (это может быть проблема с заполнением? Я не уверен)

Затем, когда я использую CTR с правильными изменениями, он возвращает кучу мусора. Любая помощь будет принята с благодарностью. Спасибо,

CBC:

CBC key: 140b41b22a29beb4061bda66b6747e14
CBC Ciphertext 1: 
  4ca00ff4c898d61e1edbf1800618fb2828a226d160dad07883d04e008a7897ee2e4b7465d5290d0c0e6c6822236e1daafb94ffe0c5da05d9476be028ad7c1d81

CTR:

CTR key: 36f18357be4dbd77f050515c73fcf9f2
CTR Ciphertext 1: 
69dda8455c7dd4254bf353b773304eec0ec7702330098ce7f7520d1cbbb20fc388d1b0adb5054dbd7370849dbf0b88d393f252e764f1f5f7ad97ef79d59ce29f5f51eeca32eabedd9afa9329

Переменные CBC

String algorithm = "AES";
String mode = "CBC";
String padding = "PKCS5Padding";
byte[] ciphertextBytes = StringToByte("4ca00ff4c898d61e1edbf1800618fb2828a226d160dad07883d04e008a7897ee2e4b7465d5290d0c0e6c6822236e1daafb94ffe0c5da05d9476be028ad7c1d81");
byte[] keyBytes = StringToByte("140b41b22a29beb4061bda66b6747e14");

Переменные CTR

String algorithm = "AES";
String mode = "CTR";
String padding = "NoPadding";
byte[] ciphertextBytes = StringToByte("770b80259ec33beb2561358a9f2dc617e46218c0a53cbeca695ae45faa8952aa0e311bde9d4e01726d3184c34451");
byte[] keyBytes = StringToByte("36f18357be4dbd77f050515c73fcf9f2");

Расшифровать Main

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import static java.lang.Character.digit;

public class CryptoClass {

public static void main(String[] args) throws Exception {
    byte[] decryptByte = Decrypt();
    String hexString = ByteToHex(decryptByte);
    StringBuilder decryptedString = HexToString(hexString);
    System.out.println(decryptedString);
}

public static byte[] Decrypt() throws Exception {
    //
    String algorithm = "AES";
    String mode = "CTR";
    String padding = "NoPadding";
    byte[] ciphertextBytes = StringToByte("770b80259ec33beb2561358a9f2dc617e46218c0a53cbeca695ae45faa8952aa0e311bde9d4e01726d3184c34451");
    byte[] keyBytes = StringToByte("36f18357be4dbd77f050515c73fcf9f2");
    IvParameterSpec ivParamSpec = null;
    int ivSize = 16;
    byte[] iv = new byte[ivSize];

    SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
    secureRandom.nextBytes(iv);
    ivParamSpec = new IvParameterSpec(iv);
    SecretKey aesKey = new SecretKeySpec(keyBytes, "AES");

    Cipher cipher = Cipher.getInstance(algorithm + "/" + mode + "/" + padding, "JsafeJCE");
    cipher.init(Cipher.DECRYPT_MODE, aesKey, ivParamSpec);

    byte[] result = cipher.doFinal(ciphertextBytes);
    return result;
}

//convert ByteArray to Hex String
public static String ByteToHex(byte[] byteArray) {
    StringBuilder sb = new StringBuilder();
    for (byte b : byteArray)
    {
        sb.append(String.format("%02X", b));
    }
    return sb.toString();
}

//convert String to ByteArray
private static byte[] StringToByte(String input) {
    int length = input.length();
    byte[] output = new byte[length / 2];

    for (int i = 0; i < length; i += 2) {
        output[i / 2] = (byte) ((digit(input.charAt(i), 16) << 4) | digit(input.charAt(i+1), 16));
    }
    return output;
}
//changes a hex string into plain text
public static StringBuilder HexToString(String hex) throws Exception {
    StringBuilder output = new StringBuilder();
    for (int i = 0; i < hex.length(); i+=2) {
        String str = hex.substring(i, i+2);
        output.append((char)Integer.parseInt(str, 16));
    }
    return output;
  }
}

* Изменить метод для решения - вместо случайного IV я вытащил IV из первых 16 бит зашифрованного текста. В задании указывалось, что это так, и по какой-то причине я замаскировал его, когда просматривал в первый раз.

 public static byte[] Decrypt() throws Exception {
    String algorithm = "AES";
    String mode = "CTR";
    String padding = "NoPadding";
    byte[] ciphertextBytes = StringToByte("0ec7702330098ce7f7520d1cbbb20fc388d1b0adb5054dbd7370849dbf0b88d393f252e764f1f5f7ad97ef79d59ce29f5f51eeca32eabedd9afa9329");
    byte[] keyBytes = StringToByte("36f18357be4dbd77f050515c73fcf9f2");


    //int ivSize = 16;
    //byte[] iv = new byte[ivSize];
    //SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
    //secureRandom.nextBytes(iv);
    byte[] ivParamSpecTMP = StringToByte("69dda8455c7dd4254bf353b773304eec");
    IvParameterSpec ivParameterSpec = new IvParameterSpec(ivParamSpecTMP);
    SecretKey aesKey = new SecretKeySpec(keyBytes, "AES");

    Cipher cipher = Cipher.getInstance(algorithm + "/" + mode + "/" + padding, "JsafeJCE");
    cipher.init(Cipher.DECRYPT_MODE, aesKey, ivParameterSpec);

    byte[] result = cipher.doFinal(ciphertextBytes);
    return result;

1 ответ

Решение

Хитрость заключается в том, что вы должны отправить IV (в виде простого текста) получателю. Если вы случайно сгенерируете IV перед расшифровкой, вы получите мусор по определению. Случайные IV должны генерироваться только перед шифрованием.

улица

Другие вопросы по тегам