17
Tags:
php
sikkerhed
kryptering
digital
signatur
Skrevet af
Bruger #2695
@ 24.04.2012
Indledning
I sidste artikel genererede vi et nøglesæt til brug i public key kryptografi. Det var ret komplekst, men vi løste problemet med udveksling af nøgler. Vi kan udlevere vores offentlige nøgle til alt og alle, så kan alle bruge den til at kryptere med, og kun jeg (indehaveren af den tilhørende private nøgle) kan dekryptere.
Men det virker faktisk også den anden vej. Jeg kan kryptere data med min private nøgle, og så kan kun den tilhørende offentlige nøgle dekryptere dem. Eller sagt på en anden måde, hvis min offentlige nøgle kan dekryptere noget data, så er det med garanti min private nøgle, som har krypteret dem.
Men hvad er meningen med det ? Hvorfor kryptere noget, som hele verden kan dekryptere ?
Svaret er digital signatur.
Digital signatur
Public key kryptografi sikrer privat kommunikation, som vi så i sidste artikel, men det kan også sikre autenticitet og integritet. Men hvad er det ?
Når vi ønsker at overføre penge i banken, så får vi et stykke papir, som vi skal skrive under på. Det er meget svært at efterligne min håndskrift, og derfor sikrer min underskrift (til en vis grad), at det er mig, som har accepteret denne overførsel.
Jeg kan altså ikke komme tilbage dagen efter og hævde, at det er sket uden min vilje. Min bankrådgiver kan heller ikke bare gennemføre overførslen uden min medvirken, for så mangler han min underskrift. Det kaldes autenticitet.
Integritet er et andet problem. På sedlen fra banken står der, at jeg vil overføre 100 kr., og det har jeg skrevet under på. Men hvad hvis bankmanden efterfølgende sætter to-tre nuller på ?
Jeg får en kopi af overførslen med min underskrift på, og der står 100 kr. på min kopi. Det vil være svært at tilføje nullerne, og det sikrer (til en vis grad) integritet.
Det ville være rart, hvis vi havde samme muligheder, når vi laver en overførsel over internettet eller handler i en netbutik, men det kan vi også.
Vi udfærdiger bare en "kontrakt"...et dokument, som beskriver vores forbligtelser. Det kunne være følgende tekstfil:
Jeg, Robert Larsen, lover hermed at skrive et sæt artikler om kryptografiske artikler i PHP til Udvikleren.dk
Den fil kan enhver lave, og jeg kan derfor ikke holdes ansvarlig for dens indhold. Men nu har jeg tænkt mig at signere den med min private nøgle, som jeg lavede i sidste artikel.
Signering
Når vi signerer noget data digitalt, så krypterer vi det altså med vores private nøgle. Hvis min offentlige nøgle kan dekryptere det tilbage til de oprindelige data, så er det med sikkerhed mig, der har krypteret dem, og ingen har ændret på de oprindelige data, for så ville de to versioner ikke være éns.
Men hvis nu det er meget store mængder data, som skal signeres...måske et videooptaget vidneudsagn, så vil det tage meget lang tid.
Derfor signerer vi ikke selve dataene men istedet et hash af dataene. Det kan vi med følgende script:
- <?php
- //Filename: rsa_sign.php
- if (count($argv) < 4) {
- echo "Usage: php " . $argv[0] . " <file to sign> <private key file> <password>\n";
- } else {
- if (file_exists($argv[1])) {
- //Først indlæser vi den private nøgle
- if ($private_key_data = file_get_contents($argv[2])) {
- //Generér et public key objekt af nøgledataene
- if ($private_key = openssl_pkey_get_private($private_key_data, $argv[3])) {
- //Beregn en SHA256 hash for filen som skal signeres
- //Vi skal bruge den binære værdi så tredje argument
- //er 'true' denne gang
- if ($hash = hash_file('sha256', $argv[1], true)) {
- //Kryptér denne hash med vores private nøgle
- if (openssl_private_encrypt($hash, $encrypted, $private_key)) {
- //Udskriv den base64 enkodede signatur
- echo base64_encode($encrypted) . "\n";
- }
- }
- }
- }
- }
- }
- ?>
Jeg signerer løftet:
$ cat løfte
Jeg, Robert Larsen, lover hermed at skrive et sæt artikler om kryptografiske artikler i PHP til Udvikleren.dk
$ php rsa_sign.php
Usage: php rsa_sign.php <file to sign> <private key file> <password>
$ php rsa_sign.php løfte my_key 'very secret' > signatur
$ cat signatur
ahAwrLYfPBkrEmOVkV70DLF94B0nMhE7Xtopedhf7+KL7DnBwfaV6Bz7/QJPq6OCyGmTSkYuWfBEAUBIxDn3P1mvE52Jn4OcvXU/836zM97uiiTSbXm3NdWl47E4uxd3UfY3ZWeJzMJScWkuSxFSxtHoHKjUQ0NveqEStBFC88E=
Signaturen er her længere end den oprindelige fil, men det er små størrelser, vi arbejder med. En 10GB fil ville ikke generere en større signatur, for det er jo en hash, som vi har krypteret. En større privat nøgle ville derimod give en større signatur.
Men vi skal også kunne verificere signaturens ægthed.
Verifikation
Når vi skal verificere signaturen, skal vi bruge den signerede fil (løfte filen), selve signatur filen og min offentlige nøgle.
Vi skal starte med at indlæse signaturen, som skal base64 dekodes og til sidst dekrypteres.
Vi skal også producere et hash af løftet, og til sidst skal vi tjekke, om dette hash og den dekrypterede signatur matcher hinanden.
Hvis ikke de gør det, så kan vi ikke stole på signaturen. Enten er det ikke den private nøgle, som modsvarer vores offentlige nøgle, som har signeret dataene, eller også er dataene blevet modificeret efter, at jeg har signeret dem.
Et script til at verificere kunne se således ud:
- <?php
- //Filename: rsa_verify.php
- if (count($argv) < 4) {
- echo "Usage: php " . $argv[0] . " <file to verify> <public key file> <signature file>\n";
- } else {
- if (file_exists($argv[1])) {
- //Indlæs public key data
- if ($public_key_data = file_get_contents($argv[2])) {
- //Generér et public key objekt
- if ($public_key = openssl_pkey_get_public($public_key_data)) {
- //Indlæs signaturen
- if ($base64_sig = file_get_contents($argv[3])) {
- //Base64 dekod
- if ($signature = base64_decode($base64_sig)) {
- //Dekrypter signaturen med den offentlige nøgle
- if (openssl_public_decrypt($signature, $decrypted, $public_key)) {
- //Beregn SHA256 hash
- if($hash = hash_file('sha256', $argv[1], true)) {
- //Sammenlign
- if ($hash === $decrypted) {
- echo "Good signature\n";
- } else {
- echo "Bad signature\n";
- }
- }
- }
- }
- }
- }
- }
- }
- }
- ?>
Og vi tjekker:
$ php rsa_verify.php
Usage: php rsa_verify.php <file to verify> <public key file> <signature file>
$ php rsa_verify.php løfte my_key.pub signatur
Good signature
Det stemmer...jeg kan ikke løbe fra, at jeg har signeret denne fil.
Brug af digitale signaturer
Digitale signaturer bruges ikke kun til indgåelse af aftaler. De kan være en integreret del af sikre netværksprotokoller.
Der findes mange typer af angreb på netværk, som digital signering kan beskytte imod, som f.eks. TCP session hijacking. Der signerer man alle data, som sendes til serveren og serveren signerer alle data, som sendes til klienten. Den modtagende side kan så tjekke signaturen, og ved dermed, at det er den rigtige man kommunikerer med.
Ovenstående kræver dog noget mere, som vi ikke har dækket endnu, så næste artikel kommer til at handle om certifikater, PKI og web of trust.
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.