微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

SSH 使用 JSch 和 PEM 私钥,而路由器使用 openssl 密钥

如何解决SSH 使用 JSch 和 PEM 私钥,而路由器使用 openssl 密钥

我想在 Kotlin 中使用 JSch 通过 SSH 连接到我的 OpenWRT 路由器,并使用 SSL 密钥。 OpenWRT 支持使用 ssh-keygen (https://openwrt.org/docs/guide-user/security/dropbear.public-key.auth) 生成的密钥。

ssh-keygen -t rsa -b 4096

这会生成一个公共 id_rsa.pub 和私有 id_rsa 密钥。 OpenWRT 接受这个 id_rsa.pub。 我想让 JSch 使用私钥:

private fun sshCommand(
            username: String? = "root",host: String? = "192.168.1.1",port: Int = 22,command: String?
    ) {
        GlobalScope.launch(dispatchers.IO) {
            var session: Session? = null
            var channel: ChannelExec? = null

            val privateKey: String = "-----BEGIN OPENSSH PRIVATE KEY-----\n" +
                    "...\n" +
                    "...\n" +
                    "-----END OPENSSH PRIVATE KEY-----"

            try {
                JSch().addIdentity("name",privateKey.toByteArray(),null,null)
                session = JSch().getSession(username,host,port)
                session.setConfig("PreferredAuthentications","publickey");
                session.setConfig("StrictHostKeyChecking","no")
                session.connect()
                channel = session.openChannel("exec") as ChannelExec
                channel.setCommand(command)
                val responseStream = ByteArrayOutputStream()
                channel.outputStream = responseStream
                channel.connect()
                while (channel.isConnected) {
                    Thread.sleep(100)
                }
                val responseString = String(responseStream.toByteArray())
                println(responseString)
            } finally {
                session?.disconnect()
                channel?.disconnect()
            }
        }
    }

然而,这会产生一个错误

com.jcraft.jsch.JSchException: invalid privatekey: [B@6166596

JSch 不支持这种密钥格式,它需要是 PEM。 所以我转换了私钥:

-----BEGIN RSA PRIVATE KEY-----
.
.
.
-----END RSA PRIVATE KEY-----

但现在错误是:

com.jcraft.jsch.JSchException: Auth fail

问题是OpenWRT上的公钥和JSch上的私钥格式不同吗?

编辑 2021 年 2 月 13 日: 我添加了这一行:

session.setConfig("PreferredAuthentications","publickey");

我还使用 this code 向 JSch 添加一个记录器,这是输出

W/System.err: INFO: Connecting to 192.168.1.1 port 22
W/System.err: INFO: Connection established
W/System.err: INFO: Remote version string: SSH-2.0-dropbear
W/System.err: INFO: Local version string: SSH-2.0-JSCH-0.1.54
    INFO: CheckCiphers: aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,3des-ctr,arcfour,arcfour128,arcfour256
D/EGL_emulation: eglMakeCurrent: 0xf0a7ee60: ver 3 0 (tinfo 0xf0aca800)
D/EGL_emulation: eglMakeCurrent: 0xf0a7ee60: ver 3 0 (tinfo 0xf0aca800)
W/System.err: INFO: CheckKexes: diffie-hellman-group14-sha1,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521
W/System.err: INFO: CheckSignatures: ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521
W/System.err: INFO: SSH_MSG_KEXINIT sent
W/System.err: INFO: SSH_MSG_KEXINIT received
W/System.err: INFO: kex: server: curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group14-sha256,diffie-hellman-group14-sha1,kexguess2@matt.ucc.asn.au
W/System.err: INFO: kex: server: ssh-rsa
W/System.err: INFO: kex: server: aes128-ctr,aes256-ctr
W/System.err: INFO: kex: server: aes128-ctr,aes256-ctr
W/System.err: INFO: kex: server: hmac-sha1,hmac-sha2-256
W/System.err: INFO: kex: server: hmac-sha1,hmac-sha2-256
    INFO: kex: server: none
W/System.err: INFO: kex: server: none
W/System.err: INFO: kex: server: 
    INFO: kex: server: 
W/System.err: INFO: kex: client: ecdh-sha2-nistp256,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1
W/System.err: INFO: kex: client: ssh-rsa,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp521
W/System.err: INFO: kex: client: aes128-ctr,3des-cbc,blowfish-cbc,aes256-ctr,aes256-cbc
W/System.err: INFO: kex: client: aes128-ctr,aes256-cbc
W/System.err: INFO: kex: client: hmac-md5,hmac-sha1,hmac-sha2-256,hmac-sha1-96,hmac-md5-96
W/System.err: INFO: kex: client: hmac-md5,hmac-md5-96
W/System.err: INFO: kex: client: none
W/System.err: INFO: kex: client: none
    INFO: kex: client: 
W/System.err: INFO: kex: client: 
W/System.err: INFO: kex: server->client aes128-ctr hmac-sha1 none
W/System.err: INFO: kex: client->server aes128-ctr hmac-sha1 none
W/System.err: INFO: SSH_MSG_KEXDH_INIT sent
W/System.err: INFO: expecting SSH_MSG_KEXDH_REPLY
W/System.err: INFO: ssh_rsa_verify: signature true
W/System.err: WARN: Permanently added '192.168.1.1' (RSA) to the list of kNown hosts.
W/System.err: INFO: SSH_MSG_NEWKEYS sent
W/System.err: INFO: SSH_MSG_NEWKEYS received
W/System.err: INFO: SSH_MSG_SERVICE_REQUEST sent
W/System.err: INFO: SSH_MSG_SERVICE_ACCEPT received
W/System.err: INFO: Authentications that can continue: publickey
    INFO: Next authentication method: publickey
W/System.err: INFO: disconnecting from 192.168.1.1 port 22
E/AndroidRuntime: FATAL EXCEPTION: Defaultdispatcher-worker-1
    Process: com.example.ps4nuker,PID: 30981
    com.jcraft.jsch.JSchException: Auth fail
        at com.jcraft.jsch.Session.connect(Session.java:519)
        at com.jcraft.jsch.Session.connect(Session.java:183)
        at com.example.ps4nuker.MainActivity$sshCommand$1.invokeSuspend(MainActivity.kt:113)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.dispatchedTask.run(dispatchedTask.kt:106)
        at kotlinx.coroutines.scheduling.Coroutinescheduler.runSafely(Coroutinescheduler.kt:571)
        at kotlinx.coroutines.scheduling.Coroutinescheduler$Worker.executeTask(Coroutinescheduler.kt:750)
        at kotlinx.coroutines.scheduling.Coroutinescheduler$Worker.runWorker(Coroutinescheduler.kt:678)
        at kotlinx.coroutines.scheduling.Coroutinescheduler$Worker.run(Coroutinescheduler.kt:665)
I/Process: Sending signal. PID: 30981 SIG: 9
disconnected from the target VM,address: 'localhost:56256',transport: 'socket'

这是 OpenWRT 路由器上的日志(最大日志级别):

Sat Feb 13 15:47:51 2021 authpriv.info dropbear[7783]: Child connection from 192.168.1.23:56269
Sat Feb 13 15:47:52 2021 authpriv.info dropbear[7783]: Exit before auth (user 'root',0 fails): disconnect received

使用相同私钥通过 Mobaxterm 连接到 SSH 时的相同 OpenWRT 日志:

Thu Feb 18 00:24:51 2021 authpriv.info dropbear[17648]: Child connection from 192.168.1.23:50127
Thu Feb 18 00:24:52 2021 authpriv.notice dropbear[17648]: Pubkey auth succeeded for 'root' with key sha1!! 85:eb:c4:d2:dd:d9:15:d3:ee:29:3a:80:df:48:8f:6c:41:73:a8:5e from 192.168.1.23:50127

解决方法

您有两个 Jsch 实例,因此会话不会获得您添加到另一个实例的身份。改为

val jSch = JSch()
jSch.addIdentity("blabla123",privateKey.toByteArray(),null,null)
session = jSch.getSession(username,host,port)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。