« Ritorna al blog

Ritorna alla lista completa degli articoli

Mettiti alla prova: crittografia e decrittografia dei dati con Sodium

PHP - SFIDE - febbraio 06, 2022

In 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:

Abilita Sodium in WampServer

 

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.
  • 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>
Mettiti alla prova: crittografia e decrittografia dei dati con Sodium
Mettiti alla prova: crittografia e decrittografia dei dati con Sodium
Mettiti alla prova: crittografia e decrittografia dei dati con Sodium