diff --git a/libraries-io/pom.xml b/libraries-io/pom.xml
index e0d643c9cbab..9dfe92d11461 100644
--- a/libraries-io/pom.xml
+++ b/libraries-io/pom.xml
@@ -63,6 +63,19 @@
jakarta.mail-api
${jakarta-mail.version}
+
+
+ org.testcontainers
+ testcontainers
+ ${testcontainers.version}
+ test
+
+
+ org.testcontainers
+ testcontainers-junit-jupiter
+ ${testcontainers.version}
+ test
+
@@ -80,15 +93,16 @@
- 0.2.16
+ 2.27.5
0.38.0
- 2.9.0
+ 2.10.0
2.11.5
5.9
6.1.4
8.7.0
2.1.3
2.0.1
+ 2.0.1
\ No newline at end of file
diff --git a/libraries-io/src/test/java/com/baeldung/java/io/jsch/BaseUserInfo.java b/libraries-io/src/test/java/com/baeldung/java/io/jsch/BaseUserInfo.java
new file mode 100644
index 000000000000..ba1a6c35d4ab
--- /dev/null
+++ b/libraries-io/src/test/java/com/baeldung/java/io/jsch/BaseUserInfo.java
@@ -0,0 +1,35 @@
+package com.baeldung.java.io.jsch;
+
+import com.jcraft.jsch.UserInfo;
+
+public class BaseUserInfo implements UserInfo {
+ @Override
+ public String getPassphrase() {
+ return null;
+ }
+
+ @Override
+ public String getPassword() {
+ return null;
+ }
+
+ @Override
+ public boolean promptPassword(String message) {
+ return false;
+ }
+
+ @Override
+ public boolean promptPassphrase(String message) {
+ return false;
+ }
+
+ @Override
+ public boolean promptYesNo(String message) {
+ return false;
+ }
+
+ @Override
+ public void showMessage(String message) {
+
+ }
+}
diff --git a/libraries-io/src/test/java/com/baeldung/java/io/jsch/ConnectIntegrationTest.java b/libraries-io/src/test/java/com/baeldung/java/io/jsch/ConnectIntegrationTest.java
new file mode 100644
index 000000000000..1a95c0382804
--- /dev/null
+++ b/libraries-io/src/test/java/com/baeldung/java/io/jsch/ConnectIntegrationTest.java
@@ -0,0 +1,176 @@
+package com.baeldung.java.io.jsch;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.nio.file.Paths;
+
+import org.junit.jupiter.api.Test;
+import org.testcontainers.containers.GenericContainer;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+import org.testcontainers.utility.MountableFile;
+
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.JSchException;
+import com.jcraft.jsch.JSchUnknownHostKeyException;
+import com.jcraft.jsch.Session;
+
+@Testcontainers
+class ConnectIntegrationTest {
+ private static final int SFTP_PORT = 22;
+
+ private static final String USERNAME = "baeldung";
+ private static final String PASSWORD = "test";
+ private static final String DIRECTORY = "upload";
+
+ // atmoz/sftp is a Docker container for an SFTP server that can easily support password and key authentication.
+ @Container
+ public static GenericContainer> sftpContainer = new GenericContainer<>("atmoz/sftp:latest")
+ .withExposedPorts(SFTP_PORT)
+ .withCommand(USERNAME + ":" + PASSWORD + ":::" + DIRECTORY)
+ .withCopyFileToContainer(
+ MountableFile.forHostPath(Paths.get("src/test/resources/com/baeldung/java/io/jsch/nopassphrase/id_rsa.pub")),
+ "/home/" + USERNAME + "/.ssh/keys/id_rsa.pub"
+ )
+ .withCopyFileToContainer(
+ MountableFile.forHostPath(Paths.get("src/test/resources/com/baeldung/java/io/jsch/passphrase/id_rsa.pub")),
+ "/home/" + USERNAME + "/.ssh/keys/id_rsa2.pub"
+ );
+
+ @Test
+ void whenTheHostKeyIsUnknown_thenTheConnectionFails() throws Exception {
+ JSch jSch = new JSch();
+
+ Session session = jSch.getSession(USERNAME, sftpContainer.getHost(), sftpContainer.getMappedPort(SFTP_PORT));
+
+ session.setUserInfo(new BaseUserInfo() {});
+
+ assertThrows(JSchUnknownHostKeyException.class, () -> session.connect());
+ }
+
+ @Test
+ void whenNoAuthenticationIsProvided_thenTheConnectionFails() throws Exception {
+ JSch jSch = new JSch();
+
+ Session session = jSch.getSession(USERNAME, sftpContainer.getHost(), sftpContainer.getMappedPort(SFTP_PORT));
+
+ session.setUserInfo(new BaseUserInfo() {
+
+ @Override
+ public boolean promptYesNo(String message) {
+ if (message.startsWith("The authenticity of host")) {
+ return true;
+ }
+
+ return false;
+ }
+ });
+
+ JSchException exception = assertThrows(JSchException.class, () -> session.connect());
+ assertEquals("Auth cancel for methods 'publickey,password,keyboard-interactive'", exception.getMessage());
+ }
+
+ @Test
+ void whenPasswordAuthIsProvided_thenTheConnectionSucceeds() throws Exception {
+ JSch jSch = new JSch();
+
+ Session session = jSch.getSession(USERNAME, sftpContainer.getHost(), sftpContainer.getMappedPort(SFTP_PORT));
+
+ session.setUserInfo(new BaseUserInfo() {
+ @Override
+ public String getPassword() {
+ return PASSWORD;
+ }
+
+ @Override
+ public boolean promptPassword(String message) {
+ return true;
+ }
+
+ @Override
+ public boolean promptYesNo(String message) {
+ if (message.startsWith("The authenticity of host")) {
+ return true;
+ }
+
+ return false;
+ }
+ });
+
+ session.connect();
+ }
+
+ @Test
+ void givenAnOpenSSHKey_whenKeyAuthIsProvided_thenTheConnectionSucceeds() throws Exception {
+ JSch jSch = new JSch();
+ jSch.addIdentity("src/test/resources/com/baeldung/java/io/jsch/nopassphrase/id_rsa");
+
+ Session session = jSch.getSession(USERNAME, sftpContainer.getHost(), sftpContainer.getMappedPort(SFTP_PORT));
+
+ session.setUserInfo(new BaseUserInfo() {
+ @Override
+ public boolean promptYesNo(String message) {
+ if (message.startsWith("The authenticity of host")) {
+ return true;
+ }
+
+ return false;
+ }
+ });
+
+ session.connect();
+ }
+
+ @Test
+ void givenAPuttyKey_whenKeyAuthIsProvided_thenTheConnectionSucceeds() throws Exception {
+ JSch jSch = new JSch();
+ jSch.addIdentity("src/test/resources/com/baeldung/java/io/jsch/nopassphrase/id_rsa.ppk");
+
+ Session session = jSch.getSession(USERNAME, sftpContainer.getHost(), sftpContainer.getMappedPort(SFTP_PORT));
+
+ session.setUserInfo(new BaseUserInfo() {
+ @Override
+ public boolean promptYesNo(String message) {
+ if (message.startsWith("The authenticity of host")) {
+ return true;
+ }
+
+ return false;
+ }
+ });
+
+ session.connect();
+ }
+
+ @Test
+ void givenAnOpenSSHKeyWithPassphrase_whenKeyAuthIsProvided_thenTheConnectionSucceeds() throws Exception {
+ JSch jSch = new JSch();
+ jSch.addIdentity("src/test/resources/com/baeldung/java/io/jsch/passphrase/id_rsa");
+
+ Session session = jSch.getSession(USERNAME, sftpContainer.getHost(), sftpContainer.getMappedPort(SFTP_PORT));
+
+ session.setUserInfo(new BaseUserInfo() {
+ @Override
+ public String getPassphrase() {
+ return "te5tPa55word";
+ }
+
+ @Override
+ public boolean promptPassphrase(String message) {
+ return true;
+ }
+
+ @Override
+ public boolean promptYesNo(String message) {
+ if (message.startsWith("The authenticity of host")) {
+ return true;
+ }
+
+ return false;
+ }
+ });
+
+ session.connect();
+ }
+}
diff --git a/libraries-io/src/test/java/com/baeldung/java/io/jsch/SftpIntegrationTest.java b/libraries-io/src/test/java/com/baeldung/java/io/jsch/SftpIntegrationTest.java
new file mode 100644
index 000000000000..41fd4826147f
--- /dev/null
+++ b/libraries-io/src/test/java/com/baeldung/java/io/jsch/SftpIntegrationTest.java
@@ -0,0 +1,175 @@
+package com.baeldung.java.io.jsch;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.nio.file.Paths;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+import org.testcontainers.containers.GenericContainer;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+import org.testcontainers.utility.MountableFile;
+
+import com.jcraft.jsch.Channel;
+import com.jcraft.jsch.ChannelSftp;
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.Session;
+import com.jcraft.jsch.SftpATTRS;
+
+@Testcontainers
+public class SftpIntegrationTest {
+
+ private static final int SFTP_PORT = 22;
+
+ private static final String USERNAME = "foo";
+ private static final String PASSWORD = "pass";
+
+ // mobilistics/sftp is a Docker container for an SFTP server that reliably allows file upload and download.
+ // Unfortunately, atmoz/sftp intermittently doesn't allow writing to the server.
+ @Container
+ public static GenericContainer> sftpContainer = new GenericContainer<>("mobilistics/sftp:latest")
+ .withExposedPorts(SFTP_PORT)
+ .withEnv("USER", USERNAME)
+ .withEnv("PASS", PASSWORD)
+ .withCopyFileToContainer(
+ MountableFile.forHostPath(Paths.get("src/main/resources/input.txt")),
+ "/data/incoming/input.txt"
+ );
+
+ @Test
+ void whenGettingTheCurrentDirectory_thenTheCorrectValueIsReturned() throws Exception {
+ JSch jSch = new JSch();
+
+ Session session = jSch.getSession(USERNAME, sftpContainer.getHost(), sftpContainer.getMappedPort(SFTP_PORT));
+
+ session.setUserInfo(new SftpUserInfo());
+
+ session.connect();
+
+ Channel channel = session.openChannel("sftp");
+ channel.connect();
+ ChannelSftp sftp = (ChannelSftp) channel;
+
+ assertEquals("/", sftp.pwd());
+ assertTrue(sftp.lpwd().endsWith("/libraries-io"));
+ }
+
+ @Test
+ void whenListingRemoteFiles_thenTheCorrectFilesAreReturned() throws Exception {
+ JSch jSch = new JSch();
+
+ Session session = jSch.getSession(USERNAME, sftpContainer.getHost(), sftpContainer.getMappedPort(SFTP_PORT));
+
+ session.setUserInfo(new SftpUserInfo());
+
+ session.connect();
+
+ Channel channel = session.openChannel("sftp");
+ channel.connect();
+ ChannelSftp sftp = (ChannelSftp) channel;
+
+ List remoteLs = sftp.ls(".");
+ assertEquals(3, remoteLs.size()); // ., ../ and incoming
+
+ ChannelSftp.LsEntry incoming = remoteLs.stream()
+ .filter(file -> file.getFilename()
+ .equals("incoming"))
+ .findFirst()
+ .get();
+
+ assertEquals("incoming", incoming.getFilename());
+
+ SftpATTRS attrs = incoming.getAttrs();
+ assertEquals("drwxr-xr-x", attrs.getPermissionsString());
+ }
+
+ @Test
+ void whenGettingFileStatus_thenTheCorrectValueIsReturned() throws Exception {
+ JSch jSch = new JSch();
+
+ Session session = jSch.getSession(USERNAME, sftpContainer.getHost(), sftpContainer.getMappedPort(SFTP_PORT));
+
+ session.setUserInfo(new SftpUserInfo());
+
+ session.connect();
+
+ Channel channel = session.openChannel("sftp");
+ channel.connect();
+ ChannelSftp sftp = (ChannelSftp) channel;
+
+ SftpATTRS attrs = sftp.stat("incoming");
+ assertEquals("drwxr-xr-x", attrs.getPermissionsString());
+ }
+
+ @Test
+ void whenPuttingFiles_thenTheFilesAreCreatedOnTheServer() throws Exception {
+ JSch jSch = new JSch();
+
+ Session session = jSch.getSession(USERNAME, sftpContainer.getHost(), sftpContainer.getMappedPort(SFTP_PORT));
+
+ session.setUserInfo(new SftpUserInfo());
+
+ session.connect();
+
+ Channel channel = session.openChannel("sftp");
+ channel.connect();
+ ChannelSftp sftp = (ChannelSftp) channel;
+
+ sftp.cd("incoming");
+
+ try (OutputStream outputStream = sftp.put("os.txt")) {
+ OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
+ outputStreamWriter.write("Hello, world!");
+ outputStreamWriter.close();
+ }
+
+ // Check the files exist
+ sftp.stat("os.txt");
+ }
+
+ @Test
+ void whenGettingAFile_thenTheFileContentsAreRetrieved() throws Exception {
+ JSch jSch = new JSch();
+
+ Session session = jSch.getSession(USERNAME, sftpContainer.getHost(), sftpContainer.getMappedPort(SFTP_PORT));
+
+ session.setUserInfo(new SftpUserInfo());
+
+ session.connect();
+
+ Channel channel = session.openChannel("sftp");
+ channel.connect();
+ ChannelSftp sftp = (ChannelSftp) channel;
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ sftp.get("incoming/input.txt", baos);
+
+ assertEquals("This is a sample text content", new String(baos.toByteArray()));
+ }
+
+ private static class SftpUserInfo extends BaseUserInfo {
+ @Override
+ public String getPassword() {
+ return PASSWORD;
+ }
+
+ @Override
+ public boolean promptPassword(String message) {
+ return true;
+ }
+
+ @Override
+ public boolean promptYesNo(String message) {
+ if (message.startsWith("The authenticity of host")) {
+ return true;
+ }
+
+ return false;
+ }
+ }
+}
diff --git a/libraries-io/src/test/resources/com/baeldung/java/io/jsch/nopassphrase/id_rsa b/libraries-io/src/test/resources/com/baeldung/java/io/jsch/nopassphrase/id_rsa
new file mode 100644
index 000000000000..78d1ae96ca82
--- /dev/null
+++ b/libraries-io/src/test/resources/com/baeldung/java/io/jsch/nopassphrase/id_rsa
@@ -0,0 +1,49 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+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
+-----END OPENSSH PRIVATE KEY-----
diff --git a/libraries-io/src/test/resources/com/baeldung/java/io/jsch/nopassphrase/id_rsa.ppk b/libraries-io/src/test/resources/com/baeldung/java/io/jsch/nopassphrase/id_rsa.ppk
new file mode 100644
index 000000000000..a75089e73e47
--- /dev/null
+++ b/libraries-io/src/test/resources/com/baeldung/java/io/jsch/nopassphrase/id_rsa.ppk
@@ -0,0 +1,46 @@
+PuTTY-User-Key-File-3: ssh-rsa
+Encryption: none
+Comment: baeldung@example.com
+Public-Lines: 12
+AAAAB3NzaC1yc2EAAAADAQABAAACAQCiYP2JZsoBSpOm4vsLhZz0ObJO08472D0l
+A5gYAn6qogRI3DKpTDd8HH+1ltF7pQK49BAv0XwcmfE2i/jmPcxtzOHoYd9LTVUa
+AVt13mqWqGn473WtCWbmviT8uKvXjXHPV9Zf8sy7BjX3apvs2J5VuVcIGqO60w9F
+jp4NQchuGyTNnAwhQxmqUoYPrO36GbLWcHa0her1V8c3+QC2mZLYCow/8VXPSQyo
+14jBCV7E2zG7y4rRPaCxjHToMSouiK6L1WAVskm4K5owRU4wEuvg0wfeikwBdSLe
+69nzc7kMEABtmwDdboCJ1UFcgx7JqW4AnxCASwG8wvRX5Esk4VOC0hlHVGP9vN1g
+gn34YB8WfqnzfY/+HZx5Q786ln4yXgQExCz/6z5VZ0RhlZNTiWj/zqshDN9romZf
+hw42ghRbWJlXwmXbc0kdMup2CDZwE0m4yDUhZD7QPI+va/3Rf0iJaX1OZciUeIVp
+ziy1szNaJv+wU+ZaV4ZKiKhabwIx4A8ShRnOzQTyHipAOjm9UJAaymuSii7rapmb
+EaypJ8EnXqcMnteLIrtorJhGoss4k8AcyHIAxWIQQrU1BQ1aLgMWfQxZsMvWVPAF
+HKGieKsHBkET46HLfX6UqFqZkjWDYd+7IM//vJPdafrzc5VGyeYNR/u7vNf7hEOG
+pysTCaZ9lQ==
+Private-Lines: 28
+AAACAHf+8v4KHvfrU8f9bwYpvD5jMNi9/2cMOstSp5/+n/qa9k2dpDamI06thNb9
+2FrmK2fgvOGJjo1YWgA0WkBTpPHzeXKQeUIdqOkp3ZvyPJSPapjS5QR1sTyNgand
+EuidF2DhiYOoWxFO2qy3dPkHb6Lr71wGy74xYNTHOxeS6HotxvnG+tPN0Xaju3x0
+D/1F5no/7Akl+edK8eb0NUm7nd/Xk6NhRkeDtT5E4UO+F/GkBlHAbhqIz2rF4FMC
+mih/S3X8vh/qfD4EwtIvNUOjh/rCGMulKdvd42IXqx4VA8fdP2PAK1h347d4B/BE
+2Yivk6IT6k7UnzkOXSFijQF5Houdx3FoLb3NaWfTp/VVwq3EQtWJFI/wQxDK/RUL
+Ug2jxgTB/t1d+FFeoZ1C7mBuvdgU8pNAjKo9/jXOhSooEfbsa2zprE95kRKdflHz
+d62qISVVzvL9EaB+TAUSOfMRnyoTQp8kxQITLf8jlOZLx0qcwZMclpIlI1I7gjWb
+ZLJIDqvZ6S7fPoz1RYdzZfouFAs9sN2ehFtKwxLc4Ui/NOgOWcsbICvjALuo6lXg
+ESKuKt/qGOcQo6ZtU1q6b4qVicn45DX4o4hPo5eDUipOUjY/j6UoQspu9L380fTZ
+CoG8aUcw+yaKYtPJSrSiP7s3vYOup9BvN3RRxYsHspagkZc1AAABAQDXhah/ZJFg
+XgCN5/GZSHRq3pPJZ0KXwfSZqmby9WmDWaaXUK3NHHL7/DqrTgNNB7fBjCOW6Fkd
+rmmsCkqh9pysr0F+/PbsqNBtmlOGmC0WY5adzxYHwfMlS85d3trVwwz0Fafqe42n
+2n8PDv2QyMXA4I6KtqrMfYsmZY9w6tJGAgLr2AumBU329f7kyXmizGc8QkXuphxG
+/tkBt3PQY6JNdwtRvtNlX0QYCJpjoEEkahssCF41smJiSr7NIIVDi/PChOsjgihu
+DbCTgmS12zUfs40wXD62tTMs02nLJNjWaiT4CUZOGVrsE+lhCy341nUqXcf3Zt5E
+J9pQTrLjoXQHAAABAQDA4DIkApmmXHiQ7A3XEj01FkKFWip2sZWKuI/JiK8yjNlI
+eIF5hX1WbzhvVXnG4luptiTO48eu0XMso89jfvEBwU4B8Wuvrbr2WbMqdiFx3ER/
+YiJH3UOt8QQP6wSI2oAb4TO6hj3ghQP+fPoCN4w+GJQEmeQN8mWgF7p0hQZ3qVEp
+WXste2y3Qz37nmbUWvySCQm2fLirEEfijSslw7iAqXuINPyLgW+98b98NYIGByVd
+YS0/w/CJcCIcXPip7vlmbLD8SzD64Y1pfOCMIHE6f5FTS+DzNqUzvwn1C4YzFbP1
+q7CMZ7vAxX2Fd9u0RoXSBWl/fT4Ua82BwfiPe3KDAAABAQDB9iPiEorWEpTNqMsB
+p11EldyrGIDoDDfw1DI6JyMHTwk+tWxwf0ZRSRu2dS6l5JG++ObWc3D8/nfLIeid
+dzh50Xbdqeb2CM9TjOpHPybOzpPchGV7Gltfj0cLuinkbhbXTXIqSpX2sjT7ADYg
+1OkZJF83YtNs5T7BOvhS5oGKc2bYvcGWzHfwa2JVvz90dWXO2Y90IYRQbjT3Hgay
+bKIbyaQHgodKKn9/cl/KyVOaKe8MKihCgeFc67owCqdiuVbfj4ASXXs06mkPJH66
+SsL2zzyz1n5hmoKsvJJSa0gKB39PVpF8++ro3VQblclExXTwz3/IJJH2NR/yS11S
+WhHe
+Private-MAC: a24059ebfd6e93a44b28a2ac99df4c6edb0e7209510f16a3b08ee002baa0246e
diff --git a/libraries-io/src/test/resources/com/baeldung/java/io/jsch/nopassphrase/id_rsa.pub b/libraries-io/src/test/resources/com/baeldung/java/io/jsch/nopassphrase/id_rsa.pub
new file mode 100644
index 000000000000..025f05236df4
--- /dev/null
+++ b/libraries-io/src/test/resources/com/baeldung/java/io/jsch/nopassphrase/id_rsa.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCiYP2JZsoBSpOm4vsLhZz0ObJO08472D0lA5gYAn6qogRI3DKpTDd8HH+1ltF7pQK49BAv0XwcmfE2i/jmPcxtzOHoYd9LTVUaAVt13mqWqGn473WtCWbmviT8uKvXjXHPV9Zf8sy7BjX3apvs2J5VuVcIGqO60w9Fjp4NQchuGyTNnAwhQxmqUoYPrO36GbLWcHa0her1V8c3+QC2mZLYCow/8VXPSQyo14jBCV7E2zG7y4rRPaCxjHToMSouiK6L1WAVskm4K5owRU4wEuvg0wfeikwBdSLe69nzc7kMEABtmwDdboCJ1UFcgx7JqW4AnxCASwG8wvRX5Esk4VOC0hlHVGP9vN1ggn34YB8WfqnzfY/+HZx5Q786ln4yXgQExCz/6z5VZ0RhlZNTiWj/zqshDN9romZfhw42ghRbWJlXwmXbc0kdMup2CDZwE0m4yDUhZD7QPI+va/3Rf0iJaX1OZciUeIVpziy1szNaJv+wU+ZaV4ZKiKhabwIx4A8ShRnOzQTyHipAOjm9UJAaymuSii7rapmbEaypJ8EnXqcMnteLIrtorJhGoss4k8AcyHIAxWIQQrU1BQ1aLgMWfQxZsMvWVPAFHKGieKsHBkET46HLfX6UqFqZkjWDYd+7IM//vJPdafrzc5VGyeYNR/u7vNf7hEOGpysTCaZ9lQ== baeldung@example.com
diff --git a/libraries-io/src/test/resources/com/baeldung/java/io/jsch/passphrase/id_rsa b/libraries-io/src/test/resources/com/baeldung/java/io/jsch/passphrase/id_rsa
new file mode 100644
index 000000000000..013eccfda8bb
--- /dev/null
+++ b/libraries-io/src/test/resources/com/baeldung/java/io/jsch/passphrase/id_rsa
@@ -0,0 +1,50 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+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
+/Q5FIxzRukaGGRcNeizEwXZ90=
+-----END OPENSSH PRIVATE KEY-----
diff --git a/libraries-io/src/test/resources/com/baeldung/java/io/jsch/passphrase/id_rsa.pub b/libraries-io/src/test/resources/com/baeldung/java/io/jsch/passphrase/id_rsa.pub
new file mode 100644
index 000000000000..2425a722e360
--- /dev/null
+++ b/libraries-io/src/test/resources/com/baeldung/java/io/jsch/passphrase/id_rsa.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC8zF9LhfB+6oKkAEQpoT/g9vNNNd0SucFY1g0x9Ko9P738xJj+TMXt98bmRRzWSrbnr9tUFBmi8SG/pW7AIUph2kFSIcPAiOPCGQ7U7P12fgv6ft5TrQGAsxnLW1jx/OsPH3MiiotM/fcMo/NLW1oFr4sRipXjRYrZ3BFiAuqTYpxdbRBc+md8JZ8cJRzx1aRU4UxD53kQeDrphzTUlp1WQltppFl2/DR3Gask9KiEeAxJE59RW/DZak/w8Kns8Q+IeGSFARYAqn3kBJtG03W4J/MEeQko9u06R3y06+4/8kR1QchWLjzB176VcM0EKNeBBlUirNH5vIKeHiMquWp1z3ej93hff1YETXeXxahAAryQj65Arf/ZrXG1JeiIQPWh0YCHcwI6o++dRk89itJ44zKQWcytu5hFvlyvWHTfIqPiLLc3mzULkDC53YOYybdy9sLPKvMdQ8PrPwAmzwJ5GEP+iXthDs505tQsVpfFXDeVjbPUnpW9o6eIrJByIsFb/hqaHGsfBEMBSSDzFUuXcogtA9eqPSNSIXhfFP9j0XBZaXDmPSp/Gwy8PC4ot0zxMHC/a9NMGKUlRGE426WMIZiHLmPDrB2N4zw7i8NoTrCNoKS+Sn2JlOLneJj/796JYw+Sk2rpqrxp9szvhoT3Z6Ufz4fAiUHYtAwU8g7YLQ== baeldung@example.com