Help us understand the problem. What is going on with this article?

GoでAESアルゴリズム(GCMモード)を使った実装をする

More than 3 years have passed since last update.

なんでもセキュリティの24日目です。誰も登録しなかったので書きますが、セキュリティエンジニアはみんなリア充らしいです。妬ましい。お前のとこにランサムウェアおくったろか。

そんなことは置いといて、GoでAESアルゴリズム(CBCモード)+PKCS7パディング+HMACを使った実装をするの続きです

さて、前回はHMACを組み合わせることで、暗号化における機密性(Confidentiality)だけでなく、完全性(Integrity)からなる認証まで実現することができました。しかし、これには1つ問題があります。面倒くさい! 面倒くさければ、手間を省こうと実装しないかもしれないし、よしんばしても実装ミスが発生するおそれがあります。その問題に対応するために出てきたのが、認証付き暗号(Authentication Encryption)です。

GCMはその1つで、アメリカ国立標準技術研究所(NIST)にも標準として認められています。また、暗号処理を並列化することで高速な処理を可能としています。そのためなのか、最新ブラウザ <--> サーバ間通信であれば、デフォルトでAES-GCMのTLS通信として選択されています。

image

また、GCMはパディングが不要なストリーム型の暗号です。

GoにおけるAES-GMCの実装

なんと、Goの"crypto/cipher"パッケージにデフォルトで入ってました。hmacみたいに独立してないし、Paddingのように自前実装が必要ないので、暗に「お前ら、うだうだ言わずGCM使っとけ?」と言われている気がします。勿論、私はそうさせて頂きますよ、Google様。

// GCM encryption
func EncryptByGCM(key []byte, plainText string) ([]byte, error) {
    block, err := aes.NewCipher(key); if err != nil {
        return nil, err
    }

    gcm, err := cipher.NewGCM(block); if err != nil {
        return nil, err
    }

    nonce := make([]byte, gcm.NonceSize())// Unique nonce is required(NonceSize 12byte)
    _, err = rand.Read(nonce); if err != nil {
        return nil, err
    }

    cipherText := gcm.Seal(nil, nonce, []byte(plainText), nil)
    cipherText = append(nonce, cipherText...)

    return cipherText, nil
}

// Decrypt by GCM
func DecryptByGCM(key []byte, cipherText []byte) (string, error) {
    block, err := aes.NewCipher(key); if err != nil {
        return "", err
    }
    gcm, err := cipher.NewGCM(block); if err != nil {
        return "", err
    }

    nonce := cipherText[:gcm.NonceSize()]
    plainByte, err := gcm.Open(nil, nonce, cipherText[gcm.NonceSize():], nil); if err != nil {
        return "", err
    }

    return string(plainByte), nil
}

func main() {
    cipherText, _ = EncryptByGCM(key, "12345")
    decryptedText, _ = DecryptByGCM(key, cipherText)
    fmt.Printf("Decrypted Text: %v\n ", decryptedText)
        // Decrypted Text: 12345
}

以上。取り急ぎ、これでGoにおけるAESアルゴリズムを用いた実装は一通り紹介出来たかと思います。

NONCE, 初期化ベクトルについて

これらは各データで一度きりしか使われないことを担保しなければいけません。元々の存在理由がリプレイ攻撃への対策です。
リプレイ攻撃は、例えばEC2サイトに注文した暗号通信を盗聴し、再度おなじ暗号通信を再送(リプレイ)することで2重の発注をさせてしまう様な攻撃です。もしくは、自分の口座に対する送金をする通信を盗聴し、それをリプレイすることで、何回も振り込ませてしまうような攻撃です。

これを使い捨てのナンスを使い暗号文を検証することで防御できるので、使いまわしてはいけません。なので、毎回ランダムに作り直しましょう。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした