Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 14717] ファイルの概要

コミット

このコミットは、Go言語の標準ライブラリ crypto/des パッケージに、EDE2 (Encrypt-Decrypt-Encrypt with two keys) モードのTriple DES (3DES) の使用例を追加するものです。EDE2は比較的稀なDESの運用モードであり、crypto/des パッケージで実装可能であるものの、その方法が直感的ではないため、具体的なコード例を提供することで利用者がこのモードを理解し、適切に実装できるよう支援することを目的としています。

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/8f1d170fc6758842a1dc89075a050716fa4dc6c3

元コミット内容

commit 8f1d170fc6758842a1dc89075a050716fa4dc6c3
Author: Adam Langley <agl@golang.org>
Date:   Sat Dec 22 10:50:11 2012 -0500

    crypto/des: add an example to demonstrate EDE2 operation.
    
    EDE2 is a rare DES mode that can be implemented with crypto/des, but
    it's somewhat non-obvious so this CL adds an example of doing so.
    
    Fixes #3537.
    
    R=golang-dev, adg
    CC=golang-dev
    https://golang.org/cl/6721056

変更の背景

この変更の背景には、Go言語の crypto/des パッケージがTriple DES (3DES) をサポートしているものの、特にEDE2モードのような特定の運用モードの実装方法が明確でないという課題がありました。Issue #3537(このコミットによって修正される)がこの問題提起の根拠となっており、開発者がEDE2モードを正しく利用するための具体的なガイダンスが求められていました。

EDE2は、3DESの中でも鍵の管理が特殊なモードであり、一般的な3DES(EDE3、3つの異なる鍵を使用)とは異なります。crypto/des パッケージの NewTripleDESCipher 関数は、24バイトの鍵(3つのDES鍵に対応)を期待しますが、EDE2モードでは実質的に2つの鍵しか使用しません。このため、2つの鍵を24バイトの形式にマッピングする方法が直感的ではないという問題がありました。このコミットは、その「非直感的さ」を解消し、開発者が混乱なくEDE2モードを実装できるように、具体的なコード例を des_test.go に追加することで、ドキュメントと実用性の向上を図っています。

前提知識の解説

DES (Data Encryption Standard)

DESは、1970年代に開発されたブロック暗号アルゴリズムで、56ビットの鍵長を持ちます。現在では鍵長が短すぎるため、単体での使用は推奨されていませんが、その派生であるTriple DES (3DES) は依然として一部で利用されています。

Triple DES (3DES)

3DESは、DESアルゴリズムを3回適用することでセキュリティを強化したブロック暗号です。DESの鍵長が短いという弱点を補うために考案されました。3DESには主に以下の2つの運用モードがあります。

  1. EDE3 (Encrypt-Decrypt-Encrypt with three keys): 3つの異なる鍵 (K1, K2, K3) を使用し、E_K3(D_K2(E_K1(plaintext))) の形式で暗号化を行います。これが最も一般的な3DESの運用モードであり、最も高いセキュリティを提供します。
  2. EDE2 (Encrypt-Decrypt-Encrypt with two keys): 2つの異なる鍵 (K1, K2) を使用し、E_K1(D_K2(E_K1(plaintext))) の形式で暗号化を行います。つまり、最初の暗号化と最後の暗号化に同じ鍵 (K1) を使用します。このモードは、EDE3よりもセキュリティレベルは低いですが、単一のDESよりもはるかに安全です。また、K1とK2が同じ場合、単一のDESと互換性を持つという特性があります。

crypto/des パッケージ

Go言語の crypto/des パッケージは、DESおよびTriple DESのブロック暗号機能を提供します。

  • des.NewCipher(key []byte): 単一のDESブロック暗号を生成します。鍵長は8バイト(56ビットの鍵と8ビットのパリティビット)。
  • des.NewTripleDESCipher(key []byte): Triple DESブロック暗号を生成します。この関数は24バイトの鍵を期待します。この24バイトは、内部的に3つの8バイトのDES鍵(K1, K2, K3)として解釈されます。

Example 関数

Go言語のテストパッケージ (testing) には、Example 関数という特殊な機能があります。これは、コードの利用例を示すための関数で、go test コマンドを実行した際に、その出力が期待される出力と一致するかどうかを検証できます。これにより、コードのドキュメントとテストを兼ねることができます。このコミットでは、ExampleNewTripleDESCipher という関数が追加されており、これは NewTripleDESCipher の使用例を示しています。

技術的詳細

このコミットの核心は、crypto/des.NewTripleDESCipher 関数が24バイトの鍵を要求するのに対し、EDE2モードが実質的に2つの鍵(K1とK2)しか使用しないというギャップを埋める方法を示すことです。

EDE2モードの E_K1(D_K2(E_K1(plaintext)))NewTripleDESCipher に適用するためには、24バイトの鍵を K1 || K2 || K1 の形式で構築する必要があります。ここで || はバイト列の連結を意味します。

コミットで追加された例では、ede2Key という16バイトの鍵(K1とK2に相当)が用意されています。この16バイトの鍵を基に、NewTripleDESCipher が期待する24バイトの tripleDESKey を以下のように構築しています。

  1. ede2Key[:16]tripleDESKey に追加します。これは K1 || K2 に相当します。
  2. ede2Key[:8]tripleDESKey に追加します。これは K1 に相当します。

結果として tripleDESKeyK1 || K2 || K1 の24バイトの形式となり、NewTripleDESCipher に渡すことで、EDE2モードのTriple DES暗号器を正しく初期化できます。

このアプローチは、NewTripleDESCipher が内部的に鍵を key[:8], key[8:16], key[16:24] の3つのDES鍵として解釈することを利用しています。したがって、key[:8] がK1、key[8:16] がK2、key[16:24] が再びK1となるように鍵を構成することで、EDE2の動作を実現します。

コアとなるコードの変更箇所

変更は src/pkg/crypto/des/des_test.go ファイルに集中しています。具体的には、ExampleNewTripleDESCipher という新しいテスト関数が追加されています。

--- a/src/pkg/crypto/des/des_test.go
+++ b/src/pkg/crypto/des/des_test.go
@@ -1503,3 +1503,21 @@ func TestSubstitutionTableKnownAnswerDecrypt(t *testing.T) {
 		}
 	}
 }
+
+func ExampleNewTripleDESCipher() {
+	// NewTripleDESCipher can also be used when EDE2 is required by
+	// duplicating the first 8 bytes of the 16-byte key.
+	ede2Key := []byte("example key 1234")
+
+	var tripleDESKey []byte
+	tripleDESKey = append(tripleDESKey, ede2Key[:16]...)
+	tripleDESKey = append(tripleDESKey, ede2Key[:8]...)
+
+	_, err := NewTripleDESCipher(tripleDESKey)
+	if err != nil {
+		panic(err)
+	}
+
+	// See crypto/cipher for how to use a cipher.Block for encryption and
+	// decryption.
+}

コアとなるコードの解説

追加された ExampleNewTripleDESCipher 関数は、以下の手順でEDE2モードのTriple DES暗号器を初期化する方法を示しています。

  1. ede2Key := []byte("example key 1234"):

    • これは、EDE2モードで使用する実質的な2つの鍵(K1とK2)を表現するための16バイトのバイト列です。この例では、"example key 1234" という文字列のバイト表現が使用されています。この16バイトのうち、最初の8バイトがK1、次の8バイトがK2として扱われます。
  2. var tripleDESKey []byte:

    • NewTripleDESCipher 関数に渡すための24バイトの鍵を格納するスライスを宣言します。
  3. tripleDESKey = append(tripleDESKey, ede2Key[:16]...):

    • ede2Key の最初の16バイト(K1とK2に相当)を tripleDESKey に追加します。これにより、tripleDESKeyK1 || K2 の状態になります。
  4. tripleDESKey = append(tripleDESKey, ede2Key[:8]...):

    • ede2Key の最初の8バイト(再びK1に相当)を tripleDESKey に追加します。これにより、tripleDESKey は最終的に K1 || K2 || K1 の24バイトの形式になります。
  5. _, err := NewTripleDESCipher(tripleDESKey):

    • 構築された24バイトの tripleDESKey を使用して、NewTripleDESCipher 関数を呼び出し、Triple DES暗号器のインスタンスを生成しようとします。エラーが発生した場合は panic します。
  6. コメント // See crypto/cipher for how to use a cipher.Block for encryption and // decryption.

    • これは、生成された cipher.Block インターフェース(NewTripleDESCipher が返す型)を実際に暗号化や復号に使用する方法については、crypto/cipher パッケージのドキュメントを参照するよう促しています。この例はあくまで鍵の準備と暗号器の初期化に焦点を当てています。

この例は、EDE2モードのTriple DESをGoで実装する際の鍵の準備方法という、特定の、しかし重要な側面を明確に示しています。

関連リンク

参考にした情報源リンク