Ovvero come non implementare la crittografia
Ogni tanto capitano quei giorni… quei giorni in cui non pensavi che certe cose potessero succedere… che certe storie mitologiche sentite agli hacker camp, alle cene VUA ecc. a te non potessero capitare… ed invece tutto ad un tratto ti sembra di essere dentro uno dei racconti delle “storie della sala macchine” https://www.soft-land.org.
Succede che ho bisogno di inserire tra i parametri di configurazione di una applicazioni dei valori crittografati, per poter automatizzare il tutto ho bisogno di un programmino in grado di ricevere su standard input il testo da cifrare e dia in standard output il testo cifrato.
Le funzioni crittografiche che mi interessano sono incluse in un programma in C# e no, non ho voglia di farmele estrarre in un programma a parte, cross-compilare per linux, portarmi dietro le dipendenze di .net e quant’altro. L’algoritmo usato è AES, quindi pensavo di cavarmela con poco, usando direttamente openssl o al più, usando funzioni già presenti in altri linguaggi di scripting, ad esempio Python il cui interprete è presente di default sulle installazioni Linux. Tanto AES 256 è standard.
Appunto: pensavo.
Mi faccio inviare il sorgente delle funzioni di codifica e decodifica.
Apro il sorgente.
public static string Encrypt(string clearText, string encryptionKey)
{
byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(encryptionKey,
newbyte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65,
0x64, 0x65, 0x76});
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms,
encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
clearText = Convert.ToBase64String(ms.ToArray());
}
}
return clearText;
}
MAPPORC…ZIO!!! Che ci fa quell’array di valori esadecimali costanti passato alle funzioni crittografiche?!?
Andiamo a vedere che parametri vuole la Rfc2898DeriveBytes: password e salt. Ora, per definizione, il salt è un numero casuale, che deve cambiare di volta in volta per evitare certi tipi di attacco. Perché ha messo una costante?!? Perché?!? Perché capitano tutti a me?!?
LE BASI CAZZO, LE BASI ALMENO!!!
Un’altra “brutta persona” mi fa notare questa vignetta in tema:

Che valori ha inserito nell’array? Li decodifico: Ivan Medvedev. Mapporco pito! Chi è sto tizio? Probabilmente l’autore della funzione e chi ha fatto il programma ha ricopiato la funzione tale e quale senza porsi nessuna domanda. Penso: l’avrà beccata su qualche sito in cxxo al mondo, visitato solo da due persone, l’autore e quest’altro. Ma su quest’ultimo punto mi sbagliavo.
Ma Cristo santo, si può?
Ma se l’è letta la documentazione delle funzioni crittografiche usate per capire come vanno usate?
No. Troppa fatica.
Mentre cerco l’equivalente di Rfc2898DeriveBytes in Python, mi imbatto su stackoverflow in un’altra persona con lo stesso problema. Ma proprio lo stesso. Anche l’array con la costante è lo stesso.
Allora quel sito è stato visitato almeno da tre persone diverse.
Recupero il codice e dopo qualche porconamento con unicode, utf-8, utf-16, encoding dei sorgenti in Python ne esco.
Ma io sono una brutta persona. Non so stare fermo. Voglio vedere chi è sto Ivan Medvedev. Una rapida ricerca, e salta fuori che è una persona di tutto rispetto con un bel curriculum. Probabilmente quella funzione sarà un peccato di gioventù, o magari avrà scritto pure sul sito che il salt va cambiato, ma non lo hanno ascoltato.
Allora, ripeto, siccome sono una brutta persona e non so stare fermo cerco: Ivan Medved AES.
Nella prima pagina di risultati, tre link. La lettura delle pagine a cui rimandavano, mi ha messo in quello stato in cui non sai se pisciarti addosso dalle risate o piangere. Provi entrambe le sensazioni assieme, in un tutt’uno.
Primo link:
https://twitter.com/pmelson/status/1303092463624769536
Inserisco lo screenshot nel caso venga rimosso il tweet:

Mi sale la tosse. Tipo quando uno si sta strozzando da solo. Ok, quella pagina è stata visitata da più di tre persone. Molte di più.
Con titolo “If you copied any of these popular StackOverflow encryption code snippets, then you coded it wrong“
Ed al secondo posto troviamo la nostra funzione.
Il terzo link rimanda ad una pagina di CVE:

Chebbello.
Ora, io sono tutto tranne che un esperto di crittografia, non ti so spiegare nei dettagli le differenze tra un algoritmo di crittografia ed un altro, mi limito alle differenze tra le varie famiglie di algoritmi.
Non sono neppure “nato imparato” come si usa dire al giorno d’oggi. Ma un minimo di conoscenza di quello che faccio me lo impongo. Non scrivo codice a caso scopiazzando di qua e di la. Quando decido di integrare un esempio trovato in giro su internet, lo verifico per bene. Non voglio avere sorprese. Mi piacerebbe che quanto faccio io fosse il minimo fatto da tutti gli sviluppatori. Ma non è così.
Infine, il libro ha qualche anno sulle spalle, l’ho letto quando ero ancora giovane ed affamato di conoscenza. Non è un testo specialistico, ma va benissimo per chi è alle prime armi con la crittografia. Spiega partendo dai più semplici i vari algoritmi elencandone i punti critici. Inoltre ha una sezione dedicata alla storia della crittografia nei secoli entusiamsante e fatta veramente molto bene.
E comunque gli autori sono bravi.

Poi ci sarebbe da raccontare sul rapporto tra colui che ha copiato il pezzo di codice e le password, ma questa è un’altra storia…