Il cifrario di Cesare è uno dei più antichi e semplici algoritmi crittografici di cifratura a sostituzione, prende nome da Giulio Cesare che si diceva lo utilizzasse per le sue comunicazioni segrete.
Il meccanismo del cifrario di Cesare è molto semplice ogni lettera del testo da cifrare viene sostituita da una lettera che si trova un numero fisso di posizioni più avanti nell'alfabeto.
Per decifrare il testo cifrato, si applica lo stesso principio ma al contrario: ogni lettera cifrata viene spostata indietro di un numero corrispondente alla chiave di cifratura (numero di caratteri spostati).
Si può intuire che è davvero semplicissimo capire cosa c'è scritto anche se "cifrato", l'unica sarebbe attribuire altre lettere all'alfabeto ordinario in modo casuale, perché non farlo con Javascript?
Iniziamo a scrivere il codice!
Iniziamo ad inizializzare le variabili, normalAlphabet
contiene l'alfabeto ordinario in minuscolo. shuffledAlphabet
invece viene pescato dall'archiviazione locale (localStorage) se è stato memorizzato in precedenza altrimenti viene generato un nuovo alfabeto casuale e successivamente memorizzato.
localStorage viene usato per memorizzare nei cookie l'alfabeto in modo da mantenere l'ordine nell'alfabeto casuale anche se si aggiorna la pagina o si rientra dopo un po' di tempo.
In seguito dobbiamo rendere casuale la generazione dell'alfabeto cifrario, in questo caso con randomizeAlphabet()
usando l'algoritmo di sort con una funzione di confronto casuale.
Definiamo encrypt()
che viene richiamata quando l'utente fa clic su "Cifra", prende il testo inserito dall'utente (plaintext), lo trasforma in minuscolo e lo cifra carattere per carattere.
Poi ogni carattere viene cercato nell'alfabeto normale e viene sostituito con il corrispondente carattere nell'alfabeto casuale (se il carattere non è presente viene riscritto).
Definiamo decrypt()
che viene richiamata quando l'utente fa clic su "Decifra", prende il testo cifrato inserito dall'utente (ciphertext), lo trasforma in minuscolo e lo decifra carattere per carattere.
Il comportamento di decrypt()
per il resto è molto simile a encrypt()
.
Infine abbiamo showMapping()
restituisce una mappatura generale dell'alfabeto normale rispetto all'alfabeto casuale, viene mostrata nell'area di testo dedicata (mapping).
Codice:
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cifrario di Cesare</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Cifrario di Cesare con lettere casuali</h1>
<label for="text">Testo:</label><br>
<textarea id="text" placeholder="Inserisci qui il testo"></textarea><br>
<button onclick="encrypt()">Cifra</button>
<button onclick="decrypt()">Decifra</button><br>
<label for="result">Risultato:</label><br>
<textarea id="result" readonly></textarea><br>
<label for="mapping">Mappatura Alfabeto:</label><br>
<textarea id="mapping" readonly></textarea>
<script src="script.js"></script>
</body>
</html>
CSS:
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #f8f9fa;
color: #333;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
align-items: center;
}
.container {
max-width: 400px;
margin: 50px auto;
padding: 20px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
h1 {
font-size: 28px;
margin-bottom: 20px;
text-align: center;
}
label {
display: block;
font-size: 18px;
margin-bottom: 5px;
}
textarea,
button {
width: 80%;
padding: 10px;
font-size: 16px;
margin-bottom: 20px;
border: 1px solid #ccc;
border-radius: 4px;
}
textarea {
height: 60px;
}
button {
background-color: #ff7300;
color: #fff;
border: none;
cursor: pointer;
}
button:hover {
background-color: #ff0000;
}
textarea[readonly] {
background-color: #f8f9fa;
cursor: not-allowed;
}
Javascript:
let normalAlphabet = 'abcdefghijklmnopqrstuvwxyz';
let shuffledAlphabet = localStorage.getItem('shuffledAlphabet');
if (!shuffledAlphabet) {
shuffledAlphabet = randomizeAlphabet();
localStorage.setItem('shuffledAlphabet', shuffledAlphabet);
}
function randomizeAlphabet() {
let alphabet = 'abcdefghijklmnopqrstuvwxyz';
let shuffledAlphabet = alphabet.split('').sort(() => Math.random() - 0.5).join('');
return shuffledAlphabet;
}
function encrypt() {
let plaintext = document.getElementById('text').value.toLowerCase();
let ciphertext = '';
for (let i = 0; i < plaintext.length; i++) {
let char = plaintext[i];
let index = normalAlphabet.indexOf(char);
if (index !== -1) {
ciphertext += shuffledAlphabet[index];
} else {
ciphertext += char;
}
}
document.getElementById('result').value = ciphertext;
}
function decrypt() {
let ciphertext = document.getElementById('text').value.toLowerCase();
let decryptedtext = '';
for (let i = 0; i < ciphertext.length; i++) {
let char = ciphertext[i];
let index = shuffledAlphabet.indexOf(char);
if (index !== -1) {
decryptedtext += normalAlphabet[index];
} else {
decryptedtext += char;
}
}
document.getElementById('result').value = decryptedtext;
}
// mappatura dell'alfabeto
function showMapping() {
let mapping = '';
for (let i = 0; i < normalAlphabet.length; i++) {
mapping += `${normalAlphabet[i]} -> ${shuffledAlphabet[i]}\n`;
}
document.getElementById('mapping').value = mapping;
}
showMapping();