Hem » Handbok » OpenSSL – PHP

OpenSSL – PHP

OpenSSL är en tilläggsmodul för PHP som ger stöd för användning av Secure Sockets Layer (SSL) och Transport Layer Security (TLS) i PHP-applikationer. SSL och TLS är säkerhetsprotokoll som används för att säkra kommunikation över en nätverksanslutning, till exempel när man använder webbtjänster eller e-post.

Med OpenSSL-modulen kan PHP-applikationer skapa och hantera säkra anslutningar, verifiera digitala certifikat, kryptera och dekryptera data och utföra andra säkerhetsrelaterade uppgifter. OpenSSL-modulen används ofta för att skapa säkra webbtjänster som kräver inloggning eller hanterar känslig information, till exempel e-handelssajter och banktjänster.

Den äldre tekniken för att kryptera data genom Mcrypt har ersatts av OpenSSL som nu gör det på ett säkrare sätt.

OpenSSL är aktiverat som standard i de flesta moderna PHP-versioner om inga andra ändringar har gjorts. Det gör att ditt webbhotell bör ha stöd för tilläggsmodulen utan att du behöver aktivera något.

Skapa en säker anslutning med OpenSSL

Här är ett exempel i PHP om hur du använder OpenSSL för att skapa en säker anslutning och hämta data.

<?php

// Ange serveradressen och porten för anslutningen
$server = 'ssl://example.com';
$port = 443;

// Skapa en ny anslutning
$conn = stream_socket_client($server . ':' . $port, $errno, $errstr, 30);

if (!$conn) {
    // Visa ett felmeddelande om anslutningen misslyckades
    echo "Anslutningen misslyckades: $errstr ($errno)";
} else {
    // Anslutningen lyckades, skicka en förfrågan till servern
    fwrite($conn, "GET / HTTP/1.0\r\n\r\n");

    // Läs svaret från servern och skriv ut det
    echo stream_get_contents($conn);

    // Stäng anslutningen
    fclose($conn);
}

?>

I det här exemplet skapas en säker anslutning till en server med hjälp av stream_socket_client-funktionen. Anslutningen är säker eftersom protokollet ”ssl://” används i serveradressen. Du kan ändra protokollet till ”tls://” för att skapa en säker anslutning med TLS.

Efter att anslutningen har skapats kan du skicka förfrågningar till servern och läsa svaren genom att använda funktionerna fwrite och stream_get_contents. När du är klar med anslutningen kan du stänga den med fclose.

Även om inga funktioner direkt kopplade till OpenSSL används i exemplet ovan så innebär ssl-protokollet dock att PHP tvingas använda det bakom kulisserna för att hantera anslutningen.

Verifiera certifikat med OpenSSL

För utöka säkerheten i en anslutning kan du verifiera certifikatet i anslutningen och koden skulle då kunna se ut enligt följande.

<?php

// Ange serveradressen och porten för anslutningen
$server = 'ssl://example.com';
$port = 443;

// Skapa en ny anslutning
$conn = stream_socket_client($server . ':' . $port, $errno, $errstr, 30);

if (!$conn) {
    // Visa ett felmeddelande om anslutningen misslyckades
    echo "Anslutningen misslyckades: $errstr ($errno)";
} else {
    // Hämta det digitala certifikatet för servern
    $cert = stream_context_get_params($conn)['options']['ssl']['peer_certificate'];

    // Verifiera certifikatet med hjälp av OpenSSL-funktionen openssl_x509_checkpurpose
    $result = openssl_x509_checkpurpose($cert, X509_PURPOSE_ANY, array('CAfile' => '/path/to/ca_bundle.crt'));

    if ($result) {
        // Certifikatet verifierades, skicka en förfrågan till servern
        fwrite($conn, "GET / HTTP/1.0\r\n\r\n");

        // Läs svaret från servern och skriv ut det
        echo stream_get_contents($conn);
    } else {
        // Certifikatet verifierades inte, visa ett felmeddelande
        echo "Certifikatet verifierades inte.";
    }

    // Stäng anslutningen
    fclose($conn);
}

?>

I det här exemplet hämtas det digitala certifikatet för servern med hjälp av stream_context_get_params-funktionen. Certifikatet verifieras sedan med hjälp av OpenSSL-funktionen openssl_x509_checkpurpose, som tar certifikatet som argument och jämför det med ett giltigt certifikat som finns i filen ”ca_bundle.crt”.

Om certifikatet verifieras kan du skicka förfrågningar till servern och läsa svaren på samma sätt som i det förra exemplet. Om certifikatet inte verifieras visas ett felmeddelande och anslutningen stängs.

Detta är ett bra sätt för att skapa säker kommunikation mellan olika applikationer och servrar.

Kryptera och dekryptera med OpenSSL

Du kan använda OpenSSL-funktioner för att kryptera data som i ett senare skede kan dekrypteras och endast de med nyckeln kan komma åt innehållet. Här är ett exempel på hur du gör det.

<?php

// Ange lösenordet som ska användas för kryptering/dekryptering
$password = 'mysecretpassword';

// Skapa en nyckel med hjälp av lösenordet och saltet
$salt = 'saltsaltsaltsalt';
$key = hash_pbkdf2('sha256', $password, $salt, 10000, 32, true);

// Ange den ursprungliga texten som ska krypteras
$plaintext = 'This is the original text.';

// Kryptera texten med hjälp av OpenSSL-funktionen openssl_encrypt
$cipher = 'aes-256-cbc';
$iv_length = openssl_cipher_iv_length($cipher);
$iv = openssl_random_pseudo_bytes($iv_length);
$ciphertext = openssl_encrypt($plaintext, $cipher, $key, OPENSSL_RAW_DATA, $iv);

// Konkatenera IV:et och krypterad text i en sammanhållen sträng
$ciphertext_iv = $iv . $ciphertext;

// Base64-koda strängen för att göra den lättare att skicka som text
$ciphertext_iv_base64 = base64_encode($ciphertext_iv);

// Skriv ut den krypterade strängen
echo $ciphertext_iv_base64;

// Dekryptera strängen igen med hjälp av OpenSSL-funktionen openssl_decrypt
$ciphertext_iv = base64_decode($ciphertext_iv_base64);
$iv = substr($ciphertext_iv, 0, $iv_length);
$ciphertext = substr($ciphertext_iv, $iv_length);
$plaintext = openssl_decrypt($ciphertext, $cipher, $key, OPENSSL_RAW_DATA, $iv);

// Skriv ut den dekrypterade texten
echo $plaintext;

?>

I det här exemplet skapas en krypteringsnyckel med hjälp av lösenordet och saltet genom att använda hash_pbkdf2-funktionen. Därefter används OpenSSL-funktionen openssl_encrypt för att kryptera den ursprungliga texten med hjälp av nyckeln. Resultatet är en sträng med krypterad text, som konkateneras med ett tillfälligt ”Initialization Vector” (IV) som används för att förbättra säkerheten.

Efter att texten har krypterats konverteras strängen till base64-format för att göra den lättare att skicka som text. Base64-kodningen gör att alla tecken i strängen blir printable ASCII-tecken, vilket gör att den kan skickas som vanlig text utan att några tecken kan tolkas fel.

När texten ska dekrypteras igen används OpenSSL-funktionen openssl_decrypt tillsammans med den ursprungliga nyckeln. För att dekryptera texten behövs även IV:et, så strängen med krypterad text och IV delas upp igen innan dekrypteringen utförs.

Slutligen skrivs den dekrypterade texten ut, vilket borde vara samma som den ursprungliga texten som krypterades i början.

Det är viktigt att komma ihåg att lösenordet, saltet och nyckeln måste vara samma vid både kryptering och dekryptering för att det ska gå att återställa texten igen.

Olika ciphers att välja mellan i kryptering

Det finns många olika ciphers (krypteringsalgoritmer) som kan användas med OpenSSL för att kryptera och dekryptera data. Valet av cipher påverkar både säkerheten och prestandan för krypteringen.

Generellt sett är de ciphers som använder sig av moderna kryptografiska algoritmer som AES och ChaCha20 säkra val, medan ciphers som använder sig av gamla algoritmer som DES och 3DES är mindre säkra och bör undvikas.

Här är några exempel på ciphers som är säkra att använda med OpenSSL:

  • AES (Advanced Encryption Standard) är en av de mest använda ciphers för symmetrisk kryptering. Den har hög säkerhet och bra prestanda, och finns i olika storlekar för att anpassa säkerheten efter behov.
  • ChaCha20 är en modern cipher med hög säkerhet och bra prestanda. Den är ofta snabbare än AES på moderna processorer, men har inte riktigt samma nivå av industristandardisering som AES.
  • ECDHE (Elliptic Curve Diffie-Hellman Ephemeral) är en cipher som används för så kallad ”perfekt förvaring” (perfect forward secrecy). Detta innebär att varje session har en unik nyckel som inte kan beräknas från tidigare sessioner, så om nyckeln komprometteras kan inte tidigare sessioner dekrypteras. ECDHE används oftast tillsammans med andra ciphers för att öka säkerheten ytterligare.

Det är alltid viktigt att välja en cipher som passar dina säkerhetskrav och prestandakrav, och att hålla sig uppdaterad om eventuella sårbarheter i olika ciphers. Du bör också se till att använda långa och säkra nycklar och lösenord för att öka säkerheten ytterligare.