サーチ…


前書き

Goでデータの暗号化と復号化を行う方法については、こちらをご覧ください。これは暗号に関するコースではなく、Goで達成する方法であることに留意してください。

暗号化と復号化

序文

これは、Goでデータを暗号化および復号化する方法の詳細な例です。使用コードは短縮されています。たとえば、エラー処理は記述されていません。エラー処理とユーザーインターフェイスを備えた完全な作業プロジェクトは、 ここ Githubにあります


暗号化

はじめにとデータ

この例では、Goで完全に動作する暗号化と復号化について説明します。これを行うには、データが必要です。この例では、独自のデータ構造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
}

次に、そのようなsecretを暗号化する必要があります。完全な実例がここにあります(Githubへのリンク) 。今、ステップバイステップのプロセス:

ステップ1

まず、秘密を保護するために一種のマスターパスワードが必要です: masterPassword := "PASS"

ステップ2

すべての暗号メソッドは文字列の代わりにバイトを扱います。したがって、私たちは秘密のデータを持つバイト配列を作成します。

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

ステップ3

虹のテーブル攻撃を防ぐために、塩を作ります。 WikipediasaltBytes := uuid.NewV4().Bytes() 。ここでは、予測不可能なUUID v4を使用します。

ステップ4

さて、私たちは、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:]

ステップ5

望ましいCBCモードはブロック全体で機能します。したがって、データがフルブロックに揃っているかどうかを確認する必要があります。もしそうでなければ、それを埋める必要があります:

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
}

ステップ6

今度はAES暗号を作成します: aesBlockEncrypter, aesErr := aes.NewCipher(keyBytes)

ステップ7

暗号化されたデータに必要なメモリを予約します: encryptedData := make([]byte, len(secretBytesDecrypted)) AES-CBCの場合、暗号化されたデータの長さは暗号化されていないデータと同じです。

ステップ8

今度は、暗号化装置を作成し、データを暗号化する必要があります。

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

今、暗号化されたデータはencryptedData変数の内部にあります。

ステップ9

暗号化されたデータを保存する必要があります。しかし、データだけでなく、塩がないと、暗号化されたデータを復号化できませんでした。したがって、これを管理するには、ある種のファイル形式を使用する必要があります。ここでは、暗号化されたデータをbase64としてエンコードします(cf. ウィキペディア

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

次に、ファイルの内容と独自のファイル形式を定義します。形式は次のようになりsalt[0x10]base64 content 。まず、塩を保管します。 base64コンテンツの先頭をマークするために、バイト10を格納します。これは、base64がこの値を使用しないために機能します。したがって、ファイルの終わりから始めて10の最初の出現を検索することによってbase64の開始を見つけることができます。

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

ステップ10

最後に、ファイルwriteErr := ioutil.WriteFile("my secret.data", fileContent, 0644)書きます。


復号化

はじめにとデータ

暗号化に関しては、いくつかのデータが必要です。したがって、暗号化されたファイルと前述の構造secretがあると仮定します。目標は、ファイルから暗号化されたデータを読み取り、解読し、構造のインスタンスを作成することです。

ステップ1

最初のステップは暗号化と同じです。秘密を解読するためには一種のマスターパスワードが必要です: masterPassword := "PASS"

ステップ2

ここで、 encryptedFileData, bytesErr := ioutil.ReadFile(filename)ファイルから暗号化されたデータを読み込みencryptedFileData, bytesErr := ioutil.ReadFile(filename)

ステップ3

前に述べたように、saltと暗号化されたデータを区切りバイト10で分割し、最後から最後まで逆方向に検索することができます。

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

ステップ4

次に、base64でエンコードされたバイトをデコードする必要があります。

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

ステップ5

さて、私たちは、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:]

ステップ6

aesBlockDecrypter, aesErr := aes.NewCipher(keyBytes)というAES暗号を作成します。

ステップ7

復号化されたデータに必要なメモリを確保します: decryptedData := make([]byte, len(encryptedBytes))定義上、暗号化されたデータと同じ長さを持ちます。

ステップ8

デクリプタを作成し、データを復号化します。

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

ステップ9

読み込まれたバイトを文字列に変換する: decryptedString := string(decryptedData) 。行が必要なので、文字列を分割します: lines := strings.Split(decryptedString, "\n")

ステップ10

行のsecretなさい:

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]

最後に、notesフィールド内の改行を再作成しますartifact.Notes = strings.Replace(artifact.Notes, string(65000), "\n", -1)



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow