AES(Advanced Encryption Standard)は強度が極めて高いと言われている共通鍵暗号化方式の一つで、アメリカ政府が政府内の標準として策定した暗号化規格です。
C#とPythonではプログラムを書いたことがありますが、golangではどうするのだろうと思い、作ってみました。
プログラムの主要部分はこちらのサイトを参考にさせていただきました。
以下、暗号化するプログラムです。
package main
import (
"fmt"
"io/ioutil"
"gopkg.in/alecthomas/kingpin.v2"
"github.com/howeyc/gopass"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
)
func main() {
var (
in = kingpin.Arg("infile", "Input text File Name").Required().String()
out = kingpin.Arg("outfile", "Output text File Name").Required().String()
)
//コマンドライン引数を受け取る
kingpin.Parse()
fmt.Println("input txt file :", *in)
fmt.Println("output txt file :", *out)
for {
//16文字のパスワード入力
fmt.Printf("Enter 16 bytes password: ")
Password, err := gopass.GetPasswdMasked()
if err != nil{
fmt.Println(err)
}
if len(Password) == 16 {
//テキストファイル読み込み
plainText, err := ioutil.ReadFile(*in)
if err != nil {
panic(err)
}
//鍵の設定
block, err := aes.NewCipher([]byte(Password)); if err != nil {
fmt.Println(err)
}
//ガロアカウンタモードのブロック暗号
gcm, err := cipher.NewGCM(block); if err != nil {
fmt.Println(err)
}
//一度きりの初期化ベクトル作成
nonce := make([]byte, gcm.NonceSize())
_, err = rand.Read(nonce); if err != nil {
fmt.Println(err)
}
cipherText := gcm.Seal(nil, nonce, plainText, nil) //暗号化
cipherText = append(nonce, cipherText...) //初期化ベクトルを先頭に付与
//Base64 Encode
sEnc := base64.StdEncoding.EncodeToString(cipherText)
err = ioutil.WriteFile(*out, []byte(sEnc), 0644); if err != nil {
fmt.Println(err)
}
break
} else {
fmt.Println("Password not equal 16 bytes")
}
}
}
cat test.txt Hello World ! あいうえお かきくけこ ①②③④⑤
go run encaes.go test.txt out.txt input txt file : test.txt output txt file : out.txt Enter 16 bytes password: ****************
cat out.txt v3rnUlLk5kha6smtAtNq2hDBrOSFQTg8jM702TQv/pgsouvQX9vlmQlWRQEh76kNcz+muHnhKXygBwqarjWNakNKxup+uZ46Jl5x+dmXF8XCAKauUs8RMoks
そして、以下が複合するプログラムです。
package main
import (
"fmt"
"io/ioutil"
"gopkg.in/alecthomas/kingpin.v2"
"github.com/howeyc/gopass"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
)
func main() {
var (
in = kingpin.Arg("infile", "Input text File Name").Required().String()
out = kingpin.Arg("outfile", "Output text File Name").Required().String()
)
//コマンドライン引数を受け取る
kingpin.Parse()
fmt.Println("input txt file :", *in)
fmt.Println("output txt file :", *out)
for {
//16文字のパスワード入力
fmt.Printf("Enter 16 bytes password: ")
Password, err := gopass.GetPasswdMasked()
if err != nil{
fmt.Println(err)
}
if len(Password) == 16 {
//暗号化されたBase64テキストファイルの読み込み
sEnc, err := ioutil.ReadFile(*in)
if err != nil {
panic(err)
}
cipherText, _ := base64.StdEncoding.DecodeString(string(sEnc))
//鍵の設定
block, err := aes.NewCipher([]byte(Password)); if err != nil {
fmt.Println(err)
}
//ガロアカウンタモードのブロック暗号
gcm, err := cipher.NewGCM(block); if err != nil {
fmt.Println(err)
}
//先頭に追加された初期化ベクトルを取り出す
nonce := cipherText[:gcm.NonceSize()]
plainByte, err := gcm.Open(nil, nonce, cipherText[gcm.NonceSize():], nil); if err != nil {
fmt.Println(err)
}
err = ioutil.WriteFile(*out, []byte(plainByte), 0644); if err != nil {
fmt.Println(err)
}
break
} else {
fmt.Println("Password not equal 16 bytes")
}
}
}
go run decaes.go out.txt dec.txt input txt file : out.txt output txt file : dec.txt Enter 16 bytes password: ****************
cat dec.txt Hello World ! あいうえお かきくけこ ①②③④⑤