2013-02-13 13 views
5

Szybki, który do tej pory unikał mnie (długa noc). Porównuję AES256 w PHP vs Java i zauważam rozbieżności. Proszę dla uproszczenia zignorować klucz ascii i wartość zerową IV, zostaną one zastąpione w produkcji. Ale muszę ominąć ten pierwszy i nie może dowiedzieć się, gdzie jestem erring:AES256 na Java vs PHP

PHP:

echo base64_encode(
    mcrypt_encrypt(
     MCRYPT_RIJNDAEL_128, 
     "1234567890ABCDEF1234567890ABCDEF", 
     "This is a test", 
     MCRYPT_MODE_CBC, 
     "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 
    ) 
); 

Java

byte[] key = "1234567890ABCDEF1234567890ABCDEF".getBytes("UTF-8"); 
byte[] iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 
AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv); 
SecretKeySpec newKey = new SecretKeySpec(key, "AES"); 
Cipher cipher = Cipher.getInstance("AES"); 
cipher.init(Cipher.ENCRYPT_MODE, newKey, ivSpec); 
byte[] results = cipher.doFinal("This is a test".getBytes("UTF-8")); 

return Base64.encodeToString(results,Base64.DEFAULT); 

wyjściowego PHP: wyjście 0KwK+eubMErzDaPU1+mwTQ==

Java : DEKGJDo3JPtk48tPgCVN3Q==

Nie do końca oczekiwałem o_O!

Próbowałem również MCRYPT_MODE_CBC, MCRYPT_MODE_CFB, MCRYPT_MODE_ECB, MCRYPT_MODE_NOFB, itp .. żaden z nich nie wyprodukował ciągu Java.

+1

Czy próbowałeś zmienić 'Cipher.getInstance (" AES ");' na 'Cipher.getInstance (" AES/CBC/NoPadding ");' –

+0

Yezzir, "AES/CBC/NoPadding" produkuje IllegalBlockSizeException: dane nie blokują wyrównany rozmiar. "AES/CBC/PKCS5Padding" produkuje "DEKGJDo3JPtk48tPgCVN3Q ==", podobnie jak "AES/CBC/PKCS7Padding". –

+0

To było głupie, bez wyściółki musisz mieć pewność, że podajesz wielokrotność rozmiaru bloku. Napiszę odpowiedź z tym, co uważam za rozwiązanie. –

Odpowiedz

1

PHP wstawia bajty wejściowe za pomocą \0, aby utworzyć wielokrotność rozmiaru bloku. Równowartość w Javie byłoby to (zakładając łańcuch chcesz zaszyfrować jest w data):

Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); 
int blockSize = cipher.getBlockSize(); 

byte[] inputBytes = data.getBytes(); 
int byteLength = inputBytes.length; 
if (byteLength % blockSize != 0) { 
    byteLength = byteLength + (blockSize - (byteLength % blockSize)); 
} 

byte[] paddedBytes = new byte[byteLength]; 

System.arraycopy(inputBytes, 0, paddedBytes, 0, inputBytes.length); 

cipher.init(Cipher.ENCRYPT_MODE, newKey, ivSpec); 
byte[] results = cipher.doFinal(paddedBytes); 

Jako ostrzeżenie do tego - od zera wyściółka nie jest pożądane. Nie ma możliwości określenia różnicy między znakami \0 na końcu łańcucha a faktycznym dopełnieniem. Lepiej używać PKCS5Padding, ale otrzymasz inne wyniki w PHP. Zadaj sobie pytanie, czy POTRZEBUJESZ szyfrowania między platformami w ten sposób.

+0

Powyższy kod generuje 0KwK + eubMErzDaPU1 + mwTQ == –

+0

Czy tego nie szukasz? Zdrap to - nie widziałem zaakceptowanej odpowiedzi –

+0

To na pewno jest =) –