2011-11-10 24 views
5

pewnych względów trzeba zaimplementować Rijndael DE/ściskania o rozmiarze bloku 256 bitów, a nie AES, który wykorzystuje format blokowy 128 bitów (powodu: dane są szyfrowane za pomocą PHP Rijndael ...).Jak szyfrować lub deszyfrować za pomocą Rijndael i blok o rozmiarze 256 bitów?

Jak mogę zmienić rozmiar-bloku na szyfr?

Jeśli otrzymam szyfr z numerem "RIJNDAEL/CFB/PKCS5Padding" i spróbuję zainicjować IV z 256 bitami, otrzymam wyjątek, ponieważ rozmiar bloku wynosi tylko 128 bitów.

+0

Prawdopodobnie będziesz musiał upewnić się, że zainstalowano klas nieograniczony szyfrowania Java JCE . Nie należą do typowej standardowej dystrybucji Java, ponieważ są nielegalne w niektórych krajach. – Romain

+0

już je masz. wciąż nie mogę dowiedzieć się, jak uzyskać obiekt szyfru z wymaganym blokiem – Laures

+0

Następnie wierzę, że @GregS ma odpowiedź. Wierzyłem, że Rijndael-256 jest częścią JCE Unlimited Providers, ale jestem przyzwyczajony do korzystania z nieco spersonalizowanej Javy mojej firmy - która ma dla niej dostawcę JCE, ale może również być prywatną implementacją. – Romain

Odpowiedz

13

Nie ma wsparcia w żadnym z dostawców Sun JCE do niczego innego niż Rijndael z 128-bitowym rozmiar bloku: to jest algorytm AES. Aby uzyskać Rijndael z 256-bitowym bloki, musisz udać się gdzieś indziej. Proponuję bibliotekę Bouncycastle java. Klasa RijndaelEngine ma konstruktor, który akceptuje rozmiar bloku w bitach. Większość ludzi uważa, że ​​klasa PaddedBufferedBlockCipher jest wygodniejsza, gdy używa się jej z odpowiednim wypełnieniem, np.

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

Zauważ, że PHP mcrypt używa bajt zerowy wyściółkę tak new ZeroBytePadding() powinien być używany zamiast new PKCS7Padding().

Osiągnięcie pełnej implementacji przy użyciu CBC i RIJNDAEL 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); 
    } 
} 

Podczas korzystania CFB, PaddedBufferedBlockCipher powinien zastąpić brzmienie:

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

Zastosowanie:

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

Czy możesz podać kod md5()? Ciąg MD5 (wejście Ciąg) { \t \t wynik ciąg = wejście; \t \t MessageDigest md; \t try { \t \t \t md = MessageDigest.getInstance ("MD5"); \t \t \t md.update (input.getBytes()); \t \t \t BigInteger mieszania = nowy BigInteger (1, md.digest()); \t \t \t result = hash.toString (16); \t \t \t podczas gdy (wynik.długość() <32) {// 40 dla SHA-1 \t \t \t \t wynik = "0" + wynik; \t \t \t} \t \t} zaczep (NoSuchAlgorithmException e) { \t \t \t w.printStackTrace(); \t \t} \t \t wynik zwrotu; \t} Powyższa metoda podaje, "java.lang.IllegalArgumentException: długość klucza nie 128/160/192/224/256 bitów." – Krish

+0

@Krish Właśnie dodałem do odpowiedzi implementację md5. –