0

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.

quantumferret
  • 473
  • 6
  • 12
  • 1
    Have you checked the class `net.schmizz.sshj.DefaultConfig`? It defines a list of algorithm factories e.g. for key-exchange. You may have to derive your own config class from this DefaultConfig. – Robert Oct 08 '21 at 16:28
  • @Robert Argh that option totally slipped my mind. At the moment I've put together a somewhat hacky solution using DefaultConfig, yes. I guess I probably will need to derive my own from it and add some logic to more gracefully turn the property strings into a list of allowed ciphers. Right now my solution is a bit of a bloated stream=>split=>filter=>map=>collect stream statement. – quantumferret Oct 08 '21 at 16:41

1 Answers1

2

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);
        }
    }
quantumferret
  • 473
  • 6
  • 12