次のコードを使用して、JavaアプリケーションでGitを操作します。有効なキーがあります(常に使用します)。キーとgitリポジトリですが、次の例外が発生します。
無効な秘密鍵:[B @ 59c40796。
この行で:
jSch.addIdentity("<key_path>/private_key.pem");
私の完全なコード:
String remoteURL = "ssh://git@<git_repository>";
TransportConfigCallback transportConfigCallback = new SshTransportConfigCallback();
File gitFolder = new File(workingDirectory);
if (gitFolder.exists()) FileUtils.delete(gitFolder, FileUtils.RECURSIVE);
Git git = Git.cloneRepository()
.setURI(remoteURL)
.setTransportConfigCallback(transportConfigCallback)
.setDirectory(new File(workingDirectory))
.call();
}
private static class SshTransportConfigCallback implements TransportConfigCallback {
private final SshSessionFactory sshSessionFactory = new JschConfigSessionFactory() {
@Override
protected void configure(OpenSshConfig.Host hc, Session session) {
session.setConfig("StrictHostKeyChecking", "no");
}
@Override
protected JSch createDefaultJSch(FS fs) throws JSchException {
JSch jSch = super.createDefaultJSch(fs);
jSch.addIdentity("<key_path>/private_key.pem");
return jSch;
}
};
オンラインで検索した後、createDefaultJSchを変更してpemWriterを使用します。
@Override
protected JSch createDefaultJSch(FS fs) throws JSchException {
JSch jSch = super.createDefaultJSch(fs);
byte[] privateKeyPEM = null;
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
List<String> lines = Files.readAllLines(Paths.get("<my_key>.pem"), StandardCharsets.US_ASCII);
PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(String.join("", lines)));
RSAPrivateKey privKey = (RSAPrivateKey) keyFactory.generatePrivate(privSpec);
PKCS8Generator pkcs8 = new PKCS8Generator(privKey);
StringWriter writer = new StringWriter();
PemWriter pemWriter = new PemWriter(writer);
pemWriter.writeObject(pkcs8);
privateKeyPEM = writer.toString().getBytes("US-ASCII");
} catch (Exception e) {
e.printStackTrace();
}
jSch.addIdentity("git", privateKeyPEM, null, null);
return jSch;
}
しかし、まだ"invalid privatekey"例外が発生しています。
私もこの問題に出くわしました。 Jgit on macを実行すると、一部のユーザーに対して次の例外が発生しました。
org.Eclipse.jgit.transport.JschConfigSessionFactory.getSession(JschConfigSessionFactory.Java:160)
at org.Eclipse.jgit.transport.SshTransport.getSession(SshTransport.Java:137)
at org.Eclipse.jgit.transport.TransportGitSsh$SshFetchConnection.<init>(TransportGitSsh.Java:274)
at org.Eclipse.jgit.transport.TransportGitSsh.openFetch(TransportGitSsh.Java:169)
at org.Eclipse.jgit.transport.FetchProcess.executeImp(FetchProcess.Java:136)
at org.Eclipse.jgit.transport.FetchProcess.execute(FetchProcess.Java:122)
at org.Eclipse.jgit.transport.Transport.fetch(Transport.Java:1236)
at org.Eclipse.jgit.api.FetchCommand.call(FetchCommand.Java:234)
... 17 more
Caused by: com.jcraft.jsch.JSchException: invalid privatekey: [B@e4487af
at com.jcraft.jsch.KeyPair.load(KeyPair.Java:664)
at com.jcraft.jsch.KeyPair.load(KeyPair.Java:561)
at com.jcraft.jsch.IdentityFile.newInstance(IdentityFile.Java:40)
at com.jcraft.jsch.JSch.addIdentity(JSch.Java:407)
at com.jcraft.jsch.JSch.addIdentity(JSch.Java:367)
at org.Eclipse.jgit.transport.JschConfigSessionFactory.getJSch(JschConfigSessionFactory.Java:276)
at org.Eclipse.jgit.transport.JschConfigSessionFactory.createSession(JschConfigSessionFactory.Java:220)
at org.Eclipse.jgit.transport.JschConfigSessionFactory.createSession(JschConfigSessionFactory.Java:176)
at org.Eclipse.jgit.transport.JschConfigSessionFactory.getSession(JschConfigSessionFactory.Java:110)
根本的な原因は、ssh秘密鍵の不一致であることが発見されました。例外は、より新しい種類のキーを持つユーザーでのみ発生しましたed25519、このキーヘッダーを出力します。
-----BEGIN OPENSSH PRIVATE KEY-----
種類の代わりに[〜#〜] rsa [〜#〜]:
-----BEGIN RSA PRIVATE KEY-----
rSAキーの再生成(ssh-keygen -t rsa
)、例外をなくしました。
次のコメントを編集します。OpenSSH7.8以降を使用している場合は、生成コマンドに-m PEMを追加する必要がある場合があります。ssh-keygen -t rsa -m PEM
OpenSSHの最近のバージョン(7.8以降)は、デフォルトでnewOpenSSH形式でキーを生成します。
-----BEGIN OPENSSH PRIVATE KEY-----
JSchはこのキー形式をサポートしていません。
ssh-keygen
を使用して、キーをclassicOpenSSH形式に変換できます。
ssh-keygen -p -f file -m pem -P passphrase -N passphrase
(キーがパスフレーズで暗号化されていない場合、passphrase
の代わりに""
を使用します)
Windowsを使用している場合、PuTTYgenを使用できます( PuTTYパッケージ から)。キーをロードして、Conversions> Export OpenSSH keyに移動します。 RSAキーの場合、classic形式を使用します。
ssh-keygen
を使用して新しいキーを作成する場合は、 -m PEM
を追加して、classic形式:
ssh-keygen -m PEM
_.pem
_およびde-base64 allという名前のファイルを読み取り、結果をPKCS8-unencryptedとして扱い、明らかに成功します。これは、ファイルがPEM形式ではなかったことを意味します。 PEM形式では、少なくともdash-BEGIN行とdash-END行が有効である必要があります。削除しないと、de-base64が失敗するか間違っています。 (一部 PEM形式には、処理が必要な822形式のヘッダーもあります。)
BouncyCastleを使用しているように見えますが、私のバージョンではRSAPrivateKey
のみを受け取る_PKCS8Generator
_コンストラクターはありません。最も機能するのはJcaPKCS8Generator (RSAPrivateKey implements PrivateKey, OutputEncryptor=null)
(つまり、異なるが関連するクラスであり、2つの引数は1つではありません)です。
PemWriter
はバッファリングされ、基礎となるStringWriter
を見る前にフラッシュしませんでした。結果として、writer.toString().getBytes()
は空/ゼロ長の配列であり、JSch
は正しく無効と見なします。
#2と#3を修正し、入力を使用し、JSch
を経由せずにJGit
を直接呼び出すと、うまくいきます。