2014-12-08 3 views
2

Ниже приведена моя логика шифрования. Хотя мой IV длится 16 байт, я все еще получаю сообщение об ошибке с недопустимой длиной IV. Был бы признателен за любую помощьAES 256-битное шифрование - java.security.InvalidAlgorithmParameterException: Неверная длина IV: должно быть 16 байтов

@Override 
public String encrypt(String dataToEncrypt, String IV) throws Exception{ 
    if(encryptionKey.length() < 10){ 
     encryptionKey = generateEncryptionKey().toString(); 
    } 
    System.out.println("number of IV bytes is "+IV.length()+" "+IV); 
    Cipher cipher = Cipher.getInstance(encrpytionAlgo); 
    SecretKey key = new SecretKeySpec(encryptionKey.getBytes(Charset.forName("UTF-8")), "AES"); 
    cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(IV.getBytes(Charset.forName("UTF-8")))); 
    byte[] encryptedTextBytes = cipher.doFinal(dataToEncrypt.getBytes(Charset.forName("UTF-8"))); 
    return new Base64().encodeAsString(encryptedTextBytes); 
} 

IV и логика

@Override 
public String generateRandomIV(){ 
     Random random = new SecureRandom(); 
     byte[] iv = new byte[16]; 
     random.nextBytes(iv); 
     System.out.println("IV is "+Base64.encodeBase64(iv)+" "+ com.sun.jersey.core.util.Base64.base64Decode(new String(Base64.encodeBase64(iv)))+ " number of bytes is "+iv.length); 
     return new String(Base64.encodeBase64(iv)); 
} 

@Override 
public SecretKey generateEncryptionKey(){ 
    KeyGenerator aesKey = null; 
    try { 
     aesKey = KeyGenerator.getInstance("AES"); 
    } catch (NoSuchAlgorithmException e) { 
      e.printStackTrace(); 
    } 
    aesKey.init(256); 
    SecretKey secretKey = aesKey.generateKey(); 
    System.out.println("Encryption key is "+ new Base64().encode(secretKey.getEncoded())); 
    return secretKey; 
} 

Ниже генерации ключа является StackTrace за исключением Исключение составляет в строке:
cipher.init (Cipher.ENCRYPT_MODE, ключ, новый IvParameterSpec (IV.getBytes (Charset.forName ("UTF-8"))));

java.security.InvalidAlgorithmParameterException: Wrong IV length: must be 16 bytes long 
at com.sun.crypto.provider.SunJCE_f.a(DashoA13*..) 
at com.sun.crypto.provider.AESCipher.engineInit(DashoA13*..) 
at javax.crypto.Cipher.a(DashoA13*..) 
at javax.crypto.Cipher.a(DashoA13*..) 
at javax.crypto.Cipher.init(DashoA13*..) 
at javax.crypto.Cipher.init(DashoA13*..) 
at com.intuit.platform.publiccloudaccess.core.services.EncryptionServiceImpl.encrypt(EncryptionServiceImpl.java:47) 
+0

Я предлагаю вам сохранить свой IV как байт []. В общем случае преобразование строки UTF-8 в массив байтов не дает вам одного байта на символ. Почему вы хотите накладные расходы на преобразование в/из String? – Rob

+0

Спасибо @Rob, что сработало. – outtoexplore

ответ

3

Вы закодировали свой IV как Base64, прежде чем возвращать его с generateRandomIV. Вы должны декодировать его, прежде чем использовать его для шифрования и дешифрования.

cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(java.util.Base64.Decoder.decode(IV.getBytes("UTF-8")))); 

Java-8 обеспечивает java.util.Base64 класс для получения различных базовых 64 кодеров и декодеров.

1

После замечания Робы

System.out.println("number of IV bytes is "+IV.length()+" "+IV); 

Здесь вы получите длину IV в терминах String. Однако

cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(IV.getBytes(Charset.forName("UTF-8"))));  

здесь вы составляете IV как массив байт и делаешь длину IV как 16 в термах строки не гарантирует, что его байты представление также 16 байт. Так как Роб предположил, что вам лучше сохранить IV в массиве байтов и использовать его в качестве байтового массива.