2011-11-10 41 views
5

由於某些原因,我需要使用塊大小爲256位的Rijndael de/compression,而不是使用128位塊大小的AES(原因是:數據使用Rijndael在PHP中進行了加密...)。如何使用Rijndael進行加密或解密以及256位的塊大小?

如何更改密碼的塊大小?

如果我剛剛得到一個"RIJNDAEL/CFB/PKCS5Padding"的密碼,並試圖用256位初始化一個IV,我得到一個異常,因爲塊大小隻有128位。

+0

你可能必須確定您已經安裝了Java JCE無限制的加密類。它們不是典型的標準Java發行版的一部分,因爲它們在某些國家是非法的。 – Romain

+0

已經有了它們。仍然無法找到如何獲得所需的塊大小的密碼對象 – Laures

+0

然後我相信@GregS有答案。我曾相信Rijndael-256是JCE Unlimited Providers的一部分,但我習慣於使用我公司的定製化Java - 它有一個JCE提供商,但它可能是私有實現。 – Romain

回答

13

任何Sun JCE提供程序都不支持除128位塊大小的Rijndael以外的其他任何提供程序:這是AES算法。要獲得256位塊大小的rijndael,你將不得不去其他地方。我建議Bouncycastle java庫。 RijndaelEngine類有一個構造函數,它接受以位爲單位的塊大小。大多數人發現PaddedBufferedBlockCipher類與適當的填充物一起使用會更方便,例如,

PaddedBufferedBlockCipher c = new PaddedBufferedBlockCipher(new RijndaelEngine(256), new PKCS7Padding()); 
0

需要注意的是PHP的mcrypt使用零字節填充所以new ZeroBytePadding()應該用來代替new PKCS7Padding()

波紋管完全實現使用CBCRIJNDAEL 256

import org.bouncycastle.crypto.CipherParameters; 
import org.bouncycastle.crypto.InvalidCipherTextException; 
import org.bouncycastle.crypto.engines.RijndaelEngine; 
import org.bouncycastle.crypto.modes.CBCBlockCipher; 
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher; 
import org.bouncycastle.crypto.paddings.ZeroBytePadding; 
import org.bouncycastle.crypto.params.KeyParameter; 
import org.bouncycastle.crypto.params.ParametersWithIV; 
import org.bouncycastle.util.encoders.Base64; 

public static String encryptWithAesCBC(String plaintext, String key, String iv) 
{ 
    try { 
     PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new RijndaelEngine(256)), new ZeroBytePadding()); 
     CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(key.getBytes()), iv.getBytes()); 
     cipher.init(true, ivAndKey); 
     return new String(Base64.encode(cipherData(cipher, plaintext.getBytes()))); 
    } catch (InvalidCipherTextException e) { 
     throw new RuntimeException(e); 
    } 
} 

public static String decryptWithAesCBC(String encrypted, String key, String iv) 
{ 
    try { 
     byte[] ciphertext = Base64.decode(encrypted); 
     PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher(new CBCBlockCipher(new RijndaelEngine(256)), new ZeroBytePadding()); 

     CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(key.getBytes()), iv.getBytes()); 
     aes.init(false, ivAndKey); 
     return new String(cipherData(aes, ciphertext)); 
    } catch (InvalidCipherTextException e) { 
     throw new RuntimeException(e); 
    } 
} 

private static byte[] cipherData(PaddedBufferedBlockCipher cipher, byte[] data) throws InvalidCipherTextException 
{ 
    int minSize = cipher.getOutputSize(data.length); 
    byte[] outBuf = new byte[minSize]; 
    int length1 = cipher.processBytes(data, 0, data.length, outBuf, 0); 
    int length2 = cipher.doFinal(outBuf, length1); 
    int actualLength = length1 + length2; 
    byte[] cipherArray = new byte[actualLength]; 
    for (int x = 0; x < actualLength; x++) { 
     cipherArray[x] = outBuf[x]; 
    } 
    return cipherArray; 
} 

private String md5(String string) 
{ 
    try { 
     java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5"); 
     byte[] array = md.digest(string.getBytes()); 
     StringBuffer sb = new StringBuffer(); 
     for (int i = 0; i < array.length; ++i) { 
      sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1, 3)); 
     } 
     return sb.toString(); 
    } catch (java.security.NoSuchAlgorithmException e) { 
     throw new RuntimeException(e); 
    } 
} 

當使用CFB,PaddedBufferedBlockCipher應該是替換以下:

PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher(new CFBBlockCipher(new RijndaelEngine(256),8), new ZeroBytePadding()); 
// PHP mcrypt uses a blocksize of 8 bit for CFB 

用法:

String salt = "fbhweui3497"; 
String key = md5(salt); 
String iv = md5(md5(salt)); 

String encrypted = encryptWithAesCBC("text to encript", key, iv); 

String decrypted = decryptWithAesCBC(encrypted, key, iv); 
+1

你能提供md5()嗎? String md5(String input){ \t \t String result = input; \t \t MessageDigest md; \t \t嘗試{ \t \t \t md = MessageDigest.getInstance(「MD5」); \t \t \t md.update(input.getBytes()); \t \t \t BigInteger hash = new BigInteger(1,md.digest()); \t \t \t result = hash.toString(16); \t \t \t while(result。長度()<32){// 40對於SHA-1 \t \t \t \t result =「0」+ result; \t \t \t} \t \t}趕上(拋出:NoSuchAlgorithmException E){ \t \t \t e.printStackTrace(); \t \t} \t \t返回結果; \t} 上述方法給出「java.lang.IllegalArgumentException:密鑰長度不是128/160/192/224/256位」。 – Krish

+0

@Krish我剛剛添加到答案md5實現。 –