Android 上使用 spongycastle 而不是 bouncycastle 的 Jsch

发布于 2024-12-11 23:12:26 字数 6975 浏览 0 评论 0原文

我目前有一个 Android 应用程序使用密码通过 ssh 连接到我的路由器。我正在寻求改进这一点,以便我可以使用密钥,但我遇到了真正的问题。据我了解,android 中包含的 bouncycastle 版本是一个残缺的版本,因此 ssh 密钥不能与 jsch 一起使用。我看过 spongycastle ,它声称是一个更完整的实现。下面是与使用 bouncycastle 基本相同的结果,Auth Fail。


10-26 18:18:23.528: INFO/System.out(10642): Log(jsch,1): Connecting to 192.168.88.1 port 22
10-26 18:18:23.538: INFO/System.out(10642): Log(jsch,1): Connection established
10-26 18:18:23.548: INFO/System.out(10642): Log(jsch,1): Remote version string: SSH-2.0-ROSSSH
10-26 18:18:23.548: INFO/System.out(10642): Log(jsch,1): Local version string: SSH-2.0-JSCH-0.1.44
10-26 18:18:23.548: INFO/System.out(10642): Log(jsch,1): CheckCiphers: aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,3des-ctr,arcfour,arcfour128,arcfour256
10-26 18:18:23.618: INFO/System.out(10642): Log(jsch,1): SSH_MSG_KEXINIT sent
10-26 18:18:23.618: INFO/System.out(10642): Log(jsch,1): SSH_MSG_KEXINIT received
10-26 18:18:23.628: INFO/System.out(10642): Log(jsch,1): kex: server->client aes128-cbc hmac-md5 none
10-26 18:18:23.628: INFO/System.out(10642): Log(jsch,1): kex: client->server aes128-cbc hmac-md5 none
10-26 18:18:23.688: INFO/System.out(10642): Log(jsch,1): SSH_MSG_KEXDH_INIT sent
10-26 18:18:23.688: INFO/System.out(10642): Log(jsch,1): expecting SSH_MSG_KEXDH_REPLY
10-26 18:18:24.058: INFO/System.out(10642): Log(jsch,1): ssh_dss_verify: signature true
10-26 18:18:24.058: INFO/System.out(10642): Log(jsch,2): Permanently added '192.168.88.1' (DSA) to the list of known hosts.
10-26 18:18:24.058: INFO/System.out(10642): Log(jsch,1): SSH_MSG_NEWKEYS sent
10-26 18:18:24.058: INFO/System.out(10642): Log(jsch,1): SSH_MSG_NEWKEYS received
10-26 18:18:24.078: INFO/System.out(10642): Log(jsch,1): SSH_MSG_SERVICE_REQUEST sent
10-26 18:18:24.088: INFO/System.out(10642): Log(jsch,1): SSH_MSG_SERVICE_ACCEPT received
10-26 18:18:24.108: INFO/System.out(10642): Log(jsch,1): Authentications that can continue: publickey,keyboard-interactive,password
10-26 18:18:24.108: INFO/System.out(10642): Log(jsch,1): Next authentication method: publickey
10-26 18:18:24.108: INFO/System.out(10642): Log(jsch,1): Authentications that can continue: password
10-26 18:18:24.118: INFO/System.out(10642): Log(jsch,1): Next authentication method: password
10-26 18:18:24.128: INFO/System.out(10642): Log(jsch,1): Disconnecting from 192.168.88.1 port 22
10-26 18:18:24.138: WARN/System.err(10642): com.jcraft.jsch.JSchException: Auth fail

jsch 没有提供大量日志信息来帮助我找出问题所在。

我想我为此使用了相当标准的代码:



static {
        Security.addProvider(new org.spongycastle.jce.provider.BouncyCastleProvider());
    }

在 OnCreate 中,我删除了原始的 bouncycastle 提供程序



        Security.removeProvider("BC");

然后我在尝试连接之前添加了身份



        jsch.addIdentity(key_filename);

    Properties sshProp = new Properties();
    sshProp.put("StrictHostKeyChecking", "no");
    session.setConfig(sshProp);
    session.connect();

有人成功完成此操作吗?我是不是忘记了什么?

编辑点附加信息:

正如我在评论中所说,我现在怀疑当我切换密钥并在 sshd 版本 OpenSSH_5.3p1 Debian-3ubuntu7 上进行测试时,


debug2: mac_setup: found hmac-md5
debug1: kex: client->server aes128-ctr hmac-md5 none
debug2: mac_setup: found hmac-md5
debug1: kex: server->client aes128-ctr hmac-md5 none
debug2: dh_gen_key: priv key bits set: 122/256
debug2: bits set: 519/1024
debug1: expecting SSH2_MSG_KEXDH_INIT
debug2: bits set: 537/1024
debug2: kex_derive_keys
debug2: set_newkeys: mode 1
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug2: monitor_read: 5 used once, disabling now
debug2: set_newkeys: mode 0
debug1: SSH2_MSG_NEWKEYS received
debug1: KEX done
debug1: userauth-request for user root service ssh-connection method none
debug1: attempt 0 failures 0
debug2: parse_server_config: config reprocess config len 638
debug2: input_userauth_request: setting up authctxt for root
debug2: input_userauth_request: try method none
debug2: monitor_read: 7 used once, disabling now
debug1: PAM: initializing for "root"
debug1: PAM: setting PAM_RHOST to "nexus"
debug1: PAM: setting PAM_TTY to "ssh"
debug2: monitor_read: 50 used once, disabling now
debug2: monitor_read: 3 used once, disabling now
Failed none for root from 192.168.88.31 port 37807 ssh2
debug1: userauth-request for user root service ssh-connection method password
debug1: attempt 1 failures 0
debug2: input_userauth_request: try method password
debug1: PAM: password authentication failed for root: Authentication failure
Failed password for root from 192.168.88.31 port 37807 ssh2
Received disconnect from 192.168.88.31: 3: com.jcraft.jsch.JSchException: Auth fail
debug1: do_cleanup
debug1: do_cleanup
debug1: PAM: cleanup

我什至没有尝试使用该密钥,而从电脑上



debug1: userauth-request for user root service ssh-connection method publickey
debug1: attempt 1 failures 0
debug2: input_userauth_request: try method publickey
debug1: test whether pkalg/pkblob are acceptable
debug1: Checking blacklist file /usr/share/ssh/blacklist.RSA-2048
debug1: Checking blacklist file /etc/ssh/blacklist.RSA-2048
debug1: temporarily_use_uid: 0/0 (e=0/0)
debug1: trying public key file /root/.ssh/authorized_keys
debug1: restore_uid: 0/0
debug1: temporarily_use_uid: 0/0 (e=0/0)
debug1: trying public key file /root/.ssh/authorized_keys2
debug1: fd 4 clearing O_NONBLOCK
debug1: matching key found: file /root/.ssh/authorized_keys2, line 2

我可以看到正在使用的关键方法。下面是我用于测试的代码,不漂亮但功能齐全。我知道这很糟糕,但密码确实包含 authtype == AUTHENTICATION_METHOD_KEY 时使用的密钥的文件名和路径



public static String testSSHCommand ( String username, String password, String hostname, int port, String command, int authtype) throws Exception {    

    JSch jsch = new JSch();

    JSch.setLogger(new Logger() {
            public boolean isEnabled(int i) {
                return true;
            }

            public void log(int i, String s) {
                System.out.println("Log(jsch," + i + "): " + s);
            }
    });


    if (authtype != AUTHENTICATION_METHOD_PASSWORD) {
        Log.v("AUTHMETHOD","authmethod was "+authtype+" with key filename of "+password);
        jsch.addIdentity(password);
    } 

    Session session = jsch.getSession(username, hostname, 22);

    if (authtype != AUTHENTICATION_METHOD_KEY) {
        session.setPassword(password);
    }


    Properties prop = new Properties();
    prop.put("StrictHostKeyChecking", "no");
    session.setConfig(prop);

    session.connect();

    if (session.isConnected() ) {
        ChannelExec channelssh = (ChannelExec)          
        session.openChannel("exec");      
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        channelssh.setOutputStream(os);
        channelssh.setCommand(command);
        channelssh.connect();        
        channelssh.disconnect();

        return os.toString();
    } else {
        return "";
    }
}

I currently have an Android application connecting to my router via ssh using a password. I'm looking to improve this so I can use keys but I am having real issues. From what I understand the version of bouncycastle included with android is a crippled version and because of this ssh keys don't work with jsch. I have looked at spongycastle which claims to be a fuller implementation. Below is the result which is basically the same as using bouncycastle, Auth Fail.


10-26 18:18:23.528: INFO/System.out(10642): Log(jsch,1): Connecting to 192.168.88.1 port 22
10-26 18:18:23.538: INFO/System.out(10642): Log(jsch,1): Connection established
10-26 18:18:23.548: INFO/System.out(10642): Log(jsch,1): Remote version string: SSH-2.0-ROSSSH
10-26 18:18:23.548: INFO/System.out(10642): Log(jsch,1): Local version string: SSH-2.0-JSCH-0.1.44
10-26 18:18:23.548: INFO/System.out(10642): Log(jsch,1): CheckCiphers: aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,3des-ctr,arcfour,arcfour128,arcfour256
10-26 18:18:23.618: INFO/System.out(10642): Log(jsch,1): SSH_MSG_KEXINIT sent
10-26 18:18:23.618: INFO/System.out(10642): Log(jsch,1): SSH_MSG_KEXINIT received
10-26 18:18:23.628: INFO/System.out(10642): Log(jsch,1): kex: server->client aes128-cbc hmac-md5 none
10-26 18:18:23.628: INFO/System.out(10642): Log(jsch,1): kex: client->server aes128-cbc hmac-md5 none
10-26 18:18:23.688: INFO/System.out(10642): Log(jsch,1): SSH_MSG_KEXDH_INIT sent
10-26 18:18:23.688: INFO/System.out(10642): Log(jsch,1): expecting SSH_MSG_KEXDH_REPLY
10-26 18:18:24.058: INFO/System.out(10642): Log(jsch,1): ssh_dss_verify: signature true
10-26 18:18:24.058: INFO/System.out(10642): Log(jsch,2): Permanently added '192.168.88.1' (DSA) to the list of known hosts.
10-26 18:18:24.058: INFO/System.out(10642): Log(jsch,1): SSH_MSG_NEWKEYS sent
10-26 18:18:24.058: INFO/System.out(10642): Log(jsch,1): SSH_MSG_NEWKEYS received
10-26 18:18:24.078: INFO/System.out(10642): Log(jsch,1): SSH_MSG_SERVICE_REQUEST sent
10-26 18:18:24.088: INFO/System.out(10642): Log(jsch,1): SSH_MSG_SERVICE_ACCEPT received
10-26 18:18:24.108: INFO/System.out(10642): Log(jsch,1): Authentications that can continue: publickey,keyboard-interactive,password
10-26 18:18:24.108: INFO/System.out(10642): Log(jsch,1): Next authentication method: publickey
10-26 18:18:24.108: INFO/System.out(10642): Log(jsch,1): Authentications that can continue: password
10-26 18:18:24.118: INFO/System.out(10642): Log(jsch,1): Next authentication method: password
10-26 18:18:24.128: INFO/System.out(10642): Log(jsch,1): Disconnecting from 192.168.88.1 port 22
10-26 18:18:24.138: WARN/System.err(10642): com.jcraft.jsch.JSchException: Auth fail

There's not a great deal of logging information from jsch to help me work out what's wrong.

I think I'm using pretty standard code for this:



static {
        Security.addProvider(new org.spongycastle.jce.provider.BouncyCastleProvider());
    }

In OnCreate I'm removing the original bouncycastle provider



        Security.removeProvider("BC");

Then I add the identity just before trying to connect



        jsch.addIdentity(key_filename);

    Properties sshProp = new Properties();
    sshProp.put("StrictHostKeyChecking", "no");
    session.setConfig(sshProp);
    session.connect();

Has anyone done this successfully? Am I forgetting something?

Edit point additional info:

As I said in the comment I'm now suspecting that the key isn't even being tried when I switch the key and test on sshd version OpenSSH_5.3p1 Debian-3ubuntu7


debug2: mac_setup: found hmac-md5
debug1: kex: client->server aes128-ctr hmac-md5 none
debug2: mac_setup: found hmac-md5
debug1: kex: server->client aes128-ctr hmac-md5 none
debug2: dh_gen_key: priv key bits set: 122/256
debug2: bits set: 519/1024
debug1: expecting SSH2_MSG_KEXDH_INIT
debug2: bits set: 537/1024
debug2: kex_derive_keys
debug2: set_newkeys: mode 1
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug2: monitor_read: 5 used once, disabling now
debug2: set_newkeys: mode 0
debug1: SSH2_MSG_NEWKEYS received
debug1: KEX done
debug1: userauth-request for user root service ssh-connection method none
debug1: attempt 0 failures 0
debug2: parse_server_config: config reprocess config len 638
debug2: input_userauth_request: setting up authctxt for root
debug2: input_userauth_request: try method none
debug2: monitor_read: 7 used once, disabling now
debug1: PAM: initializing for "root"
debug1: PAM: setting PAM_RHOST to "nexus"
debug1: PAM: setting PAM_TTY to "ssh"
debug2: monitor_read: 50 used once, disabling now
debug2: monitor_read: 3 used once, disabling now
Failed none for root from 192.168.88.31 port 37807 ssh2
debug1: userauth-request for user root service ssh-connection method password
debug1: attempt 1 failures 0
debug2: input_userauth_request: try method password
debug1: PAM: password authentication failed for root: Authentication failure
Failed password for root from 192.168.88.31 port 37807 ssh2
Received disconnect from 192.168.88.31: 3: com.jcraft.jsch.JSchException: Auth fail
debug1: do_cleanup
debug1: do_cleanup
debug1: PAM: cleanup

I can see no attempt to use the key, whereas from a pc



debug1: userauth-request for user root service ssh-connection method publickey
debug1: attempt 1 failures 0
debug2: input_userauth_request: try method publickey
debug1: test whether pkalg/pkblob are acceptable
debug1: Checking blacklist file /usr/share/ssh/blacklist.RSA-2048
debug1: Checking blacklist file /etc/ssh/blacklist.RSA-2048
debug1: temporarily_use_uid: 0/0 (e=0/0)
debug1: trying public key file /root/.ssh/authorized_keys
debug1: restore_uid: 0/0
debug1: temporarily_use_uid: 0/0 (e=0/0)
debug1: trying public key file /root/.ssh/authorized_keys2
debug1: fd 4 clearing O_NONBLOCK
debug1: matching key found: file /root/.ssh/authorized_keys2, line 2

I can see the key method being used. Below is the code I'm using for testing, not pretty but functional. I know it's horrible but password does contain the filename and path of the key to be used when authtype == AUTHENTICATION_METHOD_KEY



public static String testSSHCommand ( String username, String password, String hostname, int port, String command, int authtype) throws Exception {    

    JSch jsch = new JSch();

    JSch.setLogger(new Logger() {
            public boolean isEnabled(int i) {
                return true;
            }

            public void log(int i, String s) {
                System.out.println("Log(jsch," + i + "): " + s);
            }
    });


    if (authtype != AUTHENTICATION_METHOD_PASSWORD) {
        Log.v("AUTHMETHOD","authmethod was "+authtype+" with key filename of "+password);
        jsch.addIdentity(password);
    } 

    Session session = jsch.getSession(username, hostname, 22);

    if (authtype != AUTHENTICATION_METHOD_KEY) {
        session.setPassword(password);
    }


    Properties prop = new Properties();
    prop.put("StrictHostKeyChecking", "no");
    session.setConfig(prop);

    session.connect();

    if (session.isConnected() ) {
        ChannelExec channelssh = (ChannelExec)          
        session.openChannel("exec");      
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        channelssh.setOutputStream(os);
        channelssh.setCommand(command);
        channelssh.connect();        
        channelssh.disconnect();

        return os.toString();
    } else {
        return "";
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

慵挽 2024-12-18 23:12:26

我通过将您的方法包装到 带有 main 方法的类中来测试您的方法,这样,它就可以在普通的 Java 6 JRE(无 BouncyCastle)中工作,并带有 JSch-0.1.45(具有更多日志输出的修改版本)和“OpenSSH_5.8p1 Debian-1ubuntu3”sshd。

不过,我在代码中添加了一个 session.disconnect() 和一些睡眠。

我这里没有 Android 设备,想看看这是否会产生任何影响。

这是我的本地输出:(

authmethod was 2 with key filename of /home/paulo/.ssh/id_rsa
Log(jsch,1): Connecting to localhost port 22
Log(jsch,1): Connection established
Log(jsch,1): Remote version string: SSH-2.0-OpenSSH_5.8p1 Debian-1ubuntu3
Log(jsch,1): Local version string: SSH-2.0-JSCH-0.1.45
Log(jsch,1): CheckCiphers: aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,3des-ctr,arcfour,arcfour128,arcfour256
Log(jsch,1): aes256-ctr is not available.
Log(jsch,1): aes192-ctr is not available.
Log(jsch,1): aes256-cbc is not available.
Log(jsch,1): aes192-cbc is not available.
Log(jsch,1): arcfour256 is not available.
Log(jsch,1): CheckKexes: diffie-hellman-group14-sha1
Log(jsch,1): diffie-hellman-group14-sha1 is not available.
Log(jsch,1): SSH_MSG_KEXINIT sent
Log(jsch,1): SSH_MSG_KEXINIT received
Log(jsch,1): kex: server->client aes128-ctr hmac-md5 none
Log(jsch,1): kex: client->server aes128-ctr hmac-md5 none
Log(jsch,1): SSH_MSG_KEXDH_INIT sent
Log(jsch,1): expecting SSH_MSG_KEXDH_REPLY
Log(jsch,1): ssh_rsa_verify: signature true
Log(jsch,2): Permanently added 'localhost' (RSA) to the list of known hosts.
Log(jsch,1): SSH_MSG_NEWKEYS sent
Log(jsch,1): SSH_MSG_NEWKEYS received
Log(jsch,1): SSH_MSG_SERVICE_REQUEST sent
Log(jsch,1): SSH_MSG_SERVICE_ACCEPT received
Log(jsch,1): Authentications that can continue: publickey,keyboard-interactive,password
Log(jsch,1): Next authentication method: publickey
Log(jsch,1): Authentication succeeded (publickey).
Log(jsch,0): packet received, type: 91
Log(jsch,1): SSH_MSG_CHANNEL_OPEN_CONFIRMATION received, channel: 0
Log(jsch,0): packet received, type: 94
Log(jsch,1): SSH_MSG_CHANNEL_DATA received, channel: 0, len: 13
Log(jsch,0): packet received, type: 96
Log(jsch,1): SSH_MSG_CHANNEL_EOF received, channel: 0
Log(jsch,0): packet received, type: 98
Log(jsch,1): SSH_MSG_CHANNEL_REQUEST received, channel: 0, type: [B@1ad086a, want reply: false
Log(jsch,0): packet received, type: 97
Log(jsch,1): SSH_MSG_CHANNEL_CLOSE received, channel: 0
Log(jsch,1): Disconnecting from localhost port 22
Log(jsch,1): Caught an exception, leaving main loop due to Socket closed
Output: »Hallo, Welt!
«

我使用参数 paulo -key /home/paulo/.ssh/id_rsa localhost 22 hello 调用该程序,因此它在目标计算机上执行默认的 Hello World 程序,并且德语,因为这是我配置的区域设置。)

I tested your method by wrapping it into a class with main method, and with this, it works in a normal Java 6 JRE (no BouncyCastle), with JSch-0.1.45 (a modified version with more logging output) and "OpenSSH_5.8p1 Debian-1ubuntu3" sshd.

I added a session.disconnect() and some sleeps to the code, though.

I have no Android here to see if this would make any difference.

Here is my local output:

authmethod was 2 with key filename of /home/paulo/.ssh/id_rsa
Log(jsch,1): Connecting to localhost port 22
Log(jsch,1): Connection established
Log(jsch,1): Remote version string: SSH-2.0-OpenSSH_5.8p1 Debian-1ubuntu3
Log(jsch,1): Local version string: SSH-2.0-JSCH-0.1.45
Log(jsch,1): CheckCiphers: aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,3des-ctr,arcfour,arcfour128,arcfour256
Log(jsch,1): aes256-ctr is not available.
Log(jsch,1): aes192-ctr is not available.
Log(jsch,1): aes256-cbc is not available.
Log(jsch,1): aes192-cbc is not available.
Log(jsch,1): arcfour256 is not available.
Log(jsch,1): CheckKexes: diffie-hellman-group14-sha1
Log(jsch,1): diffie-hellman-group14-sha1 is not available.
Log(jsch,1): SSH_MSG_KEXINIT sent
Log(jsch,1): SSH_MSG_KEXINIT received
Log(jsch,1): kex: server->client aes128-ctr hmac-md5 none
Log(jsch,1): kex: client->server aes128-ctr hmac-md5 none
Log(jsch,1): SSH_MSG_KEXDH_INIT sent
Log(jsch,1): expecting SSH_MSG_KEXDH_REPLY
Log(jsch,1): ssh_rsa_verify: signature true
Log(jsch,2): Permanently added 'localhost' (RSA) to the list of known hosts.
Log(jsch,1): SSH_MSG_NEWKEYS sent
Log(jsch,1): SSH_MSG_NEWKEYS received
Log(jsch,1): SSH_MSG_SERVICE_REQUEST sent
Log(jsch,1): SSH_MSG_SERVICE_ACCEPT received
Log(jsch,1): Authentications that can continue: publickey,keyboard-interactive,password
Log(jsch,1): Next authentication method: publickey
Log(jsch,1): Authentication succeeded (publickey).
Log(jsch,0): packet received, type: 91
Log(jsch,1): SSH_MSG_CHANNEL_OPEN_CONFIRMATION received, channel: 0
Log(jsch,0): packet received, type: 94
Log(jsch,1): SSH_MSG_CHANNEL_DATA received, channel: 0, len: 13
Log(jsch,0): packet received, type: 96
Log(jsch,1): SSH_MSG_CHANNEL_EOF received, channel: 0
Log(jsch,0): packet received, type: 98
Log(jsch,1): SSH_MSG_CHANNEL_REQUEST received, channel: 0, type: [B@1ad086a, want reply: false
Log(jsch,0): packet received, type: 97
Log(jsch,1): SSH_MSG_CHANNEL_CLOSE received, channel: 0
Log(jsch,1): Disconnecting from localhost port 22
Log(jsch,1): Caught an exception, leaving main loop due to Socket closed
Output: »Hallo, Welt!
«

(I called the program with arguments paulo -key /home/paulo/.ssh/id_rsa localhost 22 hello, so it executes the default Hello World program on the target machine, and in German, because this is my configured locale.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文