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) .



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow