JSCH addIdentity公钥参数没有什么区别

时间:2017-01-12 20:46:42

标签: java sftp jsch

public class FTP {
  public static void main(String args[]){
    JSch jsch = new JSch();
    jsch.setKnownHosts("./known_hosts"); 

    Path privateKeyPath = Paths.get("./id_dsa");
    byte[] privateKey = Files.readAllBytes(privateKeyPath);

    Path publicKeyPath = Paths.get("./id_dsa.pub");
    byte[] publicKey = Files.readAllBytes(publicKeyPath);

    // Either of the lines below work... Why?
    // jsch.addIdentity("", privateKey, publicKey, null);
    // or 
    jsch.addIdentity("", privateKey, null, null);

    Session session = jsch.getSession("USER", "myHost.com", 22);

    session.connect();

  }
}

publicKey设置为null,并没有什么不同,我可以连接任何一种方式。那是为什么?

看起来publicKey似乎没有被使用,所以为什么首先将它传递给addIdentity

2 个答案:

答案 0 :(得分:5)

这是(某些)加密私钥的优化。您没有发现任何差异,因为您使用了未加密的私钥。

如果你给jsch一个OpenSSL格式的加密私钥,并且没有预先提供密码来解密它,但确实提供了公钥(永远不会加密),那个密钥对成为下一个选择身份验证,jsch使用publickey探测服务器,以确定服务器是否可能使用此密钥接受auth。如果是这样,jsch必须提示密码短语解密私钥以实际执行身份验证;如果没有,它会跳过提示并转到下一个可能性,如果有的话。请参阅com.jcraft.jsch.UserAuthPublicKey.java的来源。

OpenSSH客户端ssh几乎完全相同。如果您(作为选项,在配置中或默认情况下)提供OpenSSL格式加密的私钥,并且它找到匹配的公钥,它首先进行探测,并仅在密钥可用时提示密码才能解密。 ssh不允许提前指定密码短语Jsch.addIdentity,但它可以使用ssh-agent进程(或替代)来完成相同的操作。

自6.5以来,OpenSSH还支持使用ssh-keygen -o创建的“新格式”密钥文件,这些密钥文件可以在一个文件中加密私钥和未加密的公钥,避免单独处理公钥。 Jsch不(但是?)支持这种格式,但它确实支持PuTTY的PPK格式,它执行相同的操作,因此您将单个文件作为私钥提供,而不是公钥。

答案 1 :(得分:0)

私钥包含构建公钥所需的信息。如果jsch需要公钥,它可以从私钥中获取。

例如,您可以使用ssh-keygen从私钥文件中提取公钥:

$ ssh-keygen -t dsa
Generating public/private dsa key pair.
Enter file in which to save the key (/Users/foo/.ssh/id_dsa): key
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
...
$ ls -l
total 16
-rw-------  1 foo  bar  668 Jan 12 16:28 key
-rw-r--r--  1 foo  bar  613 Jan 12 16:28 key.pub
$ cat key.pub
ssh-dss AAAAB3NzaC1kc3MAAACBANzp8qnI3e+iO/5KkK...
$ rm key.pub
$ ssh-keygen -y -f key
ssh-dss AAAAB3NzaC1kc3MAAACBANzp8qnI3e+iO/5KkK...