前のページ <<<

5.4 暗号化データとCryptoAPI

 Crypto APIは、RFC3852で規定されたCMSデータを取り扱います(4.3電子署名データの形式および4.4 暗号化データの形式参照)。電子署名のデータは、Signed-data型が実装されています。また、暗号データは、Enveloped-data型が実装されています。ここでは、暗号データEnveloped-data型を説明します。

このデータ形式を理解しますと、暗号化されたデータだけではなく、それ以外の様々な情報を追加することができるようになります。

5.4.1 暗号データの生成と概要

まず暗号化されたデータを用意し、その内容を順に解析します。

 簡単な電子署名の方法は、2.4電子証明書を使った暗号化 で説明しています。ここでは、同様のコードを使って暗号データを生成し、その内容を簡単に解析します。
暗号データを生成するコードは、こちらから確認してください。ここでは、その結果のみを記します。
なお、このコードは、共通関数を使用し、さらにCrypt32.lib, Cryptui.libを使用します。

結果(暗号化されたデータの例)は、以下のとおりです。
Value =
0000    30 82 01 40 06 09 2a 86  48 86 f7 0d 01 07 03 a0   0..@..*.H.......
0010    82 01 31 30 82 01 2d 02  01 00 31 81 ef 30 81 ec   ..10..-...1..0..
0020    02 01 00 30 55 30 47 31  12 30 10 06 0a 09 92 26   ...0U0G1.0.....&
0030    89 93 f2 2c 64 01 19 16  02 6a 70 31 17 30 15 06   ...,d....jp1.0..
0040    0a 09 92 26 89 93 f2 2c  64 01 19 16 07 54 72 75   ...&...,d....Tru
0050    73 74 53 53 31 18 30 16  06 03 55 04 03 13 0f 54   stSS1.0...U....T
0060    72 75 73 74 53 6f 66 74  53 79 73 43 41 38 02 0a   rustSoftSysCA8..
0070    61 1b 41 e7 00 00 00 00  00 09 30 0d 06 09 2a 86   a.A.......0...*.
0080    48 86 f7 0d 01 01 01 05  00 04 81 80 5d fc 50 49   H...........].PI
0090    6b ec e9 69 0a 24 92 ec  d4 c5 5e c3 5e 5a 97 d2   k..i.$....^.^Z..
00a0    b6 d7 3d 9b 42 32 42 d3  06 c0 4c 5c 3b 95 5b 9c   ..=.B2B...L\;.[.
00b0    b1 f4 60 bb a5 c3 e2 6e  32 43 f6 5e ce 86 fe 36   ..`....n2C.^...6
00c0    6e 2c 09 f3 9c 7f e8 ec  f0 88 f2 52 17 4b 9e ed   n,.........R.K..
00d0    f6 3c e5 5b b6 9a da 96  1d c9 94 72 ff 79 96 ca   .<.[.......r.y..
00e0    56 74 bb ec 6b b8 b8 56  a1 0d 01 55 3d 71 83 b5   Vt..k..V...U=q..
00f0    a4 ed e3 02 74 42 a3 2b  a6 5e 28 3c f8 e0 f9 c5   ....tB.+.^(<....
0100    b5 c0 1d 39 4b ba d2 8d  45 08 fd a0 30 36 06 09   ...9K...E...06..
0110    2a 86 48 86 f7 0d 01 07  01 30 0c 06 08 2a 86 48   *.H......0...*.H
0120    86 f7 0d 03 04 05 00 80  1b 04 6c 18 63 64 b1 7d   ..........l.cd.}
0130    22 4e ad 17 09 82 66 61  3e 3b b5 36 07 35 ab c0   "N....fa>;.6.5..
0140    ba ab 3e e3                                        ..>.
得られたデータを解析します。
先頭のオクテットが0x30ですので、SEQUENCEデータであることがわかります。そのデータ長は、0x82、0x01、0x40の3オクテットからわかります。先頭の0x82は、それに続く2オクテットでデータ長を表すことを示しています。従いまして、データ長は、0x0140オクテットとなり、第5オクテットから最後までがこのデータ(ContentInfo情報)ということになります。ContentInfoは、contentTypeとcontentで構成されています。5番目のオクテットは、0x06ですのでオブジェクト識別子です。これをデコードしますと、"1.2.840.113549.1.7.3"となります。このOIDは、Enveloped-Dataであることを示しています。contentは、コンテキスト番号0(ゼロ、値は、0xa0)で示され、0x10オクテット目がそのデータの開始位置です。

contentは、SEQUENCEですので、0x10オクテット目を0x30と読み替えます。すると、データ長が0x0131オクテットであることがわかりますので、残りの全てがcontentであることがわかります。

contentは、4.4.4Enveloped-data型で説明されていますようなデータ型で構成されています。順番に1オクテットづつ解析することで全てのデータを解析できます。しかしながら、CryptoAPIには、このデータから、必要な情報を取り出す関数(CryptGetMsgParam)が用意されています。以下では、CryptGetMsgParamを使って暗号化データから情報を取り出す方法を説明します。

5.4.2 データ解析の準備 (CryptMsgOpenToDecode)

 まず暗号化したデータを解析するためのインスタンスを生成します。
// 暗号化データの解析準備
HCRYPTMSG       hMsg;
if(!(hMsg = CryptMsgOpenToDecode(
                         X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                         0,
                         0,
                         hProv,
                         NULL,
                         NULL)))
{
    fprintf(stderr, "CryptMsgOpenToDecode error\n");
    return 4;
}
HCRYPTMSGは、CMSデータ解析用オブジェクトのハンドルです。このhMsgを介してデータをセットし、デコードした情報を取り出します。

関数には、以下のようにデータを設定します。
第1引数には、エンコードの形式を設定します。
第2引数には、指定する必要がありませんので0(ゼロ)にします。
第3引数には、メッセージタイプは、ヘッダーから取り出せますので、0(ゼロ)を指定
第4引数には、CSPを指定します。
第5引数は、将来への予約です。
第6引数は、ストリーミングの場合に指定します。

なお、暗号化したデータに様々な情報を追加する場合は、Enveloped-DataのUnprotectedDataにセットされます、この場合は、CryptMsgOpenToEncode関数を使ってオブジェクトをオープンしますが、この方法は別項で説明します。

5.4.3 暗号化データのセット (CryptMsgUpdate)

 5.4.1で取り出したデータを利用します。このデータは、以下の変数に格納されています。
BYTE    *pbEncBlob;    // 暗号化データのポインター
DWORD   cbEncBlob;     // 暗号化データのバイト数
以下のコードを使って、暗号データをセットします。これによって、暗号化されたデータは、必要な情報に変換されます。
// 暗号化データのセット
if(!CryptMsgUpdate(hMsg, pbEncBlob, cbEncBlob, TRUE))
{
    fprintf(stderr, "CryptMsgUpdate error\n");
    return 5;
}

5.4.4 受取人数 (Recipients count)

 暗号化されたデータの受取人数を取り出します。
 受取人とは、暗号化されたデータを復号するための私有鍵を所持している者を言います。暗号化されたデータは、一人だけが復号できるデータではなく、指定した複数の者によって復号できるように設定できます。暗号化されたデータには、この受け取り者の人数が含まれていますので、その人数を確認します。
CryptoAPIは、独自の受取人情報の他にCMSの受取人情報(RecipientInfo)を取り出せます。ここでは、CMSの受取人情報を対象にします。
//      暗号化データから、受取人数を取り出す
DWORD   rcData;
DWORD   cbData;

if(!CryptMsgGetParam(
               hMsg,
               CMSG_CMS_RECIPIENT_COUNT_PARAM,
               0,
               &rcData,
               &cbData))
{
    fprintf(stderr, "CryptMsgGetParam error1\n");
    return 6;
}
printf("Recipient Count = %d\n", rcData);
関数には、以下のように設定します。
第1引数には、CMSデータ解析用オブジェクトのハンドルを指定します。
第2引数には、受取人を取り出すためのフラグCMSG_CMS_RECIPIENT_COUNT_PARAMを指定します。
第3引数には、インデックスを指定しますが、今回は不要ですので、0を指定します。
第4引数には、受取人数が入るDWORD型の領域を指定します。
第5引数には、受取人数が入る領域のサイズが戻ります。

上記の例の場合は、受取人を1人(自分自身)だけ指定していますので
Recipient Count = 1
という結果になります。

5.4.5 受取人情報 (RecipientInfo) 

 CMSの受取人情報を取り出します。
 フラグに、CMSG_CMS_RECIPIENT_INFO_PARAMを指定して取り出します。
BYTE    *ciData;

CryptMsgGetParam(
      hMsg,
      CMSG_CMS_RECIPIENT_INFO_PARAM,
      0,
      ciData,
      &cbData);
関数の
第1引数には、CMSデータ解析用オブジェクトのハンドルを指定します。
第2引数には、フラグ CMSG_CMS_RECIPIENT_INFO_PARAM を指定します。
第3引数には、インデックスを指定しますが、不要ですので、0を指定します。
第4引数には、受取人情報が入るBYTEのデータ領域を指定します。
第5引数には、受け取るデータのサイズが戻ります。

構造体CMSG_CMS_RECIPIENT_INFO_PARAMは、以下のように定義されています。
typedef struct _CMSG_CMS_RECIPIENT_INFO {
    DWORD   dwRecipientChoice;
    union {
        // CMSG_KEY_TRANS_RECIPIENT
        PCMSG_KEY_TRANS_RECIPIENT_INFO   pKeyTrans;
        // CMSG_KEY_AGREE_RECIPIENT
        PCMSG_KEY_AGREE_RECIPIENT_INFO   pKeyAgree;
        // CMSG_MAIL_LIST_RECIPIENT
        PCMSG_MAIL_LIST_RECIPIENT_INFO   pMailList;
    };
} CMSG_CMS_RECIPIENT_INFO, *PCMSG_CMS_RECIPIENT_INFO;
この情報の詳細は、4.4.5受取人情報を確認してください。

5.4.6 受取人数 (RecipientsCount)

 CryptoAPIを使って暗号データを復号するためには、CryptoAPI用の受取人情報を取り出す必要があります。
まずは、受取人数を取り出します。
//      暗号化データから、受取人数を取り出す (RecipientsCount)
if(!CryptMsgGetParam(
                 hMsg,
                 CMSG_RECIPIENT_COUNT_PARAM,
                 0,
                 &rcData,
                 &cbData))
{
    fprintf(stderr, "CryptMsgGetParam error1\n");
    return 6;
}
printf("Recipients Count = %d\n", rcData);
関数の、
第1引数には、CMSデータ解析用オブジェクトのハンドルを指定します。
第2引数には、フラグ CMSG_RECIPIENT_COUNT_PARAM を設定します。
第3引数には、0を設定
第4引数には、人数の入るDWORDのポインターをしています。
第5引数には、DWORDのサイズが戻ります。
受取人は、自分自身だけですので、Recipients Count = 1 となります。

5.4.7 受取人情報 (RecipientInfo)

 CryptoAPIでは、受取人情報として、受取人の電子証明書情報を取り出すことができます。
//      暗号化データから、受取人情報を取り出す (RecipientInfo)
PCERT_INFO      pci;
CryptMsgGetParam(hMsg,
                 CMSG_RECIPIENT_INFO_PARAM,
                 0,
                 ciData,
                 &cbData);
pci = (CERT_INFO*)ciData;
関数の、
第1引数には、 CMSデータ解析用オブジェクトのハンドルを指定します。
第2引数には、フラグ CMSG_RECIPIENT_INFO_PARAM を設定します。
第3引数には、0を設定
第4引数には、受取人情報が入るBYTEの領域を指定します。
第5引数には、データのサイズが戻ります。

受け取ったデータは、CERT_INFOの配列のポインターですので型キャストすれば内容を確認できます。ただし、ここで受け取るCERT_INFO情報は、発行者(Issuer)とシリアル番号(Serial Number)だけが有効な情報です。それぞれの情報は、5.1.7発行者名および5.1.5シリアル番号の表示で確認できます。

5.4.8 ご質問・ご要望

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

PDF-Tools
PDFおよびPDF/Aを作成・編集などができるライブラリ
128ビットの暗号化や電子署名に対応
http:
//www.trustss.co.jp/pdf/
電子証明書とCryptoAPI
5.1 電子証明書とCryptoAPI
5.2 電子証明書拡張情報とCryptoAPI
5.3 電子証明書データとCryptoAPI
5.4 暗号化データとCryptoAPI
5.1 電子証明書とCryptoAPI
5.1.1 電子証明書の準備
5.1.2 電子証明書のポインター
5.1.3 証明書情報
5.1.4 バージョンの表示
5.1.5 シリアル番号の表示
5.1.6 署名アルゴリズムの表示
5.1.7 発行者名
5.1.8 有効期間
5.1.9 サブジェクト
5.1.10 公開鍵情報
5.1.11 拡張情報
5.1.12 サンプル
5.1.13 ご質問・ご要望
5.2 電子証明書の拡張情報とCryptoAPI
5.2.1 サンプルについて
5.2.2 拡張情報のポインター
5.2.3 認証局識別子(Authority Key Identifier)
5.2.4 サブジェクト鍵識別子 (Subject Key Identifier)
5.2.5 鍵用途 (Key Usage)
5.2.6 証明書ポリシー (Certificate Polices)
5.2.7 サブジェクト代替名 (Subject Altanative Name)
5.2.8 拡張鍵用途 (Entended Key Usage)
5.2.9 サンプル
5.2.10 ご質問・ご要望
5.4 暗号化データとCryptoAPI
5.4.1 暗号データの生成
5.4.2 データ解析の準備 (CryptMsgOpenToDecode)
5.4.3 暗号化データのセット (CryptMsgUpdate)
5.4.4 受取人数 (Recipients count)
5.4.5 受取人情報 (RecipientInfo)
5.4.6 受取人数 (RecipientsCount)
5.4.7 受取人情報 (RecipientInfo)
5.4.8 ご質問・ご要望
株)トラスト・ソフトウェア・システム
暗号化・電子署名・タイムスタンプ ライブラリ作成します。
お問い合わせください。
会員用ログイン
ID:
パスワード:
ログインすると、一般公開していないページを閲覧できます。