Libreria
Dati binari
Byte, bit e formati binari.
Funzioni 22
cifra_filecifra_testocifrario_cesarecifrario_vigenerecomprimi_daticonfronta_improntecrea_chiavi_firmadati_binaridecifra_filedecifra_testodecomprimi_datie_password_comuneentropia_filefirma_datiimpronta_cartellaleggi_exifnumero_in_byteprova_tutti_cesarericonosci_tipo_filetogli_exifverifica_firmavista_esadecimale
dati_binari(valore, formato = "testo")#
Una sequenza di byte (numeri da 0 a 255) comoda da maneggiare.
valore può essere un testo, una lista di byte o altri dati binari. Il formato dice come leggere un testo: "testo" (le lettere in UTF-8), "esadecimale", "base64", "base32", "base85", "bit" o "file" (il testo è il percorso di un file da leggere). Proprietà: lunghezza. Metodi: pezzo, unisci, cerca, in_lista, in_testo, codifica, leggi_numero, salva.
stampa(dati_binari("Leo"))stampa(dati_binari("4C 65 6F", "esadecimale"))stampa(dati_binari("foto.png", "file"))dati_binari(3 byte: 4C 65 6F) dati_binari(3 byte: 4C 65 6F) dati_binari(74 byte: 89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 ...)
numero_in_byte(numero, byte = nulla, ordine = "piccolo", con_segno = falso)#
Un numero scritto come byte.
È il contrario di dati.leggi_numero(...). Un intero usa 4 byte se non dici altro, un decimale 8. ordine è "piccolo" (prima il byte meno importante) o "grande". Per i negativi serve con_segno = vero.
stampa(numero_in_byte(513, 2).in_lista())numero_in_byte(-1, 1, con_segno = vero).in_lista()[1, 2]
vista_esadecimale(sorgente, quanti = 256, da = 0)#
I byte di un file (o di dati) in righe leggibili, come hexdump.
Ogni riga mostra la posizione, 16 byte in esadecimale e le lettere stampabili (gli altri byte sono .). sorgente è il percorso di un file, una lista di byte o dei dati binari.
stampa(vista_esadecimale("foto.png", 32))00000000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 |.PNG........IHDR| 00000010 00 00 00 08 00 00 00 08 08 02 00 00 00 4b 6d 29 |.............Km)|
riconosci_tipo_file(percorso)#
Il vero tipo di un file, riconosciuto dai primi byte e non dal nome.
Restituisce un dizionario con "tipo" (per
stampa(riconosci_tipo_file("foto.jpg")["tipo"])PNG
entropia_file(percorso)#
Quanto sono "disordinati" i byte di un file, da 0 a 8 (bit per byte).
Un testo sta intorno a 4-5; un file compresso (ZIP, JPEG, MP3) o cifrato arriva quasi a 8. Un file di documenti con entropia vicina a 8 e un nome strano può essere stato cifrato da un virus (ransomware).
stampa(entropia_file("archivio.zip"))leggi_exif(percorso)#
I metadati EXIF di una foto (JPEG, PNG, WebP, TIFF) in un dizionario.
Chiavi possibili: "marca", "modello", "programma", "data_scatto", "data_modifica", "autore", "copyright", "orientamento", "larghezza", "altezza", "esposizione", "diaframma", "iso", "focale", "obiettivo" e "gps" (un dizionario con "latitudine", "longitudine", "altitudine", "mappa"). Se la foto non ha metadati il dizionario è vuoto. ATTENZIONE alla privacy: la posizione GPS dice dove è stata scattata la foto (per
variabile m = leggi_exif("vacanze.jpg")se "gps" in m allora stampa(m["avviso_privacy"]) finetogli_exif(percorso, destinazione = nulla)#
Toglie da una foto i metadati (EXIF, GPS, XMP, commenti).
L'immagine resta identica: si tolgono solo le informazioni nascoste. Funziona con JPEG, PNG e WebP. Senza destinazione sostituisce il file stesso. Restituisce quanti blocchi di metadati ha tolto (0 se la foto era già pulita). Nota: la foto perde anche l'"orientamento", quindi alcune potrebbero apparire ruotate.
togli_exif("vacanze.jpg", "vacanze_da_condividere.jpg")comprimi_dati(dati, metodo = "gzip")#
I dati compressi (più piccoli), come dati binari.
Metodi: "gzip" (il più diffuso), "zlib", "bz2", "xz" (il più piccolo, ma più lento). Un testo che si ripete si comprime tanto; una foto JPEG o un file ZIP quasi niente (sono già compressi).
stampa(comprimi_dati("ciao " * 1000).lunghezza)50
decomprimi_dati(dati)#
Il contrario di comprimi_dati; il metodo si riconosce da solo.
Riconosce gzip, zlib, bz2 e xz. Si ferma se il risultato supera 256 MB (i file "bomba" minuscoli che diventano enormi servono a bloccare i computer).
stampa(decomprimi_dati(comprimi_dati("ciao")).in_testo())ciao
cifra_testo(dati, password)#
Cifra un testo (o dei byte) con una password; il risultato è un testo illeggibile.
Usa AES-256-GCM, un cifrario vero, con la chiave ricavata dalla password con scrypt: chi non conosce la password non può leggere né modificare di nascosto il messaggio. Ogni volta il risultato è diverso (è normale). Serve il pacchetto cryptography. Se dimentichi la password i dati sono persi per sempre.
variabile segreto = cifra_testo("Il tesoro è sotto il pino", "gatto-blu-salta-alto")decifra_testo(testo, password, come_byte = falso)#
Rimette in chiaro un testo di cifra_testo.
Con la password sbagliata (o se qualcuno ha cambiato anche una sola lettera) dà un errore. Con come_byte = vero restituisce dati binari invece di un testo.
stampa(decifra_testo(segreto, "gatto-blu-salta-alto"))cifra_file(percorso, password, destinazione = nulla, sovrascrivi = falso)#
Cifra un file con una password.
Crea un file nuovo (di solito con ".leocifrato" in fondo al nome) e lascia com'è l'originale: cancellalo tu quando hai controllato che decifra_file funziona. Usa AES-256-GCM (serve il pacchetto cryptography). Restituisce il percorso del file cifrato.
cifra_file("diario.txt", "la mia frase segreta lunga")decifra_file(percorso, password, destinazione = nulla, sovrascrivi = falso)#
Il contrario di cifra_file.
Senza destinazione toglie ".leocifrato" dal nome (se il file esiste già serve sovrascrivi = vero). Restituisce il percorso del file decifrato.
stampa(decifra_file("diario.txt.leocifrato", "la mia frase segreta lunga"))crea_chiavi_firma()#
Una nuova coppia di chiavi per le firme digitali Ed25519, in un dizionario.
"privata" serve a firmare e va tenuta segreta (come una password); "pubblica" si dà a tutti e serve a controllare che i tuoi file o messaggi vengano proprio da te e non siano stati cambiati. Serve il pacchetto cryptography.
variabile chiavi = crea_chiavi_firma()firma_dati(dati, chiave_privata)#
La firma digitale (un testo) di un testo o di dati binari.
Chi ha la tua chiave pubblica controlla la firma con verifica_firma. Per firmare un file: firma_dati(dati_binari("programma.zip", "file"), chiavi["privata"]).
variabile firma = firma_dati("Vale 10 punti", chiavi["privata"])verifica_firma(dati, firma, chiave_pubblica)#
Vero se la firma è stata fatta con la chiave privata giusta
su proprio questi dati.
Falso se anche un solo byte dei dati o della firma è cambiato, o se ha firmato qualcun altro.
stampa(verifica_firma("Vale 10 punti", firma, chiavi["pubblica"]))impronta_cartella(cartella)#
L'impronta SHA-256 di ogni file di una cartella (anche nelle sottocartelle).
Restituisce un dizionario percorso -> impronta (i percorsi sono relativi alla cartella, con /). Salvalo con scrivi_json e più avanti confrontalo con confronta_impronte per sapere che cosa è cambiato.
scrivi_json("foto_prima.json", impronta_cartella("documenti"))confronta_impronte(prima, dopo)#
Che cosa è cambiato tra due "fotografie" di una cartella.
prima e dopo sono dizionari di impronta_cartella (o dopo è direttamente il nome della cartella). Restituisce un dizionario con le liste "aggiunti", "tolti", "cambiati", il numero "uguali" e "intatta" (vero se non è cambiato niente).
confronta_impronte(leggi_json("foto_prima.json"), "documenti")cifrario_cesare(testo, spostamento = 3)#
Il cifrario di Giulio Cesare. SOLO PER GIOCO: NON È SICURO.
Ogni lettera (A-Z) va avanti di spostamento posti nell'alfabeto; le altre restano uguali. Per decifrare usa lo spostamento negativo. Ci sono solo 26 chiavi: prova_tutti_cesare le prova tutte in un attimo. Per i segreti veri usa cifra_testo.
stampa(cifrario_cesare("Ciao", 3))Fldr
cifrario_vigenere(testo, chiave, decifra = falso)#
Il cifrario di Vigenère. SOLO PER GIOCO: NON È SICURO.
Come Cesare, ma lo spostamento cambia a ogni lettera seguendo le lettere della chiave (A = 0, B = 1...). Si rompe contando le lettere che si ripetono (metodo di Kasiski, 1863). Per i segreti veri usa cifra_testo.
stampa(cifrario_vigenere("attacca all'alba", "leo"))lxhlgql ezw'ezme
prova_tutti_cesare(testo)#
Mostra perché il cifrario di Cesare è debole, provando tutte le 26 chiavi.
Restituisce la lista delle 26 decifrature: nella posizione n c'è il testo decifrato con lo spostamento n. Una sola sarà italiano sensato: basta leggerle. È un
stampa(prova_tutti_cesare("Fldr")[3])Ciao
e_password_comune(password)#
Vero se la password è tra le più usate al mondo (o una loro variante facile).
Controlla un piccolo elenco locale (niente va su Internet), le varianti con maiuscole, numeri o simboli in fondo (come "Juventus2024!") e le sequenze come "abcdef" o "98765". Una password comune si indovina in pochi secondi: scegline un'altra, per
password_casuale()stampa(e_password_comune("Password123"))stampa(e_password_comune("gatto-blu-salta-alto"))vero falso
Oggetto «dati_binari»
Valore Leo di tipo dati_binari: una sequenza immutabile di byte.
| Proprietà | Significato |
|---|---|
lunghezza |
.cerca(sequenza, da = 0)#
La posizione della prima volta che compare sequenza, o nulla.
stampa(dati_binari("banana").cerca("na"))stampa(dati_binari("banana").cerca("na", 3))2 4
.codifica(formato = "esadecimale", separatore = "")#
I byte scritti come testo in un formato.
Formati: "esadecimale", "base64", "base32", "base85", "bit" (8 zeri e uni per byte). Il separatore va tra un byte e l'altro (solo per "esadecimale" e "bit").
stampa(dati_binari("Leo").codifica())stampa(dati_binari("A").codifica("bit"))4c656f 01000001
.in_lista()#
I byte come lista di numeri da 0 a 255.
stampa(dati_binari("Leo").in_lista())[76, 101, 111]
.in_testo(codifica = "utf-8")#
I byte letti come lettere di un testo.
Altre codifiche: "latin-1", "cp1252" (Windows), "utf-16", "ascii".
stampa(dati_binari([76, 101, 111]).in_testo())Leo
.leggi_numero(posizione = 0, byte = 4, ordine = "piccolo", con_segno = falso, decimale = falso)#
Legge un numero.
Legge byte byte a partire da posizione. ordine è "piccolo" (prima il byte meno importante, come nei PC, nei WAV e nei BMP) o "grande" (come in rete e nei PNG); con_segno = vero per i numeri che possono essere negativi; decimale = vero per i decimali (2, 4 o 8 byte).
stampa(dati_binari([1, 2]).leggi_numero(0, 2))stampa(dati_binari([1, 2]).leggi_numero(0, 2, "grande"))513 258
.pezzo(inizio, fine = nulla)#
I byte da inizio (compreso) a fine (escluso), come nuovi dati binari.
I numeri negativi contano dalla fine.
stampa(dati_binari("ciao").pezzo(1, 3).in_testo())ia
.salva(percorso, sovrascrivi = vero)#
Scrive i byte in un file e restituisce quanti sono.
stampa(dati_binari("ciao").salva("saluto.bin"))4
.unisci(altri...)#
Questi dati seguiti da altri (testi, liste di byte o dati binari).
stampa(dati_binari("Le").unisci("o", [33]).in_testo())Leo!