2015-01-16 2 views
1

이 코드는 여러 웹 사이트의 출처로, SO를 작성하는 데 도움을 준 소스로 언급되어 있습니다. 이것은 비 압축 버전입니다.이 중 base64 인코딩과 디코드를 hex2bin 및 bin2hex로 변경했는데, 웹 페이지간에 전달할 때 문제가 발생한다고 생각했지만, 휴지통 데이터를 해독 결과로 받고 있기 때문에있었습니다.일반적인 PHP mcrypt_encrypt() 코드가 때때로 해독에 실패합니다.

동일한 키와 다른 데이터를 사용하는 두 가지 코드를 사용하면 가끔 해독 결과로 휴지통 데이터가 표시됩니다. 반복과 달리 데이터 자체 인 것 같습니다. 데이터 크기는 30-80 자 사이입니다.

데이터는 숫자와 문자로 구성된 일련의 데이터로, 일반적인 ASCII 표준에 모두 포함되며 null이 아니며 표준 전자 메일 주소 문자 이외의 문자는 아닙니다.

나는 PHP 5.5.9-1ubuntu4.5 (젠드 : 2.5.0)으로, 우분투 14.04 LTS를 사용하고

사람은 이런 종류의 문제를 경험 한 적이 있습니까?

EDIT : 더 많은 것을 읽으면 암호화와 해독시 분명히 $ iv가 동일해야하지만 이것이 사실이라면 어째서 대부분의 시간에 작동합니까?

function mc_encrypt($encrypt, $mc_key) { 
    $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND); 
    $passcrypt = trim(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $mc_key, trim($encrypt), MCRYPT_MODE_ECB, $iv)); 
    $encode = bin2hex($passcrypt); 
    return $encode; 
} 

function mc_decrypt($decrypt, $mc_key) { 
    $decoded = hex2bin($decrypt); 
    $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND); 
    $decrypted = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $mc_key, trim($decoded), MCRYPT_MODE_ECB, $iv)); 
    return $decrypted; 
} 

답변

1

Rijndael은 대칭 블록 암호입니다. 블록에서 작동하며이 경우 블록은 256 비트 폭입니다. 암호문은 무작위로 보이기는하지만 사실은 아닙니다. 그렇지 않으면 암호화를 되돌릴 수 없습니다. 이것이 ECB 모드이기 때문에 모든 것을 랜덤 화하는 IV가 없습니다. 이 때문에 모든 키 블록과 결합 된 일반 텍스트 블록은 동일한 암호 텍스트 블록이됩니다. 따라서 문제는 동일한 데이터를 기반으로 만 재현 할 수 있습니다.

암호화가 무작위로 표시되기 때문에 암호문의 첫 번째 바이트에 공백이 포함됩니다 (문자로 표시되는 경우). trim은 6 가지 유형의 공백을 제거하고 최소한 이러한 경우 첫 번째 바이트를 제거합니다. 문제는 6/256 건에서 발생합니다 (~ 2 %).

예를 들어 첫 번째 바이트가 공백이면 제거됩니다. 이제 첫 번째 블록에는 모든 바이트가없고 해독을위한 블록 경계가 이동됩니다. 따라서 다음 블록의 첫 번째 바이트는 첫 번째 블록의 마지막 바이트로 사용되어 블록을 해독합니다. Rijndael은 블록 암호이므로 쓰레기 만 나오게됩니다. 그리고 이것은 모든 블록에서 발생합니다.rtrim(mcrypt_decrypt(...), '\0'); : 보통 rtrim

는 일반 텍스트를 unpad 대신 trim 사용됩니다. 암호문 trim은 완전히 제거해야합니다.

암호화/암호 해독의 끝이 트리밍되어 결과를 깨뜨릴 수 있기 때문에 전체적인 이야기는 아닙니다. 실제로는 PKCS#7 padding by implementing it yourself을 사용하고 *trim을 완전히 잃는 것이 가장 좋습니다. 안타깝게도 php_mcrypt는 PKCS # 7/PKCS # 5 패딩을 제공하지 않습니다.

+0

지연에 대해 죄송합니다. trim()을 제거하고 $ passcrypt로 전달하기 전에 제공된 링크에서 패딩 기능을 사용 하시겠습니까? – ChrisAdmin

+0

'$ passcrypt = trim (mcrypt_encrypt (...'와'... $ mc_key, trim ($ decoded), MCRYPT_MODE_ECB ...')의'trim'에 대해서 이야기하고 있습니다. 그 '트림'을 사용하지 말고 적절한 채우기를 사용하지 않는 것이 좋습니다. –

+0

링크에서 새 패딩을 시도하고 트림을 제거하고 시간에 따라 데이터를 약 20 번 테스트했습니다. 그래서 답을 추측합니다 - 감사합니다. – ChrisAdmin

관련 문제