Sök…


Introduktion

Ta reda på hur du krypterar och dekrypterar data med Go. Tänk på att det här inte handlar om en kryptering utan snarare hur man kan uppnå det med Go.

Kryptering och dekryptering

Förord

Detta är ett detaljerat exempel på hur du krypterar och dekrypterar data med Go. Användningskoden förkortas, t.ex. nämns inte felhanteringen. Hela arbetsprojektet med felhantering och användargränssnitt hittades på Github här .


kryptering

Introduktion och data

Detta exempel beskriver en fullständig fungerande kryptering och dekryptering i Go. För att göra det behöver vi en data. I det här exemplet använder vi vår egen datastruktur 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
}

Därefter vill vi kryptera en sådan secret . Det fullständiga fungerande exemplet hittades här (länk till Github) . Nu, steg-för-steg-processen:

Steg 1

Först av allt behöver vi ett slags huvudlösenord för att skydda hemligheten: masterPassword := "PASS"

Steg 2

Alla kryptometoder som arbetar med byte istället för strängar. Således konstruerar vi en byteuppsättning med data från vår hemlighet.

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

Steg 3

Vi skapar lite salt för att förhindra attacker av regnbågens bord, jfr. Wikipedia : saltBytes := uuid.NewV4().Bytes() . Här använder vi en UUID v4 som inte är förutsägbar.

Steg 4

Nu kan vi härleda en nyckel och en vektor ur huvudlösenordet och det slumpmässiga saltet, angående 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:]

Steg 5

Det önskade CBC-läget fungerar med hela block. Därför måste vi kontrollera om våra data är anpassade till ett fullständigt block. Om inte, måste vi padda det:

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
}

Steg 6

Nu skapar vi en AES-kodning: aesBlockEncrypter, aesErr := aes.NewCipher(keyBytes)

Steg 7

Vi reserverar nödvändigt minne för den krypterade datan: encryptedData := make([]byte, len(secretBytesDecrypted)) . I fallet med AES-CBC hade de krypterade data samma längd som de okrypterade data.

Steg 8

Nu ska vi skapa krypteraren och kryptera data:

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

Nu är den krypterade datan inuti den encryptedData variabeln.

Steg 9

De krypterade uppgifterna måste lagras. Men inte bara uppgifterna: Utan saltet kunde de krypterade uppgifterna inte dekrypteras. Därför måste vi använda något slags filformat för att hantera detta. Här kodar vi krypterade data som base64, jfr. Wikipedia :

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

Därefter definierar vi vårt filinnehåll och vårt eget filformat. Formatet ser ut så här: salt[0x10]base64 content . Först lagrar vi saltet. För att markera början på bas64-innehållet lagrar vi byte 10 . Det här fungerar, eftersom base64 inte använder detta värde. Därför kan vi hitta början på base64 genom att söka efter den första förekomsten av 10 från slutet till början av filen.

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

Steg 10

Slutligen kunde vi skriva vår fil: writeErr := ioutil.WriteFile("my secret.data", fileContent, 0644) .


dekryptering

Introduktion och data

När det gäller kryptering behöver vi lite data att arbeta med. Således antar vi att vi har en krypterad fil och den nämnda strukturen secret . Målet är att läsa den krypterade informationen från filen, dekryptera den och skapa en instans av strukturen.

Steg 1

Det första steget är identiskt med krypteringen: Vi behöver ett slags huvudlösenord för att dekryptera hemligheten: masterPassword := "PASS" .

Steg 2

Nu läser vi de krypterade data från fil: encryptedFileData, bytesErr := ioutil.ReadFile(filename) .

Steg 3

Som nämnts tidigare kunde vi dela salt och krypterad data av avgränsningsbyten 10 , sökta bakåt från slutet till början:

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

Steg 4

Därefter måste vi avkoda bas64-kodade byte:

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

Steg 5

Nu kan vi härleda en nyckel och en vektor ur huvudlösenordet och det slumpmässiga saltet, angående 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:]

Steg 6

Skapa en AES-kodning: aesBlockDecrypter, aesErr := aes.NewCipher(keyBytes) .

Steg 7

Reservera nödvändigt minne för de dekrypterade data: decryptedData := make([]byte, len(encryptedBytes)) . Per definition har den samma längd som den krypterade datan.

Steg 8

Skapa nu dekrypteraren och dekryptera data:

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

Steg 9

Konvertera lästa byte till sträng: decryptedString := string(decryptedData) . Eftersom vi behöver linjer, dela strängen: lines := strings.Split(decryptedString, "\n") .

Steg 10

Konstruera en secret ur linjerna:

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]

Slutligen, skapa om raderna inom anteckningsfältet: artifact.Notes = strings.Replace(artifact.Notes, string(65000), "\n", -1) .



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow