私はしばらくの間、PHPのopenssl拡張機能を使用してRSAキーペアを生成し、その結果をOpenSSH互換のキーペアとして保存しようとしてきました。つまり、秘密キーはPEMでエンコードされ(簡単です)、公開キーはOpenSSH固有の形式で保存されます。次の形式の:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABA...more base64 encoded stuff...
私が収集できる限り、この形式は次のもので構成されています。
- クリアテキストのキータイプとそれに続くスペース(つまり、「openssh-rsa」)
- 次のデータを表すbase64でエンコードされた文字列:
- 32ビットunsignedlongビッグエンディアンとしてエンコードされたアルゴリズム名の長さ(バイト単位)(この場合は7)
- アルゴリズム名、この場合は「ssh-rsa」
- RSA'e'番号の長さ(バイト単位)。32ビットの符号なしロングエンディアンとしてエンコードされます。
- RSA'e'番号
- RSA'n'番号の長さ(バイト単位)。32ビットの符号なしロングエンディアンとしてエンコードされます。
- RSA'n'番号
PHPのpack()関数を使用してこれを実装しようとしましたが、何を試しても、ssh-keygen -y -f
opensslによって生成された同じRSA秘密鍵でコマンドを使用して得られる結果と同じになることはありません。
これが私のコードの簡略版です:
<?php
// generate private key
$privKey = openssl_pkey_new(array(
'private_key_bits' => 1024,
'private_key_type' => OPENSSL_KEYTYPE_RSA
));
// convert public key to OpenSSH format
$keyInfo = openssl_pkey_get_details($privKey);
$data = pack("Na*", 7, 'ssh-rsa');
$data .= pack("Na*", strlen($keyInfo['rsa']['e']), $keyInfo['rsa']['e']);
$data .= pack("Na*", strlen($keyInfo['rsa']['n']), $keyInfo['rsa']['n']);
$pubKey = "ssh-rsa " . base64_encode($data);
echo "PHP generated RSA public key:\n$pubKey\n\n";
// For comparison, generate public key using ssh-keygen
openssl_pkey_export($privKey, $pem);
$umask = umask(0066); // this is needed for ssh-keygen to work properly
file_put_contents('/tmp/ssh-keygen-test', $pem);
umask($umask);
exec('ssh-keygen -y -f /tmp/ssh-keygen-test', $out, $ret);
$otherPubKey = $out[0];
echo "ssh-keygen generated RSA public key:\n$otherPubKey\n\n";
echo ($pubKey == $otherPubKey ? "yes! they are the same\n" : "FAIL! they are different\n");
?>
ssh-keygenに依存せずにこれを行う方法に関するヒントはありますか?