« Ritorna al blog
Ritorna alla lista completa degli articoli
Mettiti alla prova: crittografia e decrittografia dei dati con Sodium
PHP - SFIDE - febbraio 06, 2022In questo esercizio dovrete crittografare e decrittografare una porzione di testo utilizzando la libreria Sodium di PHP. Per poterla utilizzare occorre una versione di PHP superiore o uguale alla 7.2.0. La libreria Sodium è una delle tante estensioni di PHP; pertanto occorre abilitarla nel proprio Lamp Stack. Se utilizzate WampServer l'operazione è molto semplice:
Nella pagina start.php abbiamo due form, che svolgono entrambe le funzioni di crittografia e decrittografia di un messaggio. Potete anche decidere se usare una chiave fissa oppure casuale. La funzione che si occupa di generarla è genera_chiave():
start.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>encrypt - decrypt</title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.2/font/bootstrap-icons.css">
</head>
<body>
<?php
/*
-- SODIUM_CRYPTO_SECRETBOX_KEYBYTES (int 32)
Se la chiave ha una lunghezza di byte diversa da SODIUM_CRYPTO_SECRETBOX_KEYBYTES (32 byte), verrà generata una SodiumException.
-- SODIUM_CRYPTO_SECRETBOX_NONCEBYTES (int 24)
Se nonce ha una lunghezza di byte diversa da SODIUM_CRYPTO_SECRETBOX_NONCEBYTES (24 byte), verrà generata una SodiumException.
-- sodium_crypto_secretbox()
Crittografa un messaggio con una chiave simmetrica (condivisa).
-- sodium_crypto_secretbox_open()
Decrittografa un messaggio crittografato con una chiave simmetrica (condivisa).
-- random_bytes()
Genera una stringa di lunghezza arbitraria di byte crittografici casuali adatti per l'uso crittografico,
ad esempio quando si generano salti, chiavi o vettori di inizializzazione.
-- base64_encode()
Codifica la stringa data con base64. Questa codifica è progettata per fare in modo che i dati binari
sopravvivano al trasporto attraverso livelli di trasporto non puliti a 8 bit, come i corpi di posta.
I dati con codifica Base64 occupano circa il 33% di spazio in più rispetto ai dati originali.
-- base64_decode()
Decodifica una stringa codificata in base64.
-- mb_substr()
Esegue un'operazione substr() sicura multi-byte in base al numero di caratteri.
La posizione viene contata dall'inizio della stringa. La posizione del primo carattere è 0.
La posizione del secondo carattere è 1 e così via.
-- definizioni utili:
In crittografia il termine nonce indica un numero, generalmente casuale o pseudo-casuale, che ha un utilizzo unico. ...
Un nonce viene utilizzato spesso nei protocolli di autenticazione per assicurare che i dati scambiati nelle vecchie comunicazioni
non possano essere riutilizzati in attacchi di tipo replay attack.
*/
$key = "";
genera_chiave(false);
function genera_chiave($casuale = false)
{
global $key;
if ($casuale == true) {
$key = random_bytes(SODIUM_CRYPTO_SECRETBOX_KEYBYTES);
} else {
$key = base64_decode("AabVwJ5DUo3QyIE0RPUEETsTF2HcRA76/NVdZemq+WI=");
}
}
function encrypt_string($str)
{
global $key;
if (!empty($str)) {
// da completare
}
return "error";
}
function decrypt_string($hash)
{
global $key;
if (!empty($hash)) {
// da completare
}
return "error";
}
$form1_text_free = "";
$form1_text_encrypted = "";
$form2_text_free = "";
$form2_text_encrypted = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (isset($_POST["btn_encrypt"])) {
$form1_text_free = $_POST["text_free"];
$form1_text_encrypted = encrypt_string($form1_text_free);
}
if (isset($_POST["btn_decrypt"])) {
$form2_text_encrypted = $_POST["text_encrypted"];
$form2_text_free = decrypt_string($form2_text_encrypted);
}
}
?>
<div class="container">
<div class="row">
<div class="col-12">
<div class="py-5 text-center">
<h2>Libreria Sodium</h2>
<p class="lead">Test di crittografia e decrittografia</p>
</div>
</div>
<div class="col-md-6">
<form id="form1" name="form1" action="<?php echo $_SERVER["PHP_SELF"]; ?>" method="post" class="mt-4 mb-4">
<fieldset>
<legend>Cripta il testo</legend>
<div class="form-group">
<label for="text_free">Testo da criptare</label>
<textarea class="form-control" id="text_free" name="text_free" rows="6"><?php echo $form1_text_free; ?></textarea>
</div>
<div class="form-group">
<label for="text_free_result" class="col-sm-2 col-form-label">Risultato</label>
<textarea rows="6" readonly="" class="form-control-plaintext bg-light p-3" id="text_encrypted_result" name="text_encrypted_result"><?php echo $form1_text_encrypted; ?></textarea>
</div>
<div class="form-group mt-4">
<button type="submit" name="btn_encrypt" class="btn btn-primary w-100">Cripta testo</button>
</div>
</fieldset>
</form>
</div>
<div class="col-md-6">
<form id="form2" name="form2" action="<?php echo $_SERVER["PHP_SELF"]; ?>" method="post" class="mt-4 mb-4">
<fieldset>
<legend>Decripta il testo</legend>
<div class="form-group">
<label for="text_free">Testo da decriptare</label>
<textarea class="form-control" id="text_encrypted" name="text_encrypted" rows="6"><?php echo $form2_text_encrypted; ?></textarea>
</div>
<div class="form-group">
<label for="text_free_result" class="col-sm-2 col-form-label">Risultato</label>
<textarea rows="6" readonly="" class="form-control-plaintext bg-light p-3" id="text_decrypted_result" name="text_decrypted_result"><?php echo $form2_text_free; ?></textarea>
</div>
<div class="form-group mt-4">
<button type="submit" name="btn_decrypt" class="btn btn-success w-100">Decripta testo</button>
</div>
</fieldset>
</form>
</div>
</div>
</div>
<!-- Bootstrap Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
Per risolvere l'esercizio dovete concentrarvi su alcune delle funzioni che fanno parte della libreria che vengono maggiormente usate:
- SODIUM_CRYPTO_SECRETBOX_KEYBYTES (int 32)
- Se la chiave ha una lunghezza di byte diversa da SODIUM_CRYPTO_SECRETBOX_KEYBYTES (32 byte), verrà generata una SodiumException.
- SODIUM_CRYPTO_SECRETBOX_NONCEBYTES (int 24)
- Se nonce ha una lunghezza di byte diversa da SODIUM_CRYPTO_SECRETBOX_NONCEBYTES (24 byte), verrà generata una SodiumException. Per nonce si intende un numero, generalmente casuale o pseudo-casuale, che ha un utilizzo unico, spesso utilizzato nei protocolli di autenticazione per assicurare che i dati scambiati nelle vecchie comunicazioni non possano essere riutilizzati in attacchi di tipo replay attack.
- sodium_crypto_secretbox()
- Crittografa un messaggio con una chiave simmetrica (condivisa).
- sodium_crypto_secretbox_open()
- Decrittografa un messaggio crittografato con una chiave simmetrica (condivisa).
- random_bytes()
- Genera una stringa di lunghezza arbitraria di byte crittografici casuali adatti per l'uso crittografico, ad esempio quando si generano salti, chiavi o vettori di inizializzazione.
- base64_encode()
- Codifica la stringa data con base64. Questa codifica è progettata per fare in modo che i dati binari
sopravvivano al trasporto attraverso livelli di trasporto non puliti a 8 bit, come i corpi di posta.
I dati con codifica Base64 occupano circa il 33% di spazio in più rispetto ai dati originali.
- Codifica la stringa data con base64. Questa codifica è progettata per fare in modo che i dati binari
- base64_decode()
- Decodifica una stringa codificata in base64.
- mb_substr()
- Esegue un'operazione substr() sicura multi-byte in base al numero di caratteri. La posizione viene contata dall'inizio della stringa. La posizione del primo carattere è 0. La posizione del secondo carattere è 1 e così via.
Buon lavoro e soprattutto divertitevi :)
finish.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>encrypt - decrypt</title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.2/font/bootstrap-icons.css">
</head>
<body>
<?php
/*
-- SODIUM_CRYPTO_SECRETBOX_KEYBYTES (int 32)
Se la chiave ha una lunghezza di byte diversa da SODIUM_CRYPTO_SECRETBOX_KEYBYTES (32 byte), verrà generata una SodiumException.
-- SODIUM_CRYPTO_SECRETBOX_NONCEBYTES (int 24)
Se nonce ha una lunghezza di byte diversa da SODIUM_CRYPTO_SECRETBOX_NONCEBYTES (24 byte), verrà generata una SodiumException.
-- sodium_crypto_secretbox()
Crittografa un messaggio con una chiave simmetrica (condivisa).
-- sodium_crypto_secretbox_open()
Decrittografa un messaggio crittografato con una chiave simmetrica (condivisa).
-- random_bytes()
Genera una stringa di lunghezza arbitraria di byte crittografici casuali adatti per l'uso crittografico,
ad esempio quando si generano salti, chiavi o vettori di inizializzazione.
-- base64_encode()
Codifica la stringa data con base64. Questa codifica è progettata per fare in modo che i dati binari
sopravvivano al trasporto attraverso livelli di trasporto non puliti a 8 bit, come i corpi di posta.
I dati con codifica Base64 occupano circa il 33% di spazio in più rispetto ai dati originali.
-- base64_decode()
Decodifica una stringa codificata in base64.
-- mb_substr()
Esegue un'operazione substr() sicura multi-byte in base al numero di caratteri.
La posizione viene contata dall'inizio della stringa. La posizione del primo carattere è 0.
La posizione del secondo carattere è 1 e così via.
-- definizioni utili:
In crittografia il termine nonce indica un numero, generalmente casuale o pseudo-casuale, che ha un utilizzo unico. ...
Un nonce viene utilizzato spesso nei protocolli di autenticazione per assicurare che i dati scambiati nelle vecchie comunicazioni
non possano essere riutilizzati in attacchi di tipo replay attack.
*/
$key = "";
genera_chiave(false);
function genera_chiave($casuale = false)
{
global $key;
if ($casuale == true) {
$key = random_bytes(SODIUM_CRYPTO_SECRETBOX_KEYBYTES);
} else {
$key = base64_decode("AabVwJ5DUo3QyIE0RPUEETsTF2HcRA76/NVdZemq+WI=");
}
}
function encrypt_string($str)
{
global $key;
if (!empty($str)) {
// da completare
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$cipher_text = base64_encode($nonce . sodium_crypto_secretbox($str, $nonce, $key));
return $cipher_text;
}
return "error";
}
function decrypt_string($hash)
{
global $key;
if (!empty($hash)) {
// da completare
$decoded = base64_decode($hash);
$nonce = mb_substr($decoded, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
$chiper_text = mb_substr($decoded, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');
return sodium_crypto_secretbox_open($chiper_text, $nonce, $key);
}
return "error";
}
$form1_text_free = "";
$form1_text_encrypted = "";
$form2_text_free = "";
$form2_text_encrypted = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (isset($_POST["btn_encrypt"])) {
$form1_text_free = $_POST["text_free"];
$form1_text_encrypted = encrypt_string($form1_text_free);
}
if (isset($_POST["btn_decrypt"])) {
$form2_text_encrypted = $_POST["text_encrypted"];
$form2_text_free = decrypt_string($form2_text_encrypted);
}
}
?>
<div class="container">
<div class="row">
<div class="col-12">
<div class="py-5 text-center">
<h2>Libreria Sodium</h2>
<p class="lead">Test di crittografia e decrittografia</p>
</div>
</div>
<div class="col-md-6">
<form id="form1" name="form1" action="<?php echo $_SERVER["PHP_SELF"]; ?>" method="post" class="mt-4 mb-4">
<fieldset>
<legend>Cripta il testo</legend>
<div class="form-group">
<label for="text_free">Testo da criptare</label>
<textarea class="form-control" id="text_free" name="text_free" rows="6"><?php echo $form1_text_free; ?></textarea>
</div>
<div class="form-group">
<label for="text_free_result" class="col-sm-2 col-form-label">Risultato</label>
<textarea rows="6" readonly="" class="form-control-plaintext bg-light p-3" id="text_encrypted_result" name="text_encrypted_result"><?php echo $form1_text_encrypted; ?></textarea>
</div>
<div class="form-group mt-4">
<button type="submit" name="btn_encrypt" class="btn btn-primary w-100">Cripta testo</button>
</div>
</fieldset>
</form>
</div>
<div class="col-md-6">
<form id="form2" name="form2" action="<?php echo $_SERVER["PHP_SELF"]; ?>" method="post" class="mt-4 mb-4">
<fieldset>
<legend>Decripta il testo</legend>
<div class="form-group">
<label for="text_free">Testo da decriptare</label>
<textarea class="form-control" id="text_encrypted" name="text_encrypted" rows="6"><?php echo $form2_text_encrypted; ?></textarea>
</div>
<div class="form-group">
<label for="text_free_result" class="col-sm-2 col-form-label">Risultato</label>
<textarea rows="6" readonly="" class="form-control-plaintext bg-light p-3" id="text_decrypted_result" name="text_decrypted_result"><?php echo $form2_text_free; ?></textarea>
</div>
<div class="form-group mt-4">
<button type="submit" name="btn_decrypt" class="btn btn-success w-100">Decripta testo</button>
</div>
</fieldset>
</form>
</div>
</div>
</div>
<!-- Bootstrap Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>