前のページ <<< >>> 次のページ

5.1 電子証明書とCryptoAPI

 電子証明書の形式は前項で説明いたしました。本稿では、電子証明書に記載されている項目をCrypto APIを使って読み出す方法を説明します。

5.1.1 電子証明書の準備

 電子証明書は、あらかじめコンピュータにインストールしておき、利用できるようにしておいてください。その上で、記載項目を読み出す電子証明書のポインターを取得します。
まず、CSPを指定します。
HCRYPTPROV      hProv;
HCERTSTORE      hStore;

//      CSPハンドルの取得
if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, NULL))
{
    if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
                            CRYPT_NEWKEYSET))
    {
        fprintf(stderr, "CryptAcquireContext error\n");
        return 1;
    }
}

//      電子証明書の取り出し
PCCERT_CONTEXT  pcCert;
pcCert = CryptUIDlgSelectCertificateFromStore(
                hStore,
                NULL,
                NULL,
                NULL,
                0,
                0,
                NULL);
if(!pcCert)
{
    CertCloseStore(hStore, 0);
    CryptReleaseContext(hProv, 0);
    return 1;
}
以降は、取得した電子証明書のポインター(PCCERT_CONTEXT pcCert)を使って電子証明書の内容を確認します。
参考:
Window98以前で、GUIを使って電子証明書を選択する場合は、Windows98で利用可能なダイアログ を参照してください。

5.1.2 電子証明書のポインター

 電子証明書のポインターは、以下のように宣言されています。
typedef struct _CERT_CONTEXT {
    DWORD                   dwCertEncodingType;
    BYTE                    *pbCertEncoded;
    DWORD                   cbCertEncoded;
    PCERT_INFO              pCertInfo;
    HCERTSTORE              hCertStore;
} CERT_CONTEXT, *PCERT_CONTEXT;
typedef const CERT_CONTEXT *PCCERT_CONTEXT;
順に説明します。
dwCertEncodingTypeは、電子証明書のエンコード形式です。X509_ASN_ENCODING や PKCS_7_ASN_ENCODINGです。
pbCertEncodedは、エンコードされた電子証明書のデータへのポインターです。".cer"といった拡張子が付いて格納された電子証明書と同じデータです。したがって、このデータをファイルに書き出して、".cer"の拡張子をつけますと、電子証明書として扱うことができるようになります。
cbCertEncodedは、エンコードされた電子証明書データnバイトサイズです。
pCertInfoは、デコードされた電子証明書情報です。ここには、電子証明書に記載されたすべての情報が含まれています。
hCertStoreは、電子証明書が格納されている証明書ストアのハンドルです。

5.1.3 証明書情報

 証明書情報に格納された項目を確認します。PCERT_INFOは、以下のように宣言されています。
typedef struct _CERT_INFO {
    DWORD                       dwVersion;
    CRYPT_INTEGER_BLOB          SerialNumber;
    CRYPT_ALGORITHM_IDENTIFIER  SignatureAlgorithm;
    CERT_NAME_BLOB              Issuer;
    FILETIME                    NotBefore;
    FILETIME                    NotAfter;
    CERT_NAME_BLOB              Subject;
    CERT_PUBLIC_KEY_INFO        SubjectPublicKeyInfo;
    CRYPT_BIT_BLOB              IssuerUniqueId;
    CRYPT_BIT_BLOB              SubjectUniqueId;
    DWORD                       cExtension;
    PCERT_EXTENSION             rgExtension;
} CERT_INFO, *PCERT_INFO;
順に説明します。
dwVersionは、バージョンです。
SerialNumberは、シリアル番号です。
SignatureAlgorithmは、署名アルゴリズム情報です。
Issuerは、この電子証明書の発行者名です。
NotBeforeは、利用開始日時です。
NotAfterは、利用が終了する日時です。
Subjectは、この電子証明書の所有者名です。
SubjectPublicKeyInfoは、電子証明書が証明している公開鍵の情報です。
IssuerUniqueIdは、発行者のユニークIDです。
SubjectUniqueIdは、所有者のユニークIDです。
cExtensionは、この電子証明書に含まれる拡張情報の数量です。
rgExtensionは、拡張情報のポインターです。cExtensionで示された数だけ存在します。

5.1.4 バージョンの表示

 電子証明書のバージョンを取り出します。バージョン番号は、DWORD型ですので、容易に確認できます。
//      表示
printf("バージョン = %d\n", pcCert->pCertInfo->dwVersion);
結果は、
バージョン = 2
となり、選択した電子証明書のバージョンが"3"であることがわかります。

5.1.5 シリアル番号の表示

 シリアル番号は、バイナリーデータですので、CryptBinaryToString関数を使ってそれを表示させます。
char    pstr[1000];
DWORD   cstr = 1000;
CryptBinaryToString(pcCert->pCertInfo->SerialNumber.pbData,
                    pcCert->pCertInfo->SerialNumber.cbData,
                    CRYPT_STRING_HEXASCIIADDR,
                    pstr,
                    &cstr);
printf("Data =\n%s\n", pstr);
結果(例)は、
Data =
0000    69 00 00 00 00 00 d7 34  04 61                     i......4.a
となります。

5.1.6 署名アルゴリズムの表示

 署名アルゴリズムは、以下のように宣言されています。
typedef struct _CRYPT_ALGORITHM_IDENTIFIER {
    LPSTR               pszObjId;
    CRYPT_OBJID_BLOB    Parameters;
} CRYPT_ALGORITHM_IDENTIFIER, *PCRYPT_ALGORITHM_IDENTIFIER;
OIDは、ASCII文字列ですが、parameterは、それぞれのOIDによってさまざまなデータがセットされます。
printf("アルゴリズム OID = %s\n",
        pcCert->pCertInfo->SignatureAlgorithm.pszObjId);
CryptBinaryToString(
                pcCert->pCertInfo->SignatureAlgorithm.Parameters.pbData,
                pcCert->pCertInfo->SignatureAlgorithm.Parameters.cbData,
                CRYPT_STRING_HEXASCIIADDR, pstr, &cstr);
printf("Data =\n%s\n", pstr);
結果(例)は、
アルゴリズム OID = 1.2.840.113549.1.1.5
Data =
0000    05 00                                              ..
このことから、
署名アルゴリズムは、sha-1WithRSAであることがわかります。
parameterは、ASN.1をBERエンコードしたデータで、05 00 ですのでNULLであることがわかります。

5.1.7 発行者名

 発行者のデータをバイナリーで表示します。
CryptBinaryToString(pcCert->pCertInfo->Issuer.pbData,
                    pcCert->pCertInfo->Issuer.cbData,
                    CRYPT_STRING_HEXASCIIADDR, pstr, &cstr);
printf("Data =\n%s\n", pstr);
結果(例)は、
Data =
0000    30 47 31 12 30 10 06 0a  09 92 26 89 93 f2 2c 64   0G1.0.....&...,d
0010    01 19 16 02 6a 70 31 17  30 15 06 0a 09 92 26 89   ....jp1.0.....&.
0020    93 f2 2c 64 01 19 16 07  54 72 75 73 74 53 53 31   ..,d....TrustSS1
0030    18 30 16 06 03 55 04 03  13 0f 54 72 75 73 74 53   .0...U....TrustS
0040    6f 66 74 53 79 73 43 41  38                        oftSysCA8
となります。 このデータは、ASN.1をBERエンコードしたデータです。デコードすれば、内容はわかりますが、Crypto APIには、それをデコードする関数があります。それを使ってデコードします。
CertNameToStr(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
              &pcCert->pCertInfo->Issuer,
              CERT_SIMPLE_NAME_STR,
              pstr, cstr);
printf("Name =\n%s\n", pstr);
結果(例)は、
Name =
jp, TrustSS, TrustSoftSysCA8
となります。

5.1.8 有効期間

 有効期間は、グリニッジ時刻で格納されていますので、日本時間への変換が必要です。
COleDateTime    notBefore(pcCert->pCertInfo->NotBefore);
COleDateTime    notAfter(pcCert->pCertInfo->NotAfter);
notBefore += COleDateTimeSpan(0, 9, 0, 0);              // 日本時間への変換
notAfter  += COleDateTimeSpan(0, 9, 0, 0);              // 日本時間への変換
printf("有効期限の開始: %s\n",
        (LPCTSTR)notBefore.Format("%Y/%m/%d %H:%M:%S"));
printf("有効期限の終了: %s\n",
        (LPCTSTR)notAfter.Format("%Y/%m/%d %H:%M:%S"));
結果(例)は、
有効期限の開始: 2005/07/05 08:52:56
有効期限の終了: 2006/01/01 08:52:56
となります。

5.1.9 サブジェクト

 サブジェクト(所有者)は、発行者と同じ手順で確認できます。
CryptBinaryToString(pcCert->pCertInfo->Subject.pbData,
                    pcCert->pCertInfo->Subject.cbData,
                    CRYPT_STRING_HEXASCIIADDR, pstr, &cstr);
printf("Data =\n%s\n", pstr);

cstr = 1000;
CertNameToStr(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
              &pcCert->pCertInfo->Subject,
              CERT_SIMPLE_NAME_STR,
              pstr, cstr);
printf("Name =\n%s\n", pstr);
結果(例)は、
Name =
jp, TrustSS, CertUsers, 821, LastName FirstName
となります。

5.1.10 公開鍵情報

 公開鍵は、ビット列です。
CryptBinaryToString(
        pcCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
        pcCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
        CRYPT_STRING_HEXASCIIADDR, pstr, &cstr);
printf("Data =\n%s\n", pstr);
printf("アルゴリズム:%s\n",
        pcCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
printf("サイズ = %d, 未使用ビット = %d\n",
        pcCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
        pcCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cUnusedBits);
結果(例)は、
Data =
0000    30 81 89 02 81 81 00 d6  09 cc c8 cd 71 52 8c fb   0...........qR..
0010    5f 6d a4 08 07 d2 77 0d  c3 5e 22 41 d7 97 2b fe   _m....w..^"A..+.
0020    5e 9d 3c 07 83 c2 33 5e  b2 5d 75 0b 6c a3 ee 7e   ^.<...3^.]u.l..~
0030    56 87 80 af 4d be 66 0d  b8 9d 24 66 f6 12 d6 b9   V...M.f...$f....
0040    8c 7d 51 c2 7f ae b2 77  39 83 1a e2 f1 99 ae 57   .}Q....w9......W
0050    9a 29 da 29 f8 8e cd 92  f2 e2 65 95 5f 46 d2 2d   .).)......e._F.-
0060    74 4b f3 97 5a 6c e8 56  8b 7a 54 be 6b 1f 39 87   tK..Zl.V.zT.k.9.
0070    b9 3b 7a 20 5a 69 35 d8  e4 66 1e 94 2e b0 dc 4d   .;z Zi5..f.....M
0080    b5 22 96 bc 37 bd 75 02  03 01 00 01               ."..7.u.....

アルゴリズム:1.2.840.113549.1.1.1
サイズ = 140, 未使用ビット = 0
となります。
なお、上記のOIDは「RSA」をあらわします。

5.1.11 拡張情報

 電子証明書の拡張情報は、いろいろなものがありますので、5.2 拡張情報とCryptoAPI で説明します。ここでは、電子証明書に含まれる拡張情報の数を確認します。
printf("Num = %d\n", pcCert->pCertInfo->cExtension);
結果(例)は、
      Num = 10
となります。
このことから、拡張情報は、10個含まれてることがわかります。

5.1.12 サンプル

 電子証明書から、情報を取り出すためのサンプルです。
WindowXP、WindowsVistaもしくは、Windows2003サーバーでのみ動作します。
ライブラリ Cryptui.lib を追加してください。
 サンプルの商業利用および転載は禁止します。

5.1.13 ご質問・ご要望

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

(記載の会社名および製品名は、各社の登録商標および商標です。)

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 ご質問・ご要望
株)トラスト・ソフトウェア・システム
暗号化・電子署名・タイムスタンプ ライブラリ作成します。
お問い合わせください。
会員用ログイン
ID:
パスワード:
ログインすると、一般公開していないページを閲覧できます。