Domanda:
Quanti round di hashing sono sufficienti per un gestore di password?
CertifcateJunky
2018-06-28 18:39:02 UTC
view on stackexchange narkive permalink

Attualmente sto scrivendo il mio piccolo gestore di password che memorizza la chiave in un hash SHA256 , con salt. Creo l'hash facendo quanto segue:

  def sha256_rounds (raw, rounds = 100001): obj = hashlib.sha256 () for _ in xrange (rounds): obj.update (raw) raw = obj.digest () return obj.digest ()  

Dopo che è stato creato, viene memorizzato con quanto segue:

  key = base64.urlsafe_b64encode (provided_key) length = len (key) with open (key_file, "a +") as key_: front_salt, back_salt = os.urandom (16), os.urandom (16) key_.write ("{} {} {}: {} ". format (front_salt, key, back_salt, length))  

Le domande / dubbi che ho sono:

  • Questo è un modo accettabile per memorizzare una chiave con hash?
  • Devo usare più iterazioni?
  • La mia tecnica di salting è sufficiente? O dovrei usare una tecnica di salting diversa?

Se questo non è un approccio accettabile per memorizzare una password / chiave con hash, quali altri passaggi posso fare per renderlo più sicuro?


AGGIORNAMENTO:

Ho seguito molti dei consigli del tuo ragazzo e se vuoi vedere il risultato, finora , del mio piccolo gestore di password puoi trovarlo qui. Il consiglio di tutti è molto apprezzato e continuerò a impegnarmi per renderlo il più eccellente possibile. (se quel collegamento non funziona usa questo https://github.com/Ekultek/letmein)

I commenti non sono per discussioni estese;questa conversazione è stata [spostata in chat] (https://chat.stackexchange.com/rooms/79597/discussion-on-question-by-certifcatejunky-how-many-rounds-of-hashing-is-enough-f).
Cinque risposte:
AndrolGenhald
2018-06-28 19:38:34 UTC
view on stackexchange narkive permalink

Attualmente sto scrivendo il mio piccolo gestore di password

Questo è il tuo primo errore. Qualcosa di così complesso ha molte insidie ​​sottili in cui a volte cadono anche gli esperti, senza molta esperienza in questo settore non hai la possibilità di creare qualcosa di altrettanto vicino da proteggere.

conserva la chiave in un Hash SHA256

Uh oh ...

Questo non necessariamente indica che stai facendo qualcosa di sbagliato, ma ho forti dubbi che lo farai bene. Presumo tu stia parlando di una password principale sottoposta ad hashing qui? La password principale deve essere trasformata in una chiave utilizzando un KDF come PBKDF2, bcrypt o Argon2, quindi questa chiave viene utilizzata per crittografare le password memorizzate.

Se si desidera avere un modo per verificare che la password sia corretta, memorizzare un hash della chiave dovrebbe andare bene, ma NON DEVI memorizzare la chiave stessa ... se memorizzi la chiave chiunque abbia accesso alla tua memoria ha tutto ciò di cui ha bisogno per decrittografare tutte le password!

Se non stai parlando di hashing di una password principale e intendi una vera chiave generata casualmente, non ho idea di cosa stai cercando di ottenere qui , ma non dovresti usare un KDF lento con un gran numero di iterazioni.

In alternativa potresti eseguire l'hashing della password principale due volte, una per memorizzarla come hash per verificare successivamente che la password immessa dall'utente è corretto e di nuovo da utilizzare come chiave per la crittografia. A seconda di come viene fatto, potrebbe variare da un difetto di progettazione al dare completamente via la chiave.

Modifica: dopo aver visto il codice completo, sembra essere una quarta opzione: si memorizza un hash della password per in seguito controlla se la password inserita è corretta, quindi fai l'hash di questo hash da utilizzare come chiave, il che è dannoso quasi quanto memorizzare la chiave stessa.

I creare l'hash facendo quanto segue:

  def sha256_rounds (raw, rounds = 100001): obj = hashlib.sha256 () for _ in xrange (rounds):
obj.update (raw) raw = obj.digest () return obj.digest ()  

Non è proprio chiaro cosa sia raw qui, ma presumo sia la password. Quello che stai facendo è un hash non salato usando SHA256. Non provare a creare il tuo KDF!

Dopo che è stato creato viene memorizzato con quanto segue:

  key = base64.urlsafe_b64encode (provided_key) length = len (chiave) con open (key_file, "a +") come key_: front_salt, back_salt = os.urandom (16), os.urandom (16) key_.write ("{} {} {}: {}". format (front_salt, key, back_salt, length))  

Quindi, stai creando la chiave hashing la password, quindi aggiungendo un sale davanti e dietro? Non solo la concatenazione di 2 diversi sali davanti e dietro non è standard, ma qui non si ottiene nulla perché viene eseguita dopo che il KDF è già terminato! Stai solo aggiungendo alcuni valori casuali per il gusto di averli lì.


Per mostrare quanto questo sia grave (come del commit 609fdb5ce976c7e5aa1832670505da60012b73bc), tutto ciò che serve per scaricare tutte le password memorizzate em> senza richiedere alcuna password principale è questo:

  from encryption.aes_encryption import AESCipherfrom lib.settings import store_key, MAIN_DIR, DATABASE_FILE, display_formatted_list_outputfrom sql.sql import create_connection, select_all_dataconn, cursor = create_connection (DATABASE_FILE) display_formatted_list_output (select_all_data (cursor, "encrypted_data"), store_key (MAIN_DIR))  

Sebbene provare a creare un gestore di password possa essere una buona esperienza di apprendimento, per favore non usarlo mai per qualcosa di lontanamente importante. Come suggerisce @Xenos, non sembra che tu abbia abbastanza esperienza che creare il tuo gestore di password sarebbe comunque davvero vantaggioso, sarebbe probabilmente un'opportunità di apprendimento migliore per dare un'occhiata a un gestore di password open source esistente.

Non sono nemmeno sicuro che "creare il tuo gestore di password" sia una buona esperienza.Penso che immergersi in uno esistente e osservare come funzionano e come sono codificati sia un'esperienza molto più interessante ed efficiente, dal momento che non commetterai errori (provando a fare il tuo PM, farai errori ea meno chequalcuno sta rileggendo il tuo codice, continuerai a fare ea credere in questi errori)
Non verrà utilizzato per nulla di importante, lo sto solo creando per imparare, sto solo memorizzando il valore hash delle password principali, non la password stessa
Rispetto ai gestori di password di terze parti a codice chiuso, creare il proprio gestore di password, purché si utilizzino le funzioni di crittografia delle password appropriate di altre persone per la password memorizzata e la funzione di hashing per la password principale, è, imo, molto più sicuro e paranoicoopzione piuttosto che fidarsi ciecamente che qualcun altro sarà al sicuro, non avere backend governativi e non vendere le password sul mercato nero.Ovviamente, questa logica non vale per quelli di terze parti open source.
@kloddant così la sicurezza dall'oscurità?Primo, i gestori di password offline difficilmente dispongono di "backend governativi" o vendono le tue password sul mercato nero.Se vieni infettato da qualsiasi tipo di malware, potrebbe essere in grado di distinguere tra un gestore di password noto e sicuro (e alzare le mani) e una versione fai-da-te, che può essere attaccata più facilmente.Inoltre, il gestore di password di OP è ora open source (e cancellarlo ora non aiuta) e probabilmente meno sicuro della maggior parte dei gestori di password open source.
@kloddant Anche se sono favorevole all'idea di utilizzare il software FOSS, essere FOSS di per sé non lo rende più sicuro.Non consiglierei di crearne uno tuo a meno che tu non sia un esperto di sicurezza (e forse nemmeno allora).C'è un vantaggio nell'avere una revisione professionale;non solo più occhi sul codice, ma soprattutto più _esperti_ occhi sul codice.
@CertifcateJunky: Per quello che vale, sbagliare la crittografia è un problema solo se stai definendo il tuo formato di file.È un po 'difficile rovinare la crittografia (KDF ecc.) Se stai lavorando su formati di database di password esistenti (come KDBX di KeePass) ... non ci vuole uno scienziato missilistico (crittografo?) Per confrontare l'XML originale e il tuonuovo XML e verifica che il tuo codice non aggiunga / rimuova informazioni estranee.Quindi, se stai solo cercando di migliorare l'interfaccia utente e imparare come funziona, potrebbe valere la pena attenersi a un formato di file esistente.Come bonus ottieni anche l'interoperabilità.
@Mehrdad Non è vero al 100%, poiché potresti ancora usare un PRNG cattivo invece di un buon CSPRNG per la generazione salt o iv, consentire lo scambio di segreti in memoria, ecc.Ciò preserverebbe la compatibilità pur rimanendo insicuro.Un buon punto comunque.
@AndrolGenhald: Suppongo ... ma se ne sai abbastanza per usare una funzione hash sicura è piuttosto difficile non sapere abbastanza per usare un RNG sicuro.Anche se sarei d'accordo sul fatto che cose come prevenire attacchi di canale laterale e rafforzare contro vari attacchi da altri programmi (incluso JS) sono * molto * più difficili, quindi non consiglierei di diffondere il gestore di password ad altri a meno che tu non sappia davvero cosa seifacendo (nel caso qualcuno trovi un buco) ... ma sì per uso personale gli darei un passaggio.(Sì, immagino che questa sia sicurezza per oscurità. Scusa ...)
Non stavo sostenendo la sicurezza per oscurità;Stavo dicendo che scrivere il proprio software di gestione delle password, non le funzioni crittografiche in sé, ma solo il software che le utilizza, è meglio che fidarsi del software di qualcun altro.
@kloddant Il problema è che puoi ancora fare molte cose sbagliate mentre usi buone implementazioni di funzioni crittografiche (come dimostrato dalla domanda).
@AndrolGenhald Non credo che kloddant lo stia negando.Sta dicendo che il rischio particolare deve essere bilanciato dal rischio che si corre nell'affidarsi al software closed source di terze parti (e ammettiamolo, le perdite di Snowden hanno dimostrato che quel rischio è molto reale).
@AndrolGenhald Se vuoi vederlo e come funziona, _so_far_, ho aggiunto un collegamento al repository git alla fine della mia domanda.Grazie per il vostro consiglio!
Andiamo ragazzi, _è un gestore di password privato_.Genera password che sostituiscono le "tr0ub4dor" di altre persone.Per quello che è il suo scopo, potresti anche usare un paio di giri di RANDU come "funzione hash" e l'attuale Dow Jones come "sale" ... - Naturalmente, se qualcuno ha accesso al database, tu 'Allora sei fregato, ma oserei dire se consideri questo rischio significativo, allora hai sbagliato le tue priorità.Evitare qualsiasi software closed-source sulla tua macchina è una mossa _molto_ più sensata.(Il che non vuol dire che non dovresti invece utilizzare un gestore open source collaudato.)
@leftaroundabout Per me il problema non è che è insicuro se qualcuno vi accede;se desideri memorizzare le tue password in un foglio di calcolo non crittografato che potrebbe essere accettabile a seconda di ciò che consideri una minaccia.Il problema è che _tenta_ di crittografare le password in modo da tenerle al sicuro e non riesce.
Vero.E come hai detto, l'implementazione del PO ha davvero poco senso.Stavo solo obiettando alla tua affermazione iniziale che scrivere il proprio gestore di password è un errore.Potrebbe non _essere utile_ di per sé farlo, ma non può davvero nuocere a dilettarsi con esso da soli (a meno che, in effetti, non lo usi effettivamente per cose importanti e rilasciando altri livelli di sicurezza, che sarebbe un'idea orribile).E _può_ essere abbastanza istruttivo.
@leftaroundabout Immagino che dipenda da come interpreti "molta esperienza".In relazione all'esperienza dell'OP, intendevo "molta esperienza" per significare che puoi almeno ottenere la crittografia corretta e non avere altre evidenti vulnerabilità o errori.In questo modo _dovresti_ essere per lo più ok se il tuo database crittografato perde, ma probabilmente non vuoi raccomandare a nessun altro di usarlo.Le minacce che _tu_ consideri importanti non sono necessariamente le stesse che _tutti gli altri_ considerano importanti e un gestore di password generale dovrebbe proteggere da tutte le minacce che può.
Jeffrey Goldberg
2018-06-30 01:57:26 UTC
view on stackexchange narkive permalink

Per prima cosa lasciatemi rivelare che lavoro per 1Password, un gestore di password, e sebbene possa sembrare self-serving, devo aggiungere la mia voce a coloro che vi dicono che scrivere un gestore di password sicuro è più difficile di quanto possa sembrare a prima vista. D'altra parte, è positivo che tu ci provi e lo chiedi in pubblico. Questo è un buon modo per imparare che è più difficile di quanto possa sembrare a prima vista.

Non eseguire l'autenticazione. Crittografa invece

Ho dato una rapida occhiata alla fonte a cui ti colleghi nel tuo aggiornamento e sono lieto di vedere che hai seguito alcuni consigli che sono stati offerti così lontano. Ma a meno che io non stia interpretando male il tuo codice, hai ancora un errore di progettazione fondamentale che lo rende estremamente insicuro .

Sembra che tu tratti la voce della password principale come un'autenticazione domanda invece che come derivazione della chiave di crittografia. Cioè, stai controllando la password inserita (dopo l'hashing) con qualcosa che è stato memorizzato e, se il controllo ha esito positivo, stai utilizzando quella chiave memorizzata per decrittografare i dati.

Quello che dovresti fare è memorizzare un chiave di crittografia crittografata. Chiamiamola la chiave principale. Questo dovrebbe essere generato in modo casuale quando si configura per la prima volta una nuova istanza. Questa chiave principale è ciò che utilizzi per crittografare e decrittografare i dati effettivi.

La chiave principale non viene mai memorizzata in chiaro. Dovrebbe essere crittografato con quella che a volte viene chiamata Key Encryption Key (KEK). Questa KEK è derivata tramite la funzione KDF (Key Derivation Function) dalla password principale dell'utente e da un salt.

Quindi l'output del tuo utilizzo di PBKDF2 (grazie per averlo usato invece di hashing ripetuto) sarà la tua KEK e usi la KEK per decrittografare la chiave principale, quindi utilizzi la chiave principale decrittografata per decrittografare i tuoi dati.

Forse è quello che stai facendo e ho letto male il tuo codice. Ma se stai solo confrontando ciò che ottieni attraverso il tuo KDF con qualcosa memorizzato e poi prendi una decisione se decrittografare, allora il tuo sistema è enormemente e orrendamente insicuro.

Per favore crea la prima riga più audace del progetto README urla il fatto che è estremamente insicuro. E aggiungilo anche a ogni file sorgente.

Alcuni altri punti

Qui ci sono solo alcune altre cose che ho notato guardando il sorgente

  • Usa una modalità di crittografia autenticata come GCM invece di CBC.

  • Il tuo approccio di crittografare l'intera cosa funzionerà per piccole quantità di dati, ma ha vinto non scalare una volta che hai set di dati più grandi.

    Quando arriva il momento di crittografare (parti di) record separatamente, tieni presente che avrai bisogno di un nonce (per GCM) o di vettori di inizializzazione univoci (se ti attacchi incautamente con CBC) per ogni record.

  • La distruzione dei tuoi dati dopo 3 errori è pericolosa e non aggiunge sicurezza.

    Un aggressore sofisticato si limiterà a copiare file di dati e scrivere il proprio script per tentare di decifrare la password. Faranno anche la propria copia dei dati acquisiti. La distruzione dei tuoi dati rende solo facile per qualcuno distruggere accidentalmente o intenzionalmente i tuoi dati.

Quanti round di PBKDF2

Quindi alla tua domanda originale. La risposta è che dipende. Da un lato, dipende da quanto è forte la password principale e dal tipo di risorse che un utente malintenzionato utilizzerà per risolvere il problema. E dipende anche da quali risorse il difensore può lanciargli contro. Ad esempio, eseguirai il tuo KDF su un dispositivo mobile con una capacità della batteria limitata?

Ma come accade noi di 1Password stiamo cercando di misurare il costo del cracking offrendo premi a persone o gruppi che violano una password a 42,5 bit con hash con 100.000 round di PBKDF2-HMAC-SHA256.

Guadagni in diminuzione dall'hashing lento

Ma ciò che è più importante che capire come pesare tutti questi è capire che l'hashing lento, sebbene assolutamente essenziale per un gestore di password KDF, produce guadagni marginali decrescenti una volta regolato abbastanza alto .

Supponi di utilizzare 100.000 round e di avere una password principale, P . Se scegliessi una cifra casuale, da 0 a 9 e la aggiungessi a P , otterrai un aumento di dieci volte della resistenza all'incrinatura. Per ottenere lo stesso aumento aumentando i round di PBKDF2, dovresti arrivare a 1 milione di round. Il punto è che una volta che hai una discreta quantità di hashing lento, ottieni molta più forza per lo sforzo del difensore aumentando la forza della password rispetto a quando aumenti il ​​numero di round.

Ho scritto su questo alcuni anni fa in Bcrypt è fantastico, ma il cracking delle password non è fattibile?

Con aria di sfida non è facile.Nel README ti dice di non usarlo, posso aggiungere qualcosa dicendo che è insicuro e un work in progress in alto però.Inoltre, non hai letto male il codice, quello che sto facendo è l'hashing della chiave e confrontalo con l'hash memorizzato.Ora capisco che probabilmente non è la soluzione migliore.La ringrazio per la risposta.
@CertifcateJunky: Considera sempre cosa potrebbe fare qualcuno cambiando il tuo codice sorgente e ricompilandolo.Questo rende ovvio il motivo per cui non puoi semplicemente controllare la password inserita e quindi consentire l'uso di una chiave che era già memorizzata su disco: cambia il codice per bypassare quel controllo e hai ancora una chiave di decrittazione funzionante, se i bit della chiave non lo sonoIn realtà * dipendono * dalla password di sblocco.Questa è la differenza tra l'autenticazione dell'utente e la richiesta di fornire effettivamente un segreto che si trasforma nella chiave.Se il tuo codice funziona in questo modo, va ben oltre "probabilmente non è la soluzione migliore".
KEK ... mi ha fatto ridere.
@PeterCordes Ci ho lavorato di più e mi è venuta l'idea (soprattutto grazie ai consigli di tutti) di mantenere la password principale, ma usandola solo come verifica (per ora) e generando una "chiave" da quella password conpersonaggi casuali e cosa no.La chiave viene decrittografata e utilizzata solo se l'hash della password principale corrisponde all'hash memorizzato, inoltre la chiave non viene mai memorizzata decrittografata (a meno che non si conti la memoria che è un altro gioco di palla).Quella "chiave" viene utilizzata per crittografare le password invece della password principale.
@CertifcateJunky: Sì, trasformare la password principale in una chiave di decrittazione per la chiave principale è l'idea giusta.Questa risposta suggerisce alcuni * buoni * modi per trasformare le password in chiavi.
@PeterCordes Sto anche esaminando le modifiche ai file come ulteriore precauzione.
crovers
2018-06-28 19:43:35 UTC
view on stackexchange narkive permalink

Non utilizzare SHA256 grezzo: può essere accelerato utilizzando GPU e quindi soggetto a forza bruta. Non è rotto, da nessuna parte, semplicemente non è più la migliore pratica. PBKDF2 funziona per contrastarlo in una certa misura, ma dovresti usare bcrypt o scrypt preferenzialmente.

Reinventare la ruota (che è più o meno quello che stai facendo se non stai usando PBKDF2-SHA256, bcrypt o scrypt) non è mai una buona idea in crittografia.

@Azxdreuwa Gli ASIC per scrypt (usati per litecoin) sono possibili perché sono stati scelti parametri deboli.Il vero problema con scrypt è che ridimensiona insieme l'utilizzo della memoria e della cpu ed è stato progettato per un contesto di crittografia del disco in cui il parametro può essere più alto.In un contesto web in cui è necessario un costo inferiore, è facile finire per essere meno sicuri di bcrypt, anche se si spera ancora resistenti agli ASIC.Argon2 ha fortunatamente parametri separati per CPU e costo della memoria.
Nel caso in cui non fosse ovvio dal mio commento precedente, quegli ASIC non potevano essere usati per parametri di scrypt diversi da quelli scelti per litecoin (che sono particolarmente cattivi).
ilkkachu
2018-06-29 19:38:41 UTC
view on stackexchange narkive permalink

Guardando il codice nel link che hai postato (riprodotto sotto, in parte), sono un po 'confuso.

Se l'ho letto correttamente, main () chiama store_key () per caricare una chiave da un file sul disco, quindi usa compare () per confrontare una chiave fornita dall'utente con quella. Entrambi vengono eseguiti tramite sha256_rounds () che esegue PBKDF2 su di essi.

Quindi si utilizza la stessa stored_key , quella caricata dal file, fare la crittografia?

Questo è completamente e assolutamente al contrario. Chiunque abbia accesso al file della chiave può semplicemente caricare la chiave archiviata e utilizzarla per decrittografare i dati archiviati o archiviare nuovi dati crittografati con la stessa chiave, senza dover passare attraverso lo script a " verifica "la password.

Nella migliore delle ipotesi, penso che tu stia confondendo utilizzando la password / passphrase fornita dall'utente per produrre una chiave per la crittografia e autenticare l'utente contro un hash della password memorizzata . Non puoi fare entrambe le cose con lo stesso hash, la crittografia è completamente irrilevante se hai memorizzato la chiave di crittografia insieme ai dati crittografati.

Certo, le password vengono elaborate con una sorta di hash / KDF sia quando utilizzato per l'autenticazione che per produrre una chiave di crittografia. Ma questo è più come un passaggio di pre-elaborazione necessario solo perché gli esseri umani non possono memorizzare chiavi a 256 bit e dobbiamo invece fare affidamento su password a bassa entropia. Quello che fai con l'hash / chiave che hai è diverso tra i due casi d'uso.


Poi c'è la cosa che hai un salt hardcoded in sha256_rounds () , che praticamente sconfigge lo scopo di un sale in generale. Potrei anche commentare il codice più in generale, ma questo non è codereview.SE.

Per favore dimmi che ho letto il codice sbagliato.


Le parti del codice Ho guardato:

  def main (): stored_key = store_key (MAIN_DIR) se non confronta (stored_key): ... else: ... # later
password = prompt ("inserisci la password da memorizzare:", hide = True) encrypted_password = AESCipher (stored_key) .encrypt (password) def store_key (percorso): key_file = "{} /. key" .format (percorso) in caso contrario os.path.exists (key_file): ... else: retval = open (key_file) .read () amount = retval.split (":") [- 1] edited = retval [16:] edited = edited [: int (importo)] restituisce modificato  
no, questo lo riassume.Non ho detto che fosse sicuro, solo che ne stavo facendo uno: P, vedo il tuo punto però.
@CertifcateJunky, bene, se sei contento di non dire che era sicuro, potresti semplicemente abbandonare le chiamate AES / SHA per sempre e concentrarti sull'archiviazione e sul caricamento dei dati.Se si considera l'idea di giocare con le primitive crittografiche, almeno iniziare con una descrizione di alto livello degli algoritmi e dei dati utilizzati dal sistema, quali parti sono segrete e cosa influenza cosa.E vai a leggere alcune descrizioni di come funzionano le utilità di crittografia esistenti (ecc.) E considera perché fanno quello che fanno.
Penso che tu stia fraintendendo quello che ho detto e non prendendolo nel modo in cui lo intendevo.Capisco perfettamente quello che stai dicendo e sto effettivamente cercando di trovare un modo per modificarlo.Era uno scherzo, non un'affermazione seria.
Bufke
2018-06-29 19:05:50 UTC
view on stackexchange narkive permalink

Utilizza uno strumento aggiornato che deciderà per te e aumenterà il conteggio predefinito o persino l'algoritmo nel tempo. Suggerirei libsodium, ma ce ne sono altri. Libsodium ha i valori predefiniti per l ' hashing delle password "interattivo" e per la crittografia simmetrica. Assicurati che il tuo software possa un giorno "aggiornare" le impostazioni secondo necessità. Uno strumento come libsodium cambierà le impostazioni predefinite di volta in volta in modo che tu possa seguirli.

Sviluppo per un gestore di password open source e utilizzo libsodium. Inoltre ho trovato che valeva la pena leggere il documento sulla sicurezza di Mitro.

Lo scopo dello strumento è imparare come funziona l'hashing e come funzionano i gestori di password.Non sto suggerendo a nessuno di utilizzare questo strumento, perché beh, _L'ho scritto_ (lol).Ma penso che sia una buona pratica per determinare come funzionano le cose.Se sei interessato, puoi vederlo [qui] (https://github.com/Ekultek/letmein)
Di sicuro, lo capisco perfettamente.Vai a scriverlo, commetti errori e impara!Suggerirei comunque di guardare altri software come libsodium per imparare cosa usano.In genere un gestore di password si occupa di archiviare le password e presentare un'interfaccia utente.Quasi tutti useranno altre librerie software per eseguire la crittografia effettiva.Separazione degli interessi.Grazie per il link!Vedo che stai usando python: potresti essere interessato a questo https://www.crypto101.io/ che usa Python negli esempi.
Lo guarderò.Sono curioso di sapere come mantengono la loro crittografia allo standard.Grazie per il collegamento!


Questa domanda e risposta è stata tradotta automaticamente dalla lingua inglese. Il contenuto originale è disponibile su stackexchange, che ringraziamo per la licenza cc by-sa 4.0 con cui è distribuito.
Loading...