12

Jschを使用して SFTP サーバーに接続するこの単純な Java プログラムがあります。

Java 1.4.2 では「認証失敗」例外で接続が失敗しますが、Java 1.7 では問題なく接続されます。

try {
    JSch jsch = new JSch();

    jsch.setKnownHosts(KNOWN_HOSTS_PATH);
    jsch.addIdentity(PRIVATE_KEY_PATH, PASSPHRASE);

    Session session = jsch.getSession(USERNAME, HOSTNAME, 22);
    session.connect(2500);

    Channel channel = session.openChannel("shell");
    channel.setInputStream(System. in );
    channel.setOutputStream(System.out);
    channel.connect();
} catch (Exception e) {
    e.printStackTrace(System.err);
}

私が使っている鍵はssh-rsa 4096ビットキーです。キー ファイルは.pub、秘密キーと同じディレクトリに存在します。

ロガーを接続すると、例外 ( で発生channel.connect();)の前に次のメッセージが表示されます。

情報: <redacted> ポート 22 に接続しています
情報: 接続が確立されました
情報: リモート バージョン文字列: SSH-2.0-OpenSSH_5.1p1 Debian-5
情報: ローカル バージョン文字列: SSH-2.0-JSCH-0.1.42
情報: CheckCiphers: aes256-ctr、aes192-ctr、aes128-ctr、aes256-cbc、aes192-cbc、aes128-cbc、3des-ctr、arcfour、arcfour128、arcfour256
情報: arcfour は利用できません。
情報: arcfour128 は利用できません。
情報: arcfour256 は利用できません。
情報: SSH_MSG_KEXINIT が送信されました
情報: SSH_MSG_KEXINIT を受信しました
情報: kex: サーバー-> クライアント aes128-ctr hmac-md5 なし
INFO: kex: client->server aes128-ctr hmac-md5 none
情報: SSH_MSG_KEXDH_INIT が送信されました
情報: SSH_MSG_KEXDH_REPLY を期待しています
情報: ssh_rsa_verify: 署名は true
情報: ホスト '<redacted>' は既知であり、RSA ホスト キーを計算します
情報: SSH_MSG_NEWKEYS が送信されました
情報: SSH_MSG_NEWKEYS を受信しました
情報: SSH_MSG_SERVICE_REQUEST が送信されました
情報: SSH_MSG_SERVICE_ACCEPT を受信しました
情報: 続行できる認証: publickey、keyboard-interactive、password
INFO: 次の認証方法: publickey
情報: 続行できる認証: パスワード
情報: 次の認証方法: パスワード
情報: <redacted> ポート 22 から切断しています
com.jcraft.jsch.JSchException: 認証失敗
        com.jcraft.jsch.Session.connect (Session.java:452) で
        TestJsch.main (TestJsch.java:19) で

Java 1.7 で同じプログラムを実行すると、次のように表示されます。

情報: <redacted> ポート 22 に接続しています
情報: 接続が確立されました
情報: リモート バージョン文字列: SSH-2.0-OpenSSH_5.1p1 Debian-5
情報: ローカル バージョン文字列: SSH-2.0-JSCH-0.1.42
情報: CheckCiphers: aes256-ctr、aes192-ctr、aes128-ctr、aes256-cbc、aes192-cbc、aes128-cbc、3des-ctr、arcfour、arcfour128、arcfour256
情報: SSH_MSG_KEXINIT が送信されました
情報: SSH_MSG_KEXINIT を受信しました
情報: kex: サーバー-> クライアント aes128-ctr hmac-md5 なし
INFO: kex: client->server aes128-ctr hmac-md5 none
情報: SSH_MSG_KEXDH_INIT が送信されました
情報: SSH_MSG_KEXDH_REPLY を期待しています
情報: ssh_rsa_verify: 署名は true
情報: ホスト '<redacted>' は既知であり、RSA ホスト キーを計算します
情報: SSH_MSG_NEWKEYS が送信されました
情報: SSH_MSG_NEWKEYS を受信しました
情報: SSH_MSG_SERVICE_REQUEST が送信されました
INFO: SSH_MSG_SERVICE_ACCEPT を受信しましたINFO: 続行できる認証: publickey、keyboard-interactive、password
INFO: 次の認証方法: publickey
情報: 認証に成功しました (公開鍵)。
Linux <編集済み> 2.6.26-2-amd64 #1 SMP Mon Jun 13 16:29:33 UTC 2011 x86_64

<サーバーウェルカムメッセージが続きます>

1.4 VM 用の Java Cryptography Extensions (JCE) をインストールしました。

その問題の原因は何ですか?

4

5 に答える 5

4

Java には、強力な暗号化アルゴリズムを使用するための制限があります。$JRE_HOME/lib/security/US_Export_policy.jarとの内容を確認してください$JRE_HOME/lib/security/local_policy.jar。次のようなものが見つかった場合:

// File: default_local.policy
// Some countries have import limits on crypto strength.
// This policy file is worldwide importable.
grant {
    permission javax.crypto.CryptoPermission "DES", 64;
    permission javax.crypto.CryptoPermission "DESede", *;
    permission javax.crypto.CryptoPermission "RC2", 128,
                   "javax.crypto.spec.RC2ParameterSpec", 128;
    permission javax.crypto.CryptoPermission "RC4", 128;
    permission javax.crypto.CryptoPermission "RC5", 128,
          "javax.crypto.spec.RC5ParameterSpec", *, 12, *;
    permission javax.crypto.CryptoPermission "RSA", 2048;
    permission javax.crypto.CryptoPermission *, 128;
};

決定は、JCE Unlimited Strength Jurisdiction Policy をダウンロードしてインストールすることです。以前は Sun のサイトにありましたが、今はどこにあるかわかりません。

この記事で詳細を読むことができます

編集:いくつかの調査の後、私の答えが間違っていることがわかりました。

Java 1.4 は、長さが 2048 バイトを超える RSA キーをサポートしていませんBUG 4524097

于 2012-08-31T13:17:30.833 に答える
3

jsch に関する私の問題は、パーミッションに関するものです。だから私はそれらを問​​題として排除するために次のことをします

  1. 生成されたキーを使用して、コマンド ラインでリモートに ssh できることを確認します。
  2. パスワードを渡して、リモートに接続できることを確認します。
  3. ディレクトリのアクセス許可をローカルとリモートのgood ssh summaryで確認してください。
  4. ローカル ホストをリモートとして使用してみてください。

ソースコードのダウンロードに失敗し、デバッグセッションでステップスルーします。

于 2012-08-20T07:04:42.323 に答える
1

Open SSHキーを使用してみましたか?jschはOpenSSHキー形式を使用します。既存のものをOpenSSH形式に変換できます。方法は次のとおりです。puttykeygenを使用して、既存のキーをロードします。復号化するためにパスワードの入力を求められる場合があります。その後、上の変換オプションをクリックして、「OpenSSHキーのエクスポート」を選択します。上記のプログラムで、この新しく生成されたキーを使用します。お役に立てれば。

于 2012-07-20T21:25:02.227 に答える
-2

このコードは正常に動作します...

public class Exec2 {

static String SSH_SERVER_PATH = "localhost";
static String SSH_SERVER_USERNAME = "root";
static String SSH_SERVER_PASSWORD = "root";

public static void main(String[] arg) {
    try {
        JSch jsch = new JSch();
        String host = SSH_SERVER_PATH;
        String user = SSH_SERVER_USERNAME;

        Session session = jsch.getSession(user, host, 22);

        // username and password will be given via UserInfo interface.

        UserInfo ui = new MyUserInfo();
        session.setUserInfo(ui);
        session.connect();

        String command = "uname";

        Channel channel = session.openChannel("exec");
        ((ChannelExec) channel).setCommand(command);

        channel.setInputStream(null);

        ((ChannelExec) channel).setErrStream(System.err);

        InputStream in = channel.getInputStream();

        channel.connect();

        byte[] tmp = new byte[1024];
        while (true) {
            while (in.available() > 0) {
                int i = in.read(tmp, 0, 1024);
                if (i < 0)
                    break;
                System.out.print(new String(tmp, 0, i));
            }
            if (channel.isClosed()) {
                System.out.println("exit-status: " + channel.getExitStatus());
                break;
            }
            try {
                Thread.sleep(1000);
            } catch (Exception ee) {
            }
        }
        channel.disconnect();
        session.disconnect();
    } catch (Exception e) {
        System.out.println(e);
    }
}

public static class MyUserInfo implements UserInfo, UIKeyboardInteractive {

    String passwd;

    public String getPassword() {
        return passwd;
    }

    public boolean promptYesNo(String str) {
        return true;
    }


    public String getPassphrase() {
        return null;
    }

    public boolean promptPassphrase(String message) {
        return true;
    }

    public boolean promptPassword(String message) {
        passwd = SSH_SERVER_PASSWORD;
        return true;
    }

    public void showMessage(String message) {
        System.out.println("message = " + message);
    }

    public String[] promptKeyboardInteractive(String destination,
            String name, String instruction, String[] prompt, boolean[] echo) {
        if (prompt[0].equals("Password: ")){
            String[] response = new String[1];
            response[0] = SSH_SERVER_PASSWORD;
            return response;
        }
        return null;
    }
}
}
于 2013-01-11T16:41:27.003 に答える
-3

public String getPassphrase() { null を返します。}

public boolean promptPassphrase(String message) {
    return true;
}

public boolean promptPassword(String message) {
    passwd = SSH_SERVER_PASSWORD;
    return true;
}

public void showMessage(String message) {
    System.out.println("message = " + message);
于 2014-02-04T16:05:28.563 に答える