2012-03-20 22 views
8

Dưới đây là một kịch bản PHP demo mà mã hóa và giải mã dữ liệu:Tại sao mcrypt_encrypt() đặt ký tự nhị phân ở cuối chuỗi của tôi?

<? 

$encryptionkey = 'h8y2p9d1'; 

$card_nbr = "1234"; 
echo "original card_nbr: $card_nbr <br>\n"; 

$card_nbr_encrypted=encrypt_data($card_nbr); 
echo "card_nbr_encrypted: $card_nbr_encrypted <br>\n"; 

$card_nbr_decrypted=decrypt_data($card_nbr_encrypted); 
echo "card_nbr_decrypted: $card_nbr_decrypted <br>\n"; 

$len=strlen($card_nbr_decrypted); 
echo "length: $len <br>\n"; 



function encrypt_data($text){ 
    global $encryptionkey; 
    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB); 
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); 
    $encrypted_text = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $encryptionkey, $text, MCRYPT_MODE_ECB, $iv); 
    return $encrypted_text; 
} 

function decrypt_data($text){ 
    global $encryptionkey; 
    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB); 
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); 
    $decrypted_text = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $encryptionkey, $text, MCRYPT_MODE_ECB, $iv); 
    return $decrypted_text; 
} 

?> 


Đầu ra là:

original card_nbr: 1234 
card_nbr_encrypted: vY¨(Z$<§G3-žÃ-Éù3Ý2Ê×rz¨VÛ 
card_nbr_decrypted: 1234 (and 28 binary characters) 
length: 32 


Sản lượng được giải mã thành công, nhưng 28 ký tự nhị phân được thêm vào kết thúc. Điều này có thể dễ dàng được nhìn thấy trong Firefox, khi xem nguồn HTML. Độ dài chuỗi 32 cũng thể hiện điều này. Bất kỳ ý tưởng?

enter image description here

+0

xem liệu điều đó có thể giúp được bất kỳ sự trợ giúp nào http://php.net/manual/en/function.base64-encode.php –

+0

@Mian_Khurram_Ijaz Tôi không thấy lý do tại sao điều đó sẽ giúp – Ben

+0

đầu ra thực sự ở định dạng nhị phân Vì vậy, để làm cho nó an toàn trên mạng base64_encode là hữu ích mã hóa và giải mã đang làm việc tốt vì vậy tôi nghĩ nếu chars nhị phân là vấn đề sau đó sử dụng base64 .. –

Trả lời

8

Chuỗi trả về được điền để điền vào n * blocksize byte sử dụng ký tự null \0 vì vậy đó là lý do tại sao bạn thấy dữ liệu bổ sung.

Nếu bạn chạy $card_nbr_decrypted= rtrim($card_nbr_decrypted, "\0");, nó sẽ trả lại dữ liệu thực tế.

+0

Một giải pháp sử dụng 'rtrim' là, tất nhiên, bị hỏng nếu bạn muốn để mã hóa dữ liệu nhị phân tùy ý có thể thực sự kết thúc bằng một số số không. Trong trường hợp đó, bạn nên truyền độ dài của chuỗi out-of-band và 'substr' trở lại chiều dài đó (dễ, nhưng làm rò rỉ độ dài của chuỗi), hoặc tự đệm trước khi mã hóa - tôi khuyên bạn nên sử dụng phương pháp đệm PKCS # 7 vì nó dễ hiểu. – hobbs

+0

Vấn đề với PKCS # 7 là bozos đã viết và duy trì mcrypt đã cung cấp hỗ trợ cho nó. – zaph

3

Nó có vẻ là một known problem. Sử dụng rtrim() sau khi giải mã để loại bỏ NUL dư thừa.

2

Bạn đang nhận được byte trống vì bạn đang sử dụng Khối mã điện tử (ECB) cho số block cipher mode of operation của bạn, phần cuối của bản rõ để vừa với kích thước khối. Trong trường hợp của bạn, kích thước khối là 256 bit vì bạn đang sử dụng MCRYPT_RIJNDAEL_256.

Bạn có thể tránh vấn đề đệm này cùng nhau nếu bạn sử dụng Phản hồi mật mã (CFB) - MCRYPT_MODE_CFB - không có byte rỗng, không cần cắt. Tuy nhiên, với CFB, bạn nên HMAC dữ liệu được mã hóa của mình, để xác minh nó không bị làm giả mạo với (see "Mallet"). Bạn có thể tìm thấy ví dụ về triển khai hoạt động tại: Cryptography For The Average Developer.

Ngoài ra, chế độ ECB được coi là kém an toàn hơn vì có thể reveal data patterns. Ngoài ra, ECB (và CBC kể từ khi nó cũng miếng đệm) có thể dễ bị tổn thương đến padding oracle attack.

-1

Tôi nghĩ vấn đề là bạn đang sử dụng dữ liệu nhị phân khi:

mcrypt_encrypt - Mã hóa rõ với các thông số cho

Bạn có thể sử dụng base64_encode ($ text) để sử dụng văn bản gốc.

+0

Mã hóa không giống như mã hóa. –

+0

Tôi biết. Nhưng nếu bạn sử dụng mcrypt_encrypt Sẽ rất hữu ích khi gửi văn bản $ dưới dạng văn bản gốc base64 để tránh các sự cố với mã hóa. Bạn có thể sử dụng base64_encode ($ text) hoặc rtrim() như những người dùng khác đề xuất. – bLuEdDy