2012-08-07 5 views
1

내가 여기에 몇 가지 이상한 문제 데 ....PHP 대 JAVA AES 암호화, 차이점은 무엇입니까?

나는 다음 두 스크립트가 있습니다

첫째, (I 테스트 http://writecodeonline.com/php/을 사용하고 있습니다) PHP 스크립트를

$key = '[E%Xr6pG-IDIA89_&=NI[AREofOy0#Mv[[email protected]^PwgT!NVY*[email protected]($p4luBM)[email protected]*jBP3s$g#-XTH{[email protected]*0StJ'; 
$string = 'Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing '; 

// 
$encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, md5($key), $string, MCRYPT_MODE_ECB)); 

$decrypted = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, md5($key), base64_decode($encrypted), MCRYPT_MODE_ECB), "\0"); 


echo $encrypted . "<br>"; 
echo $decrypted; 

두 번째 , Java 클래스,

import java.io.*; 
import java.net.*; 
import java.security.InvalidKeyException; 
import java.security.NoSuchAlgorithmException; 

import javax.crypto.*; 
import javax.crypto.spec.*; 

import org.apache.commons.codec.binary.Base64; 
import org.apache.commons.codec.digest.DigestUtils; 


public class Main { 

    /** 
    * @param args 
    * @throws Exception 
    */ 
    public static void main(String[] args) throws Exception { 

     String pw = "[E%Xr6pG-IDIA89_&=NI[AREofOy0#Mv[[email protected]^PwgT!NVY*[email protected]($p4luBM)[email protected]*jBP3s$g#-XTH{[email protected]*0StJ"; 
     String str = encode("Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing ", pw); 
     System.out.println(str); 
     System.out.println(decode(str, pw)); 
    } 

    public static String encode(String s, String p) throws Exception 
    { 
     String cleartext = padRight(s, s.length()+(16-(s.length()%16))); 
     String key = DigestUtils.md5Hex(p); 
     SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES"); 
     Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding"); 
     cipher.init(Cipher.ENCRYPT_MODE, skeySpec); 
     byte[] encrypted = cipher.doFinal(cleartext.getBytes()); 
     return Base64.encodeBase64String(encrypted); 
    } 

    public static String decode(String encrypted, String p) throws Exception 
    { 
     byte[] bts = Base64.decodeBase64(encrypted); 


     String key = DigestUtils.md5Hex(p); 
     SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES"); 
     Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding"); 
     cipher.init(Cipher.DECRYPT_MODE, skeySpec); 



     byte[] decrypted = cipher.doFinal(bts); 

     return new String(decrypted).replaceAll("\0", ""); 
    } 

    public static String padRight(String s, int n) { 
     while (s.length() < n) 
     { 
      s+="\0"; 
     } 
     return s; 
    } 

} 

뭔가 이상한 일이 발생합니다. PHP 스크립트를 테스트하면 다음과 같이 표시됩니다.

/wyCRFRmXFDGk0O5+EAHWv8MgkRUZlxQxpNDufhAB1r/DIJEVGZcUMaTQ7n4QAda/wyCRFRmXFDGk0O5+EAHWv8MgkRUZlxQxpNDufhAB1r/DIJEVGZcUMaTQ7n4QAda/wyCRFRmXFDGk0O5+EAHWv8MgkRUZlxQxpNDufhAB1r/DIJEVGZcUMaTQ7n4QAda/wyCRFRmXFDGk0O5+EAHWg== 

은 암호화 된 코드입니다. 나는 자바 코드를 테스트 할 때

은, 그러나, 내가 얻을 : 당신이 자세히 보면

/wyCRFRmXFDGk0O5+EAHWv8MgkRUZlxQxpNDufhAB1r/DIJEVGZcUMaTQ7n4QAda/wyCRFRmXFDGk0O5+EAHWv8MgkRUZlxQxpNDufhAB1r/DIJEVGZcUMaTQ7n4QAda/wyCRFRmXFDGk0O5+EAHWv8MgkRUZlxQxpNDufhAB1r/DIJEVGZcUMaTQ7n4QAda/wyCRFRmXFDGk0O5+EAHWsdyQJ3DP2jBsJcLh2n2wv0= 

, 당신이 표시됩니다 (어떻게 든) 자바 텍스트는 더 이상! 그러나 기묘하게도, 두 텍스트가 서로 엇갈리는 "+ EAH"까지 정확히 똑같습니다. 나는 이것을 완전히 이상하게 생각한다 - 왜?

나는이 코드를 lorum ipsum에서 다른 많은 문자열에 대해 "Testing"이라는 단어를 오류없이 테스트했기 때문에이 코드를 테스트했습니다. 이것이 (지금까지) 일으키는 것으로 밝혀진 유일한 방법은 여러 번 공백으로 구분 된 짧은 단어를 반복하는 것입니다.

나는이 이상한 행동을 유발하는 다른 방법이 무엇인지 모르기 때문에 이것에 대해 매우 걱정하고 있습니다. 그래서 내 질문에 이르게 ... 데이비 존 락커의 이름으로 뭐라 구요?

답변

4

저는 암호화 전문가는 아니지만 패딩 문제 일 수 있습니다. 다음과 같이 시도해보십시오.

$blockSize = mcrypt_get_block_size(MCRYPT RIJNDAEIL_128, MCRYPT_MODE_ECB); 
$padding = $blockSize - (strlen($string) % $blockSize); 
$string .= str_repeat(chr($padding), $padding); 

이 된 PKCS # 5 패딩을 사용하는 대신 PHP의 널 (null) 패딩의 다음과 같이

PHP는 패딩을 설정합니다.

자바
변경 다음 줄

Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding"); 

에 : 나는 결과를 비교할 수있는 자바 환경이없는 불행하게도

Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); 

, 그러나 나는 희망 도움이됩니다.

+0

감사 톤! 그것은 매력처럼 작동합니다! 향후 시청자를 위해 MCRYPT_RIJNDAEL_256을 MCRYPT RIJNDAEIL_128 (으)로 변경해야한다는 점에 유의하고 싶습니다. –

+0

도움을 주셔서 감사합니다. 나는 또한 나의 대답을 수정했다, 나는 처음부터 128을 넣으려고했다. 아침에 조금 이른 아침에 졸 았을 것입니다. :) – Diego

+0

문제 없습니다!나는 오히려 피곤했다 - 내 코멘트에 MCRYPT_RIJNDAEIL_128을 쓰려고했다. MCRYPT RIJNDAEIL_128 –

1

코드는 상수의 이름의 철자가 올바른 코드는 다음과 같습니다

$blockSize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB); 
$padding = $blockSize - (strlen($tokenRaw) % $blockSize); 
$tokenRaw .= str_repeat(chr($padding), $padding); 

$encode = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $tokenRaw, MCRYPT_MODE_ECB));