RSA の説明に出てくる文字は、PKI ツールが配るファイル名ではなく、ひとつのオブジェクト内部のフィールド名です。秘密鍵ファイルが持つ構造体では、先頭のフィールドは公開で、後ろのフィールドはトンネルを終端するマシンから決して出てはいけません。この二つの事実の間に、どのファイルがどの問いに答えるかという実務的な疑問の大半があります。本稿はまず構造体を読み、次にそれをこぼさずに調べるコマンドを示します。

素数を探す前に鍵が RSA か確認する

証明書はある鍵が存在し署名されたことを示しますが、その鍵が RSA であることは示しません。システムは楕円曲線や Ed25519 の上に築けますし、同じディレクトリ構成がどれにも使えます。そこになかった素因数を探し始める前に、アルゴリズムを確認してください。

この三つの読み取り専用コマンドが問いに答え、ツールのバージョンを記録します。

openssl version
openssl x509 -in vpn-client.crt -noout -text
openssl pkey -in vpn-client.key -noout -text

バージョンが重要なのは、オプション名がメジャーリリース間で移ったからです。証明書の出力では公開鍵アルゴリズムの行と鍵長を探し、鍵の出力では RSA 鍵は modulus と公開指数を表示します。楕円曲線の鍵は代わりに名前付き曲線を表示し、どれほど探しても n や q は得られません。

base64 ではなく構造体を読む

PEM はヘッダ行で包んだ base64 で、復号すると DER、つまり巨大な整数ではなくシリアライズされた構造体になります。RSA 秘密鍵は PKCS#1 と PKCS#8 という二つの一般的なコンテナで運ばれ、どちらも同じ数値の集合に解決します。

素数の組が二つの場合、秘密の構造体は九つのフィールド、すなわちバージョン、modulus の n、公開指数 e、秘密指数 d、素数 p と q、二つの CRT 指数、そして CRT 係数を持ちます。RFC 8017 の A.1 節がこれらの構成要素と ASN.1 の配置を定めており、三つ以上の素数も認めているため、汎用のパーサは素数項目を余分に出力することがあります。順序に注意してください、よくある誤りは、公開側の半分が秘密ファイルの内部に保存されるため、公開フィールドがあるからといってそのファイルを共有して安全になるわけではないという点です。その後に続くすべてが、ホストに残すべき素材です。

符号化は内容と混同しやすい層を加えます。openssl asn1parse は構造体を木として描くのでフィールドの順序が見えますが、何も復号せず、鍵が使えるかどうかも教えてくれません。

鍵を出力せずに証明書と鍵を突き合わせる

続く問いはたいてい、証明書と鍵が一対かどうかです。modulus を比べればそれに答えられますが、秘密に近い素材を端末の記録に写してしまい、それがチケットに残ることもあります。公開側の半分を比べれば、画面に機微なものを出さずに同じ問いに答えられます。

openssl pkey -in vpn-client.key -pubout -out /tmp/key.pub
openssl x509 -in vpn-client.crt -pubkey -noout > /tmp/cert.pub
cmp /tmp/key.pub /tmp/cert.pub && echo MATCH

ファイルが同一なら証明書はその鍵の公開側の半分を運んでおり、違いがあれば間違った組を持っています。この不一致が、交渉は順調なのに認証で拒否されるトンネルの最も一般的な原因です。その後で一時ファイル二つを削除してください、秘密は入っていませんが、障害の途中では作業ディレクトリがきれいなほうが考えやすいからです。

隣のファイルが何でないかを知る

証明書は、相手が CA 証明書で解錠する暗号化された公開鍵ではなく、公開鍵と身元データのあいだの署名された結び付きです。CA の秘密署名鍵は、それ自身の証明書とも、どのクライアント鍵とも別に保たれます。要求もまた証明書ではなく、要求された情報と公開鍵を要求への署名とともに運ぶので、登録の入力であって権利の証明ではありません。

FileAnswersDoes not prove
vpn-client.keyPossession of the private keyThat the identity is enrolled
vpn-client.crtA signed binding of public key to identityThat the client holds the matching key
vpn-client.csrThe requested binding and public keyThat access was granted
dh2048.pemGroup parameters for key exchangeAny RSA component
crl.pemRevocation status for certificatesAnything about a private key

このうち二つは RSA パラメータと混同されることが多く、二度名指しする必要があります。Diffie-Hellman パラメータファイルは鍵確立のための群パラメータを含み、RSA の素数は含みません、大きな素数として表示されるとしてもです。失効リストは証明書の状態を公開するもので、秘密指数が隠れられる場所ではありません。

したがって台帳の各行は四つを記録すべきです、つまり対象の種類、所有者、目的、そして秘密の素材が含まれるかどうかです。最後の列がファイルをどこへ複製してよいかを決め、そこを人は飛ばします。

対応を記録し、それからハンドシェイクを検証する

何かを変える前に、検証の出力を日付と OpenSSL のバージョンとともに保存してください。そうすれば後のローテーションを記憶ではなく証拠と比べられます。

openssl verify -CAfile ca.crt vpn-client.crt
openssl x509 -in vpn-client.crt -noout -subject -issuer -dates

公開鍵の比較のあとは、その組を消費する経路を実際に通します、つまりトンネルを上げ、証明書が提示されて受け入れられることを確かめ、ゲートウェイがどの身元を記録したかを見ます。鍵と証明書が一致しているのに認証が失敗するなら、不具合は組ではなく、信頼、身元の対応付け、アクセス方針の側にあります。

切り戻しのために、以前の鍵と証明書を日付付きのディレクトリに保ち、必ず両方を一緒に戻してください、片方だけは決して戻さないでください。証明書のない鍵と鍵のない証明書は外から見れば同じように失敗するので、半端に戻した組は午前二時に解くのが高くつきます。

関連記事