java - 加密 AES/CBC/NoPadding 未产生正确的结果

标签 java encryption aes

我的 AES 加密代码有问题。我只正确加密了前 16 个字符,其余字符不正确。

下面是我的代码。

import java.io.ByteArrayOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

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

public class AESEncryptionTest {
  public static AESEncryptionTest encryptor;

  public String MODE;
  public Cipher encCipher;

  public int blocks;

  public byte[] IV = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

  public byte[] key;

  public static AESEncryptionTest getInstance(){
    if(encryptor == null){
      encryptor = new AESEncryptionTest();
      encryptor.init();
    }
    return encryptor;
  }

  public void init(){
   try{
     String alg = "AES/CBC/NoPadding";
     key = convert32ByteHexTo16ByteHex("C145B6D7C8EBD1A15B9FAE5D6DD7FECA");
     System.out.println("IV:" + toHex(IV, false));
     System.out.println("KEY:" + toHex(key, false));
     System.out.println("Algo:" + alg);
     IvParameterSpec encivspec = new IvParameterSpec(IV);  
     SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
     encCipher = Cipher.getInstance(alg);
     encCipher.init(Cipher.ENCRYPT_MODE, secretKey, encivspec);
   } catch (Exception ex) {
     ex.printStackTrace();
   }
 }

 public void resetIV(){
   for(byte b: IV)
     b = 0x00;
 }

 public byte[] encrypt(String msg) throws Exception{  
  try{
    System.out.println("Java ersion:" + System.getProperty("java.version"));
    System.out.println("OS :" + System.getProperty("os.arch"));
    System.out.println("sun.arch.data.model x:" +   System.getProperty("sun.arch.data.model"));

    ByteArrayOutputStream ba= new ByteArrayOutputStream();
    CipherOutputStream cos = new CipherOutputStream(ba, encCipher);
    PrintWriter pw = new PrintWriter(new OutputStreamWriter(cos));
    pw.println(msg);
    pw.close();
    return ba.toByteArray();
  }catch(Exception e){
    e.printStackTrace();
    //throw new EncryptionFailedException(e.getMessage());
    throw e;
  }
 } 

 private byte[] convert32ByteHexTo16ByteHex(String hexStr){
  byte arr[] = new byte[16];
  for(int i=0; i<arr.length; i++){
    arr[i] = (byte)(Integer.parseInt(hexStr.substring(i * 2, (i*2) + 2), 16) & 0xFF);
  }
  return arr;
 }

public String toHex(byte[] arr, boolean withPrefix) {
  int offset = 0;
  int length = arr.length;
  StringBuffer sb = new StringBuffer();

  for (int i = offset; i < length; i++) {
    if (withPrefix) {
      sb.append("0x");
    }

  for (int j = 0; j < 2; j++) {
    byte nibble = (byte) (j == 0 ? arr[i] >> 4 & 0xf : arr[i] & 0xf);

    if (nibble < 10) {
      sb.append(nibble);
    } else {
      sb.append((char) ('A' + (nibble - 10)));
    }
  }

   if (i != length - 1) {
     sb.append(',');
   }
 }

 return sb.toString();
}

public static void main(String args[]){
  AESEncryptionTest util = AESEncryptionTest.getInstance();
  String rec = "DTYCOFIRE201311120001201311151531BER01 600082SBC9131G    Y103H163                                                                                         First line^Second line^Third line                                                                                                                                                                                                                              201311151531TYCOFIRE201311120001_img1.JPG                     TYCOFIRE201311120001_img2.JPG                                                                                                                         1122                          TYCOFIRE                                            \n";
  try {
    System.out.println("rec:" + rec);
    byte b[] = util.encrypt(rec);
    System.out.println("encrypted:" + new String(b));
  } catch (Exception e) {
  e.printStackTrace();
  }
}
}

当我比较文本时,只有 16 个字符转换正确。其余不匹配。我通过传递前 16 个字符确认了这一点。

你能告诉我上面的程序出了什么问题吗?

Java version:1.6.0_32
OS :x86
sun.arch.data.model x:32

最佳答案

block 密码,如 AES,加密整个 block 。对于 AES,一个 block 为 128 位(= 16 字节)。除非您的消息是确切数量的 block ,否则最后一个 block 将太短,此时加密将失败。填充用于将消息的最后部分扩展到下一个 block 边界。对于 CBC 模式下的 Java,使用 PKCS5 填充进行加密和解密。它将自动添加和删除,然后您就可以忘记它。

关于java - 加密 AES/CBC/NoPadding 未产生正确的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20092939/

相关文章:

java - slick2d - statebasedgame错误 - 在当前线程中找不到OpenGL上下文

javascript - 如何从 CryptoJS AES 对象中创建一个字符串?

c# - 如何在javascript中加密url并在c#中解密

ruby - AES 在 ColdFusion 中加密,在 ruby​​ 中解密

c++ - 调用 always_inline 时内联失败,Qt 中的目标特定选项不匹配

php - 在 PHP 中使用 AES 加密时,应该在哪里存储 key ?

java - 如何在 Java 上验证构造函数参数?

java - 当输入为 double 时,HashMap<Integer,Double> 出现 NullPointerException

python - 增加 AES-CBC 加密算法在 pycrypto for python 中的传播

java - 从 XML 获取自定义 TextView 的自定义属性