4
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

既存のSSH秘密鍵をWindows証明書ストアに置く

Posted at

SSHの秘密鍵をWindowsに管理させれば、Windowsのログインパスワードと秘密鍵の復号化を紐付けられて便利なんじゃないかと思った。

注: 単にWindowsログインパスワードと鍵の暗号化を関連付けたいなら、KeePass + KeeAgent の方がマシなので通常の人間はそちらを使うべき。

概要

SnapCrab_NoName_2018-10-13_6-22-24_No-00.png

  • OpenSSHの id_rsa ファイルは生のRSA鍵ペアなので、これを openssl コマンドで PKCS#12 ファイルに変更することでWindowsにインポートできる。
  • インポートした鍵をSSH鍵として使うには、PuTTY-CACのようなCAPIに対応したクライアントを使う

SSH2の鍵は基本的にRSA署名が扱える鍵ならなんでも良く、必ずしもssh-keygenで作る必要性は無い。 gpg-agent に登録したPGP鍵を認証に使う( https://qiita.com/tsuyoshi_cho/items/79c09905ae3f192b3a0f )とか、yubikeyを認証に使う( https://qiita.com/dseg/items/77d77467970b1b510285 ) といった色々な方法が既に紹介されている。

今回は、GPGとかYubikeyの代わりに、Windows OS標準の公開鍵機構を使って、既存のOpenSSH鍵をインポートして使ってみる。

(この記事でやっている事は、 ユーザ証明書を使って認証しているわけではなく 、単にRSA鍵を証明書フォーマットに変換しているだけにしている。実際には、SSHプロトコル自体は真面目な証明書認証もサポートしている https://www.conoha.jp/guide/openssh.php この記事の手法は、サーバ側は単に .ssh/authorized_keys を使ったいわゆる普通のSSH公開鍵認証さえ設定されていれば良いのがポイントとなる。)

OpenSSH鍵を証明書に変換する

ssh-keygen で作った鍵ファイルのうち、 id_rsa は生のRSA鍵データとなっている。このままでは有効期限とか名前といったデータが欠けていて証明書として使うことはできないが、幾つかのパラメタ(名前CNや有効期限days)を補ってやることで証明書に変換することができる。

この手の変換作業は openssl コマンドで実施するのが定番になっている。適当な環境にopensslをインストールし、適当にコンフィグファイル(ここではwrap.conf)を用意し、

wrap.conf
distinguished_name=none
x509_extensions = usr_cert

[usr_cert]
keyUsage=digitalSignature

[none]

適当に自己署名証明書(out.cer)を生成し、

out.cerの生成
OPENSSL_CONF=wrap.conf openssl req -key ~/.ssh/id_rsa -days 7000 -x509 -subj /CN=my_ssh_key1 > out.cer

適当にPKCS#12形式でエクスポート(out.p12)すれば、

out.p12の生成
# エクスポート用のパスフレーズを要求されるが、空で良い
openssl pkcs12 -export -in out.cer -inkey ~/.ssh/id_rsa -name "My SSH Key1" > out.p12

Windowsにインポート可能なPKCS#12ファイルができる。

Windowsに秘密鍵をインポートする

生成されたファイル out.p12 をダブルクリックする("暗号化シェル拡張"で開く)と、証明書のインポートウィザードが始まる。(.cerには秘密鍵が入っていないため使えないのに注意)

SnapCrab_NoName_2018-10-13_6-53-6_No-00.png

ここでは 現在のユーザー を選択する。適当にウィザードを進めると鍵の強度設定になるが、ここは 秘密キーの保護を強力にする を選択し、このキーをエクスポート可能にするをOFFにする。後者は、元にした秘密鍵(id_rsaに入っていたもの)を再度取り出せるようにするかという選択で、アプリケーションの挙動には影響しないが特に理由の無い限りエクスポート不可の方が良い。

SnapCrab_NoName_2018-10-13_6-55-1_No-00.png

あとは "自動的に証明書ストアを選択する" 等を適当に選択し、保護レベルを設定してウィザードを完了させると、証明書が証明書ストアに登録される。

"秘密キーの保護を強力にする" を選択することで、知らないソフトが勝手に証明書を使うのを防ぐことができる。これが選択されている場合、未知のアプリから証明書の利用要求があると、Windowsはダイアログを表示してユーザに確認を求める。保護レベルをデフォルトの"中"から"高"にすると、更にパスフレーズを設定することもできる。

登録内容の確認

"ファイル名を指定して実行" から certmgr.msc を開き、 "個人" → "証明書" と選ぶとインポートした証明書が確認できる。

SnapCrab_NoName_2018-10-13_7-1-10_No-00.png

証明書をダブルクリックすると内容を確認できる:

SnapCrab_NoName_2018-10-13_7-2-13_No-00.png

ここではRoot CAに信頼されていないといった警告が出るが、 放置で良い 。SSHの公開鍵認証では、特に鍵がCAによって承認されている必要は無い。

このプロパティダイアログは、コマンドラインから証明書を登録する際に使用するfingerprintの取得にも使用する。

PuTTY-CACのPageantに鍵を置く

通常のPuTTYやMSのOpenSSH移植ではWindowsの鍵ストアにアクセスすることはできない。しかし、Yubikey界隈でよく使用されているPuTTY-CAC https://risacher.org/putty-cac/index-old.html を使うことで、Windowsの鍵ストアが認識している秘密鍵をSSH鍵として使用できる。

PuTTY-CACのリリースページ( https://github.com/NoMoreFood/putty-cac/releases )からpageant.exeをダウンロードして起動する。適切に鍵をインポートできていれば、"Add CAPI Cert"を選択した際にメニューで証明書を選択できる:

SnapCrab_NoName_2018-10-13_6-37-24_No-00.png

コマンドラインからのロード

流石にGUIで毎回ロードするのはキツいものがあるので、コマンドラインからロードする。通常のPuTTYの場合、Pageantを起動する際に、コマンドラインで証明書ファイル(.ppk)を指定することでロードできるが、PuTTY-CACではこれが拡張され証明書のfingerprintを指定できるようになっている。

fingerprintを確認するには、証明書のプロパティを使う:

SnapCrab_NoName_2018-10-13_6-41-13_No-00.png

(これはダミー証明書なのでキー使用法等が異なっている)

ここでは、拇印が 0309c343745244222037eb4b34415795836f4aa4 となっているので、コマンドラインには

pageant.exe CAPI:0309c343745244222037eb4b34415795836f4aa4

のように、 CAPI: を足して指定することでロードできる。

使う

後は適当にPuTTYのPageantを使えるクライアントで使用できる。

Cygwinで使用する場合は、Yubikeyのサイトにあるように https://developers.yubico.com/PGP/SSH_authentication/Windows.htmlssh-pageant を導入して

ssh-pageantの起動
eval $(/usr/bin/ssh-pageant -r -a "/tmp/.ssh-pageant-$USERNAME")

のようにすれば、Pageantにロードした秘密鍵情報をCygwinのSSHからも使用できる。

インポート時に"秘密キーの保護を強力にする"を選択した場合、初回の鍵使用時は

SnapCrab_NoName_2018-10-13_7-9-35_No-00.png

のようなダイアログが現われ、 OK をクリックするまで処理が保留される。

秘密鍵の保護手法として適切か?

一応、MS的には、 個人の証明書ストアに格納された秘密鍵はDPAPIで保護される ということになっている。

DPAPI(Data Protection API)で個人データを保護する場合は、 ユーザに紐付けられた512bitsのマスターキーをパスワードで暗号化 した上で使用しているので、Windowsのログオンパスワードで保護されているのと同様のレベルの保護があると言える。(ただし、この資料はちょっと古い)

ただ、UIとしてはあんまり強固にはなっていない。一応使用時点で承認を求めるように設定できるが、1回の起動で1度だけで、"N時間おきに確認を求める"といった設定ができない。せっかくWindows Helloとかが有ってEdgeのWebAuthn実装では適切に運用されているのに、証明書のような標準ベースのUIで使えないのはちょっと惜しい気がする。

Windows HelloをSSH秘密鍵の保護に使いたいなら、KeePass + KeeAgentのような外部のパスワードマネージャを使うしかないのが現状と言える。MSは OpenSSH server/clientのWin32移植 をメンテナンスして、これにはNTサービス化されたssh-agentまで含まれているが、今回のようにCAPIを使用した証明書の管理は一切サポートしていない。

もっとも、最近はMSも盛んにDevOpsフレンドリーを目指しているので、AppleとかUbuntuのようにOSのGUIレベルでssh-agentをサポートする時代がそのうち来るのかもしれない。

4
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?