どうも、たくチャレ(@takuchalle)です。

AES で暗号化をする必要が出てきたのでやってみました。 言語は何でもよかったので、Windows/Linux などに簡単にバイナリ配布できるようにGoを選びました。

AES 暗号化

ここでは AES 暗号化に関して詳しく紹介することはしませんので、このあたりの記事などを参考にしてください。

今回は以下の条件で行っていきます。

  • 鍵長 256bit
  • CBC モード

CBC(Cipher Block Chaining) モードについて簡単に説明します。

先ほど紹介した記事にもある通り、AES 暗号化は 128bit ブロック単位で暗号化していきます。

一番シンプルなモードは ECB(Electronic Codebook)モードといい、 以下の図のように 128bit ブロック単位それぞれに暗号鍵で暗号化していきます。これだとデータのパターンが隠ぺいできないので比較的弱い暗号化になります。

ECB

一方 CBC モードとは、以下の図のようにひとつ前の暗号化結果とXORを取っていき最後まで暗号化していきます。その時に最初の入力としてIV(Initialization Vector)を与えることができます。 IVを暗号化するたびに変えることで同じ平文データでも異なる暗号化結果が得ることができます。復号するときにそのIVが必要なので、通常は暗号化ファイルの先頭か末尾にIVをつけるようにします。

ECB

実装例

package main

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"fmt"
	"io"
)

func main() {
	key := []byte("abcdefghijklmnopqrstuvwxyz123456") // 256bit(32byte)
	plaintext := []byte("exampleplaintext")           // 128bit(16byte)

	ciphertext := make([]byte, len(plaintext)) // 暗号化してもサイズは同じ
	iv := make([]byte, aes.BlockSize) // BlockSize は 16byte
	// IV は何でもいいのでランダムな値を使用する
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		panic(err)
	}

	c, err := aes.NewCipher(key) // 鍵の設定
	if err != nil {
		panic(err)
	}

	enc := cipher.NewCBCEncrypter(c, iv)
	enc.CryptBlocks(ciphertext, plaintext) // 暗号化 

	fmt.Printf("plain text = %s\n", plaintext)
	fmt.Printf("cipher text = %x\n", ciphertext)
	fmt.Printf("iv = %x\n", iv)
}

こちらの記事でランダムなバイナリ列の AES 鍵の生成方法を紹介しているので、合わせてご覧ください。

同じカテゴリの記事