Suche…


Einführung

Finden Sie heraus, wie Sie mit Go Daten verschlüsseln und entschlüsseln können. Beachten Sie, dass dies kein Kurs über Kryptographie ist, sondern wie Sie ihn mit Go erreichen.

Verschlüsselung und Entschlüsselung

Vorwort

Dies ist ein detailliertes Beispiel, wie Daten mit Go verschlüsselt und entschlüsselt werden. Der Anwendungscode ist kurz, dh die Fehlerbehandlung wird nicht erwähnt. Der vollständige Arbeitsprojekt mit der Fehlerbehandlung und Benutzeroberfläche könnte auf Github finden hier .


Verschlüsselung

Einleitung und Daten

Dieses Beispiel beschreibt eine vollständige Verschlüsselung und Entschlüsselung in Go. Dazu benötigen wir Daten. In diesem Beispiel verwenden wir unsere eigenen Datenstruktur 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
}

Als nächstes wollen wir ein solches secret verschlüsseln. Das vollständige Arbeitsbeispiel finden Sie hier (Link zu Github) . Nun der Schritt für Schritt:

Schritt 1

Zunächst benötigen wir eine Art Master-Passwort, um das Geheimnis zu schützen: masterPassword := "PASS"

Schritt 2

Alle Krypto-Methoden, die mit Bytes statt mit Strings arbeiten. Daher bauen wir ein Byte-Array mit den Daten unseres Geheimnisses auf.

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

Schritt 3

Wir erzeugen etwas Salz, um Regenbogenangriffe zu verhindern, vgl. Wikipedia : saltBytes := uuid.NewV4().Bytes() . Hier verwenden wir eine UUID v4, die nicht vorhersehbar ist.

Schritt 4

Nun können wir einen Schlüssel und einen Vektor aus dem Master-Passwort und dem Zufalls-Salt für RFC 2898 ableiten:

keyLength := 256
rfc2898Iterations := 6

keyVectorData := pbkdf2.Key(masterPassword, saltBytes, rfc2898Iterations, (keyLength/8)+aes.BlockSize, sha1.New)
keyBytes := keyVectorData[:keyLength/8]
vectorBytes := keyVectorData[keyLength/8:]

Schritt 5

Der gewünschte CBC-Modus funktioniert mit ganzen Blöcken. Daher müssen wir prüfen, ob unsere Daten auf einen vollständigen Block ausgerichtet sind. Wenn nicht, müssen wir es auffüllen:

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
}

Schritt 6

Jetzt erstellen wir eine AES-Chiffre: aesBlockEncrypter, aesErr := aes.NewCipher(keyBytes)

Schritt 7

Wir reservieren den erforderlichen Speicher für die verschlüsselten Daten: encryptedData := make([]byte, len(secretBytesDecrypted)) . Im Falle von AES-CBC hatten die verschlüsselten Daten die gleiche Länge wie die unverschlüsselten Daten.

Schritt 8

Nun sollten wir den Verschlüsseler erstellen und die Daten verschlüsseln:

aesEncrypter := cipher.NewCBCEncrypter(aesBlockEncrypter, vectorBytes)
aesEncrypter.CryptBlocks(encryptedData, secretBytesDecrypted)

Die verschlüsselten Daten befinden sich jetzt in der Variablen encryptedData .

Schritt 9

Die verschlüsselten Daten müssen gespeichert werden. Aber nicht nur die Daten: Ohne das Salz könnten die verschlüsselten Daten nicht entschlüsselt werden. Daher müssen wir ein Dateiformat verwenden, um dies zu verwalten. Hier verschlüsseln wir die verschlüsselten Daten als base64, vgl. Wikipedia :

encodedBytes := make([]byte, base64.StdEncoding.EncodedLen(len(encryptedData)))
base64.StdEncoding.Encode(encodedBytes, encryptedData)

Als Nächstes definieren wir unseren Dateiinhalt und unser eigenes Dateiformat. Das Format sieht folgendermaßen aus: salt[0x10]base64 content . Zuerst lagern wir das Salz. Um den Anfang des base64-Inhalts zu markieren, speichern wir das Byte 10 . Dies funktioniert, weil base64 diesen Wert nicht verwendet. Daher konnten wir den Anfang von base64 finden, indem wir das erste Vorkommen von 10 vom Ende bis zum Anfang der Datei suchen.

fileContent := make([]byte, len(saltBytes))
copy(fileContent, saltBytes)
fileContent = append(fileContent, 10)
fileContent = append(fileContent, encodedBytes...)

Schritt 10

Schließlich könnten wir unsere Datei schreiben: writeErr := ioutil.WriteFile("my secret.data", fileContent, 0644) .


Entschlüsselung

Einleitung und Daten

Für die Verschlüsselung benötigen wir einige Daten, um damit arbeiten zu können. Wir gehen also davon aus, dass wir eine verschlüsselte Datei und die erwähnte Struktur secret . Ziel ist es, die verschlüsselten Daten aus der Datei zu lesen, zu entschlüsseln und eine Instanz der Struktur zu erstellen.

Schritt 1

Der erste Schritt ist identisch mit der Verschlüsselung: Wir benötigen eine Art Master-Passwort, um das Geheimnis zu entschlüsseln: masterPassword := "PASS" .

Schritt 2

Nun lesen wir die verschlüsselten Daten aus der Datei: encryptedFileData, bytesErr := ioutil.ReadFile(filename) .

Schritt 3

Wie bereits erwähnt, konnten wir Salt- und verschlüsselte Daten nach dem Trennzeichen-Byte 10 aufteilen, das vom Ende bis zum Anfang gesucht wurde:

for n := len(encryptedFileData) - 1; n > 0; n-- {
    if encryptedFileData[n] == 10 {
        saltBytes = encryptedFileData[:n]
        encryptedBytesBase64 = encryptedFileData[n+1:]
        break
    }
} 

Schritt 4

Als Nächstes müssen wir die base64-codierten Bytes dekodieren:

decodedBytes := make([]byte, len(encryptedBytesBase64))
countDecoded, decodedErr := base64.StdEncoding.Decode(decodedBytes, encryptedBytesBase64)
encryptedBytes = decodedBytes[:countDecoded]

Schritt 5

Nun können wir einen Schlüssel und einen Vektor aus dem Master-Passwort und dem Zufalls-Salt für RFC 2898 ableiten:

keyLength := 256
rfc2898Iterations := 6

keyVectorData := pbkdf2.Key(masterPassword, saltBytes, rfc2898Iterations, (keyLength/8)+aes.BlockSize, sha1.New)
keyBytes := keyVectorData[:keyLength/8]
vectorBytes := keyVectorData[keyLength/8:]

Schritt 6

Erstellen Sie eine AES-Verschlüsselung: aesBlockDecrypter, aesErr := aes.NewCipher(keyBytes) .

Schritt 7

Reservieren Sie den erforderlichen Speicher für die entschlüsselten Daten: decryptedData := make([]byte, len(encryptedBytes)) . Definitionsgemäß hat es dieselbe Länge wie die verschlüsselten Daten.

Schritt 8

Erstellen Sie nun den Entschlüsseler und entschlüsseln Sie die Daten:

aesDecrypter := cipher.NewCBCDecrypter(aesBlockDecrypter, vectorBytes)
aesDecrypter.CryptBlocks(decryptedData, encryptedBytes)

Schritt 9

Konvertieren Sie die gelesenen Bytes in string: decryptedString := string(decryptedData) . Da wir Zeilen benötigen, teilen Sie die Zeichenfolge: lines := strings.Split(decryptedString, "\n") .

Schritt 10

Konstruiere ein secret aus den Linien:

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]

Erstellen Sie schließlich die Zeilenumbrüche innerhalb des Notizfeldes neu: artifact.Notes = strings.Replace(artifact.Notes, string(65000), "\n", -1)



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow