Pergunta

I setup a program for a class I am taking on crypto. I will follow this with my code and another section for my variable differences. My goal is to decrypt the text for our homework. I do not want someone to decrypt this for me, but would like some help as to what is causing this within my code. When I decrypt CBC I get the correct output with no problem, though it does have some extra chars in it (this may be an issue with padding? I am not sure)

Then when I use the CTR with the correct changes it returns a bunch of garbage. Any help would be greatly appreciated. Thank you,

CBC:

CBC key: 140b41b22a29beb4061bda66b6747e14
CBC Ciphertext 1: 
  4ca00ff4c898d61e1edbf1800618fb2828a226d160dad07883d04e008a7897ee2e4b7465d5290d0c0e6c6822236e1daafb94ffe0c5da05d9476be028ad7c1d81

CTR:

CTR key: 36f18357be4dbd77f050515c73fcf9f2
CTR Ciphertext 1: 
69dda8455c7dd4254bf353b773304eec0ec7702330098ce7f7520d1cbbb20fc388d1b0adb5054dbd7370849dbf0b88d393f252e764f1f5f7ad97ef79d59ce29f5f51eeca32eabedd9afa9329

CBC Variables

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

CTR Variables

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

Decrypt 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;
  }
}

*Edit method for solution - instead of a random IV I pulled the IV from the first 16 bits of the ciphertext. In the assignment it stated that this was the case, for some reason I glossed over it when I looked through it the first time.

 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;
Foi útil?

Solução

The trick is that you must send the IV (in plain text) to the receiver. If you randomly generate the IV before decryption you will get garbage by definition. Random IV's should only be generated before encryption.

Standard practice is for the sender to prefix the IV to the ciphertext. The receiver uses the first 16 bytes as an IV and the rest as the actual ciphertext.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top