2010-04-02 189 views
9

我想創建一個AES加密方法,但由於某些原因,我不斷收到AES加密的Java密鑰長度無效

java.security.InvalidKeyException: Key length not 128/192/256 bits

下面是代碼:

public static SecretKey getSecretKey(char[] password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException{ 
    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWithMD5AndDES"); 
    // NOTE: last argument is the key length, and it is 256 
    KeySpec spec = new PBEKeySpec(password, salt, 1024, 256); 
    SecretKey tmp = factory.generateSecret(spec); 
    SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES"); 
    return(secret); 
} 


public static byte[] encrypt(char[] password, byte[] salt, String text) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, InvalidParameterSpecException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException{ 
    SecretKey secret = getSecretKey(password, salt); 

    Cipher cipher = Cipher.getInstance("AES"); 

    // NOTE: This is where the Exception is being thrown 
    cipher.init(Cipher.ENCRYPT_MODE, secret); 
    byte[] ciphertext = cipher.doFinal(text.getBytes("UTF-8")); 
    return(ciphertext); 
} 

任何人都可以看到我做錯了什麼?我認爲它可能與SecretKeyFactory算法有關,但這是我能找到的唯一一個在我正在開發的終端系統上支持的算法。任何幫助,將不勝感激。謝謝。使用任何填充機制

+1

您能否粘貼例外? – 2010-04-02 19:59:32

+0

在[此鏈接]的早期文章中有一個答案(http://stackoverflow.com/questions/992019/java-256bit-aes-encryption/992413#992413)。希望這可以幫助! – 2010-04-02 20:23:02

+0

因此,似乎Java實例不支持我所需要的: '帶有消息「非法密鑰大小或默認參數」的消息java.security.InvalidKeyException' – wuntee 2010-04-02 20:42:29

回答

-1

填補空位

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
+0

哎呀,對不起這個填充輸入不是關鍵 – 2010-04-02 20:03:58

8

對於一個更強的密鑰強度的加密,你需要下載Java加密擴展(JCE)無限強度權限策略文件。

http://java.sun.com/javase/downloads/index.jsp(檢查其他下載)。

+0

我已經下載了額外的罐子,將它們添加到項目中,但我仍然得到異常... – wuntee 2010-04-03 22:48:19

+0

您不要將它們添加到項目中,那些是運行時庫。 README.txt文件指出,您必須將它們安裝到運行時安全文件夾(覆蓋那裏的文件) 如果您使用JDK,則:/ path/to/jdk/jre/libs/security/ 如果您使用JRE :/ path/to/jre/libs/security/ – 2010-04-06 23:46:30

+0

這是否解決了您的問題? – 2010-05-09 23:18:50

-1

當我把下面的代碼並運行它,我沒有收到任何例外:

import java.io.UnsupportedEncodingException; 
import java.security.InvalidKeyException; 
import java.security.NoSuchAlgorithmException; 
import java.security.spec.InvalidKeySpecException; 
import java.security.spec.InvalidParameterSpecException; 
import java.security.spec.KeySpec; 

import javax.crypto.BadPaddingException; 
import javax.crypto.Cipher; 
import javax.crypto.IllegalBlockSizeException; 
import javax.crypto.NoSuchPaddingException; 
import javax.crypto.SecretKey; 
import javax.crypto.SecretKeyFactory; 
import javax.crypto.spec.PBEKeySpec; 
import javax.crypto.spec.SecretKeySpec; 


public class Main 
{ 
    public static void main(String[] args) 
    { 
     String pass = "this is the pass"; 
     char[] pw = new char[pass.length()]; 
     for(int k=0; k<pass.length();++k) 
     { 
      pw[k] = pass.charAt(k); 
     } 
     try { 
      byte[] q = encrypt(pw,"asdf".getBytes(),"der text"); 
      System.out.println(new String(q)); 
     } catch (InvalidKeyException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (NoSuchAlgorithmException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (InvalidKeySpecException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (NoSuchPaddingException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (InvalidParameterSpecException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IllegalBlockSizeException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (BadPaddingException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (UnsupportedEncodingException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

    } 

    public static SecretKey getSecretKey(char[] password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException{ 
     SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWithMD5AndDES"); 
     // NOTE: last argument is the key length, and it is 256 
     KeySpec spec = new PBEKeySpec(password, salt, 1024, 256); 
     SecretKey tmp = factory.generateSecret(spec); 
     SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES"); 
     return(secret); 
    } 


    public static byte[] encrypt(char[] password, byte[] salt, String text) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, InvalidParameterSpecException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException{ 
     SecretKey secret = getSecretKey(password, salt); 

     Cipher cipher = Cipher.getInstance("AES"); 

     // NOTE: This is where the Exception is being thrown 
     cipher.init(Cipher.ENCRYPT_MODE, secret); 
     byte[] ciphertext = cipher.doFinal(text.getBytes("UTF-8")); 
     return(ciphertext); 
    } 
} 

我從來沒有能夠重新創建你有例外。我正在運行J2SE 1.6並在Eclipse上開發。

難道你的密碼不是16字節長嗎?

+0

密碼不是關鍵。用戶正確使用基於密碼的密鑰推導函數(PBKDF)。您已刪除必需的保護。提示:存在'GeneralSecurityException'這樣的事情,通常情況下,您要麼將其拋出到您的方法中,要麼您創建運行時異常(例如,如果找不到算法,則爲「IllegalStateException」)。 – 2014-01-05 16:57:23

+0

我沒有刪除任何保護。 encrypt()方法調用getSecretKey(),它調用PBEKeySpec(),就像OP在其原始代碼中一樣。 – Chopstick 2014-01-05 18:01:49

2

您可以按照幾個其他類似問題的建議來安裝JCE Unlimited Strength jars,或者嘗試在主函數或驅動程序中包含此代碼。

try { 
    java.lang.reflect.Field field = Class.forName("javax.crypto.JceSecurity").getDeclaredField("isRestricted"); 
    field.setAccessible(true); 
    field.set(null, java.lang.Boolean.FALSE); 
} catch (Exception ex) { 
    ex.printStackTrace(); 
} 
+0

在java 8中不起作用 – 2016-05-18 22:10:16

2

這裏的問題是密鑰導出函數和給定密碼的密鑰大小不匹配。您使用的PBKDF是"PBEWithMD5AndDES",在此字符串中,DES部分指示輸出的類型。由於衆所周知,單個DES僅使用8個字節的密鑰(64位,56個有效位大小和奇偶校驗位)。 AES密鑰應該是128,192和256位,不應該包含奇偶校驗位。

要創建AES強度密鑰大小,至少應該使用PBKDF2而不是PBKDF1,最好使用SHA-256或SHA-512來獲得更高的密鑰大小。對於128位密鑰,您應該可以使用SHA-1。因此請使用"PBKDF2WithHmacSHA1"SecretKeyFactory中的內部版本。請注意,鍵值超過160位的PBKDF2/SHA1將導致操作不理想。如果您想創建更多數據(例如單獨的IV),您可能希望在輸出上使用基於密鑰的簡單密鑰導出函數(KBKDF)。

正如其他人所指出的,如果您使用超過128位的密鑰,您將需要無限加密權限文件。以下代碼


注:

  • 沒有完整性保護,你可能甚至需要使用零IV保持機密
  • CBC,這可能是確定的,但只有在鹽完全隨機(用密文存儲鹽)
  • 1024是PBKDF2的迭代次數相對較少
  • PBKDF2與您正在使用的PBKDF1不兼容
public static SecretKey getSecretKey(char[] password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException{ 
    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
    // NOTE: last argument is the key length, and it is 128 
    KeySpec spec = new PBEKeySpec(password, salt, 1024, 128); 
    SecretKey tmp = factory.generateSecret(spec); 
    SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES"); 
    return(secret); 
} 

public static byte[] encrypt(char[] password, byte[] salt, String text) throws GeneralSecurityException { 
    SecretKey secret = getSecretKey(password, salt); 
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
    cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(new byte[cipher.getBlockSize()])); 
    byte[] ciphertext = cipher.doFinal(text.getBytes(StandardCharsets.UTF_8)); 
    return(ciphertext); 
}