Vagy én buggyantam meg?
Szervusztok!
Egy Crypt::CBC-vel encrypt-ált adatot feltolok Net::FTP vel majd ezt az adatot szedem le File::Fetch-el direktbe egy string típusú változóba amit szeretnék decryptálni. Az eredeti adat nem áll viszont elő. Elkezdtem piszkálni és érdekes eredményre jutottam.
A vett adatokat ha file-ba írom, majd visszaolvasom minden megjavul. Az md5 összege viszont nem változik!
adat - encrypt - ftp - netSzerver - get - $ciphertext - decrypt - szemét
adat - encrypt - ftp - netSzerver - get - $ciphertext \ / nemA$ciphertextVáltozó - decrypt - adat
file
Az md5 összegeket Digest::MD5-el állítom elő, és az megegyezik a a file írás - olvasás művelet előtt/után.
Itt jutott eszembe hogy valami kódlap váltás zűr lehet talán? Kínosan ügyelve átírok mindent :raw-ra, de semmi.
Próbaképp a letöltést átírtam LWP::Simple::get-re de sajnos ez sem jött be.
Mitől változik meg az adat és hol?
A hozzászólásokat nagyon köszönöm előre is!
vfero
Hozzászólások
ftp bin mode?
Esetleg?!
# Set the transfer mode to binary
$ftp->binary or die "Cannot set binary mode: $!";
Sajnos nem segít.
Ahelyett, hogy hosszú tipp-ellenőrzés-tipp... hurokba bocsátkoznánk, javaslom átnézni ezt, és eszerint próbálkozni még egy kicsit: http://www.perlmonks.org/?node_id=621108
köszönöm, ez is megvolt, a raw mode ismert volt, most a perl -d van terítéken.
Mondjuk a kód ismerete sokat segítene
----
올드보이
http://molnaristvan.eu/
$debug = 0 esetén a kimenet szemét
$debug = 1 esetén értelmes adatot kapok
(a hibakezelés és egyéb részeket szándékosan csonkoltam)
vfero
Na most a leírásban File::Fetch van, itt viszont, LWP::Simple. Mellesleg ez a kód amit ide bepasztáztál strict módban hibával elhasal, lévén $c nem létezik a kontextusában. Azt gonodolnám, hogy amikor változóba töltve próbálod dekódolni a file-t van az adat végén egy új sor karakter, amit beolvasáskor nem olvasol el.
Szerintem nézd meg, van-e a végén új sor karakter.
----
올드보이
http://molnaristvan.eu/
Megpróbáltam, de sajnos nem. md5 szerint is stimmelnek.
Így néz most ki:
Az md5-t hol és hogyan ellenőrzöd?
Nem lehet, hogy már az az ellenőrzés is hibás?
Rég használtam perlt, szóval csak tipp, de mintha azzal a readdel megváltozna a változód hossza.
És ahogy a google találatokat itt félálomban elnézem, a decryptnek mintha nem lenne mindegy, hogy hány bináris nulla van a végén (tévedés joga fenntartva)
A szerveren levő file hash-ével megegyezőt ad vissza.
vfero
Nekem még mindég zavaros a dolog. Amikor még nem tudott a syslog-ng (csak pénzért) titkostott kimenetet csináltam egy logfile titkosito scriptet: https://github.com/kayapo/encryptedlogstore esetleg segit az áttekintése (tudom más annyiban, hogy Crypt::OpenSSL::RSA modullal titkost).
Kódolni és dekódolni a fileokat csak akkora darabonként szabad ami még a cipher chunk méretébe bele fér, ez függ a kódoló eljárásától (de ezt gondolom úgy is olvastad a Crypt doksijában)
Még annyi, hpgy a file tartalmát és a változóban lévő adatot, próbáltad már kiritani a képernyőre?
----
올드보이
http://molnaristvan.eu/
Szia István!
Kösz a tippet, ez is megtörtént már. A perl -d opció ezért lett beletéve. Du. fogok egy új 0-ról megírt példát összeütni, már csak a saját meggyőződésem érdekében is és azt majd felteszem egészben.
Üdv,
vfero
Továbbra is piszkálja a csőröm a téma.
Mondd, meg tudod csinálni, hogy az itt még if($debug)-ként induló blokkban a $ciphertext = $c; előtt binárisan összehasonlítod a $cipertext és a $c értékét?
Kíváncsi lennék, mit kapsz.
(szóval nem az, hogy eltérnek-e, hanem, hogy pontosan miben térnek el - sajnos túl rég használtam perlt, nem emlékszem, ezt mivel lehetne megoldani :( )
Kicsontoztam, de az most működik. Még nem tudom hogy mi a különbség, ami elrontja, de jelentkezem majd még. Most alszom, csak utána rágódok a gumicsonton. :S
Addig is köszönöm mindenkinek!
Szerintem te ezt tűlspiráztad, nekem a lentebbi kód gond nélkül megy:
A file tartalma egy %h nevű hash abban meg egy vicc van.
----
올드보이
http://molnaristvan.eu/
Ez így igaz, de megpróbálom majd visszatenni a kivett dolgokat, és eldönteni, hogy mi rontja el.
Csak szép sorjában git -el mentegetve.
Majd ne felejtsd el megírni a megoldást (már, hogy mit írtál el ;) )
----
올드보이
http://molnaristvan.eu/
Igen, ez van folyamatban, tegnap még nem volt eredményem. Belső embereknek is mutattam már, hát ...
A probléma, hogy az LWP::Simple get() függvénye a karakterkódolás figyelembe vételével adja vissza a tartalmat, miközben Te bináris fájlt töltesz le, de nem application/octet-stream Content-Type-pal.
Ehelyett ha saját magad használod az LWP-t, akkor megoldható, hogy a Content-Type charsetet ne vegye figyelembe:
use LWP::UserAgent;
sub get {
my ($url) = @_;
my $ua = LWP::UserAgent->new;
$ua->timeout(10);
$ua->env_proxy;
my $response = $ua->get($url);
if ($response->is_success) {
return $response->decoded_content(charset => 'none');
}
else {
die $response->status_line;
}
}
Szép amit írsz, de végigolvastad a sztorit?
Ha fogja, kirakja egy fájlba, majd onnan visszaolvassa, akkor _állítólag_ jól működik.
Ezt nem igazán lehet azzal magyarázni, amit te írtál... ha jól sejtem.
Ha már így kérded, igen, végigolvastam.
Ha részletesebb magyarázatot szeretnél, akkor íme:
Az LWP::Simple szintén az LWP-t használja, a választ tartalmazó HTTP::Response objektum a decoded_content() függvényével adja vissza a letöltött tartalmat. A decoded_content valójában a HTTP::Message modulban van megvalósítva. A kapott választ a Content-Type válaszfejlécben szereplő karakterkódolással, annak hiányában alapértelemezetten a "natív" "ISO-8859-1" kódolással értelmezi és ha van benne az \x00-\x7f tartomány kívül is karakter, akkor az utf8::upgrade függvénnyel alakítja a perl belső unicode string formátumára.
A mi esetünkben a letöltött tartalom bináris, szinte biztosan van benne 7 biten kívül eső karakter, ezért szinte biztosan unicode stringként kapjuk vissza (hint: Encode::is_utf8 függvénnyel tesztelhető). Amikor :raw módoban fájlba írjuk ki, akkor a unicode string visszaalkításra kerül egyszerű ISO-8859-1 kódolt bájtszekvenciává. Utána ezt a bájtszekvenciát :raw módoban olvassuk vissza, akkor már nem unicode stringet kapunk eredményül, hanem megmarad egyszerű bájtszekvenicaként, ISO-8859-1 stringként.
A Crypt::CBC decrypt függvénye kapott adatot pack() függvénnyel és "a" templatetel alakítja paddolt bájt blokkokká. Ha unicode stringet kap paraméterül, akkor a pack "a" templateje csak az alsó 8 bitjét veszi figyelembe az egyes unicode karaktereknek és csak ezeket használja adatként a kódoláshoz. Ha viszont korrektül a bájtszekvenciát kapja meg, akkor a unicode karakterek UTF-8 bájtszekvenciáját kódolja el.
Ezért lényeges, hogy kódoláshoz sose használjunk perles unicode stringet, hanem mindig csak szigorúan bájtszekvenciát (a kívánt kódolás mellett). Bináris adatot pedig végképp szerencsétlen unicode stringként tárolni, hiszen nincsen és sosem volt karakterkódolása, ami alapján értelmezni lehetett volna benne a karaktereket (hát hacsaknem tényleg a latin1/iso-8859-1). Ezért javasolom, hogy kényszerítsük az LWP tartalomnál a karakterkódolás ignorálását és kérjük szépen csak vissza a kapott bájtsorozatot, hiszen valójában erre van szükségünk. Utána már ennek a decryptálása is helyes lesz.
Félreértesz, attól tartok: egy egyszerű fájlba írás, majd visszaolvasás mi olyat tehet az itt látható formájában, amitől megváltozna a kiírt, beolvasott adat?
Mondom, a kíírás elött még megvan neki a perles unicode flagje és a perl belső unicode ábrázolásában van tárolva. A :raw kiírás fájlba ezt ISO-8859-1-es kódlap szerinti bájtszekvenciává alakítja és ez kerül bele a fájlba. A :raw visszaolvasásnál már nem unicode string lesz az visszaolvasott string, hanem megmarad egyszerű bájtszekvenciaként (unicode flag nélkül).
A pack függvény másképp kezeli a unicode string (tehát perles unicode flag aktív, több bájtos karakterekből áll a string) karaktereit, meg a nem unicode string (perles unicode flag nem aktív, egyszerű bájszekvencia) karaktereit (ezek egyszűen bájtszekvenciák egyes bájtjai).
Az Encode::is_utf8 függvénye megmondja egy stringről, hogy az a perl belső unicode ábrázolásában van tárolva, vagy egyszerű hagyományos bájtszekvenciaként.
A perl ráadásul a unicode stringet különböző I/O műveleteknél beállításoktól függően konvertálja valamilyen karakterkódolás szerinti bájtszekvenciává (ez lehet ISO-8859-1, de akár UTF-8 is). Ha Te expliciten nem alakítod bájtszekvenciává, vagy nem sikerült a perlt megfelelően beállítanod, hogy automatikusan megfelelően végezze el az átkódolást, akkor érdekes és kellemetlen meglepetésekben lehet részed.
Input műveleteknél érdemes a stringeket az input kódolásáról a perl belső unicode formátumára alakítani, míg kiírásnál pedig érdemes a kívánt kódolás szerinti bájtszakvenciává alakítani és azt kiírni. Egyes bináris adatokon végzett műveleteknél (hashes, titkosítás) szintén javasolt a kívánt kódolás szerinti bájtszekvenciává alakítani a stringet és azon elvégezni a műveletet, különben eléggé undefined lesz az eredmény. Lásd a topic problémáját.
A get() hívás után a következő sor használata is helyrehozza a stringet, de azért ez csak hack, nem szerencsés megoldás:
use Encode qw(encode is_utf8);
$ciphertext = encode('ISO-8859-1', $ciphertext) if is_utf8($ciphertext);
Mennyit szivott mar a vilag a sok fajta kodolasi szabvany miatt :) (sub)
+1
Szervusztok!
Köszönöm mindenkinem a munkáját, azt hiszem lehet benne valami amit Xanco írt!
Külön köszönöm a szabatos magyarázatot is, idővel talán meg is fogom érteni. ;)
Az adat folyamot base64-re módosítottam, és így kerül fel, majd vissza. Ez így már az eredeti környezetben is elsőre megy hiba nélkül.
A javasolt ISO-8859-1 átkódolás is működik, de ez valóban erősnek tűnik.
Kösz +1x!
Páka,
vfero