By Paranoid
(autorov blog: Hysteria Corner)
Tijekom razvoja jedne aplikacije pojavila se potreba upisivanja osjetljivih podataka iz PHP-a u MS SQL bazu.
Sa jedne strane stajala je aplikacija rađena u C# koja je te podatke uredno spremala i dohvaćala iz MS SQL baze, a sa druge strane bilo je potrebno te podatke samo zapisati u istu tu bazu koristeći PHP tako da se mogu pročitati iz C#-a.
Zvuči jednostavno, zar ne? Kriptirane podatke samo zapišeš iz PHP-a i juriš dalje. E, pa i nije baš ispalo tako.
• • • • •
C# aplikacija koristila je RSA ključeve u XML obliku. Primjer:
<RSAKeyValue>
<Modulus>1234...</Modulus>
<Exponent>ABCD</Exponent>
<P>gibberish...</P>
<Q>even more gibberish...</Q>
<DP>bla bla bla...</DP>
<DQ>...</DQ>
<!-- itd... -->
</RSAKeyValue>
Koliko sam se god trudio (my google-fu sucks) nisam uspio nači niti jednu PHP klasu koja bi napravila nešto smisleno sa tim ključevima.
No, srećom, tu u igru ulazi OpenSSL, svima drag, poznat, pouzdan te podržan na obje tražene platforme (Windows i Linux).
Izradu certifikata i pripadajućih ključeva, te implementaciju sa strane C#-a neću opisivati jer ima preko nekoliko dobrih tutorijala na Internetu. (Primjer: Primjer).
Linkani primjer radi savršeno sve dok se kriptirana vrijednost ne pokuša zapisati u VARBINARY polje u MSSQL bazi.
Zašto? Pogledajmo primjer u C# koji zapisuje nešto u VARBINARY polje:
public byte[] Kriptiraj(String data)
{
UnicodeEncoding ByteConverter = new UnicodeEncoding();
byte[] data = ByteConverter.GetBytes(text);
byte[] enc = null;
using (RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)_certificate.PrivateKey)
{
enc = rsa.Encrypt(data, false);
}
return enc;
}
Podaci koji se namjeravaju kriptirati prvo se konvertiraju u Unicode. U 'defaultnom' slučaju (kao ovom) koristi se UTF-16LE enkoding. rsa.Encrypt vraća ByteArray ili 'po naški' - hex string. Istu konverziju potrebno je napraviti i u PHP-u:
function kriptiraj($plain_data, $public_key)
{
// konverzija u UTF-16LE
$to_crypt = mb_convert_encoding($plain_data, "UCS-2LE");
// $public_key je ključ učitan iz certifikata
// $encrypted_data je 'output' varijabla u koju se sprema rezultat kriptiranja
openssl_public_encrypt($to_crypt, $encrypted_data, $public_key);
// prebacivanje kriptiranih podataka u hex
$enc = unpack("H*hex", $encrypted_data);
// $data sadrži kriptirane podatke u hexu koji se zapisuju u bazu
$data = "0x" . $enc["hex"];
return $data;
}
Kako kriptirane podatke pretvoriti u nešto čitljivo sa strane PHP-a ostavljam kao vježbu čitatelju.
• • • • •
Vezani postovi:
- Postoji li nešto u PHP-u?
- Sun kupio MySQL
- PHP i MSSQL