quantumferret
quantumferret

Reputation: 503

Set allowed transport and MAC ciphers for SSHClient

I'm trying to modify an SSH client using SSHJ so that it only allows certain ciphers. I have properties in a properties file something like this:

sftp.transport.ciphers = aes256-gcm,aes256-ctr,aes256-etcera
sftp.mac.ciphers = hmac-sha3-512,...

Using Jsch limiting ciphers used would be like so:

session.setConfig("cipher.s2c", sftpTransportCiphers);
session.setConfig("cipher.c2s", sftpTransportCiphers);

I've been combing through the docs for SSHJ and at this point I've run around in circles a bit and probably missed something, so best to just ask. I'm not seeing a clean way to take a comma-delimited string and turn it into a list of ciphers as SSHJ would recognize it.

A simple example with SSHJ's SSHClient configured similarly to the JSCH version above would be greatly appreciated.

Upvotes: 0

Views: 1108

Answers (1)

quantumferret
quantumferret

Reputation: 503

For future reference/anyone else who wants a quick solution, here's a derived class from DefaultConfig, as suggested by @Robert.

    import net.schmizz.sshj.DefaultConfig;
    import net.schmizz.sshj.common.Factory;
    import net.schmizz.sshj.common.LoggerFactory;
    import net.schmizz.sshj.transport.cipher.*;
    import net.schmizz.sshj.transport.mac.MAC;
    import org.slf4j.Logger;

    import java.util.Arrays;
    import java.util.List;
    import java.util.Properties;
    import java.util.stream.Collectors;

    public class MyConfig extends DefaultConfig {
        private Logger logger;

        public MyConfig() {
            super();
            setLoggerFactory(LoggerFactory.DEFAULT);
        }

        @Override
        void setLoggerFactory(LoggerFactory loggerFactory) {
            super.setLoggerFactory(loggerFactory);
            logger = loggerFactory.getLogger(getClass());
        }

        public void setTransportCiphers(String input) {
            String[] ciphers = input.trim().split(",");
            List<String> factoryNames = Factory.Named.Util.getNames(getCipherFactories());

            List<Factory.Named<Cipher>> transportCiphers = Arrays.stream(ciphers)
                .filter(factoryNames::contains)
                .map(cipher -> Factory.Named.Util.get(getCipherFactories(), cipher))
                .collect(Collectors.toList());

            logger.info("Client-side cipher factories set to: {}", transportCiphers);

            setCipherFactories(transportCiphers);
        }

        public void setMacCiphers(String input) {
            String[] ciphers = input.trim().split(",");
            List<String> factoryNames = Factory.Named.Util.getNames(getMACFactories());

            List<Factory.Named<MAC>> macCiphers = Arrays.stream(ciphers)
                .filter(factoryNames::contains)
                .map(mac -> Factory.Named.Util.get(getMACFactories(), mac))
                .collect(Collectors.toList());

            logger.info(Client-side MAC factories set to: {}", Factory.Named.Util.getNames(macCiphers));

            setMACFactories(macCiphers);
        }
    }

Upvotes: 2

Related Questions