2009-06-30 19 views
12

Ben şöyle bir şey bir kod var:Şifrelenmiş Dize mcrypt_decrypt sonra Trim?

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

Endişe o $decrypted_string arkasında veya önünde bir karşılıksız boşluk veya boş karakterler tanıtacak mcrypt_decrypt deşifre sürecinde.

Bu yüzden kırpmalı mıyım?

Not: Kodu çalıştırabilir ve bulabilirdim. Ancak, hiçbir zaman ismimi kanıtlamak için yeterince örnek üretemediğimden, muhtemelen mcrypt_decrypt algoritmasının iç çalışmasına dayanan bazı somut ve teorik cevaplar istiyorum. Sormamın başka bir nedeni de bunun başkalarına yardım edeceğine inanıyorum.

Not 2: the answer below (now deleted and only 10K users can see it) ile bağlı olmaksızın, examples here doğru şifresi dize almak için kırpma kullanırım gibi görünüyor.

+0

Yanlış bilgi için üzgünüm, Ngu, mcrypt kullandığımda CBC modunu kullandım. –

+0

Err ... CBC modunu kullanmamıştım ... :-( –

cevap

18

Aslında her iki mcrypt_encrypt() ve mcrypt_decrypt() hem de diğer tr/şifre çözme functons (mcrypt_generic() veya mdecrypt_generic() benzeri) n * <<blocksize>> bir uzunluğa pedi $data parametre yapmak. Dolgu karakteri NUL karakteridir (\x0 veya \0), oysa <<blocksize>> şifrelemeye ve kullanılan blok şifreleme modlarına bağlıdır. Block cipher modes of operation ve Padding (cryptography)'a bir göz atmalısınız.

Aşağıda, makinemdeki kullanılabilir şifreler ve modların her biri için mcrypt_get_block_size() çıktısı verilmiştir. Açıkçası, fonksiyon, CFB, OFB ve CTR gibi modların, uzunlukları blok büyüklüğünün katları olmayan mesajları işlemek için herhangi bir özel önlem gerektirmediğini göz önünde bulundurmaktadır, çünkü bunların hepsi, düz metnin XORing'i ile çalışmaktadır. blok şifresi (Vikipedi'den alıntı). Örneğinizde kullanılan CBC, her zaman şifrelenmeden önce son bloğun doldurulmasını gerektirir.

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 

nedenle size şifre sabit uzunluk blokları üzerinde çalışıyorsa şifre çözme fonksiyonlarının çıkışı orijinal dize almak için rtrim() zorunda: TripleDES benim uygulamasında

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

Bu doğru çözümdür.Çok tırnak işareti kullanmak çok önemlidir ve '\ 0'! – shadowhand

+2

Btw civarında tek tırnaklar yoktur, bu çok olası değildir. "trim (...," \ 0 ")' ü kullanarak sabit bir blok boyutu kullanıldığında bile şifrelenmiş verilerinizi kırmanız gerekir, ancak ikili verileri şifrelediğinizde * mümkündür * – shadowhand

+0

Ben sadece 'trim' kullanarak bir milyon örnek buldum, ama bu bağlamda gerçekten önemli olan bir boşluk oluşturuyordu ve bu yine dünya ile her şey olabilir. Biliyorum, 2 saatlik hata ayıklamadan sonra, ve sonra Bir çözüm ve tüm bunlar – CWSpear

8

, ben deşifre dize bulundu \ 5 veya 6 karakterle dolduruldu. Bu, yukarıda belirtilen \ 0 veya \ 4 karakterleri veya PHP.net örneklerinde görülmedi. Dolgu karakterinin ASCII değerini belirlemek için ord() işlevini kullanın. ord() tek bir karakter üzerinde çalışır, bu nedenle bir dizgeyi ayırmak veya karakter dizisine doğrudan dizi gösterimi ile erişmek için str_split() kullanın - $ string [5].

Nihai kaplama sonucu - trim($decrypt, "\0..\32");

Nihai kod sonucu - İkili veri şifrelemek/şifre çözmek zorunda

$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

Bazı durumlarda, pedin [RFC 5652] (https://tools.ietf.org/html/rfc5652#page-28) 'e göre belirlendiği, karakterin ped için kullanıldığı anlaşılıyor. aslında doldurma miktarını gösterir.Ben sadece hangi algo/mod kombinasyonunu biliyor olsaydım s (veya temelindeki kütüphane sürümleri?) bunu sadece "\ 0" kullanarak yapacak! – grossvogel

4

. Maalesef trim, ikili verileri bozabilir ve boş bir karaktere eşit olan meşru bitleri düzeltebilir.

ikili verilerin boyutunu sağlamak öncesi ve şifreleme sonra aynı, Roket tehlikeli madde taşıyan burada büyük bir yanıt gönderdi: How can I decrypt binary data that ended with NUL characters in PHP?

Özet:

// 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); 

Ben kullanımı konusunda emin değilim CBC karşı ECB ... araştırmanın

+0

Bu, CBC'ye aynı şekilde uygulanır. –

0

24 saatten sonra bir nihayet bu benim için çalıştı:

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

Yanıt kodu, PHP mcrypt'in varsayılan ayarladığı boş OP'lerle çalışmaz ve OP'nin kullandığı durum budur. PKCS # 7/PKCS # 5 dolgu için, doldurmanın geçerli olduğunu bir kontrol edin. Yanlış anahtarı kullanmayı düşünün, $ strPad büyük olasılıkla yanlış olur, potansiyel olarak verilerin uzunluğundan daha büyük bir değer. Ancak kötü bir dolgu hatası döndürmeyin, bu da bir kalıplama kehaneti oluşturma eğilimindedir, bunun yerine sadece hiçbir şey yapmayın. Çoğu kütüphane PKCS # 7 doldurmayı destekler ve şifrelemeye otomatik olarak dolgu ekler ve şifre çözme işleminde daha fazla şey yapılmasına gerek kalmaz. – zaph

İlgili konular