EternalWindows
自己署名入り証明書 / 基本制約

今回は、拡張情報の1つである基本制約(Basic Constraints)について説明します。 この情報は、証明書がCAのものであるかを示すフラグと証明書のパスの深さを含んでいます。 フラグの値がTRUEである場合、その証明書はCAのものであることを示し、 さらに前節で述べたCERT_KEY_CERT_SIGN_KEY_USAGEが鍵用途として格納されている場合は、 証明書が自己CAのものであることを特定することができます。 自己CAの証明書は、自身が証明書のパスの最上位になるということから、 後に位置する証明書の数、つまり証明書のパスの深さを指定することができます。 基本制約は、署名を検証することのできるCA証明書の場合では、 クリティカルに記さなければなりませんが、 そうでない一般ユーザーの証明書では、クリティカルの有無は問いません。 次に、基本制約について定義する構造体を示します。

typedef struct _CERT_BASIC_CONSTRAINTS2_INFO {
  BOOL                           fCA;
  BOOL                           fPathLenConstraint;
  DWORD                          dwPathLenConstraint;
 } CERT_BASIC_CONSTRAINTS2_INFO,  *PCERT_BASIC_CONSTRAINTS2_INFO;

fCAは、証明書がCAの証明書であるかどうかを指定します。 fPathLenConstraintは、証明書のパスの深さを制限するかどうかを指定します。 このメンバはfCAがTRUEであり、さらに拡張情報の 鍵用途にCERT_KEY_CERT_SIGN_KEY_USAGEが含まれている場合に意味を持ちます。 dwPathLenConstraintは、証明書のパスにおいて、 中間に位置することができる証明書の最大数を指定します。 このメンバは、fPathLenConstraintがTRUEの場合にのみ意味を持ちます。

中間に位置する証明書というのは、恐らく次のようなことでしょう。 たとえば、A(Root)という証明書でBという証明書に署名を行った場合、 Bの証明書のパスはA->Bということになりますが、 この最初と最後の間に入る証明書が中間の証明書となります。 Aの証明書のdwPathLenConstraintが0であった場合、 先のAとBの間に入る証明書が存在していないので、 これはAが期待している通りのパス構成になっています。 ただし、BがCAの証明書であった場合、 そのBはCという証明書を発行するようなことも可能となり、 証明書のパスがAの期待する通りにならないことが考えられます。 Cの証明書のパスがA->B->Cとなる場合、Bという中間に位置する証明書が存在しているために 中間の証明書の数が1となり、Aの証明書のdwPathLenConstraintの値と矛盾が生じてしまうわけです。 このような問題を防ぐためには、BがAのdwPathLenConstraintを確認し、 自身が中間のCAとして機能して問題ないかを判断する必要があります。

次に、基本制約を拡張情報に追加する例を示します。

void AddBasicConstraints(PCERT_EXTENSION pCertExtension)
{
	CERT_BASIC_CONSTRAINTS2_INFO basicConstraints;
	DWORD                        dwSize;
	LPBYTE                       lpData;
	
	basicConstraints.fCA                 = TRUE;
	basicConstraints.fPathLenConstraint  = TRUE;
	basicConstraints.dwPathLenConstraint = 1;

	CryptEncodeObject(X509_ASN_ENCODING, szOID_BASIC_CONSTRAINTS2, &basicConstraints, NULL, &dwSize);
	lpData = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, dwSize);
	CryptEncodeObject(X509_ASN_ENCODING, szOID_BASIC_CONSTRAINTS2, &basicConstraints, lpData, &dwSize);

	pCertExtension->pszObjId     = szOID_BASIC_CONSTRAINTS2;
	pCertExtension->fCritical    = TRUE;
	pCertExtension->Value.cbData = dwSize;
	pCertExtension->Value.pbData = lpData;
}

fPathLenConstraintにTRUEを指定しているため、 dwPathLenConstraintに証明書のパスにおける中間の証明書の最大数を指定することができます。 ここでは、1としているため中間に位置する証明書の数は1であり、 言い方を変えれば、証明書が2つ後に続いてもよいということになります。 ただし、fPathLenConstraintをTRUEにする場合は、fCAをTRUEにしておかなければならず、 さらに鍵用途にCERT_KEY_CERT_SIGN_KEY_USAGEが含まれている必要があります。 また、中間に位置したCAの証明書に証明書のパスを 確認させるように、fCriticalにはTRUEを指定することになります。


戻る