EternalWindows
自己署名入り証明書 / 公開鍵の情報

証明書に含まれる公開鍵は、CERT_INFO構造体のSubjectPublicKeyInfoで識別されます。 このメンバの型であるCERT_PUBLIC_KEY_INFOは次のように定義されています。

typedef struct _CERT_PUBLIC_KEY_INFO {
  CRYPT_ALGORITHM_IDENTIFIER  Algorithm;
  CRYPT_BIT_BLOB              PublicKey;
} CERT_PUBLIC_KEY_INFO, *PCERT_PUBLIC_KEY_INFO;

Algorithmは、公開鍵のアルゴリズムタイプを指定します。 PublicKeyは、公開鍵のバイナリデータを指定します。

CERT_PUBLIC_KEY_INFO構造体を初期化するには、 まず何より、公開鍵を作成しておかなければなりません。 これは、特定のCSPの鍵コンテナに鍵ペアを作成するという作業になりますから、 CSPの章で紹介したCryptGenKeyを呼び出せば実現することができます。 鍵ペアが作成されていれば、後はCryptExportPublicKeyInfoを呼び出すことで、 公開鍵をエクスポートすることができます。

BOOL WINAPI CryptExportPublicKeyInfo(
  HCRYPTPROV hCryptProv,
  DWORD dwKeySpec,
  DWORD dwCertEncodingType,
  PCERT_PUBLIC_KEY_INFO pInfo,
  DWORD *pcbInfo
);

hCryptProvは、鍵ペアが格納されている鍵コンテナを開いたCSPのハンドルを指定します。 dwKeySpecは、エクスポートしたい鍵ペアの用途を指定します。 鍵ペアの用途は、AT_KEYEXCHANGEまたはAT_SIGNATUREのどちらかです。 dwCertEncodingTypeは、エンコーディングタイプを指定します。 pInfoは、エクスポートされる公開鍵の情報を受け取るバッファを指定します。 このバッファは、PCERT_PUBLIC_KEY_INFOで識別することができます。 pcbInfoは、pInfoに指定したバッファのサイズを格納した変数のアドレスを指定します。 ちなみに、公開鍵のサイズだけ取得したいような場合は、CertGetPublicKeyLengthを呼び出すことができます。

CryptExportPublicKeyInfoを呼び出す手順を、CSPのハンドルを取得する段階から見ていきます。 CSPはMS_DEF_PROVとし、鍵コンテナの名前は"MyContainer"、 その鍵コンテナにはAT_SIGNATUREの鍵ペアが格納されているものとします。

if (!CryptAcquireContext(&hProv, TEXT("MyContainer"), MS_DEF_PROV, PROV_RSA_FULL, 0)) {
		MessageBox(NULL, TEXT("CSPのハンドルの取得に失敗しました。"), NULL, MB_ICONWARNING);
		return 0;
}

if (!CryptExportPublicKeyInfo(hProv, AT_SIGNATURE, X509_ASN_ENCODING, NULL, &dwSize)) {
	HeapFree(GetProcessHeap(), 0, lpData);
	return 0;
}

pPublicKeyInfo = (PCERT_PUBLIC_KEY_INFO)HeapAlloc(GetProcessHeap(), 0, dwSize);
CryptExportPublicKeyInfo(hProv, AT_SIGNATURE, X509_ASN_ENCODING, pPublicKeyInfo, &dwSize);
certInfo.SubjectPublicKeyInfo = *pPublicKeyInfo;

まずは、CryptAcquireContextでCSPのハンドルを取得します。 今回の例では、鍵コンテナの鍵ペアにアクセスすることになるため、 第5引数にはCRYPT_VERIFYCONTEXTではなく0を指定し、 第2引数には鍵コンテナの名前を指定します。 CryptExportPublicKeyInfoの1回目の呼び出しでは第4引数にNULLを指定し、 第5引数にバッファのサイズが格納されるようにします。 CryptExportPublicKeyInfoでは、鍵ペアが存在しないことによるエラーが発生 する可能性があるので、1回目の呼び出しでは戻り値を確認しています。 そして、2回目の呼び出しで確保したバッファを指定し、 初期化されたバッファをCERT_PUBLIC_KEY_INFO構造体 としてCERT_INFO構造体のSubjectPublicKeyInfoに設定します。


戻る