13
Tags:
php
sikkerhed
kryptering
Skrevet af
Bruger #2695
@ 22.04.2012
Introduktion
Sidste artikel handlede om symmetrisk kryptografi, også kendt som secret key kryptografi, og det næste logiske skridt er asymmetrisk kryptografi også kendt som public key kryptografi.
Med asymmetrisk kryptografi skal afsender og modtager blive enige om en nøgle, som de vil bruge i deres hemmelige kommunikation. Er afsender og modtager den samme (f.eks. hvis vi vil kryptere vores egne data, så kun vi selv kan læse dem), er det intet problem, men hvis nu vi vil kommunkere sikkert med vores bank eller en samarbejdspartner på den anden side af jorden, så har vi et problem.
Sender vi nøglen over internettet, så passerer den forbi en masse routere og gateways. Kan vi stole på, at vores internet service udbyder ikke lytter med ? Hvad med hackerne, som måske har adgang til systemerne ?
Det svarer lidt til at vi råber nøglen til modtageren på den anden side af gaden. Alle i nærheden kender nu nøglen.
Heldigvis har nogen kloge hoveder fundet matematiske operationer, som gør det muligt at kryptere med én nøgle og dekryptere med en anden. Jeg og min samarbejdspartner finder altså hver vores eget personlige nøglepar, og så udveksler vi de offentlige nøgler, så jeg kender min partners offentlige nøgle, og han kender min.
Det gør resten af verden så måske også, men de kan kun bruge den til at kryptere med. Vi skal holde den anden halvdel, altså nøglen som kan dekryptere, hemmelig. Faktisk findes der servere, hvor man kan lægge sin offentlige nøgle, så andre let kan finde den. Min nøgle kan I finde her:
http://pgp.mit.edu:11371/pks/lookup?op=vindex&search=0xCC331E8AC16A1996I kan kryptere med den, men kun jeg har den tilhørende private nøgle, så ingen andre end mig kan dekryptere dataene.
Public key kryptografi
Public key kryptografi gør det altså nemmere at udveksle nøgler, men har vi så stadig brug for secret key algoritmerne ?
Det har vi i høj grad, for public key algoritmerne har deres svagheder, nogle af dem er:
* Krypterede data kommer til at fylde mere
* Algoritmerne er betydeligt langsommere end private key
Grundet ovenstående svagheder bruger man faktisk ikke public key algoritmerne til at kryptere data. Man bruger dem til at kryptere nøgler.
Hybride kryptosystemer
Et hybridt kryptosystem benytter sig af både public key og secret key algoritmerne. Når man skal beskrive, hvordan kryptosystemer virker, bruger man ofte de tre fiktive personer Alice, Bob og Eve.
Alice og Bob vil kommunikere hemmeligt med hinanden, og Eve kan lytte med.
1) Alice opretter et nøglepar og sender Bob sin offentlige nøgle.
2) Bob genererer en tilfældig hemmelig nøgle.
3) Bob krypterer denne nøgle med Alices offentlige nøgle og sender den til hende
4) Alice dekrypterer den hemmelige nøgle med sin private nøgle.
5) Alice og Bob kender nu begge den hemmelige nøgle og bruger den fremover sammen med en secret key algoritme til at kommunikere hemmeligt
Da Bob sendte den krypterede nøgle til Alice, stod Eve i nærheden og lyttede med, så hun har også en kopi, men hun har ikke adgang til Alices private nøgle, så hun kan ikke dekryptere den.
På denne måde kan vi udnytte de forskellige algoritmers fordele og undgå deres ulemper. Var der flere parter, som skulle være med i den hemmelige samtale, så kan de alle sende deres offentlige nøgle til Bob, som så kunne sende dem hver den samme hemmelige nøgle krypteret med deres egen offentlige nøgle.
Der findes adskillige public key algoritmer, men jeg vil fokusere på RSA algoritmen, og denne gang bruger vi OpenSSL funktionerne.
Generering af nøglepar
Vi skal have lavet et nøglepar, som vi skal have gemt til senere brug, men først et ord om nøglestørrelser.
I sidste artikel sagde jeg, at 256 var en meget stor nøgle, og det er det også for symmetriske algoritmer, for der kan alle bitmønstre bruges og derfor er der 2 opløftet i 256 forskellige nøgler (et ét tal med 77 nuller). Sådan er det ikke for asymmetriske algoritmer. Asymmetriske algorimter bruger ikke et arbitrært bitmønster som nøgle men store tal med særlige egenskaber. En RSA nøgle består af tre meget store tal, som er fundet ved at udføre nogle matematiske operationer på to store primtal. Ikke alle tal kan bruges, og derfor skal asymmetriske nøgler være meget større for at give den samme sikkerhed. Ifølge firmaet "RSA Security" svarer en 1024 bit RSA nøgle til en 80 bit symmetrisk nøgle, og vi skal helt op på en 15360 bit RSA nøgle for at få samme sikkerhed som en 256 bit symetrisk nøgle.
Men jo større nøglen er, desto længere tid tager det at generere den og kryptere med den, og de krypterede data kommer også til at fylde mere.
2048 bits burde ikke kunne brydes før år 2030, men gå efter 4096 for en sikkerheds skyld. I resten af artiklen bruger jeg 1024 fordi det giver kortere filer.
- <?php
- //Filename: create_keypair.php
- if (count($argv) < 3) {
- echo "Usage: php " . $argv[0] . " <password> <keyfile>\n";
- } else {
- //Vores private nøgle krypteres med en symmetrisk algoritme,
- //og dette password bruges til at generere en nøgle
- $password = $argv[1];
- //Vi gemmer den private nøgle krypteret i denne fil
- $outfile = $argv[2];
- //Den offentlige nøgle gemmes i en fil af samme navn men med '.pub' appended
-
- //Vi genererer en 1024 bit RSA nøgle
- $private_key = openssl_pkey_new(array(
- 'private_key_bits' => 1024,
- 'private_key_type' => OPENSSL_KEYTYPE_RSA
- ));
-
- if ($private_key) {
- //Eksportér nøglen krypteret til $outfile
- openssl_pkey_export_to_file($private_key, $outfile, $password);
- //Hent detaljer (incl. public key) ud af den private nøgle
- $details = openssl_pkey_get_details($private_key);
- //Skriv den offentlige nøgle til en fil
- file_put_contents($outfile . '.pub', $details['key']);
- }
- }
- ?>
Vi prøver det af:
$ php create_keypair.php
Usage: php create_keypair.php <password> <keyfile>
$ php create_keypair.php 'very secret' my_key
$ cat my_key.pub
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDL1VsJlS0NwmG20SIHRN1pdZbw
bGPXIhGlnEVvB0Mh5GcJ1DFixteXVGqf6jpSSl6473mlOuxywAeFPvbcyuHm0p1v
ePxD0gr8z27Di/FkLdja9dZam2/jaMyEq606V/OdQnbEglSlEBc/u2kFr6aNojVX
QYc+trW6sXiue6QQMQIDAQAB
-----END PUBLIC KEY-----
$ cat my_key
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,389A90AD7AD03FE7
jQ9OCvItCuTThNHhq+pgqkarXyjyHt46aKI/zwaUlmf4Jj0qMH2LSVeFqUXjjHsv
i4IicLFZT0vPvIa37j/H5rnoLVIAp+l7jClYWxATmy9voFXo06ZJiBYnw9dVOQLK
Cr+QS71Vbi0pexWP8h9+O5nmBqIW6m3AZfSkJKIALjFolrxogIZEno6CCffQZp/B
P+VuJhHdasjhbUQXq62JRUSge+SXp3S5SPU6D/Co3G/cT4oqGYhiEY5f9HGeVlKq
gR/Q+mKTSWR9gJ3YqxmKUtvo+/GdkDTFv5HlKq012rT3mJHcuok79CP5/J7pLVtc
fjJSySHXANJodnyCZPPUMYeX9XKxuAvGIDVndB8wCb7nqmAw/g8oV7PYFQoAPuMb
/gdrdUyozQbGWwe4m16HdLgHOutWPYpWkcoeXi/uRsmG/VNURnrdAqGeN1sMeQeh
k5mP8wTsEth7NWdPQgoI13q2tYuMNdTEJpvbHaAeemk1cFR1yy4d361q5WMHQHZo
U61QDTiPmRTsNmrOWaOizRHhdWkbbOliEfmd99MUsxY2Qa04t0MRpAHK6IgDrEWK
Km7GtN8S0ESeMB3hlGdEx8E6kv+C2qtniY3yocB4YfcHLxZiA015jcXttBtuXcyc
hPK6cu58oicVPyM3xgc9L/q0HlAmLDdF4vzxSQxp0o9RZCDG6M2Sk1DHlKDia4Db
SC5x5uSEpRAv3vV4/BLYVXwaZT32GtOM0VGn7J8LmMjU19HEckwF29zIVRJXhEfM
irgoiFmlxwa8Zd0Ei6/6gvW7phLHhUjNYUPyGoVNL8C+Ksjc7laWiw==
-----END RSA PRIVATE KEY-----
Nu har vi noget, vi kan arbejde med, så lad os finde ud af, hvordan man krypterer. Send bare din offentlige nøgle fil ud til højre og venstre, men hold den private fil væk fra offentligheden.
Kryptering med RSA
Som sagt krypterer man ikke data med RSA, man krypterer nøgler. OpenSSL har funktionen 'openssl_public_encrypt' til at kryptere med en public key. Vi kan så selv generere en tilfældig 256 bit nøgle, kryptere data med den og en selvvalgt algoritme, kryptere den hemmelige nøgle med vores RSA nøgle og så til sidst gemme de krypterede data sammen med den krypterede nøgle.
Hvis ikke vi har for megen data, som skal krypteres, så kan OpenSSL gøre det meste for os med funktionen 'openssl_seal'. Den skal have alle de data, som skal krypteres. Så genererer den en nøgle, krypterer dataene med denne nøgle og RC4 algoritmen og giver os den hemmelige nøgle krypteret med RSA nøglen (den kan endda tage flere RSA nøgler).
Den er bare ikke så brugbar, hvis vi skal kryptere en stor fil, for det hele skal være i hukommelsen på én gang...både den krypterede og den ikke krypterede version, så vi klarer os selv. Det lærer vi også mest af:
- <?php
- //Filename: rsa_encrypt.php
- if (count($argv) < 4) {
- echo "Usage: php " . $argv[0] . " <infile> <outfile> <public keyfile>\n";
- } else {
- //Vi åbner filen, som skal krypteres
- if ($in_file = fopen($argv[1], 'r')) {
- //Vi åbner filen, som vi skal skrive til
- if ($out_file = fopen($argv[2], 'w')) {
- //Og vi indlæser indholdet af nøglefilen
- if ($key_content = file_get_contents($argv[3])) {
- //Generer et OpenSSL RSA public key objekt
- if ($public_key = openssl_pkey_get_public($key_content)) {
- //Generer en tilfældig 256 bit nøgle til symmetrisk kryptering af filen
- $safe = true;
- if ($random_key = openssl_random_pseudo_bytes(256 / 8, $safe)) {
- //Krypter denne nøgle med den offentlige nøgle
- if (openssl_public_encrypt($random_key, $encrypted_key, $public_key)) {
- //Base64 enkod nøglen så vi kan udlede den fra filen igen
- $base64 = base64_encode($encrypted_key);
- fputs($out_file, $base64 . "\n");
-
- //Generer et RC4 krypto objekt
- $rc4 = mcrypt_module_open(MCRYPT_ARCFOUR, '', MCRYPT_MODE_STREAM, '');
- //Initialiser rc4 objektet med den tilfældige ukrypterede nøgle
- mcrypt_generic_init($rc4, $random_key, '');
-
- //Læs indhold af fil som skal krypteres
- while ($str = fread($in_file, 1024)) {
- //Krypter data
- $encrypted = mcrypt_generic($rc4, $str);
- //Skriv data til fil
- fwrite($out_file, $encrypted);
- }
- //Befri ressourcer holdt af vores RC4 objekt
- mcrypt_generic_deinit($rc4);
- mcrypt_module_close($rc4);
- }
- }
- }
- }
- fclose($out_file);
- }
- fclose($in_file);
- }
- }
- ?>
Det var komplekst, men det virker:
$ cat plaintext
Dette er vores meget hemmelige data. De må endelig ikke falde i fjendens hænder!!!
$ php rsa_encrypt.php
Usage: php rsa_encrypt.php <infile> <outfile> <public keyfile>
$ php rsa_encrypt.php plaintext encrypted my_key.pub
$ xxd encrypted
0000000: 4341 3161 7458 7364 2b38 3653 2b4a 527a CA1atXsd+86S+JRz
0000010: 3869 7a76 5755 6663 5450 6962 4256 384c 8izvWUfcTPibBV8L
0000020: 5954 6b64 4859 374a 4971 4748 5a4e 3979 YTkdHY7JIqGHZN9y
0000030: 386e 7230 5367 414e 5a76 7175 3372 3238 8nr0SgANZvqu3r28
0000040: 376c 6f32 4654 526b 416f 3233 4534 6b50 7lo2FTRkAo23E4kP
0000050: 4261 6a4a 4553 6872 716a 2f43 3650 754f BajJEShrqj/C6PuO
0000060: 7634 7151 6949 484f 6151 435a 6c7a 4a77 v4qQiIHOaQCZlzJw
0000070: 797a 562f 6737 6938 614e 7a35 7778 4351 yzV/g7i8aNz5wxCQ
0000080: 7a34 482f 7a6a 484a 306f 7676 694c 694b z4H/zjHJ0ovviLiK
0000090: 6370 496a 2b67 3277 5969 2b48 676a 384b cpIj+g2wYi+Hgj8K
00000a0: 762b 6c71 7a77 746c 6964 383d 0ae9 ea3c v+lqzwtlid8=...<
00000b0: 53b4 a6c4 ec43 acb5 7a4e 990a 4fcd fc0e S....C..zN..O...
00000c0: fb57 130e 480e 34c4 6b1e 54b0 7ed5 2297 .W..H.4.k.T.~.".
00000d0: f139 3376 4501 cd1a 9185 06ef dca2 2c3d .93vE.........,=
00000e0: 7809 78e1 ae2f 0662 d728 7fb8 d42f 8d98 x.x../.b.(.../..
00000f0: 1f1b bc2d 00c6 d954 f959 638a f2ee 68cc ...-...T.Yc...h.
0000100: 7130 q0
Det første, som ligger i 'encrypted' er en base64 enkodet version af den RSA krypterede hemmelige nøgle, som kan dekryptere den sidste del, som er de egentlige data.
Lad os se om vi kan dekryptere det.
Dekryptering med RSA
Dekryptering er det modsatte af krypteringen, så nu skal vi have fat i vores private key. 'openssl_seal' har et modstykke, som hedder 'openssl_open', men igen skal den have al den krypterede data i hukommelsen på én gang, så vi går manuelt frem.
Først skal vi læse første linje fra filen, som indeholder den base64 enkodede streng. Den skal base64 dekodes, og resultatet skal vi forsøge at dekryptere med RSA og vores private nøgle.
Lykkes det kan vi dekryptere resten af filen med RC4. Det gør vi således:
- <?php
- //Filename: rsa_decrypt.php
- if (count($argv) < 5) {
- echo "Usage: php " . $argv[0] . " <infile> <outfile> <private keyfile> <private key password>\n";
- } else {
- //Vi åbner filen, som skal dekrypteres
- if ($in_file = fopen($argv[1], 'r')) {
- //Vi åbner filen, som vi skal skrive til
- if ($out_file = fopen($argv[2], 'w')) {
- //Og vi indlæser indholdet af nøglefilen
- if ($key_content = file_get_contents($argv[3])) {
- //Generer et OpenSSL RSA private key objekt
- if ($private_key = openssl_pkey_get_private($key_content, $argv[4])) {
- //Læs første linje fra filen
- $base64 = fgets($in_file);
- //Base64 dekod den.
- $encrypted_key = base64_decode($base64);
- //Nu har vi nøglen som blev krypteret med vores public key. Dekrypter den.
- if (openssl_private_decrypt($encrypted_key, $random_key, $private_key)) {
- //Generer et RC4 krypto objekt
- $rc4 = mcrypt_module_open(MCRYPT_ARCFOUR, '', MCRYPT_MODE_STREAM, '');
- //Initialiser rc4 objektet med den tilfældige nøgle
- mcrypt_generic_init($rc4, $random_key, '');
-
- //Læs krypteret fil
- while ($encrypted = fread($in_file, 1024)) {
- //Dekrypter læst data
- $decrypted = mcrypt_generic($rc4, $encrypted);
- //Skriv dekrypterede data
- fwrite($out_file, $decrypted);
- }
- //Befri ressourcer holdt af vores RC4 objekt
- mcrypt_generic_deinit($rc4);
- mcrypt_module_close($rc4);
- }
- }
- }
- fclose($out_file);
- }
- fclose($in_file);
- }
- }
- ?>
Og det virker:
$ php rsa_decrypt.php
Usage: php rsa_decrypt.php <infile> <outfile> <private keyfile> <private key password>
$ php rsa_decrypt.php encrypted decrypted my_key 'very secret'
$ cat decrypted
Dette er vores meget hemmelige data. De må endelig ikke falde i fjendens hænder!!!
Fantastisk!!!
Til at dekryptere skulle vi bruge vores password, for den private nøgle var jo også krypteret. Det er en ekstra sikkerhed, hvis vores nøglefil skulle falde i de forkerte hænder, så skal de stadig bryde noget kryptering for at få fat i den egentlige nøgle.
Afslutning
Det var så en introduktion til asymmetrisk kryptografi. Det er blevet komplekst, men jeg håber, at det var til at finde ud af.
Public key kryptering kan bruges til mere end vi har dækket her, bl.a. digitale signaturer og det bliver så emnet for næste artikel.
Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.
Del også gerne artiklen med dine Facebook venner:
Kommentarer (0)
Du skal være
logget ind for at skrive en kommentar.