Il checksum codice128 non è crittograficamente sicuro.
Penso che tu abbia frainteso lo scopo di un checksum. Un checksum è progettato per consentire di rilevare la corruzione accidentale o errori nella lettura dei dati. I dati vengono convertiti in un checksum e confrontati con il checksum previsto. Se i due differiscono, si sa che c'è stato un errore nella lettura dei dati. L'intenzione è di ridurre la possibilità che un errore accidentale nella lettura abbia come risultato lo stesso checksum. Lo stesso algoritmo di checksum è pubblico ed è facile da calcolare, ad esempio con la seguente funzione, dove code128_table
è una specifica tabella indice (codice A, B o C):
uint8_t code128_checksum(uint8_t *buf, uint32_t len)
{
uint32_t sum = *buf - 32;
while (--len)
sum += len * code128_table[*(buf + len)];
return sum % 103 + 32;
}
Questo checksum è estremamente semplice, progettato solo per rendere possibile il rilevamento di errori durante il processo di scansione. È una somma "vera", il che significa che non è altro che la sommatoria delle rappresentazioni di ciascun carattere componente moltiplicato per un fattore di peso. Quindi la somma è letteralmente solo quella, una somma dei dati che sta proteggendo. Non è progettato per fornire alcun tipo di proprietà crittografiche al codice a barre. Il modo in cui è progettato, tutti i seguenti sono banalmente possibili, in ordine crescente complessità computazionale:
-
Hashing - Dato un codice a barre non checksum, calcola il checksum.
-
Collisione : crea due codici a barre con contenuti diversi ma identici.
-
Secondo preimage - Dato un codice a barre con checksum, creane un altro con lo stesso checksum.
-
Prima preimage - Dato solo un checksum, crea un codice a barre con lo stesso checksum.
L'unica cosa che è (modestamente) buona è garantire che una modifica casuale al codice a barre non abbia come risultato un checksum identico. Anche per quello, non è particolarmente buono. Un checksum superiore (anche se non ancora crittograficamente sicuro) della stessa dimensione di digest sarebbe CRC8, in quanto un CRC è superiore a un checksum regolare ai fini della rilevazione degli errori. Una semplice implementazione di un CRC a 8 bit (dove crc8_table
è un selezionato con cura Il polinomio CRC a 8 bit ) si presenta come segue:
uint8_t crc8(uint8_t *buf, uint32_t len)
{
uint8_t crc = ~0;
while (len--)
crc = crc8_table[crc ^ *buf++];
return crc;
}
Indipendentemente dal fatto che si utilizzi un semplice checksum, CRC o un funzione di hash crittograficamente protetta , se lo spazio delle chiavi è di soli 8 caratteri decimali e tutti gli 8 caratteri dell'ID sequenziale sono validi per l'ID azienda B2DS, potresti, banalmente, creare tutti i 99,999,998 codici a barre possibili, con checksum associati corrispondenti . Un'implementazione completamente non ottimizzata impiegò 19 secondi sul mio computer. Lo spazio delle chiavi è troppo piccolo, anche con un hash crittograficamente sicuro.
Come @Philipp ha menzionato in un commento, una soluzione migliore sarebbe distribuire i codici a barre con un ID casuale. Consentire a ciascun ID di essere utilizzato un numero limitato di volte e monitorare i tentativi di utilizzare un codice a barre con un ID che non è stato emesso esplicitamente. Se ciò avviene, anche se ci sono migliaia di codici a barre validi in un dato momento, un codice a barre casuale avrebbe solo una possibilità su dieci.000 di essere valido, rendendo molto più difficile l'uso fraudolento dei codici.