連載
Enterprise Library概説

暗号化機能を簡単に実装しよう

―― 対称暗号機能と暗号ハッシュを簡単に利用するための機能を提供する「Cryptography Application Block」 ――

アバナード株式会社 市川 龍太(patterns & practices Champion
2006/08/10
Page1 Page2

 前回では、ASP.NET 2.0の認証・認可機能を踏まえながら、Security Application Blockを使った認可機能について解説した。

 今回は暗号化機能を提供するCryptography Application Block(以下CryptoAB)について解説する。なお、前回で2006年1月に.NET Framework 2.0に対応したEnterprise Library 2.0(以下EntLib 2.0)がリリースされたことはすでに述べているが、CryptoABはHash Provider(=ハッシュ生成アルゴリズムをカプセル化し容易に利用するための機能を提供するプロバイダ)が増えたこと以外では特に機能の変更はないため、本稿の内容はEntLib 2.0以前のバージョンでも適用可能である。

暗号化とは

 暗号化を一言でいえば、「あるデータが第三者に読み取られたり、変更されたりしないように、解読できない形式へ変換すること」ということになるが、より厳密にいうなら、「暗号化アルゴリズムと、データが特定の人から送られたことを保証するための手法との組み合わせ(この組み合わせを「暗号プリミティブ」という)によって、データの機密性、整合性、信ぴょう性を保つこと」ということになるだろう。

 ここで暗号プリミティブとして挙げられるものを以下に示す。

暗号プリミティブ 解説
共有キー暗号方式(対称暗号化方式) 単一の共有キー(=共有鍵)を使用して、データの暗号化や復号化を行う方式
公開キー暗号方式(非対称暗号化方式) 公開キーと秘密キー(=秘密鍵)のペアを使用して、データの暗号化や復号化を行う方式
デジタル署名 送信元に固有のデジタル署名を作成し、データの送信元を確認するために利用される
暗号ハッシュ 任意の長さのデータを固定長のバイト・シーケンスに変換する処理。ハッシュは統計的に一意になる
暗号プリミティブの一覧

 まずはこれらの暗号プリミティブと.NET Frameworkの関係について個別に見ていくとしよう。

■共有キー暗号方式(対称暗号化方式)

 共有キー暗号方式では、単一のキーを利用して任意のデータの暗号化と復号を行う。このように暗号化と復号で同じキーを使用することから対称暗号化方式とも呼ばれる。

 共有キー暗号方式は、後述する公開キー暗号方式と比べて非常に高速である半面、共有キーを取得した人は誰でもデータを復号化できてしまうため、実際の運用時には共有キーの扱いに注意が必要である。

■公開キー暗号方式(非対称暗号化方式)

 公開キー暗号方式では、一般に公開してもよい公開キーと、公開してはいけない秘密キーを利用して任意のデータの暗号化と復号を行う。

 公開キーと秘密キーはペアとして作成/利用されるため、公開キーで暗号化されたデータは、ペアの秘密キーでしか復号できないようになっており、また、秘密キーで署名されたデータはペアの公開キーでしか検査もできない。このように暗号化に利用するキーと復号に利用するキーが別のキーであることから、非対称暗号化方式とも呼ばれる。

■デジタル署名

 デジタル署名は、任意のメッセージに対してハッシュ・アルゴリズムを適用してハッシュ値を生成し、これを先述した公開キー暗号方式の秘密キーを使って暗号化して作成する。

 デジタル署名されたメッセージを復号化する場合は、暗号化で利用した秘密キーのペアとなる公開キーを使って復号化し、ハッシュ値を復元する。最後に同様のハッシュ・アルゴリズムを使ってメッセージからハッシュ値を求め、復元されたハッシュ値と比較することで、データが改ざんされていないことを検査することができるのである。

■ハッシュ

 任意長のデータ値を固定長のデータに変換する関数をハッシュ関数と呼び、そのハッシュ関数から変換された固定長の値をハッシュ値と呼ぶ。一般にハッシュとは、このハッシュ値を求めることを指す。

 ハッシュ値は任意長の文字列のうち、たった1文字を変更しただけでも、その後のハッシュでは別の値が生成され、同一の値にハッシュされる2つの異なる入力を見つけるのは、計算上不可能である。

 以上、ここまで4種類の暗号プリミティブについて簡単に解説したわけだが、.NET Frameworkにはこれら暗号プリミティブのためのクラスがすでに用意されているのである。

 以下にこれら暗号プリミティブと.NET Frameworkが提供する代表的な暗号クラスとのマッピング表を示す。

暗号プリミティブ アルゴリズム クラス名 アルゴリズム解説
共有キー暗号方式
(対称暗号化方式)
DES
(Data Encryption Standard)
DESCryptoServiceProvider 1960年代後半にIBM社によって開発された64bitブロック暗号方式
TripleDES TripleDESCryptoServiceProvider DESを3重に適用することで強度を高めた64bitブロック暗号方式
RC2
(Ron’s Code 2)
RC2CryptoServiceProvider Ron Rivest氏によって開発された64bitブロック暗号方式であり、DESに比べて暗号化速度が速く、暗号キーがある程度可変長である
Rijndael RijndaelManaged ベルギーの数学者Joan Daemen氏とVincent Rijmen氏によって開発された暗号方式で、ブロック長は128/192/256bitの中から選択できる
公開キー暗号方式
(非対称暗号化方式)
DSA
(Digital Signature Algorithm)
DSACryptoServiceProvider NIST*1が電子署名の標準として開発した公開キー暗号方式
RSA
(Rivest Shamir Adleman)
RSACryptoServiceProvider Ronald Rivest氏、Adi Shamir氏、Leonard Adleman氏の3人が1978年に開発した公開キー暗号方式
署名の暗号化 DSA DSACryptoServiceProvider 上記のDSAを参照
RSA RSACryptoServiceProvider 上記のRSAを参照
ハッシュ SHA1
(Secure Hash Algorithm 1)
HMACSHA1 NISTが規格化した160bit長のハッシュ関数
TripleDES MACTripleDES 上記のDESを参照
MD5 MD5CryptoServiceProvider Ronald Rivest氏によって開発された128bit長のハッシュ関数
SHA1 SHA1Managed 上記のSHA1を参照
SHA256 SHA256Managed NISTが規格化した256bit長のハッシュ関数
SHA384 SHA384Managed NISTが規格化した384bit長のハッシュ関数
SHA512 SHA512Managed NISTが規格化した512bit長のハッシュ関数
暗号アルゴリズムと.NET Frameworkのマッピング
*1 NIST(National Institute of Standards and Technology)は、米国政府機関である米国標準技術局を指す。
・表中の各クラスはSystem.Security.Cryptography名前空間配下に存在している。
・HMACSHA1はHMAC(Hash-based Message Authentication Code)を計算する。

 このように.NET Frameworkにはすでに主だった暗号化アルゴリズムに対応したクラスが用意されており、これらのクラスを利用することでアプリケーションから暗号化機能を利用することが可能なのである。

 それではすでに暗号化クラスが用意されているにもかかわらず、なぜわざわざEntLibで同様の機能を持つCryptoABが提供されているのだろうか? この疑問に対する回答としてはシンプルなインターフェイス、それからセキュリティという2つの要因が挙げられる。

■シンプルなインターフェイス

 まず任意の文字列を任意の対称アルゴリズムで暗号化された文字列に変換する処理について記述した場合の、以下のCryptoABを使わないサンプル・プログラムとCryptoABを使った場合のサンプル・プログラムを見比べてみてほしい。

 まずはCryptoABを使わない場合のサンプル・プログラムの例だ(C#)。

using System;
using System.Text;
using System.IO;
using System.Security.Cryptography;

namespace NotCryptoABSample
{
  class Program
  {
    static void Main(string[] args)
    {
      // 変数algorithmNameには任意の対称アルゴリズム名
      // (例えば「DES」「TripleDES」「RC2」「Rijndael」など)を指定
      string algorithmName = "Rijndael";
      using(SymmetricAlgorithm symmetricAlgorithm  =
              SymmetricAlgorithm.Create(algorithmName))
      {
        symmetricAlgorithm.GenerateKey();
        symmetricAlgorithm.GenerateIV();

        byte[] key = symmetricAlgorithm.Key;
        byte[] IV = symmetricAlgorithm.IV;

        using(ICryptoTransform encryptor =
                symmetricAlgorithm.CreateEncryptor())
        using(MemoryStream msEncrypt = new MemoryStream())
        using(CryptoStream csEncrypt = new CryptoStream(
                msEncrypt, encryptor, CryptoStreamMode.Write))
        {
          UTF8Encoding textConverter = new UTF8Encoding();
          byte[] toEncrypt =
            textConverter.GetBytes("暗号化したい任意の文字列");
          csEncrypt.Write(toEncrypt, 0, toEncrypt.Length);
          csEncrypt.FlushFinalBlock();

          string encryptedString =
            Encoding.UTF8.GetString(msEncrypt.ToArray());
        }
      }
    }
  }
}
CryptoABを使わない場合のサンプル・プログラム

 これをCryptoABを使って同様のRijndaelアルゴリズムを使った暗号化を行うと以下のようなサンプル・プログラムになる。

using System;
using Microsoft.Practices.EnterpriseLibrary.Security.Cryptography;

namespace CryptoABSample
{
  class Program
  {
    static void Main(string[] args)
    {
      string encryptedString = Cryptographer.EncryptSymmetric(
        "SymmManaged", "暗号化したい任意の文字列");
    }
  }
}
CryptoABを使った場合のサンプル・プログラム
前準備としてConfigurationコンソールで構成を設定しておく必要があるが、それについては後述する。

 両方のサンプル・プログラムを見比べるとその差は一目りょう然であるが、CryptoABを利用した場合は、単にコードの記述量が減少するだけでなく、オブジェクトの解放処理(上記コードではusingステートメントを使用)までもカプセル化してくれるのである。

■セキュリティ

 共有キー暗号方式は手軽に導入できる半面、共有キーの取り扱いについて注意する必要がある。つまりせっかく任意のデータを暗号化しても、第三者が共有キーを取得してしまえば、誰でも復号してデータを取り出すことが可能なのである。もちろんこれは公開キー暗号方式を利用した場合の秘密キーの取り扱いについても同様である。

 CryptoABを利用しないサンプル・プログラムではプログラム内で「symmetricAlgorithm.GenerateKey();」と記述することで自動的にキー値を生成しているが、実際の運用では暗号したデータをいつでも復号化できるようにあらかじめ生成しておいたキーを外部ストアに格納し、それを取り込んで暗号化、復号を行うのが一般的であろう。

 この場合、キーを格納する外部ストアの候補としてレジストリ、ACL(アクセス制御リスト)による適切なアクセス制限を設定した外部ファイル、アプリケーション構成ファイル(WebアプリケーションはWeb.config、WindowsアプリケーションはApp.config)などが挙げられる。

 特に.NET Framework 2.0からは、RSAアルゴリズムを使ってアプリケーション構成ファイル内の各構成セクションを暗号化することが可能になっているため(詳細はHow To: Encrypt Configuration Sections in ASP.NET 2.0 Using RSAを参照)、キーが設定されているセクションを暗号化することも可能であるが、この場合でも今度はアプリケーション構成ファイルの暗号化に利用した秘密キーの保護という問題が発生することになる。

 それではこのキーの保護という問題に対してCryptoABはどのような管理を行っているのだろうか?

■Data Protection APIを利用したキーの保護

 CryptoABはキーの保護にData Protection API(以下DPAPI)を利用している。DPAPIとはWindows 2000以降のオペレーティング・システムで提供されているデータの暗号化と復号を行うためのWin32 APIのことである。

 DPAPIでは、DPAPIの関数を呼び出したコードに関連付けられているユーザー・アカウントのパスワードを使用して、暗号化キーを生成する。そしてオペレーティング・システムがこの暗号化キーを管理することで、暗号化キーの保護という問題を解消している。

 なお、DPAPIの詳細については以下のURLを参考にするとよいだろう。

 それではCryptoABの導入手順について解説していこう。


 INDEX
  連載:Enterprise Library概説
  暗号化機能を簡単に実装しよう
  1.暗号化とは
    2.ConfigurationコンソールでCryptoABの構成を設定する
 
インデックス・ページヘ  「Enterprise Library概説」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間