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