CyberduckのSFTP接続でInvalid Item Lengthと出たときの対応

macOS上でCyberduckをFTP等のファイル転送クライアントに使っている方も多いかと思います。

先日、新しいチームメンバー（非エンジニア）がSFTPでファイルをアップロードするために設定をしようとしたが、うまく行かない問題にぶつかりました。  
その際の調査から、予想外の結果に行き着いたので紹介します。

## エラー内容

エラーとしては

> Invalid Item Length (-XXXXXXXX)

みたいなものでした（ `XXXXXXX`は適当な数字です）。

## まずは疑う鍵ペア

SFTPで鍵ペアを利用した認証なので、当然、最初に疑うのは**鍵ペア**です。  
とりあえず鍵ペアに問題がなければ通常のsshでもログインできるはずなので試してみました。

```bash
$ ssh -i 秘密鍵へのパス ホスト名
```

上記を実行したところ問題なくsshでログインできました。  
この時点で鍵に問題がある可能性は（ほぼ）消えます。

## Cyberduckのデバッグ出力をONに
とりあえずCyberduckのデバッグ出力をONにしました。  
macOSでは以下のコマンドでデバッグログが `/var/log/system.log` に出力されるようになります。

```bash
$ defaults write ~/Library/Preferences/ch.sudo.cyberduck.plist logging debug
```

こちらでSFTPを試してみましたが、特に目ぼしいものは出てきませんでした…

#### デバッグ出力が不要になったら

残しておいて特に害があるわけではありませんが、上記設定を戻す場合は `defaults delete`で削除するのをお忘れなく。

```bash
$ defaults read ~/Library/Preferences/ch.sudo.cyberduck.plist logging    # 設定されているか確認
debug
$ defaults delete ~/Library/Preferences/ch.sudo.cyberduck.plist logging  # 削除する
$ defaults read ~/Library/Preferences/ch.sudo.cyberduck.plist logging    # 設定されていないことを確認
2018-11-10 17:05:07.378 defaults[10390:76555]
The domain/default pair of (/Users/********/Library/Preferences/ch.sudo.cyberduck.plist, logging) does not exist
```

## ssh-agentは使えた
Cyberduckのログを見ていて`SSH Agent`的な文言が出ていたので調べてみたところ、[CyberduckのWiki](https://trac.cyberduck.io/wiki/help/en/howto/sftp#PublickeyauthenticationusingSSHagent) に以下の記述がありました。

> There is support for OpenSSH ssh-agent

どうやら、ssh-agent（macOSではデフォルトで動作しています）に登録してある秘密鍵を自動的に使ってくれるようです。

試す価値はありそうだな、と思い秘密鍵を追加してみました。

```bash
$ ssh-add 秘密鍵へのパス
```

案の定、ログを見ているとssh-agentが使われ、Cyberduckで無事に接続できました。

ただ、これでは `ssh-add` を毎回ターミナルで入力するか、何かしら設定をしておく必要があることになり、少し面倒です。  
また、Cyberduckの設定だけでうまくいかないことの根本解決になっておりません。

もう少し調べてみました。

## 変わっていたOpenSSHのデフォルト
秘密鍵を試しに見てみました。

```bash
$ cat 秘密鍵へのパス
-----BEGIN OPENSSH PRIVATE KEY-----
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    :
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-----END OPENSSH PRIVATE KEY-----
```

で、更にさきほどの[CyberduckのWiki](https://trac.cyberduck.io/wiki/help/en/howto/sftp#PublicKeyAuthentication)を眺めていると、以下のような記述がありました。

> Private keys containing a DSA or RSA private key in PEM format are supported (look for -----BEGIN DSA PRIVATE KEY----- or -----BEGIN RSA PRIVATE KEY----- in the file)..

・・・

・・・・・・・

あれ :question::question:

`BEGIN OPENSSH PRIVATE KEY` :arrow_left: :arrow_right: `BEGIN RSA PRIVATE KEY`

ちょっと違う :exclamation:

そうなんです。どうやら、OpenSSH 7.8以降から`ssh-keygen`で生成される秘密鍵のフォーマットのデフォルトが変更されていたようで、Cyberduckは対応していなかったのです（ログにはそんな風に出てなかったけど…）

[OpenSSH 7.8のリリースノートより](https://www.openssh.com/txt/release-7.8)

> ssh-keygen(1): write OpenSSH format private keys by default
> instead of using OpenSSL's PEM format. The OpenSSH format,
> supported in OpenSSH releases since 2014 and described in the
> PROTOCOL.key file in the source distribution, offers substantially
> better protection against offline password guessing and supports
> key comments in private keys. If necessary, it is possible to write
> old PEM-style keys by adding "-m PEM" to ssh-keygen's arguments
> when generating or updating a key.

古いフォーマットで生成する場合は`-m PEM`を`ssh-keygen`に渡せば良いらしいです。

```bash
$ ssh-keygen -m PEM
```

中身を確認してみます。

```bash
$ cat 秘密鍵へのパス
-----BEGIN RSA PRIVATE KEY-----
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    :
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-----END RSA PRIVATE KEY-----
```

ちゃんと前のフォーマットになってますね :exclamation:  
今回はじめて知ったのですが、秘密鍵の`RSA`とか`OPENSSH`ってフォーマットを表してるんですね。

参考Stackoverflow: https://stackoverflow.com/a/20065522/

とりあえず無事にCyberduckの設定だけでSFTPできるようになりました。