2009-06-30 1 views
12

내가 좋아하는 뭔가를가는 코드가 :mcrypt_decrypt 후에 해독 된 문자열을 잘라야합니까?

$cipher_alg = MCRYPT_RIJNDAEL_128; 
$decrypted_string = mcrypt_decrypt($cipher_alg, $key, 
$encrypted_string , MCRYPT_MODE_CBC, trim(hex2bin(trim($hexiv)))); 

내가 걱정 그 $decrypted_string의 후면 또는 전면 무상 공백 또는 널 (null) 문자를 소개합니다 mcrypt_decrypt를 디코딩하는 과정이다.

트리밍해야합니까?

참고 : 코드를 실행하여 찾을 수 있습니다. 그러나 내 견해를 증명할 수있는 충분한 표본을 결코 실행할 수 없기 때문에, 나는 mcrypt_decrypt 알고리즘의 내부 작업을 기반으로 한 구체적이고 이론적 인 답변을 원합니다. 제가 묻는 또 다른 이유는 이것이 다른 사람들을 도울 것이라고 믿는다는 것입니다.

주 2 : the answer below (now deleted and only 10K users can see it)과에도 불구하고, examples here가 올바른 암호 해독 문자열을 얻을 트리밍 사용합니까 것으로 보인다.

+0

잘못된 정보로 인해 죄송합니다. Ngu는 mcrypt를 사용했을 때 CBC 모드를 사용하고있는 것으로 보입니다. –

+0

Err ... CBC 모드를 사용하지 않았습니다. :-( –

답변

18

사실 모두 mcrypt_encrypt()mcrypt_decrypt()뿐만 아니라 다른 EN-/복호화 functons은 (mcrypt_generic() 또는 mdecrypt_generic() 등)은 n * <<blocksize>>의 길이 패드 $data 파라미터 할. 패딩 문자는 NUL 문자 (\x0 또는 \0)이며 <<blocksize>>은 사용되는 암호 및 블록 암호 모드에 따라 다릅니다. Block cipher modes of operationPadding (cryptography)을 확인해야합니다.

다음은 내 컴퓨터에서 사용 가능한 암호 및 모드에 대한 mcrypt_get_block_size()의 출력입니다. 함수는 CFB, OFB 및 CTR 과 같은 모드가 길이가 블록 크기의 배수가 아닌 메시지를 처리하기 위해 특별한 조치를 필요로하지 않는다는 것을 분명히 고려하지 않습니다. 일반 텍스트의 출력과 함께 일반 텍스트를 XOR하여 작동하기 때문입니다. 블록 암호 (위키 피 디아에서 인용). 귀하의 예에서 사용되는 CBC는 항상 최종 블록이 암호화되기 전에 채워져 있어야합니다.

cast-128 
    cbc: 8 bytes 
    cfb: 8 bytes 
    ctr: 8 bytes 
    ecb: 8 bytes 
    ncfb: 8 bytes 
    nofb: 8 bytes 
    ofb: 8 bytes 
    stream: not supported 
gost 
    cbc: 8 bytes 
    cfb: 8 bytes 
    ctr: 8 bytes 
    ecb: 8 bytes 
    ncfb: 8 bytes 
    nofb: 8 bytes 
    ofb: 8 bytes 
    stream: not supported 
rijndael-128 
    cbc: 16 bytes 
    cfb: 16 bytes 
    ctr: 16 bytes 
    ecb: 16 bytes 
    ncfb: 16 bytes 
    nofb: 16 bytes 
    ofb: 16 bytes 
    stream: not supported 
twofish 
    cbc: 16 bytes 
    cfb: 16 bytes 
    ctr: 16 bytes 
    ecb: 16 bytes 
    ncfb: 16 bytes 
    nofb: 16 bytes 
    ofb: 16 bytes 
    stream: not supported 
arcfour 
    cbc: not supported 
    cfb: not supported 
    ctr: not supported 
    ecb: not supported 
    ncfb: not supported 
    nofb: not supported 
    ofb: not supported 
    stream: 1 bytes 
cast-256 
    cbc: 16 bytes 
    cfb: 16 bytes 
    ctr: 16 bytes 
    ecb: 16 bytes 
    ncfb: 16 bytes 
    nofb: 16 bytes 
    ofb: 16 bytes 
    stream: not supported 
loki97 
    cbc: 16 bytes 
    cfb: 16 bytes 
    ctr: 16 bytes 
    ecb: 16 bytes 
    ncfb: 16 bytes 
    nofb: 16 bytes 
    ofb: 16 bytes 
    stream: not supported 
rijndael-192 
    cbc: 24 bytes 
    cfb: 24 bytes 
    ctr: 24 bytes 
    ecb: 24 bytes 
    ncfb: 24 bytes 
    nofb: 24 bytes 
    ofb: 24 bytes 
    stream: not supported 
saferplus 
    cbc: 16 bytes 
    cfb: 16 bytes 
    ctr: 16 bytes 
    ecb: 16 bytes 
    ncfb: 16 bytes 
    nofb: 16 bytes 
    ofb: 16 bytes 
    stream: not supported 
wake 
    cbc: not supported 
    cfb: not supported 
    ctr: not supported 
    ecb: not supported 
    ncfb: not supported 
    nofb: not supported 
    ofb: not supported 
    stream: 1 bytes 
blowfish-compat 
    cbc: 8 bytes 
    cfb: 8 bytes 
    ctr: 8 bytes 
    ecb: 8 bytes 
    ncfb: 8 bytes 
    nofb: 8 bytes 
    ofb: 8 bytes 
    stream: not supported 
des 
    cbc: 8 bytes 
    cfb: 8 bytes 
    ctr: 8 bytes 
    ecb: 8 bytes 
    ncfb: 8 bytes 
    nofb: 8 bytes 
    ofb: 8 bytes 
    stream: not supported 
rijndael-256 
    cbc: 32 bytes 
    cfb: 32 bytes 
    ctr: 32 bytes 
    ecb: 32 bytes 
    ncfb: 32 bytes 
    nofb: 32 bytes 
    ofb: 32 bytes 
    stream: not supported 
serpent 
    cbc: 16 bytes 
    cfb: 16 bytes 
    ctr: 16 bytes 
    ecb: 16 bytes 
    ncfb: 16 bytes 
    nofb: 16 bytes 
    ofb: 16 bytes 
    stream: not supported 
xtea 
    cbc: 8 bytes 
    cfb: 8 bytes 
    ctr: 8 bytes 
    ecb: 8 bytes 
    ncfb: 8 bytes 
    nofb: 8 bytes 
    ofb: 8 bytes 
    stream: not supported 
blowfish 
    cbc: 8 bytes 
    cfb: 8 bytes 
    ctr: 8 bytes 
    ecb: 8 bytes 
    ncfb: 8 bytes 
    nofb: 8 bytes 
    ofb: 8 bytes 
    stream: not supported 
enigma 
    cbc: not supported 
    cfb: not supported 
    ctr: not supported 
    ecb: not supported 
    ncfb: not supported 
    nofb: not supported 
    ofb: not supported 
    stream: 1 bytes 
rc2 
    cbc: 8 bytes 
    cfb: 8 bytes 
    ctr: 8 bytes 
    ecb: 8 bytes 
    ncfb: 8 bytes 
    nofb: 8 bytes 
    ofb: 8 bytes 
    stream: not supported 
tripledes 
    cbc: 8 bytes 
    cfb: 8 bytes 
    ctr: 8 bytes 
    ecb: 8 bytes 
    ncfb: 8 bytes 
    nofb: 8 bytes 
    ofb: 8 bytes 
    stream: not supported 

따라서 당신이 당신의 암호가 고정 된 길이 블록에서 작동하는 경우 암호 해독 기능의 출력이 원래의 문자열을 얻을 수 rtrim()에 있습니다 TripleDES를 내 구현에서

$output = rtrim($decrypted, "\0"); 
+1

올바른 해결책입니다. \ '주위에 작은 따옴표를 사용하지 말고 큰 따옴표를 사용하는 것이 매우 중요합니다! – shadowhand

+2

Btw, 아주 가능성이 희박합니다. 'trim (..., "\ 0")'을 사용하면 고정 길이가 아닌 블록 크기를 사용하는 경우에도 해독 된 데이터를 깨뜨릴 수 있지만 이진 데이터를 암호화 할 때는 * 가능 * 할 수 있음 – shadowhand

+0

stud @StefanGehrig. "trim"을 사용하여 수백만 개의 예제를 찾았지만 실제로 컨텍스트 내에서 중요한 공백을 제거하고 있었으며이 작업은 세계와 다시 만날 수 있습니다 .2 시간의 디버깅 후, 해결책과 그 모든 것. – CWSpear

8

, 나는 해독 된 문자열을 발견 \ 5 또는 \ 6 문자로 채워져 있습니다. 위에서 언급 한 예상 \ 0 또는 \ 4 문자가 아니거나 PHP.net 예제입니다. 패딩 문자의 ASCII 값을 확인하려면 ord() 함수를 사용하십시오. ord()는 단일 문자에서 작동하므로 str_split()을 사용하여 문자열을 분리하거나 배열 표기법 ($ string [5])으로 직접 문자에 액세스하십시오.

최종 트림 결과 - trim($decrypt, "\0..\32");

최종 코드 결과 - 나는 이진 데이터를 암호화/해독했다

$key  = "encryption key"; 
    $encrypt = base64_decode($encrypt); 
    $iv_size = mcrypt_get_iv_size(MCRYPT_3DES, MCRYPT_MODE_ECB); 
    $iv   = mcrypt_create_iv($iv_size, MCRYPT_RAND); 
    $decrypt = mcrypt_decrypt(MCRYPT_3DES, $key, $encrypt, MCRYPT_MODE_ECB, $iv); 
    $final  = trim($decrypt, "\0..\32"); // removes potential null padding 
+0

어떤 경우에는 패딩이 [RFC 5652] (https://tools.ietf.org/html/rfc5652#page-28)에 따라 결정되는 것처럼 보입니다. 실제로 패딩의 양을 나타냅니다. 나는 단지 어떤 algo/mode 조합을 알고 있었으면 좋겠다. s (또는 기본 라이브러리 버전?)는 "\ 0"을 사용하여이 작업을 수행합니다! – grossvogel

4

. 불행히도 트림은 바이너리 데이터를 깨뜨리고 null 문자와 같은 합법적 인 비트를 잘라낼 수 있습니다.

이진 데이터의 크기를 확인하기 전에 암호화 후 동일, 로켓 위험물 여기에 좋은 답변을 게시 : How can I decrypt binary data that ended with NUL characters in PHP?

요약 :

// PKCS7 Padding 
$blocksize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB); 
$pad = $blocksize - (strlen($data) % $blocksize); 
$data .= str_repeat(chr($pad), $pad); 

$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_ECB); 


/* Then somewhere else in your code */ 
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encrypted, MCRYPT_MODE_ECB); 

// PKCS7 Padding 
$strPad = ord($decrypted[strlen($decrypted)-1]); 
$newData = substr($decrypted, 0, -$strPad); 

내가 사용에 대한 확실하지 않다 CBC 대 ECB ... 연구

+0

이것은 CBC에도 똑같이 적용됩니다. –

0

24 후 시간의 마지막이 나를 위해 일한 :

function removePadding($decryptedText){ 
    $strPad = ord($decryptedText[strlen($decryptedText)-1]); 
    $decryptedText= substr($decryptedText, 0, -$strPad); 
    return $decryptedText; 
} 
+0

답변 코드는 PHP mcrypt가 기본적으로 사용하는 null 채우기와 함께 작동하지 않으며 OP가 사용중인 것입니다. PKCS # 7/PKCS # 5 패딩의 경우 패딩이 유효한지 확인해야합니다. 잘못된 키의 사용을 고려해보십시오. $ strPad가 잘못된 것일 수 있습니다. 잠재적으로 데이터 길이보다 큰 값입니다. 그러나 패딩 오라클을 만드는 경향이있는 잘못된 패딩 오류를 반환하지 말고 대신 아무것도 수행하지 마십시오. 대부분의 라이브러리는 PKCS # 7 패딩을 지원하며 암호화시 패딩을 자동으로 추가하고 암호 해독시 패딩을 제거하므로 더 이상 수행 할 필요가 없습니다. – zaph

관련 문제