简体   繁体   English

加密AES / CBC / NoPadding无法产生正确的结果

[英]Encryption AES/CBC/NoPadding not yielding the correct results

I have an issue with my AES encryption code. 我的AES加密代码有问题。 I am only getting first 16 characters encrypted correctly and remaining are not correct. 我只得到正确加密的前16个字符,其余不正确。

Below is my code. 下面是我的代码。

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();
  }
}
}

When i compare the text only 16 characters converted correctly. 当我比较文本时,只有16个字符正确转换。 remaining are not matching. 其余不匹配。 I confirmed this by passing first 16 characters. 我通过传递前16个字符来确认这一点。

Can you please let me know what went wrong in the above program? 您能否让我知道以上程序出了什么问题?

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

Block cyphers, like AES, encrypt whole blocks. 像AES这样的块密码器会加密整个块。 A block is 128 bits (=16 bytes) for AES. AES的块为128位(= 16字节)。 Unless your message is an exact number of blocks, then the last block will be too short and encryption will fail at that point. 除非您的消息是确切的块数,否则最后一个块将太短,并且此时加密将失败。 Padding is used to extend the last part of your message to the next block boundary. 填充用于将消息的最后部分扩展到下一个块边界。 For Java in CBC mode use PKCS5 padding for both encryption and decryption. 对于CBC模式下的Java,请使用PKCS5填充进行加密和解密。 It will be added, and removed, automatically and you can then forget about it. 它会自动添加和删除,然后您就可以忽略它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM