### Configure Jsch Programmatically with Public Key Auth Source: https://github.com/mwiede/jsch/wiki/Jsch-Configuration A minimal example demonstrating programmatic configuration of Jsch, including setting known hosts from a string and adding an identity file for public key authentication. ```java final JSch jSch = new JSch(); jSch.setKnownHosts(new ByteArrayInputStream(myKnownHostsAsString.getBytes())); jSch.addIdentity("~/.ssh/id_rsa"); final Session newSession = jSch.getSession(myHost); newSession.connect(connectTimeout); ``` -------------------------------- ### Example OpenSSH Config for Public Key Authentication Source: https://github.com/mwiede/jsch/wiki/Jsch-Configuration An example `~/.ssh/config` file entry specifying connection details for a host, including hostname, user, and the identity file to use for public key authentication. Comments are included for clarity. ```ssh-config # some comment Host host2 HostName host2.somewhere.edu User foobar IdentityFile ~/.ssh/old_keys/host2_key ``` -------------------------------- ### Configure Jsch using OpenSSH Config for Legacy Servers Source: https://github.com/mwiede/jsch/wiki/Jsch-Configuration An example of an `~/.ssh/config` file entry that enables a legacy key exchange algorithm (`diffie-hellman-group1-sha1`) for a specific host. This is useful when connecting to legacy SSH servers. ```ssh-config Host somehost.example.org KexAlgorithms +diffie-hellman-group1-sha1 ``` -------------------------------- ### Perform SFTP Operations in Java Source: https://context7.com/mwiede/jsch/llms.txt Demonstrates file uploads with progress monitoring, downloads, directory navigation, and attribute management using ChannelSftp. ```java import com.jcraft.jsch.*; import java.util.Vector; public class SftpExample { public static void main(String[] args) { Session session = null; ChannelSftp sftp = null; try { JSch jsch = new JSch(); jsch.addIdentity("~/.ssh/id_rsa"); session = jsch.getSession("user", "server.example.com", 22); session.setConfig("StrictHostKeyChecking", "no"); session.connect(); // Open SFTP channel sftp = (ChannelSftp) session.openChannel("sftp"); sftp.connect(); // Upload file with progress monitor SftpProgressMonitor monitor = new SftpProgressMonitor() { long total = 0; public void init(int op, String src, String dest, long max) { System.out.println("Starting: " + src + " -> " + dest + " (" + max + " bytes)"); } public boolean count(long count) { total += count; System.out.println("Transferred: " + total + " bytes"); return true; // return false to cancel } public void end() { System.out.println("Transfer complete!"); } }; sftp.put("/local/path/file.txt", "/remote/path/file.txt", monitor, ChannelSftp.OVERWRITE); // Download file sftp.get("/remote/path/data.csv", "/local/path/data.csv"); // List directory contents Vector files = sftp.ls("/remote/path"); for (ChannelSftp.LsEntry entry : files) { System.out.println(entry.getLongname()); } // Directory operations sftp.mkdir("/remote/newdir"); sftp.cd("/remote/newdir"); System.out.println("Current directory: " + sftp.pwd()); // File operations sftp.chmod(0644, "/remote/path/file.txt"); sftp.rename("/remote/old.txt", "/remote/new.txt"); // Get file attributes SftpATTRS attrs = sftp.stat("/remote/path/file.txt"); System.out.println("Size: " + attrs.getSize()); System.out.println("Permissions: " + attrs.getPermissionsString()); // Remove file and directory sftp.rm("/remote/path/temp.txt"); sftp.rmdir("/remote/emptydir"); } catch (SftpException e) { System.err.println("SFTP error: " + e.getMessage()); } catch (Exception e) { e.printStackTrace(); } finally { if (sftp != null) sftp.disconnect(); if (session != null) session.disconnect(); } } } ``` -------------------------------- ### Connect via SSH Jump Host Source: https://context7.com/mwiede/jsch/llms.txt Establishes a connection to a target server by creating a local port forwarding tunnel through an intermediate bastion host. ```java import com.jcraft.jsch.*; public class JumpHostExample { public static void main(String[] args) { Session jumpSession = null; Session targetSession = null; ChannelSftp sftp = null; try { JSch jsch = new JSch(); jsch.addIdentity("~/.ssh/id_rsa"); jsch.setKnownHosts("~/.ssh/known_hosts"); // Connect to jump host (bastion) jumpSession = jsch.getSession("jumpuser", "bastion.example.com", 22); jumpSession.connect(); System.out.println("Connected to jump host"); // Create tunnel through jump host to target server int forwardedPort = jumpSession.setPortForwardingL(0, "internal.server.com", 22); System.out.println("Tunnel created on port " + forwardedPort); // Connect to target through the tunnel targetSession = jsch.getSession("targetuser", "127.0.0.1", forwardedPort); targetSession.setHostKeyAlias("internal.server.com"); // Use actual hostname for known_hosts targetSession.connect(); System.out.println("Connected to target server through jump host"); // Now perform operations on target server sftp = (ChannelSftp) targetSession.openChannel("sftp"); sftp.connect(); sftp.ls(".").forEach(entry -> { ChannelSftp.LsEntry e = (ChannelSftp.LsEntry) entry; System.out.println(e.getLongname()); }); } catch (Exception e) { e.printStackTrace(); } finally { if (sftp != null) sftp.disconnect(); if (targetSession != null) targetSession.disconnect(); if (jumpSession != null) jumpSession.disconnect(); } } } ``` -------------------------------- ### Configure Jsch using Java System Properties for Legacy Servers Source: https://github.com/mwiede/jsch/wiki/Jsch-Configuration Demonstrates launching a Java application with system properties to override Jsch's default connection configuration, specifically for the 'kex' (key exchange) algorithm. This is useful when direct Jsch code access is not possible. ```bash java -jar my_spring_boot_app.jar -Djsch.kex=ssh-ed25519,diffie-hellman-group14-sha1 ``` -------------------------------- ### Implement Host Key Verification in Java Source: https://context7.com/mwiede/jsch/llms.txt Uses the JSch library to load known_hosts and implement a UserInfo interface for interactive host key acceptance. ```java import com.jcraft.jsch.*; public class HostKeyVerificationExample { public static void main(String[] args) { try { JSch jsch = new JSch(); // Load known_hosts file jsch.setKnownHosts("~/.ssh/known_hosts"); // Get host key repository HostKeyRepository hkr = jsch.getHostKeyRepository(); HostKey[] hostKeys = hkr.getHostKey(); if (hostKeys != null) { System.out.println("Known hosts from: " + hkr.getKnownHostsRepositoryID()); for (HostKey hk : hostKeys) { System.out.println(hk.getHost() + " " + hk.getType() + " " + hk.getFingerPrint(jsch)); } } Session session = jsch.getSession("user", "server.example.com", 22); // Implement UserInfo for interactive host key acceptance session.setUserInfo(new UserInfo() { public String getPassphrase() { return null; } public String getPassword() { return "password"; } public boolean promptPassword(String message) { return true; } public boolean promptPassphrase(String message) { return false; } public boolean promptYesNo(String message) { // Handle unknown host key System.out.println(message); // In production, prompt user or verify against known fingerprint return true; // Accept the host key } public void showMessage(String message) { System.out.println(message); } }); // Hash host entries when adding to known_hosts session.setConfig("HashKnownHosts", "yes"); session.connect(); // Get connected host's key HostKey connectedKey = session.getHostKey(); System.out.println("Connected to: " + connectedKey.getHost()); System.out.println("Key type: " + connectedKey.getType()); System.out.println("Fingerprint: " + connectedKey.getFingerPrint(jsch)); session.disconnect(); } catch (Exception e) { e.printStackTrace(); } } } ``` -------------------------------- ### Establish SSH Session with Password Authentication Source: https://context7.com/mwiede/jsch/llms.txt Connect to an SSH server using a username, hostname, and password. Disabling StrictHostKeyChecking is shown for simplicity but is not recommended for production environments. ```java import com.jcraft.jsch.JSch; import com.jcraft.jsch.Session; import com.jcraft.jsch.JSchException; public class PasswordAuthExample { public static void main(String[] args) { try { JSch jsch = new JSch(); // Create session with username, host, and port Session session = jsch.getSession("username", "example.com", 22); // Set password directly session.setPassword("mypassword"); // Skip host key checking (not recommended for production) session.setConfig("StrictHostKeyChecking", "no"); // Connect with 30 second timeout session.connect(30000); System.out.println("Connected successfully!"); System.out.println("Server version: " + session.getServerVersion()); // Perform operations... // Always disconnect when done session.disconnect(); } catch (JSchException e) { System.err.println("Connection failed: " + e.getMessage()); } } } ``` -------------------------------- ### Authenticate with Public Key Source: https://context7.com/mwiede/jsch/llms.txt Load private keys using addIdentity to authenticate sessions. Supports various key formats and optional passphrase protection. ```java import com.jcraft.jsch.JSch; import com.jcraft.jsch.Session; public class PublicKeyAuthExample { public static void main(String[] args) { try { JSch jsch = new JSch(); // Load private key (with optional passphrase) jsch.addIdentity("~/.ssh/id_rsa", "passphrase"); // Or load key without passphrase jsch.addIdentity("~/.ssh/id_ed25519"); // Load known_hosts file for host key verification jsch.setKnownHosts("~/.ssh/known_hosts"); Session session = jsch.getSession("user", "server.example.com", 22); session.connect(30000); System.out.println("Authenticated with public key!"); session.disconnect(); } catch (Exception e) { e.printStackTrace(); } } } ``` -------------------------------- ### Implement Logging and Debugging in JSch Source: https://context7.com/mwiede/jsch/llms.txt Shows how to set global, instance-level, or session-level loggers using built-in implementations or custom classes. ```java import com.jcraft.jsch.*; public class LoggingExample { public static void main(String[] args) { try { // Option 1: Use built-in SLF4J logger JSch.setLogger(new Slf4jLogger()); // Option 2: Use built-in java.util.logging logger // JSch.setLogger(new JulLogger()); // Option 3: Use built-in Log4j2 logger // JSch.setLogger(new Log4j2Logger()); // Option 4: Custom logger implementation JSch.setLogger(new Logger() { public boolean isEnabled(int level) { return level >= Logger.INFO; } public void log(int level, String message) { String prefix = switch (level) { case Logger.DEBUG -> "DEBUG"; case Logger.INFO -> "INFO"; case Logger.WARN -> "WARN"; case Logger.ERROR -> "ERROR"; case Logger.FATAL -> "FATAL"; default -> "UNKNOWN"; }; System.out.println("[" + prefix + "] " + message); } }); JSch jsch = new JSch(); // Per-instance logger jsch.setInstanceLogger(new Logger() { public boolean isEnabled(int level) { return true; } public void log(int level, String message) { System.out.println("[Instance] " + message); } }); Session session = jsch.getSession("user", "server.example.com", 22); // Per-session logger session.setLogger(new Logger() { public boolean isEnabled(int level) { return true; } public void log(int level, String message) { System.out.println("[Session] " + message); } }); session.setConfig("StrictHostKeyChecking", "no"); session.setPassword("password"); session.connect(); // Logs will show KEX, cipher negotiation, etc. session.disconnect(); } catch (Exception e) { e.printStackTrace(); } } } ``` -------------------------------- ### Configure Cryptographic Algorithms in JSch Source: https://context7.com/mwiede/jsch/llms.txt Demonstrates global and per-session configuration of SSH algorithms, including legacy support and DH group exchange parameters. ```java import com.jcraft.jsch.*; public class AlgorithmConfigExample { public static void main(String[] args) { try { JSch jsch = new JSch(); // Global configuration (affects all sessions) // Add legacy key exchange algorithm JSch.setConfig("kex", JSch.getConfig("kex") + ",diffie-hellman-group14-sha1"); // Enable RSA/SHA1 for legacy servers (disabled by default) JSch.setConfig("server_host_key", JSch.getConfig("server_host_key") + ",ssh-rsa"); JSch.setConfig("PubkeyAcceptedAlgorithms", JSch.getConfig("PubkeyAcceptedAlgorithms") + ",ssh-rsa"); Session session = jsch.getSession("user", "legacy-server.example.com", 22); // Per-session configuration session.setConfig("cipher.s2c", "aes256-ctr,aes192-ctr,aes128-ctr"); session.setConfig("cipher.c2s", "aes256-ctr,aes192-ctr,aes128-ctr"); session.setConfig("mac.s2c", "hmac-sha2-256,hmac-sha2-512"); session.setConfig("mac.c2s", "hmac-sha2-256,hmac-sha2-512"); // Enable compression session.setConfig("compression.s2c", "zlib@openssh.com,zlib,none"); session.setConfig("compression.c2s", "zlib@openssh.com,zlib,none"); // Configure Diffie-Hellman group exchange parameters session.setConfig("dhgex_min", "2048"); session.setConfig("dhgex_max", "8192"); session.setConfig("dhgex_preferred", "4096"); session.setConfig("StrictHostKeyChecking", "no"); session.setPassword("password"); session.connect(); System.out.println("Connected with custom algorithms!"); session.disconnect(); } catch (Exception e) { e.printStackTrace(); } } } ``` ```bash # Alternative: Configure via system properties at JVM startup # java -Djsch.kex=curve25519-sha256,diffie-hellman-group14-sha256 \ # -Djsch.cipher=aes256-ctr,aes128-ctr \ # -Djsch.mac=hmac-sha2-256 \ # MyApp ``` -------------------------------- ### Configure JSch Compression Source: https://github.com/mwiede/jsch/blob/master/ChangeLog.md Use these commands to set the compression implementation globally or for a specific session. ```java JSch.setConfig("zlib@openssh.com", "com.jcraft.jsch.juz.Compression") + JSch.setConfig("zlib", "com.jcraft.jsch.juz.Compression") ``` ```java session.setConfig("zlib@openssh.com", "com.jcraft.jsch.juz.Compression") + session.setConfig("zlib", "com.jcraft.jsch.juz.Compression") ``` -------------------------------- ### Configure Local Port Forwarding in Java Source: https://context7.com/mwiede/jsch/llms.txt Establishes SSH tunnels to forward local ports to remote services, including dynamic port assignment and management of active forwardings. ```java import com.jcraft.jsch.*; public class LocalPortForwardingExample { public static void main(String[] args) { try { JSch jsch = new JSch(); jsch.addIdentity("~/.ssh/id_rsa"); Session session = jsch.getSession("user", "jumphost.example.com", 22); session.setConfig("StrictHostKeyChecking", "no"); session.connect(); // Forward local port 3306 to remote database server // Connections to localhost:3306 will tunnel to db.internal:3306 int assignedPort = session.setPortForwardingL(3306, "db.internal", 3306); System.out.println("Forwarding localhost:" + assignedPort + " -> db.internal:3306"); // Forward local port 8080 to remote web server session.setPortForwardingL(8080, "webserver.internal", 80); System.out.println("Forwarding localhost:8080 -> webserver.internal:80"); // Use 0 to let system assign available port int dynamicPort = session.setPortForwardingL(0, "redis.internal", 6379); System.out.println("Forwarding localhost:" + dynamicPort + " -> redis.internal:6379"); // List active port forwardings String[] forwardings = session.getPortForwardingL(); for (String fwd : forwardings) { System.out.println("Active forwarding: " + fwd); } // Keep connection alive for tunneling System.out.println("Press Enter to close tunnel..."); System.in.read(); // Remove specific forwarding session.delPortForwardingL(3306); session.disconnect(); } catch (Exception e) { e.printStackTrace(); } } } ``` -------------------------------- ### Integrate OpenSSH Configuration Source: https://context7.com/mwiede/jsch/llms.txt Parses standard OpenSSH configuration files to automatically apply host aliases, identity files, and port settings to JSch sessions. ```java import com.jcraft.jsch.*; import java.io.File; public class OpenSSHConfigExample { public static void main(String[] args) { try { JSch jsch = new JSch(); // Parse ~/.ssh/config file String configPath = System.getProperty("user.home") + "/.ssh/config"; if (new File(configPath).exists()) { OpenSSHConfig config = OpenSSHConfig.parseFile(configPath); jsch.setConfigRepository(config); } // Load known_hosts String knownHostsPath = System.getProperty("user.home") + "/.ssh/known_hosts"; if (new File(knownHostsPath).exists()) { jsch.setKnownHosts(knownHostsPath); } // Connect using Host alias from config file // ~/.ssh/config might contain: // Host myserver // HostName actual.server.com // User myusername // IdentityFile ~/.ssh/mykey // Port 2222 Session session = jsch.getSession("myserver"); // Uses alias from config session.connect(30000); System.out.println("Connected using OpenSSH config!"); session.disconnect(); } catch (Exception e) { e.printStackTrace(); } } } ``` -------------------------------- ### Parse and Use OpenSSH Config with Jsch Source: https://github.com/mwiede/jsch/wiki/Jsch-Configuration Reads and parses the user's `~/.ssh/config` and `~/.ssh/known_hosts` files to configure Jsch. Ensure the config file exists before attempting to parse. ```java final JSch jSch = new JSch(); final String configFile = System.getProperty("user.home") + File.separator + ".ssh" + File.separator + "config"; final File file = new File(configFile); if (file.exists()) { final OpenSSHConfig openSSHConfig = OpenSSHConfig.parseFile(file.getAbsolutePath()); jSch.setConfigRepository(openSSHConfig); } final String knownHostsFile= System.getProperty("user.home") + File.separator + ".ssh" + File.separator + "known_hosts"; if(new File(knownHostsFile).exists()) { jSch.setKnownHosts(knownHostsFile); } final Session newSession = jSch.getSession(myHost); newSession.connect(connectTimeout); ... ``` -------------------------------- ### Open Interactive Shell Session with JSch Source: https://context7.com/mwiede/jsch/llms.txt Opens an interactive shell channel for executing commands remotely. Configures terminal type and environment variables. Connects standard input and output for interaction. ```java import com.jcraft.jsch.*; import java.io.*; public class InteractiveShellExample { public static void main(String[] args) { try { JSch jsch = new JSch(); jsch.addIdentity("~/.ssh/id_rsa"); Session session = jsch.getSession("user", "server.example.com", 22); session.setConfig("StrictHostKeyChecking", "no"); session.connect(); // Open shell channel ChannelShell channel = (ChannelShell) session.openChannel("shell"); // Set terminal type channel.setPtyType("xterm"); // Set environment variables channel.setEnv("TERM", "xterm-256color"); channel.setEnv("LANG", "en_US.UTF-8"); // Connect I/O streams channel.setInputStream(System.in); channel.setOutputStream(System.out); // Enable agent forwarding if needed // channel.setAgentForwarding(true); channel.connect(); // Shell is now interactive - user can type commands // Wait for channel to close while (!channel.isClosed()) { Thread.sleep(100); } channel.disconnect(); session.disconnect(); } catch (Exception e) { e.printStackTrace(); } } } ``` -------------------------------- ### Execute Remote Command and Capture Output Source: https://context7.com/mwiede/jsch/llms.txt Use ChannelExec to run a command on the remote server and capture both stdout and stderr. Ensure JSch is configured with identity and session details. The command output is printed to the console, and the exit status is displayed upon completion. ```java import com.jcraft.jsch.*; import java.io.InputStream; import java.io.ByteArrayOutputStream; public class RemoteExecExample { public static void main(String[] args) { Session session = null; ChannelExec channel = null; try { JSch jsch = new JSch(); jsch.addIdentity("~/.ssh/id_rsa"); session = jsch.getSession("user", "server.example.com", 22); session.setConfig("StrictHostKeyChecking", "no"); session.connect(30000); // Open exec channel channel = (ChannelExec) session.openChannel("exec"); channel.setCommand("ls -la /var/log"); // Capture stdout and stderr ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ByteArrayOutputStream errorStream = new ByteArrayOutputStream(); channel.setOutputStream(outputStream); channel.setErrStream(errorStream); InputStream in = channel.getInputStream(); channel.connect(); // Read command output byte[] tmp = new byte[1024]; while (true) { while (in.available() > 0) { int i = in.read(tmp, 0, 1024); if (i < 0) break; System.out.print(new String(tmp, 0, i)); } if (channel.isClosed()) { if (in.available() > 0) continue; System.out.println("\nExit status: " + channel.getExitStatus()); break; } Thread.sleep(100); } } catch (Exception e) { e.printStackTrace(); } finally { if (channel != null) channel.disconnect(); if (session != null) session.disconnect(); } } } ``` -------------------------------- ### Configure Maven Dependencies for JSch Source: https://context7.com/mwiede/jsch/llms.txt Provides the Maven coordinates for the JSch fork and optional Bouncy Castle dependencies, including instructions for handling transitive dependency exclusions. ```xml com.github.mwiede jsch 2.28.0 org.bouncycastle bcprov-jdk18on 1.83 com.github.mwiede jsch 2.28.0 some.library that-uses-jsch 1.0.0 com.jcraft jsch ``` -------------------------------- ### Re-enable RSA/SHA1 globally via JSch configuration Source: https://github.com/mwiede/jsch/blob/master/Readme.md Use this to globally update the server host key and public key algorithm configuration for the JSch instance. ```java JSch.setConfig("server_host_key", JSch.getConfig("server_host_key") + ",ssh-rsa") ``` ```java JSch.setConfig("PubkeyAcceptedAlgorithms", JSch.getConfig("PubkeyAcceptedAlgorithms") + ",ssh-rsa") ``` -------------------------------- ### Override Jsch Config Programmatically for Legacy Servers Source: https://github.com/mwiede/jsch/wiki/Jsch-Configuration Sets a specific configuration key on a Jsch Session instance to override default settings, useful for connecting to legacy servers. The configuration key 'kex' is modified by appending a new algorithm. ```java session.setConfig("kex", session.getConfig("kex") + ",diffie-hellman-group14-sha1"); ``` -------------------------------- ### Re-enable RSA/SHA1 per-session Source: https://github.com/mwiede/jsch/blob/master/Readme.md Use this to update the configuration for a specific SSH session without affecting global settings. ```java session.setConfig("server_host_key", session.getConfig("server_host_key") + ",ssh-rsa") ``` ```java session.setConfig("PubkeyAcceptedAlgorithms", session.getConfig("PubkeyAcceptedAlgorithms") + ",ssh-rsa") ``` -------------------------------- ### Generate SSH Key Pairs with JSch Source: https://context7.com/mwiede/jsch/llms.txt Generates RSA, ECDSA, and Ed25519 key pairs programmatically. Supports passphrase encryption for private keys and allows loading existing keys for inspection. ```java import com.jcraft.jsch.*; public class KeyPairGenerationExample { public static void main(String[] args) { try { JSch jsch = new JSch(); // Generate RSA key pair (2048 bits) KeyPair rsaKeyPair = KeyPair.genKeyPair(jsch, KeyPair.RSA, 2048); rsaKeyPair.writePrivateKey("/tmp/id_rsa", "passphrase".getBytes()); rsaKeyPair.writePublicKey("/tmp/id_rsa.pub", "user@example.com"); System.out.println("RSA fingerprint: " + rsaKeyPair.getFingerPrint()); rsaKeyPair.dispose(); // Generate ECDSA key pair (256 bits) KeyPair ecdsaKeyPair = KeyPair.genKeyPair(jsch, KeyPair.ECDSA, 256); ecdsaKeyPair.writePrivateKey("/tmp/id_ecdsa"); ecdsaKeyPair.writePublicKey("/tmp/id_ecdsa.pub", "user@example.com"); System.out.println("ECDSA fingerprint: " + ecdsaKeyPair.getFingerPrint()); ecdsaKeyPair.dispose(); // Generate Ed25519 key pair (requires Java 15+ or Bouncy Castle) KeyPair ed25519KeyPair = KeyPair.genKeyPair(jsch, KeyPair.ED25519); ed25519KeyPair.writePrivateKey("/tmp/id_ed25519"); ed25519KeyPair.writePublicKey("/tmp/id_ed25519.pub", "user@example.com"); System.out.println("Ed25519 fingerprint: " + ed25519KeyPair.getFingerPrint()); ed25519KeyPair.dispose(); // Load and inspect existing key KeyPair loaded = KeyPair.load(jsch, "/tmp/id_rsa"); System.out.println("Key type: " + loaded.getKeyTypeString()); System.out.println("Key size: " + loaded.getKeySize()); System.out.println("Is encrypted: " + loaded.isEncrypted()); loaded.dispose(); } catch (Exception e) { e.printStackTrace(); } } } ``` -------------------------------- ### Replace Direct Maven Dependency Source: https://github.com/mwiede/jsch/blob/master/Readme.md Replace the original JSch dependency with the forked version in your Maven project's pom.xml. ```xml com.jcraft jsch 0.1.55 ``` ```xml com.github.mwiede jsch 2.28.0 ``` -------------------------------- ### Replace Transitive Maven Dependency Source: https://github.com/mwiede/jsch/blob/master/Readme.md Exclude the original JSch dependency and include the forked version when JSch is a transitive dependency in your Maven project. ```xml com.github.mwiede jsch 2.28.0 foo bar com.jcraft jsch ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.