Search code examples
javaspring-integrationsftp

Spring Integration SFTP connection fails - Unable to negotiate key exchange for kex algorithms


I am using Spring Integration (Version: 6.1.2) to connect to an SFTP server. While creating an SFTPSession, I get this exception -

java.lang.IllegalStateException: failed to create SFTP Session
....
Caused by: org.apache.sshd.common.SshException: Unable to negotiate key exchange for kex algorithms (

client: 
curve25519-sha256,
[email protected],
curve448-sha512,
ecdh-sha2-nistp521,
ecdh-sha2-nistp384,
ecdh-sha2-nistp256,
diffie-hellman-group-exchange-sha256,
diffie-hellman-group18-sha512,
diffie-hellman-group17-sha512,
diffie-hellman-group16-sha512,
diffie-hellman-group15-sha512,
diffie-hellman-group14-sha256,
ext-info-c

server: 
diffie-hellman-group1-sha1,
diffie-hellman-group14-sha1)

Obviously, the server only supports the old algorithms. How do I add support for these algorithms on my SFTP session?

Here is my code -

DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory();
factory.setHost("ftp.sssss.com");
factory.setPort(Integer.valueOf(22));
factory.setAllowUnknownKeys(true);
factory.setUser("user");
factory.setPassword("password");

SftpSession sftpSession = factory.getSession();

Solution

  • Apparently those algorithms have been deprecated: https://issues.apache.org/jira/browse/SSHD-1004.

    This SO thread explains how to enable those old keys: Mina SSHD enable KEX with SHA1 in version 2.6.0.

    The DefaultSftpSessionFactory supports an external SshClient:

    /**
     * Instantiate based on the provided {@link SshClient}, e.g. some extension for HTTP/SOCKS.
     * @param sshClient the {@link SshClient} instance.
     * @param isSharedSession true if the session is to be shared.
     */
    public DefaultSftpSessionFactory(SshClient sshClient, boolean isSharedSession) {
    

    So, you need to do like this:

    SshClient client = SshClient.setUpDefaultClient();
    client.setKeyExchangeFactories(NamedFactory.setUpTransformedFactories(
            false,
            BuiltinDHFactories.VALUES,
            ClientBuilder.DH2KEX
        ));
    client.setSignatureFactories(new ArrayList<>(BuiltinSignatures.VALUES))
    

    and inject that client into DefaultSftpSessionFactory.