1.簡単な暗号化

1.5 鍵の生成

 ここで、暗号化と復号で使う「鍵」を生成します。先に説明しましたように、以下の関数で生成される鍵は、セッション鍵で一度だけ使われる鍵です。そのため、CSPに保存されませんので、セキュリティ上問題はありません。もちろん、アプリケーションは、パスワードや鍵が重要なものであるという認識を持ってアプリケーションを作成しなければなりません。

以下のようにします。
#define KEYLENGTH_128   0x0080 * 0x10000        // 128-bit長

HCRYPTKEY   hKey;

if(!CryptDeriveKey(
            hProv,          // CSPのハンドル
            CALG_RC4,       // 暗号化のアルゴリズム
            hHash,          // ハッシュ値のハンドル
            KEYLENGTH_128,  // 暗号化鍵のビット長とフラグ
            &hKey))         // 鍵のハンドル
{
    fprintf(stderr, "CryptDeriveKey error\n");
    return 4;
}
第2引数には、共通鍵暗号のアルゴリズムを指定します。アルゴリズムは、いくつか用意されていますが、CSPそれぞれで利用できるアルゴリズムが違います。詳細は、1.12 CSPについて を参照してください。
また、上記で指定しましたCALG_RC4は、ストリーム暗号のアルゴリズムです。これに対して、ブロック暗号(CALG_RC2、CALG_DESなど)が指定できます。詳細は、1.12 CSPについて を参照してください。
第3引数には、ハッシュ値のハンドルを指定します。この値から、暗号用の鍵を生成します。
第4引数には、生成されるべき鍵の長さ(ビット長)とフラグをセットします。詳細は、1.13 鍵の生成について を参照してください。
第5引数に、生成された鍵のハンドルが戻ります。

1.6 暗号化

 いよいよデータを暗号化します。
 暗号化用の鍵を生成する際に、ストリーム暗号用の鍵を生成しました。この暗号方式では、暗号化する前のデータのバイト長と暗号化したデータのバイト長が同じになります。そのため、説明では簡単に暗号化データを取り出しています。入力のデータ長も短いために暗号化の関数を一度コールするだけで完成しています。実際は、入力のデータが大きい場合や、出力のデータ長を受け取りたい場合などもあります。それらは別ページ(準備中)で解説します。

以下に、暗号化のコードを記します。
BYTE    pbData[100] = "This is a test data.";
DWORD   dwDataLen = (DWORD)strlen((char*)pbData) + 1;

if(!CryptEncrypt(
            hKey,         // 鍵のハンドル
            0,            // 暗号化と同時にハッシュ化する場合に指定
            TRUE,         // 最後のデータを渡すときに真
            0,            // ゼロを指定
            pbData,       // 暗号化されるデータのポインター
            &dwDataLen,   // 暗号化データのバイト長データの格納ポインター
            (DWORD)100))  // データバッファーの大きさ
{
    fprintf(stderr, "CryptEncrypt error\n");
    return 5;
}
第2引数には、暗号化されるデータを暗号化と同時にハッシュ値にする場合に設定します。電子署名のアプリケーションなどで利用されます。今回のようなアプリケーションでは、その必要がありませんので、0(ゼロ)をセットします。
第3引数は、大量のデータを分割して関数に渡す場合に利用します。例えば、2回に分けて渡す場合は、最初のデータを渡すときにFALSEを指定し、2つ目のデータを渡すときにTRUEを指定します。
第4引数は、特殊な暗号化を行う場合に指定します。ここでは、0(ゼロ)を指定します。
第5引数には、暗号化するデータのポインターが入ります。戻りデータの大きさがわからないとき、で解説しますが、NULLが設定されてもエラーになりませんのでご注意ください。
第6引数には、データの長さが入ります。
第7引数には、暗号化データが格納されるバッファーのバイト長を指定します。

暗号化データは、pbDataに格納され、そのバイト長は、dwDataLenに格納されます。

1.7 復号

 次は、暗号化したデータを復号します。
 復号の場合も、暗号化と同様に鍵のハンドルを用意します。この方法は、暗号化とまったく同じ手順で行います。以下では、同じ手順で求めたプロバイダーと鍵のハンドルを使って暗号化データを復号します。
if(!CryptDecrypt(
            hKey,          // 鍵のハンドル
            0,             // 復号と同時にハッシュ計算をする場合に指定
            TRUE,          // 最後のデータを渡すときに真、他は偽
            0,             // 特殊な服後をする場合にフラグをセットする
            pbData,        // [in]暗号化データ/[out]復号したデータ
            &dwDataLen))   // [in]暗号化データのバイト長
                    /[out]復号したデータのバイト長
{
    fprintf(stderr, "CryptDecrypt error\n");
    return 6;
}
printf("データは、「%s」です。\n", pbData)
第2引数には、ハッシュ計算のインスタンスのハンドルを渡します。復号と同時にハッシュ値が計算されます。このハッシュ値をもとのハッシュ値と比較するような電子署名のアプリケーションで利用します。ここでは、その機能を利用しませんので0(ゼロ)を指定します。
第3引数は、大量のデータを渡す場合に利用します。データを分割して関数に渡す場合、残りのデータがある場合は、FALSEをセットし、残りのデータがなくなった最後のデータを渡すときにTRUEを渡します。
第4引数は、特殊な復号を行う場合にフラグをセットしますが、こんかいのアプリケーションでは使用しませんので、0(ゼロ)をセットします。
第5引数には、データのポインターを渡します。入力では、暗号化したデータが入ります。出力では、復号されたデータが入ります。戻りデータの大きさがわからないとき、で解説しますが、NULLが設定されてもエラーになりませんのでご注意ください。
第5引数には、データのバイト長をセットします。もし、復号されたデータが、暗号化されたデータと違う場合(ブロック暗号化の場合)は、この値が関数によって変更されますので第3引数のTRUEを渡した時に確認が必要です。

1.8 リソースの開放

 暗号化や復号の処理が終わりましたら、利用したリソースを開放します。
 ハッシュ計算のインスタンスハンドルは、以下の方法で開放します。
if(!CryptDestroyHash(hHash))
{
    fprintf(stderr, "CryptDestroyHash error\n");
    return;
}
引数に、ハッシュ計算のハンドルを指定します。

続いて CSP のハンドルを開放します。
if(!CryptReleaseContext(hProv, 0))
{
    fprintf(stderr, "CryptReleaseContext error\n");
    return;
}
第1引数に CSP のハンドルを指定します。
第2引数には、0(ゼロ)を指定します。

また、暗号化や復号処理のために確保した領域も開放するのを忘れないようにしてください。

1.9 サンプル・コード

サンプルのコードです。
サンプルは商業利用および転載を禁止します。

1.10 ご質問・ご要望

 ご質問やご要望は、こちらからお送りください。(匿名でも可能です。)

PDF-Tools
PDFおよびPDF/Aを作成・編集などができるライブラリ
128ビットの暗号化や電子署名に対応
http:
//www.trustss.co.jp/pdf/