注目の記事

【OpenSSH 7.8】秘密鍵を生成する形式が変更になった件について

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは。DI部の春田です。

皆さん、日頃からssh-keygenのコマンドはよく使われるかと思います。

先日、GoのSSHライブラリに関する記事をあげましたが、秘密鍵のヘッダが変更されている件について、もう少し詳しく調べていきます。 また、OpenSSHそのものについても興味が湧いたので、こちらも深掘りしてみました。

【Tips】Go言語の x/crypto/ssh パッケージで パスフレーズで保護された秘密鍵を扱う

目次

OpenSSHとは?

OpenSSH is the premier connectivity tool for remote login with the SSH protocol. It encrypts all traffic to eliminate eavesdropping, connection hijacking, and other attacks. In addition, OpenSSH provides a large suite of secure tunneling capabilities, several authentication methods, and sophisticated configuration options.

The OpenSSH suite consists of the following tools:

  • Remote operations are done using ssh, scp, and sftp.
  • Key management with ssh-add, ssh-keysign, ssh-keyscan, and ssh-keygen.
  • The service side consists of sshd, sftp-server, and ssh-agent.

OpenSSH is developed by a few developers of the OpenBSD Project and made available under a BSD-style license.

OpenSSHより

  • SSHプロトコルでリモートログインするための接続ツール
  • 全てのトラフィックを暗号化し、ネットワークの盗聴や乗っ取り、その他諸々の攻撃を排除する
  • トンネリング、認証機能、オプション設定をまとめたソフトウェアパッケージを提供
  • ssh scp sftp コマンドを使って、リモート操作が可能
  • ssh-add ssh-keysign ssh-keyscan ssh-keygen といったコマンドから鍵を管理できる
  • sshd sftp-server ssh-agent といったサービスサイドの機能を実装
  • OpenBSDの少数の開発者によって開発されている。BSDライセンスで公開

せっかくなので、単語ごとにさらに細かく見ていきましょう。Wikipediaの定義をまとめます。

語句の説明

プロトコル - Wikipedia

コンピュータ等の電子機器間で通信する際の取り決め。どのような状況でどのようなタイプのデータをどのような順番で送るかが記載されている。

Secure Shell - Wikipedia

Secure Shell(セキュアシェル、SSH)は、暗号や認証の技術を利用して、安全にリモートコンピュータと通信するためのプロトコル。パスワードなどの認証部分を含むすべてのネットワーク上の通信が暗号化される。

トラフィック - Wikipedia

ネットワークを流れる情報のこと、または、その情報量。

トンネリング - Wikipedia

インターネット等のなんらかのネットワークで接続されている、物理的and・or論理的に離れた2点間を、仮想の回線(トンネル)によりあたかも同一点であるかのように扱えるようにすること。

認証 - Wikipedia

Certificationは被認証者が認証場所に直接アクセスして行う認証。Authenticationは被認証者が認証場所に直接アクセスする事無く遠隔地から電子的に受ける認証。

SSH File Transfer Protocol - Wikipedia

SSH File Transfer Protocol(略称:SFTP)は、SSHの仕組みを使用しコンピューター間でファイルを安全に転送するプロトコル。sftpは、このプロトコルを利用するコマンドの名前。

Secure Copy - Wikipedia

Secure Copy(scp)は、sftp同様、Secure Shell(ssh)に含まれるsshの機能を使ってセキュリティの高い(セキュアな)ファイル転送を行うコマンドの1つ。scpで使用される通信プロトコルは、Secure Copy Protocol(SCP)と呼ばれる。

BSD - Wikipedia

BSD(ビーエスディー)は、Berkeley Software Distribution の略語で、1977年から1995年までカリフォルニア大学バークレー校 (University of California, Berkeley, UCB) の Computer Systems Research Group (CSRG) が開発・配布したソフトウェア群、およびUNIXオペレーティングシステム (OS)。

OpenBSD - Wikipedia

OpenBSD(オープンビーエスディー)は、オープンソースのUnix系オペレーティングシステム。NetBSD や FreeBSD と同じく、BSDの子孫である。1995年、NetBSD の主要開発者だったテオ・デ・ラート (Theo de Raadt) により 、NetBSD から分岐する形で開発が始まった。

BSDライセンス - Wikipedia

BSD License(ビーエスディー ライセンス)は、フリーソフトウェアで使われているライセンス体系のひとつ。カリフォルニア大学によって策定され、同大学のバークレー校内の研究グループ、Computer Systems Research Groupが開発したソフトウェア群であるBSDなどで採用されている。「無保証」であることの明記と著作権およびライセンス条文自身の表示を再頒布の条件とするライセンス規定である。この条件さえ満たせば、BSDライセンスのソースコードを複製・改変して作成したオブジェクトコードをソースコードを公開せずに頒布できる。

普段何気なくSSH接続を使っているかと思いますが、ほとんどのOSでこのOpenSSHが基盤になっています。 OpenSSH: Users

人と人の会話は、耳を済ませば関係ない人も聞くことができるように、コンピュータとコンピュータの通信も簡単に盗聴することができます。そのため遠隔のコンピュータへ通信する際は、SSHのようなセキュアなプロトコルが欠かせません。 OpenSSHはフリーソフトウェアとして公開されており、誰でも使うことができますが、「無保証」です。仮にOpenSSHに重大な脆弱性が見つかったとしたら、その影響範囲は計り知れませんね・・・

OpenSSH 7.8 非互換の可能性がある変更について

本題に入ります。

前回の記事でも取り上げましたが、2018年8月24日にOpenSSHのバージョンアップで、非互換の可能性がある変更 (Potentially-incompatible changes) が発生しています。それ以前の秘密鍵は、OpenSSLのPEM形式で作成されていましたが、本バージョンからOpenSSHの形式がデフォルトとなり、秘密鍵のヘッダの形式が大きく変わっています。

OpenSSH: Release Notes

字面が似ていますが SSL は Secure Sockets Layer の略で、OpenSSH の暗号化アルゴリズムは OpenSSL と依存関係にあります。

従来のOpenSSLのPEM形式で作成される秘密鍵は、

ssh-keygen -f ~/.ssh/id_rsa_test -t rsa

# ~/.ssh/id_rsa_test
-----BEGIN RSA PRIVATE KEY-----
*************************************
*************************************
*************************************
-----END RSA PRIVATE KEY-----

という構成になり、パスフレーズで保護すると、

ssh-keygen -p -f ~/.ssh/id_rsa_test -t rsa

# ~/.ssh/id_rsa_test
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,04D8BFBCCAD07CFD5C137BB4E1197102

*************************************
*************************************
*************************************
-----END RSA PRIVATE KEY-----

というように、ヘッダの下に秘密鍵の暗号化についての情報が記載されます。

しかし、OpenSSH 7.8から変更となった、OpenSSH形式の秘密鍵は、

ssh-keygen -p -f ~/.ssh/id_rsa_test -t rsa

# ~/.ssh/id_rsa_test
-----BEGIN OPENSSH PRIVATE KEY-----
*************************************
*************************************
*************************************
-----END OPENSSH PRIVATE KEY-----

という構成になり、パスフレーズを付与しても暗号化についての情報が記載されなくなってしまいました。

そもそもOpenSSH形式は2014年からサポートされていたようですが、こちらの方がOffline Password Crackingに対してより強固な形式であるため、デフォルトで変更となったようです。

Golang の x/crypto/ssh パッケージでは、パスフレーズで保護された秘密鍵かどうかを判断するのに、秘密鍵の Proc-Type: をパースしていますが、新しいOpenSSHで作成された秘密鍵はこの情報を持たないので、ここの条件分岐をスルーしてしまうバグが発生しています。

crypto/keys.go at master · golang/crypto · GitHub

対策としては、-m PEM を指定すると、

ssh-keygen -p -f ~/.ssh/id_rsa_test -t rsa -m PEM

# ~/.ssh/id_rsa_test
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,5B0211B9361E6F5730502467994D3995

*************************************
*************************************
*************************************
-----END RSA PRIVATE KEY-----

というように昔の形式で出力されます。

ただ、Golangに限らず、他言語のSSHライブラリにも影響を及ぼしそうな仕様変更ですね。

最後に

まずは、お手元のOpenSSHのバージョンを ssh -V で確認しておきましょう!

バージョンが7.8以上で、旧形式の秘密鍵を作成したいときは、ssh-keygen -m PEM とオプションを加えてください。