XOR cipher
I membri di un’organizzazione segreta hanno inventato un nuovo algoritmo crittografico basato sull’operatore bitwise XOR per scambiarsi messaggi cifrati. Un detective ha intercettato diversi messaggi ed è riuscito ad ottenere lo pseudocodice dell’algoritmo.
I messaggi sono codificati in liste concatenate di caratteri, ad ognuno dei quali è stato applicato l’algoritmo di codifica con una chiave segreta. La chiave è una stringa alfanumerica di lunghezza variabile.
Lo pseudocodice dell’algoritmo è il seguente:
Il simbolo \(\oplus\) è l’operatore bitwise xor (^
), mentre mod
corrisponde all’operatore modulo (%
).
Aiuta il detective implementando lo pseudocodice nelle seguenti funzioni C:
char charEncodec(const char c, const char key)
void listEncodec(Node *list, const char *key, const int seed)
Se necessario, si possono aggiungere funzioni di supporto, ma è necessario che le funzioni richieste siano implementate esattamente con i prototipi forniti.
Lo pseudocodice non è codice completo in C: non considera i tipi dei vari oggetti, l’uso di puntatori/riferimenti, e dunque dell’operatore “->” anziché l’operatore “.”: `e lasciato allo studente il compito di determinare questi dettagli come adeguato.
L’implementazione della lista in C è quella utilizzata durante le lezioni del corso e viene fornita già implementata nei file dell’esercizio come segue:
typedef struct node {
char value;
struct node *next;
} Node;
La funzione isPrintable
viene fornita con il testo dell’esercizio, accetta in input un singolo carattere e restituisce un intero:
- 0 se non può essere stampato a terminale (ad esempio se si tratta dei caratteri
\0
,\n
,\t
, …) - 1 altrimenti
La funzione len
prende in input un stringa e restituisce la lunghezza della stringa. Viene fornita già implementata nel testo dell’esercizio.
La soluzione proposta è la seguente:
char charEncodec(const char c, const char key)
{
char result = c ^ key;
if (!isPrintable(result))
= c;
result return result;
}
void listEncodec(Node *list, const char *key, const int seed)
{
if (list == NULL)
return;
// È necessario l'operatore -> poiché list è un puntatore
// in tal modo si accede al campo value della struttura
// puntata da list
->value = charEncodec(list->value, key[seed % len(key)]);
list// Chiamata ricorsiva
(list->next, key, seed + 1);
listEncodec}