JavaCBC解密工作正常,但CTR失败

JavaCBC解密工作正常,但CTR失败,java,encryption,aes,cbc-mode,Java,Encryption,Aes,Cbc Mode,我为我正在学习的加密课程设置了一个程序。我将在下面介绍我的代码,并在另一节介绍我的变量差异。我的目标是为我们的家庭作业解密文本。我不想有人解密这对我来说,但想一些帮助,因为什么是造成这在我的代码。当我解密CBC时,我得到了正确的输出,没有问题,尽管它确实有一些额外的字符(这可能是填充的问题?我不确定) 然后,当我使用带有正确更改的CTR时,它返回一堆垃圾。任何帮助都将不胜感激。 谢谢, CBC: CTR: CBC变量 String algorithm = "AES"; String mode =

我为我正在学习的加密课程设置了一个程序。我将在下面介绍我的代码,并在另一节介绍我的变量差异。我的目标是为我们的家庭作业解密文本。我不想有人解密这对我来说,但想一些帮助,因为什么是造成这在我的代码。当我解密CBC时,我得到了正确的输出,没有问题,尽管它确实有一些额外的字符(这可能是填充的问题?我不确定)

然后,当我使用带有正确更改的CTR时,它返回一堆垃圾。任何帮助都将不胜感激。 谢谢,

CBC:

CTR:

CBC变量

String algorithm = "AES";
String mode = "CBC";
String padding = "PKCS5Padding";
byte[] ciphertextBytes = StringToByte("4ca00ff4c898d61e1edbf1800618fb2828a226d160dad07883d04e008a7897ee2e4b7465d5290d0c0e6c6822236e1daafb94ffe0c5da05d9476be028ad7c1d81");
byte[] keyBytes = StringToByte("140b41b22a29beb4061bda66b6747e14");
String algorithm = "AES";
String mode = "CTR";
String padding = "NoPadding";
byte[] ciphertextBytes = StringToByte("770b80259ec33beb2561358a9f2dc617e46218c0a53cbeca695ae45faa8952aa0e311bde9d4e01726d3184c34451");
byte[] keyBytes = StringToByte("36f18357be4dbd77f050515c73fcf9f2");
CTR变量

String algorithm = "AES";
String mode = "CBC";
String padding = "PKCS5Padding";
byte[] ciphertextBytes = StringToByte("4ca00ff4c898d61e1edbf1800618fb2828a226d160dad07883d04e008a7897ee2e4b7465d5290d0c0e6c6822236e1daafb94ffe0c5da05d9476be028ad7c1d81");
byte[] keyBytes = StringToByte("140b41b22a29beb4061bda66b6747e14");
String algorithm = "AES";
String mode = "CTR";
String padding = "NoPadding";
byte[] ciphertextBytes = StringToByte("770b80259ec33beb2561358a9f2dc617e46218c0a53cbeca695ae45faa8952aa0e311bde9d4e01726d3184c34451");
byte[] keyBytes = StringToByte("36f18357be4dbd77f050515c73fcf9f2");
解密主

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,则根据定义将得到垃圾。仅应在加密之前生成随机IV


标准做法是发送方在密文前加上IV前缀。接收器将前16个字节用作IV,其余字节用作实际密文。

您知道预期的明文值吗?如果是这样的话,将这些添加到你的问题中会有帮助。标准做法是发送者在密码文本中预先输入IV。接收者使用前16个字节作为IV,其余的作为实际的密码。@rossum谢谢你的评论!整合到我的答案中(但带有“密文”和“前缀”:P)以下内容修复了它。我不得不更改一些代码。静脉注射是完全错误的。用更改编辑了原始帖子。
 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;