Ahoj.

Riesim problem so sifrovanim v Jave. Aby som popisal situaciu:

Existuje urcity program v C++ s openssl, ktory sifruje a desifruje vstupny subor.

V principe robi to, ze si vygeneruje DES, ktorym zasifruje data a to DES zasifruje nejakym
public RSA a pribali to k datam. Proste klasika.

K tomu existuje implementacia encryptora v Jave, ktory robi to iste.
Mam overene, ze decryptor v c++ si s tym poradi bez problemov.

Fragment encryptora:

// nageneruj des
KeyGenerator keygen = KeyGenerator.getInstance("DESede", "BC");
m_desKey = keygen.generateKey();

// zasifruj des public klucom a zapis na disk
JDKX509CertificateFactory f = new JDKX509CertificateFactory();
X509Certificate cert = (X509Certificate) f.engineGenerateCertificate(pem_file);
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC");
rsaCipher.init(Cipher.ENCRYPT_MODE, cert);
file.write(rsaCipher.doFinal(data));    // zapise 128 byte

... pridaj data a tak dalej ...

Ja som teraz naimplementoval decryptor v Jave ako protikus encryptora a narazil som na nasledovny problem:


// citam zo suboru, z hlavicky som ziskal, ze zasifrovany DES ma 128 byte
byte[] zasifrovane_des = read(128);

// nacitam si z disku privatny kluc
KeyPair kp = readKeyPair(pem_na_disku, password);
PrivateKey pk = kp.getPrivate();

// inicializujem sifru
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC"); // pouzil som to iste co v encoder
rsaCipher.init(Cipher.DECRYPT_MODE, pk);

// desifrujem zabaleny DES
// tu to vrati 24 byte, pokial som zasifroval java encoderom. Pokial som zasifroval c++ encoderom, vrati to 32 byte. // Logicky nasledne dalej v kode leti vynimka "key size greather than 24 byte". // Finta je ale v tom, ze ked tych 32 byte pokusne orezem na 24, tak to funguje.
byte[] desifrovane_des = rsaCipher.doFinal(zasifrovane_des);

// ziskam des z jeho binarnej reprezentacie
SecretKeySpec kspc = new SecretKeySpec(desifrovane_des, 0, desifrovane_des.length, "DESede");
SecretKeyFactory skf = SecretKeyFactory.getInstance("DESede");
SecretKey des = skf.generateSecret(kspc);

// todo desifrujem
// pokial desifrujem data vytvorene c++ encoderom --> java.security.InvalidKeyException: key size greater than 24 bytes
// pokial desifrujem data vytvorene java encoderom --> ok

Exception vyleti len v pripade, ze desifrujem data, ktore vytvoril c++ encoder. Pokial desifrujem
data, ktore som si sam zasifroval, zbehne to ok ( DES ma spravne 24 byte ).
Takisto c++ decoder nema problem desifrovat mnou zasifrovane data.

Chyba spociva v tom, ze pokial pracujem s datami z c++ encodera, rsaCipher.doFinal() mi vrati 32 namiesto 24 byte. Ked som ale natvrdo skusil tych 32 byte orezat na 24 byte, normalne to zafungovalo.
V oboch pripadoch tym rsa dekodujem pole bajtov velke 128 byte.

To vo mne evokuje dojem, ako keby c++ encoder pouzival iny padding alebo nieco v tom zmysle. Zaroven ma ale zaraza, ze
c++ decoder nema problem s mnou zasifrovanymi datami.

Pokusne som si dal v oboch pripadoch vypisovat veci ako getAlgorythm(), getFormat() a podobne.
Boli vzdy identicke.

Zatial som to v rychlosti vyriesil prasackym orezom na 24 byte, ale chcem tomu prist na klb.

( Ono je ale mozne, ze to orezava aj ten povodny c++ decoder a ja o tom vlastne ani neviem, pripadne to openssl riesi za neho).

Nejaky napad kam mam hrabnut aby som tomu prisiel na klb?

--
Diky
D

Odpovedet emailem