Zoeken…


Invoering

Ontdek hoe u gegevens kunt coderen en decoderen met Go. Houd er rekening mee dat dit geen cursus over cryptografie is, maar hoe je dit kunt bereiken met Go.

Versleuteling en ontsleuteling

Voorwoord

Dit is een gedetailleerd voorbeeld van het coderen en decoderen van gegevens met Go. De gebruikscode is korter, bijvoorbeeld de foutafhandeling wordt niet vermeld. De volledig werkende project met error handling en de user interface kan worden gevonden op Github hier .


Encryption

Introductie en gegevens

Dit voorbeeld beschrijft een volledig werkende codering en decodering in Go. Hiervoor hebben we gegevens nodig. In dit voorbeeld gebruiken we onze eigen secret datastructuur:

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
}

Vervolgens willen we zo'n secret coderen. Het volledige werkende voorbeeld is hier te vinden (link naar Github) . Nu het stapsgewijze proces:

Stap 1

Allereerst hebben we een soort hoofdwachtwoord nodig om het geheim te beschermen: masterPassword := "PASS"

Stap 2

Alle cryptomethoden die met bytes werken in plaats van tekenreeksen. We construeren dus een byte-array met de gegevens van ons geheim.

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

Stap 3

We maken wat zout om regenboogtabelaanvallen te voorkomen, cf. Wikipedia : saltBytes := uuid.NewV4().Bytes() . Hier gebruiken we een UUID v4 die niet voorspelbaar is.

Stap 4

Nu kunnen we een sleutel en een vector afleiden uit het hoofdwachtwoord en het willekeurige zout, met betrekking tot 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:]

Stap 5

De gewenste CBC-modus werkt met hele blokken. We moeten dus controleren of onze gegevens op een volledig blok zijn afgestemd. Zo niet, dan moeten we het opvullen:

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
}

Stap 6

Nu maken we een AES-codering: aesBlockEncrypter, aesErr := aes.NewCipher(keyBytes)

Stap 7

We reserveren het nodige geheugen voor de gecodeerde gegevens: encryptedData := make([]byte, len(secretBytesDecrypted)) . In het geval van AES-CBC hadden de gecodeerde gegevens dezelfde lengte als de niet-gecodeerde gegevens.

Stap 8

Nu moeten we de codeerder maken en de gegevens coderen:

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

Nu bevinden de gecodeerde gegevens zich in de variabele encryptedData .

Stap 9

De gecodeerde gegevens moeten worden opgeslagen. Maar niet alleen de gegevens: zonder het zout konden de gecodeerde gegevens niet worden gedecodeerd. Daarom moeten we een soort bestandsindeling gebruiken om dit te beheren. Hier coderen we de gecodeerde gegevens als base64, cf. Wikipedia :

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

Vervolgens definiëren we onze bestandsinhoud en onze eigen bestandsindeling. De indeling ziet er als volgt uit: salt[0x10]base64 content . Eerst slaan we het zout op. Om het begin van de base64-inhoud te markeren, slaan we de byte 10 . Dit werkt omdat base64 deze waarde niet gebruikt. Daarom konden we het begin van base64 vinden door te zoeken naar het eerste exemplaar van 10 vanaf het einde tot het begin van het bestand.

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

Stap 10

Eindelijk kunnen we ons bestand schrijven: writeErr := ioutil.WriteFile("my secret.data", fileContent, 0644) .


decryptie

Introductie en gegevens

Wat codering betreft, hebben we wat gegevens nodig om mee te werken. We gaan er dus van uit dat we een gecodeerd bestand hebben en dat de genoemde structuur secret . Het doel is om de gecodeerde gegevens uit het bestand te lezen, te decoderen en een instantie van de structuur te maken.

Stap 1

De eerste stap is identiek aan de codering: we hebben een soort hoofdwachtwoord nodig om het geheim te ontsleutelen: masterPassword := "PASS" .

Stap 2

Nu lezen we de gecodeerde gegevens uit het bestand: encryptedFileData, bytesErr := ioutil.ReadFile(filename) .

Stap 3

Zoals eerder vermeld, konden we zout en gecodeerde gegevens splitsen door de scheiding byte 10 , achteruit gezocht vanaf het einde tot het begin:

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

Stap 4

Vervolgens moeten we de base64-gecodeerde bytes decoderen:

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

Stap 5

Nu kunnen we een sleutel en een vector afleiden uit het hoofdwachtwoord en het willekeurige zout, met betrekking tot 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:]

Stap 6

Maak een AES-codering: aesBlockDecrypter, aesErr := aes.NewCipher(keyBytes) .

Stap 7

Reserveer het benodigde geheugen voor de gedecodeerde gegevens: decryptedData := make([]byte, len(encryptedBytes)) . Per definitie heeft het dezelfde lengte als de gecodeerde gegevens.

Stap 8

Maak nu de decrypter en decodeer de gegevens:

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

Stap 9

Converteer de gelezen bytes naar string: decryptedString := string(decryptedData) . Omdat we lijnen nodig hebben, splitst u de string: lines := strings.Split(decryptedString, "\n") .

Stap 10

Construeer een secret uit de lijnen:

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]

Maak ten slotte de regeleinden in het artifact.Notes = strings.Replace(artifact.Notes, string(65000), "\n", -1) : artifact.Notes = strings.Replace(artifact.Notes, string(65000), "\n", -1) .



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow