Go
Crittografia
Ricerca…
introduzione
Scopri come crittografare e decrittografare i dati con Go. Tieni presente che questo non è un corso sulla crittografia, ma piuttosto come ottenerlo con Go.
Crittografia e decrittografia
Prefazione
Questo è un esempio dettagliato su come crittografare e decodificare i dati con Go. Il codice degli usi è abbreviato, ad esempio la gestione degli errori non è menzionata. Il progetto completo di lavoro con gestione degli errori e interfaccia utente può essere trovato su Github qui .
crittografia
Introduzione e dati
Questo esempio descrive una crittografia e una decrittazione funzionanti complete in Go. Per fare ciò, abbiamo bisogno di un dato. In questo esempio, usiamo la nostra propria struttura dati secret
:
type secret struct {
DisplayName string
Notes string
Username string
EMail string
CopyMethod string
Password string
CustomField01Name string
CustomField01Data string
CustomField02Name string
CustomField02Data string
CustomField03Name string
CustomField03Data string
CustomField04Name string
CustomField04Data string
CustomField05Name string
CustomField05Data string
CustomField06Name string
CustomField06Data string
}
Successivamente, vogliamo crittografare un tale secret
. L'esempio funzionante completo può essere trovato qui (link a Github) . Ora, il processo passo-passo:
Passo 1
Prima di tutto, abbiamo bisogno di una specie di password principale per proteggere il segreto: masterPassword := "PASS"
Passo 2
Tutti i metodi di crittografia che funzionano con byte invece di stringhe. Quindi, costruiamo un array di byte con i dati del nostro segreto.
secretBytesDecrypted := []byte(fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
artifact.DisplayName,
strings.Replace(artifact.Notes, "\n", string(65000), -1),
artifact.Username,
artifact.EMail,
artifact.CopyMethod,
artifact.Password,
artifact.CustomField01Name,
artifact.CustomField01Data,
artifact.CustomField02Name,
artifact.CustomField02Data,
artifact.CustomField03Name,
artifact.CustomField03Data,
artifact.CustomField04Name,
artifact.CustomField04Data,
artifact.CustomField05Name,
artifact.CustomField05Data,
artifact.CustomField06Name,
artifact.CustomField06Data,
))
Passaggio 3
Creiamo un po 'di sale per prevenire gli attacchi dei tavoli arcobaleno, cf. Wikipedia : saltBytes := uuid.NewV4().Bytes()
. Qui, usiamo un UUID v4 che non è prevedibile.
Passaggio 4
Ora, siamo in grado di ricavare una chiave e un vettore dalla password principale e dal sale casuale, per quanto riguarda RFC 2898:
keyLength := 256
rfc2898Iterations := 6
keyVectorData := pbkdf2.Key(masterPassword, saltBytes, rfc2898Iterations, (keyLength/8)+aes.BlockSize, sha1.New)
keyBytes := keyVectorData[:keyLength/8]
vectorBytes := keyVectorData[keyLength/8:]
Passaggio 5
La modalità CBC desiderata funziona con blocchi interi. Pertanto, dobbiamo verificare se i nostri dati sono allineati a un blocco completo. In caso contrario, dobbiamo riempirlo:
if len(secretBytesDecrypted)%aes.BlockSize != 0 {
numberNecessaryBlocks := int(math.Ceil(float64(len(secretBytesDecrypted)) / float64(aes.BlockSize)))
enhanced := make([]byte, numberNecessaryBlocks*aes.BlockSize)
copy(enhanced, secretBytesDecrypted)
secretBytesDecrypted = enhanced
}
Passaggio 6
Ora creiamo un codice AES: aesBlockEncrypter, aesErr := aes.NewCipher(keyBytes)
Passaggio 7
Ci riserviamo la memoria necessaria per i dati crittografati: encryptedData := make([]byte, len(secretBytesDecrypted))
. Nel caso di AES-CBC, i dati crittografati avevano la stessa lunghezza dei dati non crittografati.
Passaggio 8
Ora, dovremmo creare il codificatore e crittografare i dati:
aesEncrypter := cipher.NewCBCEncrypter(aesBlockEncrypter, vectorBytes)
aesEncrypter.CryptBlocks(encryptedData, secretBytesDecrypted)
Ora, i dati crittografati si trovano all'interno della variabile encryptedData
.
Passaggio 9
I dati crittografati devono essere memorizzati. Ma non solo i dati: senza il sale, i dati crittografati non potevano essere decifrati. Quindi, dobbiamo usare un qualche tipo di formato di file per gestirlo. Qui, codifichiamo i dati crittografati come base64, cf. Wikipedia :
encodedBytes := make([]byte, base64.StdEncoding.EncodedLen(len(encryptedData)))
base64.StdEncoding.Encode(encodedBytes, encryptedData)
Successivamente, definiamo il nostro contenuto di file e il nostro formato di file. Il formato ha questo aspetto: salt[0x10]base64 content
. Per prima cosa, immagazziniamo il sale. Per marcare l'inizio del contenuto di base64, memorizziamo il byte 10
. Funziona, perché base64 non usa questo valore. Pertanto, potremmo trovare l'inizio di base64 cercando la prima occorrenza di 10
dalla fine all'inizio del file.
fileContent := make([]byte, len(saltBytes))
copy(fileContent, saltBytes)
fileContent = append(fileContent, 10)
fileContent = append(fileContent, encodedBytes...)
Passaggio 10
Infine, potremmo scrivere il nostro file: writeErr := ioutil.WriteFile("my secret.data", fileContent, 0644)
.
decrittazione
Introduzione e dati
Per quanto riguarda la crittografia, abbiamo bisogno di alcuni dati con cui lavorare. Pertanto, assumiamo di avere un file crittografato e la struttura citata secret
. L'obiettivo è leggere i dati crittografati dal file, decodificarlo e creare un'istanza della struttura.
Passo 1
Il primo passo è identico alla crittografia: è necessario un tipo di password principale per decrittografare il segreto: masterPassword := "PASS"
.
Passo 2
Ora, leggiamo i dati crittografati dal file: encryptedFileData, bytesErr := ioutil.ReadFile(filename)
.
Passaggio 3
Come accennato in precedenza, potremmo dividere il sale e i dati crittografati dal byte delimitatore 10
, ricercato all'indietro dalla fine all'inizio:
for n := len(encryptedFileData) - 1; n > 0; n-- {
if encryptedFileData[n] == 10 {
saltBytes = encryptedFileData[:n]
encryptedBytesBase64 = encryptedFileData[n+1:]
break
}
}
Passaggio 4
Successivamente, dobbiamo decodificare i byte codificati base64:
decodedBytes := make([]byte, len(encryptedBytesBase64))
countDecoded, decodedErr := base64.StdEncoding.Decode(decodedBytes, encryptedBytesBase64)
encryptedBytes = decodedBytes[:countDecoded]
Passaggio 5
Ora, siamo in grado di ricavare una chiave e un vettore dalla password principale e dal sale casuale, per quanto riguarda RFC 2898:
keyLength := 256
rfc2898Iterations := 6
keyVectorData := pbkdf2.Key(masterPassword, saltBytes, rfc2898Iterations, (keyLength/8)+aes.BlockSize, sha1.New)
keyBytes := keyVectorData[:keyLength/8]
vectorBytes := keyVectorData[keyLength/8:]
Passaggio 6
Creare un codice AES: aesBlockDecrypter, aesErr := aes.NewCipher(keyBytes)
.
Passaggio 7
Riservare la memoria necessaria per i dati decrittografati: decryptedData := make([]byte, len(encryptedBytes))
. Per definizione, ha la stessa lunghezza dei dati crittografati.
Passaggio 8
Ora crea il decodificatore e decrittografa i dati:
aesDecrypter := cipher.NewCBCDecrypter(aesBlockDecrypter, vectorBytes)
aesDecrypter.CryptBlocks(decryptedData, encryptedBytes)
Passaggio 9
Converti i byte letti nella stringa: decryptedString := string(decryptedData)
. Perché abbiamo bisogno di linee, dividere la stringa: lines := strings.Split(decryptedString, "\n")
.
Passaggio 10
Costruisci un secret
fuori dalle righe:
artifact := secret{}
artifact.DisplayName = lines[0]
artifact.Notes = lines[1]
artifact.Username = lines[2]
artifact.EMail = lines[3]
artifact.CopyMethod = lines[4]
artifact.Password = lines[5]
artifact.CustomField01Name = lines[6]
artifact.CustomField01Data = lines[7]
artifact.CustomField02Name = lines[8]
artifact.CustomField02Data = lines[9]
artifact.CustomField03Name = lines[10]
artifact.CustomField03Data = lines[11]
artifact.CustomField04Name = lines[12]
artifact.CustomField04Data = lines[13]
artifact.CustomField05Name = lines[14]
artifact.CustomField05Data = lines[15]
artifact.CustomField06Name = lines[16]
artifact.CustomField06Data = lines[17]
Infine, ricrea le interruzioni di riga all'interno del campo delle note: artifact.Notes = strings.Replace(artifact.Notes, string(65000), "\n", -1)
.