签名长度不正确:得到127但是期待128

时间:2016-10-31 08:57:46

标签: java security jsch

我在Java 1.8升级后面临一个奇怪的问题。我在我们的一个实用程序中使用jsch-0.1.54.jar从各个地方下载文件。这个特殊的实用程序使用了将近4 - 5年没有任何问题(当时jsch-0.1.48)。那时环境是java 1.6。最近我们升级到java 1.8,结果我们升级了这个特定的实用程序。现在我们遇到了一个奇怪的问题,它偶尔会出现,大多数情况下文件的下载都是完美的。

错误日志

INFO: SSH_MSG_KEXDH_INIT sent
INFO: expecting SSH_MSG_KEXDH_REPLY
INFO: Disconnecting from SRV2000 port 22
2016-10-28 08:42:18:0576 ERROR  [main] net.AerisAbstractMethod - Failed to open connection 
com.jcraft.jsch.JSchException: Session.connect: java.security.SignatureException: Signature length not correct: got 127 but was expecting 128
    at com.jcraft.jsch.Session.connect(Session.java:565)
    at com.jcraft.jsch.Session.connect(Session.java:183)
    at com.aeris.net.AerisSFTPMethod.connectToServer(AerisSFTPMethod.java:65)
    at com.aeris.net.AerisAbstractMethod.getListOfFiles(AerisAbstractMethod.java:143)
    at com.aeris.worker.AerisUploaderDownloader.performUploadDownloadListing(AerisUploaderDownloader.java:112)
    at com.aeris.main.AerisCommonSftpUtility.main(AerisCommonSftpUtility.java:102)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.simontuffs.onejar.Boot.run(Boot.java:340)
    at com.simontuffs.onejar.Boot.main(Boot.java:166)

成功记录:(在大多数情况下,它是成功的)

INFO: SSH_MSG_KEXDH_INIT sent
INFO: expecting SSH_MSG_KEXDH_REPLY
INFO: ssh_rsa_verify: signature true
WARN: Permanently added 'SRV2000' (RSA) to the list of known hosts.
INFO: SSH_MSG_NEWKEYS sent
INFO: SSH_MSG_NEWKEYS received
INFO: SSH_MSG_SERVICE_REQUEST sent
INFO: SSH_MSG_SERVICE_ACCEPT received
INFO: Authentications that can continue: publickey,password,keyboard-interactive
INFO: Next authentication method: publickey
INFO: Authentication succeeded (publickey).
2016-10-28 08:36:48:0794 INFO   [main] net.AerisAbstractMethod - Session connected to server
2016-10-28 08:36:48:0794 INFO   [main] net.AerisAbstractMethod - Opening SFTP channel..
2016-10-28 08:36:48:0810 INFO   [main] net.AerisAbstractMethod - Connecting to server through channel.
2016-10-28 08:36:48:0857 INFO   [main] net.AerisAbstractMethod - Connection successful.
2016-10-28 08:36:48:0857 INFO   [main] net.AerisAbstractMethod - Changing to directory:C:/interfaces/ib/wf/work
2016-10-28 08:36:48:0888 INFO   [main] net.AerisAbstractMethod - Start file Listing of the remote directory:C:/interfaces/ib/wf/work

       0 Oct 28, 2016 04:15 ./
       0 Oct 28, 2016 04:15 ../

我使用Vandyke(sftp软件提供商)进行了完整的分析,但没有发现任何错误。我也尝试使用不同的工具sftp,但我没有收到任何错误。以下是连接SFTP服务器的代码段。任何人都可以帮忙解决这个问题吗?

protected void connectToServer() throws AerisConnectionException {
        JSch jSch =(JSch)this.client;
        try {

            session = jSch.getSession(config.getUsername(), config.getRemoteserver(), config.getPort());
            LOGGER.info("Creating SSH Session using Username:"+config.getUsername()+ " Server :" +config.getRemoteserver()+ " at PORT:"+config.getPort());
            if(config.getAuth().equalsIgnoreCase("PASSWD")||config.getAuth().equalsIgnoreCase("KEYPASS")){
                LOGGER.info("Setting password ...");
                session.setPassword(config.getPassword());
            }

            Properties jShconfig = new Properties();            
            jShconfig.put("StrictHostKeyChecking", "no");
            jShconfig.put("PreferredAuthentications", 
                      "publickey,password,keyboard-interactive");
            jShconfig.put("LogLevel", "VERBOSE");


            LOGGER.info("Setting timeout to "+config.getTimeOut());
            session.setTimeout(config.getTimeOut()*1000);
            session.setConfig(jShconfig);           

            session.connect();
            LOGGER.info("Session connected to server");
            this.connected=true;

        } catch (JSchException e) {
            LOGGER.error("Failed to open connection ",e);
            throw new AerisConnectionException("Failed to open connection.");
        }

    }

1 个答案:

答案 0 :(得分:5)

虽然让堆栈跟踪确认会很好,但我打赌服务器正在使用RSA'主机'验证的关键是错误地修剪'在极少数情况下领先零。

由PKCS#1定义的RSA签名值(以及加密值),其SSH uses(包括SSL在内的许多其他内容)也需要编码为固定长度的八位字符串' K'等于编码模数所需的长度,或非正式地与模数相同的尺寸。但是,由于基础数学值是一个很大的非负(也就是无符号)整数,特别是modexp(s,d,n),历史上一些实现省略了前导零八位字节 - 在将值视为时有效的省略整数 - 导致编码值有时短于应有的值。

RSA签名(或加密)值实际上是(1,n)中的均匀随机数。因此,当服务器使用的RSA密钥具有“循环二进制”时,像这里的1024这样的大小,这个修剪将发生随机约200次中的1次,或者如果被修剪为有符号数就会发生400次。

我不知道,但在测试中我确认(Oracle) Java 6确实接受这样一个'短' Signature类型RSA或此处SHA1withRSA实际使用的值,两者都暗示PKCS1-v1_5方案,但 Java 7和8抛出例外你锯。 OTOH OpenSSH和PuTTY(也被WinSCP和FileZilla使用)确实接受了' short'值,同时始终发送正确的长度值;这种波斯特利亚行为可能使得更难以检测到同伴以这种方式行为不端。 (注意:我检查了OpenSSH 5.5和7.3,这是我手边最早和最新的,但只有当前的PuTTY 0.67,因为我保持在线状态。)

您可以尝试将服务器软件实现者指向已发布的标准,但它可能没有任何好处。你可以问jcraft特殊情况;对于mpint / ASN.1,他们已经在DSA和ECDSA案例中有逻辑,我可能认为这同样是丑陋的。 或者如果服务器有另一个(可用)密钥,请通过将"server_host_key"配置为不包括ssh-rsa来请求 - 最简单的方法是获取现有/默认列表,拆分,删除{ {1}}(并且不要清空)并重新加入,而不是通过列出今天的特定算法来混淆您的用户和/或(共)维护者。