2013-11-20 2 views
1

У меня проблема с кодом шифрования AES. Я получаю только первые 16 символов, зашифрованных правильно, и остальные не верны.Шифрование AES/CBC/NoPadding не дает правильных результатов

Ниже приведен мой код.

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 
+2

Соответствие * * * ??? –

ответ

0

Блокирующие шифры, такие как AES, шифруют целые блоки. Блок имеет 128 бит (= 16 байт) для AES. Если ваше сообщение не является точным числом блоков, последний блок будет слишком коротким, и в этом случае шифрование не будет выполнено. Прокладка используется для расширения последней части вашего сообщения до следующей границы блока. Для Java в режиме CBC используйте дополнение PKCS5 для шифрования и дешифрования. Он будет добавлен и удален автоматически, и вы сможете забыть об этом.

+0

Благодарим вас за ответ. Мое сообщение фиксированной длины, которая составляет 704 (44 блока по 16 байт каждого блока), длина байтов, чтобы в конце не осталось дополнительных символов. Не могли бы вы сообщить мне, не хватает ли чего-либо в вышеуказанной программе? – user3012487

+0

Вы не указали свой код дешифрования. Если заполнение не является проблемой, возможно, вы используете режим ECB для дешифрования. Это будет правильно расшифровывать первый блок, если вы используете нуль IV и сбой на всех последующих блоках. Убедитесь, что вы используете режим CBC с обеих сторон. – rossum

Смежные вопросы