Apache MINA sshd client: adapt to sshd 2.2.0

Update target platforms, maven and bazel builds to use sshd 2.2.0.

Adapt internal classes to changed sshd interfaces and remove previous
work-arounds for asking repeatedly for key passwords and for loading
keys lazily; both are now done by sshd.

CQ: 19034
CQ: 19035
Bug: 541425
Change-Id: I85e1df6ebb8a94953a912d9b2b8a7b5bdfbd608a
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
diff --git a/WORKSPACE b/WORKSPACE
index 46d8002..8ee3fec 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -59,15 +59,15 @@
 )
 
 maven_jar(
-    name = "sshd-core",
-    artifact = "org.apache.sshd:sshd-core:2.0.0",
-    sha1 = "f4275079a2463cfd2bf1548a80e1683288a8e86b",
+    name = "sshd-osgi",
+    artifact = "org.apache.sshd:sshd-osgi:2.2.0",
+    sha1 = "a45d48cb53678e699816e8e054e55fa33f5a4558",
 )
 
 maven_jar(
     name = "sshd-sftp",
-    artifact = "org.apache.sshd:sshd-sftp:2.0.0",
-    sha1 = "a12d64dc2d5d23271a4dc58075e55f9c64a68494",
+    artifact = "org.apache.sshd:sshd-sftp:2.2.0",
+    sha1 = "3d011e00adf38e49bb8711a9dd762fe908a2170c",
 )
 
 maven_jar(
diff --git a/lib/BUILD b/lib/BUILD
index d89ebab..992f7bd 100644
--- a/lib/BUILD
+++ b/lib/BUILD
@@ -68,14 +68,14 @@
 )
 
 java_library(
-    name = "sshd-core",
+    name = "sshd-osgi",
     visibility = [
         "//org.eclipse.jgit.junit.ssh:__pkg__",
         "//org.eclipse.jgit.ssh.apache:__pkg__",
         "//org.eclipse.jgit.ssh.apache.test:__pkg__",
         "//org.eclipse.jgit.test:__pkg__",
     ],
-    exports = ["@sshd-core//jar"],
+    exports = ["@sshd-osgi//jar"],
 )
 
 java_library(
diff --git a/org.eclipse.jgit.junit.ssh/BUILD b/org.eclipse.jgit.junit.ssh/BUILD
index e9a04c7..8c17cb7 100644
--- a/org.eclipse.jgit.junit.ssh/BUILD
+++ b/org.eclipse.jgit.junit.ssh/BUILD
@@ -7,7 +7,7 @@
     resource_strip_prefix = "org.eclipse.jgit.junit.ssh/resources",
     resources = glob(["resources/**"]),
     deps = [
-        "//lib:sshd-core",
+        "//lib:sshd-osgi",
         "//lib:sshd-sftp",
         # We want these deps to be provided_deps
         "//org.eclipse.jgit:jgit",
diff --git a/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF
index 91dd1aa..0d66ecc 100644
--- a/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF
@@ -8,27 +8,28 @@
 Bundle-Vendor: %provider_name
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
-Import-Package: org.apache.sshd.common;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.config.keys;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.file.virtualfs;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.helpers;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.io;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.kex;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.keyprovider;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.session;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.util.buffer;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.util.logging;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.util.security;version="[2.0.0,2.1.0)",
- org.apache.sshd.server;version="[2.0.0,2.1.0)",
- org.apache.sshd.server.auth;version="[2.0.0,2.1.0)",
- org.apache.sshd.server.auth.gss;version="[2.0.0,2.1.0)",
- org.apache.sshd.server.auth.keyboard;version="[2.0.0,2.1.0)",
- org.apache.sshd.server.auth.password;version="[2.0.0,2.1.0)",
- org.apache.sshd.server.command;version="[2.0.0,2.1.0)",
- org.apache.sshd.server.session;version="[2.0.0,2.1.0)",
- org.apache.sshd.server.shell;version="[2.0.0,2.1.0)",
- org.apache.sshd.server.subsystem;version="[2.0.0,2.1.0)",
- org.apache.sshd.server.subsystem.sftp;version="[2.0.0,2.1.0)",
+Import-Package: org.apache.sshd.common;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.config.keys;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.file.virtualfs;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.helpers;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.io;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.kex;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.keyprovider;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.session;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.util.buffer;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.util.logging;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.util.security;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.util.threads;version="[2.2.0,2.3.0)",
+ org.apache.sshd.server;version="[2.2.0,2.3.0)",
+ org.apache.sshd.server.auth;version="[2.2.0,2.3.0)",
+ org.apache.sshd.server.auth.gss;version="[2.2.0,2.3.0)",
+ org.apache.sshd.server.auth.keyboard;version="[2.2.0,2.3.0)",
+ org.apache.sshd.server.auth.password;version="[2.2.0,2.3.0)",
+ org.apache.sshd.server.command;version="[2.2.0,2.3.0)",
+ org.apache.sshd.server.session;version="[2.2.0,2.3.0)",
+ org.apache.sshd.server.shell;version="[2.2.0,2.3.0)",
+ org.apache.sshd.server.subsystem;version="[2.2.0,2.3.0)",
+ org.apache.sshd.server.subsystem.sftp;version="[2.2.0,2.3.0)",
  org.eclipse.jgit.annotations;version="[5.4.0,5.5.0)",
  org.eclipse.jgit.lib;version="[5.4.0,5.5.0)",
  org.eclipse.jgit.transport;version="[5.4.0,5.5.0)",
diff --git a/org.eclipse.jgit.junit.ssh/pom.xml b/org.eclipse.jgit.junit.ssh/pom.xml
index 2310ec0..1c2830e 100644
--- a/org.eclipse.jgit.junit.ssh/pom.xml
+++ b/org.eclipse.jgit.junit.ssh/pom.xml
@@ -74,7 +74,7 @@
 
     <dependency>
       <groupId>org.apache.sshd</groupId>
-      <artifactId>sshd-core</artifactId>
+      <artifactId>sshd-osgi</artifactId>
       <version>${apache-sshd-version}</version>
     </dependency>
 
diff --git a/org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestGitServer.java b/org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestGitServer.java
index f5af2e5..25d952f 100644
--- a/org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestGitServer.java
+++ b/org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestGitServer.java
@@ -55,10 +55,9 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
 
 import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.NamedResource;
 import org.apache.sshd.common.SshConstants;
 import org.apache.sshd.common.config.keys.AuthorizedKeyEntry;
 import org.apache.sshd.common.config.keys.KeyUtils;
@@ -67,6 +66,8 @@
 import org.apache.sshd.common.session.Session;
 import org.apache.sshd.common.util.buffer.Buffer;
 import org.apache.sshd.common.util.security.SecurityUtils;
+import org.apache.sshd.common.util.threads.CloseableExecutorService;
+import org.apache.sshd.common.util.threads.ThreadUtils;
 import org.apache.sshd.server.ServerAuthenticationManager;
 import org.apache.sshd.server.SshServer;
 import org.apache.sshd.server.auth.UserAuth;
@@ -110,8 +111,8 @@
 	@NonNull
 	protected PublicKey testKey;
 
-	private final ExecutorService executorService = Executors
-			.newFixedThreadPool(2);
+	private final CloseableExecutorService executorService = ThreadUtils
+			.newFixedThreadPool("SshTestGitServerPool", 2);
 
 	/**
 	 * Creates a ssh git <em>test</em> server. It serves one single repository,
@@ -138,11 +139,12 @@
 		server = SshServer.setUpDefaultServer();
 		// Set host key
 		try (ByteArrayInputStream in = new ByteArrayInputStream(hostKey)) {
-			hostKeys.add(SecurityUtils.loadKeyPairIdentity("", in, null));
+			SecurityUtils.loadKeyPairIdentities(null, null, in, null)
+					.forEach((k) -> hostKeys.add(k));
 		} catch (IOException | GeneralSecurityException e) {
 			// Ignore.
 		}
-		server.setKeyPairProvider(() -> hostKeys);
+		server.setKeyPairProvider((session) -> hostKeys);
 
 		configureAuthentication();
 
@@ -276,8 +278,10 @@
 	public void addHostKey(@NonNull Path key, boolean inFront)
 			throws IOException, GeneralSecurityException {
 		try (InputStream in = Files.newInputStream(key)) {
-			KeyPair pair = SecurityUtils.loadKeyPairIdentity(key.toString(), in,
-					null);
+			KeyPair pair = SecurityUtils
+					.loadKeyPairIdentities(null,
+							NamedResource.ofName(key.toString()), in, null)
+					.iterator().next();
 			if (inFront) {
 				hostKeys.add(0, pair);
 			} else {
@@ -335,14 +339,14 @@
 	public void setTestUserPublicKey(Path key)
 			throws IOException, GeneralSecurityException {
 		this.testKey = AuthorizedKeyEntry.readAuthorizedKeys(key).get(0)
-				.resolvePublicKey(PublicKeyEntryResolver.IGNORING);
+				.resolvePublicKey(null, PublicKeyEntryResolver.IGNORING);
 	}
 
 	private class GitUploadPackCommand extends AbstractCommandSupport {
 
 		protected GitUploadPackCommand(String command,
-				ExecutorService executorService) {
-			super(command, executorService, false);
+				CloseableExecutorService executorService) {
+			super(command, ThreadUtils.noClose(executorService));
 		}
 
 		@Override
@@ -370,8 +374,8 @@
 	private class GitReceivePackCommand extends AbstractCommandSupport {
 
 		protected GitReceivePackCommand(String command,
-				ExecutorService executorService) {
-			super(command, executorService, false);
+				CloseableExecutorService executorService) {
+			super(command, ThreadUtils.noClose(executorService));
 		}
 
 		@Override
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml
index bbd1ffe..34f0ac9 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml
@@ -63,7 +63,7 @@
          unpack="false"/>
 
    <plugin
-         id="org.apache.sshd.core"
+         id="org.apache.sshd.osgi"
          download-size="0"
          install-size="0"
          version="0.0.0"
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/feature.xml
index 0e3966d..a84d590 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/feature.xml
@@ -34,7 +34,7 @@
          unpack="false"/>
 
    <plugin
-         id="org.apache.sshd.core"
+         id="org.apache.sshd.osgi"
          download-size="0"
          install-size="0"
          version="0.0.0"
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.target
index bfa286e..80086da 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.target
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?><?pde?><!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --><target name="jgit-4.10" sequenceNumber="1557147616">
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><?pde?><!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --><target name="jgit-4.10" sequenceNumber="1557148658">
   <locations>
     <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="slicer" includeSource="true" type="InstallableUnit">
       <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>
@@ -75,10 +75,10 @@
       <unit id="com.jcraft.jzlib.source" version="1.1.1.v201205102305"/>
       <unit id="net.i2p.crypto.eddsa" version="0.3.0.v20181102-1323"/>
       <unit id="net.i2p.crypto.eddsa.source" version="0.3.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.core" version="2.0.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.core.source" version="2.0.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.sftp" version="2.0.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.sftp.source" version="2.0.0.v20181102-1323"/>
+      <unit id="org.apache.sshd.osgi" version="2.2.0.v20190425-2127"/>
+      <unit id="org.apache.sshd.osgi.source" version="2.2.0.v20190425-2127"/>
+      <unit id="org.apache.sshd.sftp" version="2.2.0.v20190425-2127"/>
+      <unit id="org.apache.sshd.sftp.source" version="2.2.0.v20190425-2127"/>
       <repository location="http://download.eclipse.org/tools/orbit/downloads/drops/S20190501151401/repository"/>
     </location>
     <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="slicer" includeSource="true" type="InstallableUnit">
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11.target
index 35a41eb..ed4dc51 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11.target
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?><?pde?><!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --><target name="jgit-4.11" sequenceNumber="1557147626">
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><?pde?><!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --><target name="jgit-4.11" sequenceNumber="1557148673">
   <locations>
     <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="slicer" includeSource="true" type="InstallableUnit">
       <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>
@@ -75,10 +75,10 @@
       <unit id="com.jcraft.jzlib.source" version="1.1.1.v201205102305"/>
       <unit id="net.i2p.crypto.eddsa" version="0.3.0.v20181102-1323"/>
       <unit id="net.i2p.crypto.eddsa.source" version="0.3.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.core" version="2.0.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.core.source" version="2.0.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.sftp" version="2.0.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.sftp.source" version="2.0.0.v20181102-1323"/>
+      <unit id="org.apache.sshd.osgi" version="2.2.0.v20190425-2127"/>
+      <unit id="org.apache.sshd.osgi.source" version="2.2.0.v20190425-2127"/>
+      <unit id="org.apache.sshd.sftp" version="2.2.0.v20190425-2127"/>
+      <unit id="org.apache.sshd.sftp.source" version="2.2.0.v20190425-2127"/>
       <repository location="http://download.eclipse.org/tools/orbit/downloads/drops/S20190501151401/repository"/>
     </location>
     <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="slicer" includeSource="true" type="InstallableUnit">
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.12-staging.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.12-staging.target
index f4fb882..aa9d951 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.12-staging.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.12-staging.target
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?><?pde?><!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --><target name="jgit-4.12-staging" sequenceNumber="1557147634">
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><?pde?><!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --><target name="jgit-4.12-staging" sequenceNumber="1557148680">
   <locations>
     <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="slicer" includeSource="true" type="InstallableUnit">
       <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>
@@ -75,10 +75,10 @@
       <unit id="com.jcraft.jzlib.source" version="1.1.1.v201205102305"/>
       <unit id="net.i2p.crypto.eddsa" version="0.3.0.v20181102-1323"/>
       <unit id="net.i2p.crypto.eddsa.source" version="0.3.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.core" version="2.0.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.core.source" version="2.0.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.sftp" version="2.0.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.sftp.source" version="2.0.0.v20181102-1323"/>
+      <unit id="org.apache.sshd.osgi" version="2.2.0.v20190425-2127"/>
+      <unit id="org.apache.sshd.osgi.source" version="2.2.0.v20190425-2127"/>
+      <unit id="org.apache.sshd.sftp" version="2.2.0.v20190425-2127"/>
+      <unit id="org.apache.sshd.sftp.source" version="2.2.0.v20190425-2127"/>
       <repository location="http://download.eclipse.org/tools/orbit/downloads/drops/S20190501151401/repository"/>
     </location>
     <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="slicer" includeSource="true" type="InstallableUnit">
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.target
index 54d43fb..2a4103b 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.target
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?><?pde?><!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --><target name="jgit-4.6" sequenceNumber="1557147672">
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><?pde?><!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --><target name="jgit-4.6" sequenceNumber="1557148684">
   <locations>
     <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="slicer" includeSource="true" type="InstallableUnit">
       <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>
@@ -75,10 +75,10 @@
       <unit id="com.jcraft.jzlib.source" version="1.1.1.v201205102305"/>
       <unit id="net.i2p.crypto.eddsa" version="0.3.0.v20181102-1323"/>
       <unit id="net.i2p.crypto.eddsa.source" version="0.3.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.core" version="2.0.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.core.source" version="2.0.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.sftp" version="2.0.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.sftp.source" version="2.0.0.v20181102-1323"/>
+      <unit id="org.apache.sshd.osgi" version="2.2.0.v20190425-2127"/>
+      <unit id="org.apache.sshd.osgi.source" version="2.2.0.v20190425-2127"/>
+      <unit id="org.apache.sshd.sftp" version="2.2.0.v20190425-2127"/>
+      <unit id="org.apache.sshd.sftp.source" version="2.2.0.v20190425-2127"/>
       <repository location="http://download.eclipse.org/tools/orbit/downloads/drops/S20190501151401/repository"/>
     </location>
     <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="slicer" includeSource="true" type="InstallableUnit">
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.target
index d7c2a48..53c95ac 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.target
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?><?pde?><!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --><target name="jgit-4.7" sequenceNumber="1557147667">
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><?pde?><!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --><target name="jgit-4.7" sequenceNumber="1557148689">
   <locations>
     <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="slicer" includeSource="true" type="InstallableUnit">
       <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>
@@ -75,10 +75,10 @@
       <unit id="com.jcraft.jzlib.source" version="1.1.1.v201205102305"/>
       <unit id="net.i2p.crypto.eddsa" version="0.3.0.v20181102-1323"/>
       <unit id="net.i2p.crypto.eddsa.source" version="0.3.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.core" version="2.0.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.core.source" version="2.0.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.sftp" version="2.0.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.sftp.source" version="2.0.0.v20181102-1323"/>
+      <unit id="org.apache.sshd.osgi" version="2.2.0.v20190425-2127"/>
+      <unit id="org.apache.sshd.osgi.source" version="2.2.0.v20190425-2127"/>
+      <unit id="org.apache.sshd.sftp" version="2.2.0.v20190425-2127"/>
+      <unit id="org.apache.sshd.sftp.source" version="2.2.0.v20190425-2127"/>
       <repository location="http://download.eclipse.org/tools/orbit/downloads/drops/S20190501151401/repository"/>
     </location>
     <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="slicer" includeSource="true" type="InstallableUnit">
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.target
index 19bc0b1..4caf1d9 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.target
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?><?pde?><!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --><target name="jgit-4.8" sequenceNumber="1557147665">
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><?pde?><!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --><target name="jgit-4.8" sequenceNumber="1557148692">
   <locations>
     <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="slicer" includeSource="true" type="InstallableUnit">
       <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>
@@ -75,10 +75,10 @@
       <unit id="com.jcraft.jzlib.source" version="1.1.1.v201205102305"/>
       <unit id="net.i2p.crypto.eddsa" version="0.3.0.v20181102-1323"/>
       <unit id="net.i2p.crypto.eddsa.source" version="0.3.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.core" version="2.0.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.core.source" version="2.0.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.sftp" version="2.0.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.sftp.source" version="2.0.0.v20181102-1323"/>
+      <unit id="org.apache.sshd.osgi" version="2.2.0.v20190425-2127"/>
+      <unit id="org.apache.sshd.osgi.source" version="2.2.0.v20190425-2127"/>
+      <unit id="org.apache.sshd.sftp" version="2.2.0.v20190425-2127"/>
+      <unit id="org.apache.sshd.sftp.source" version="2.2.0.v20190425-2127"/>
       <repository location="http://download.eclipse.org/tools/orbit/downloads/drops/S20190501151401/repository"/>
     </location>
     <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="slicer" includeSource="true" type="InstallableUnit">
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.target
index 10fa0bc..8f3d593 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.target
@@ -1,9 +1,6 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<?pde?>
-<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.9" sequenceNumber="1557147670">
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><?pde?><!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --><target name="jgit-4.9" sequenceNumber="1557148695">
   <locations>
-    <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
+    <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="slicer" includeSource="true" type="InstallableUnit">
       <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>
       <unit id="org.eclipse.jetty.client.source" version="9.4.14.v20181114"/>
       <unit id="org.eclipse.jetty.continuation" version="9.4.14.v20181114"/>
@@ -22,7 +19,7 @@
       <unit id="org.eclipse.jetty.util.source" version="9.4.14.v20181114"/>
       <repository id="jetty-9.4.14" location="http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.14.v20181114"/>
     </location>
-    <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
+    <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="slicer" includeSource="true" type="InstallableUnit">
       <unit id="org.apache.ant" version="1.10.5.v20180808-0324"/>
       <unit id="org.apache.ant.source" version="1.10.5.v20180808-0324"/>
       <unit id="org.apache.commons.codec" version="1.10.0.v20180409-1845"/>
@@ -78,15 +75,15 @@
       <unit id="com.jcraft.jzlib.source" version="1.1.1.v201205102305"/>
       <unit id="net.i2p.crypto.eddsa" version="0.3.0.v20181102-1323"/>
       <unit id="net.i2p.crypto.eddsa.source" version="0.3.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.core" version="2.0.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.core.source" version="2.0.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.sftp" version="2.0.0.v20181102-1323"/>
-      <unit id="org.apache.sshd.sftp.source" version="2.0.0.v20181102-1323"/>
+      <unit id="org.apache.sshd.osgi" version="2.2.0.v20190425-2127"/>
+      <unit id="org.apache.sshd.osgi.source" version="2.2.0.v20190425-2127"/>
+      <unit id="org.apache.sshd.sftp" version="2.2.0.v20190425-2127"/>
+      <unit id="org.apache.sshd.sftp.source" version="2.2.0.v20190425-2127"/>
       <repository location="http://download.eclipse.org/tools/orbit/downloads/drops/S20190501151401/repository"/>
     </location>
-    <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
+    <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="slicer" includeSource="true" type="InstallableUnit">
       <unit id="org.eclipse.osgi" version="0.0.0"/>
       <repository location="http://download.eclipse.org/releases/2018-09/"/>
     </location>
   </locations>
-</target>
+</target>
\ No newline at end of file
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/S20190501151401.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/S20190501151401.tpd
index 437db99..6cb4d12 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/S20190501151401.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/S20190501151401.tpd
@@ -57,8 +57,8 @@
 	com.jcraft.jzlib.source [1.1.1.v201205102305,1.1.1.v201205102305]
 	net.i2p.crypto.eddsa [0.3.0.v20181102-1323,0.3.0.v20181102-1323]
 	net.i2p.crypto.eddsa.source [0.3.0.v20181102-1323,0.3.0.v20181102-1323]
-	org.apache.sshd.core [2.0.0.v20181102-1323,2.0.0.v20181102-1323]
-	org.apache.sshd.core.source [2.0.0.v20181102-1323,2.0.0.v20181102-1323]
-	org.apache.sshd.sftp [2.0.0.v20181102-1323,2.0.0.v20181102-1323]
-	org.apache.sshd.sftp.source [2.0.0.v20181102-1323,2.0.0.v20181102-1323]
+	org.apache.sshd.osgi [2.2.0.v20190425-2127,2.2.0.v20190425-2127]
+	org.apache.sshd.osgi.source [2.2.0.v20190425-2127,2.2.0.v20190425-2127]
+	org.apache.sshd.sftp [2.2.0.v20190425-2127,2.2.0.v20190425-2127]
+	org.apache.sshd.sftp.source [2.2.0.v20190425-2127,2.2.0.v20190425-2127]
 }
diff --git a/org.eclipse.jgit.ssh.apache.test/BUILD b/org.eclipse.jgit.ssh.apache.test/BUILD
index a13cf0b..18a48dc 100644
--- a/org.eclipse.jgit.ssh.apache.test/BUILD
+++ b/org.eclipse.jgit.ssh.apache.test/BUILD
@@ -10,7 +10,7 @@
     deps = [
         "//lib:eddsa",
         "//lib:junit",
-        "//lib:sshd-core",
+        "//lib:sshd-osgi",
         "//lib:sshd-sftp",
         "//org.eclipse.jgit:jgit",
         "//org.eclipse.jgit.ssh.apache:ssh-apache",
diff --git a/org.eclipse.jgit.ssh.apache/BUILD b/org.eclipse.jgit.ssh.apache/BUILD
index a1a6c8e..372cfc2 100644
--- a/org.eclipse.jgit.ssh.apache/BUILD
+++ b/org.eclipse.jgit.ssh.apache/BUILD
@@ -12,7 +12,7 @@
     deps = [
         "//lib:eddsa",
         "//lib:slf4j-api",
-        "//lib:sshd-core",
+        "//lib:sshd-osgi",
         "//lib:sshd-sftp",
         "//org.eclipse.jgit:jgit",
     ],
diff --git a/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF
index 96dbd8a..d1f7d49 100644
--- a/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF
@@ -32,46 +32,47 @@
    org.apache.sshd.client.session,
    org.apache.sshd.client.keyverifier"
 Import-Package: net.i2p.crypto.eddsa;version="[0.3.0,0.4.0)",
- org.apache.sshd.agent;version="[2.0.0,2.1.0)",
- org.apache.sshd.client;version="[2.0.0,2.1.0)",
- org.apache.sshd.client.auth;version="[2.0.0,2.1.0)",
- org.apache.sshd.client.auth.keyboard;version="[2.0.0,2.1.0)",
- org.apache.sshd.client.auth.password;version="[2.0.0,2.1.0)",
- org.apache.sshd.client.auth.pubkey;version="[2.0.0,2.1.0)",
- org.apache.sshd.client.channel;version="[2.0.0,2.1.0)",
- org.apache.sshd.client.config.hosts;version="[2.0.0,2.1.0)",
- org.apache.sshd.client.config.keys;version="[2.0.0,2.1.0)",
- org.apache.sshd.client.future;version="[2.0.0,2.1.0)",
- org.apache.sshd.client.keyverifier;version="[2.0.0,2.1.0)",
- org.apache.sshd.client.session;version="[2.0.0,2.1.0)",
- org.apache.sshd.client.subsystem.sftp;version="[2.0.0,2.1.0)",
- org.apache.sshd.common;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.auth;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.channel;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.compression;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.config.keys;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.config.keys.loader;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.digest;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.forward;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.future;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.helpers;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.io;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.kex;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.keyprovider;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.mac;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.random;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.session;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.session.helpers;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.signature;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.subsystem.sftp;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.util;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.util.buffer;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.util.closeable;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.util.io;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.util.logging;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.util.net;version="[2.0.0,2.1.0)",
- org.apache.sshd.common.util.security;version="[2.0.0,2.1.0)",
- org.apache.sshd.server.auth;version="[2.0.0,2.1.0)",
+ org.apache.sshd.agent;version="[2.2.0,2.3.0)",
+ org.apache.sshd.client;version="[2.2.0,2.3.0)",
+ org.apache.sshd.client.auth;version="[2.2.0,2.3.0)",
+ org.apache.sshd.client.auth.keyboard;version="[2.2.0,2.3.0)",
+ org.apache.sshd.client.auth.password;version="[2.2.0,2.3.0)",
+ org.apache.sshd.client.auth.pubkey;version="[2.2.0,2.3.0)",
+ org.apache.sshd.client.channel;version="[2.2.0,2.3.0)",
+ org.apache.sshd.client.config.hosts;version="[2.2.0,2.3.0)",
+ org.apache.sshd.client.config.keys;version="[2.2.0,2.3.0)",
+ org.apache.sshd.client.future;version="[2.2.0,2.3.0)",
+ org.apache.sshd.client.keyverifier;version="[2.2.0,2.3.0)",
+ org.apache.sshd.client.session;version="[2.2.0,2.3.0)",
+ org.apache.sshd.client.subsystem.sftp;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.auth;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.channel;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.compression;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.config.keys;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.config.keys.loader;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.digest;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.forward;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.future;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.helpers;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.io;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.kex;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.keyprovider;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.mac;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.random;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.session;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.session.helpers;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.signature;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.subsystem.sftp;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.util;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.util.buffer;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.util.closeable;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.util.io;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.util.io.resource;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.util.logging;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.util.net;version="[2.2.0,2.3.0)",
+ org.apache.sshd.common.util.security;version="[2.2.0,2.3.0)",
+ org.apache.sshd.server.auth;version="[2.2.0,2.3.0)",
  org.eclipse.jgit.annotations;version="[5.4.0,5.5.0)",
  org.eclipse.jgit.errors;version="[5.4.0,5.5.0)",
  org.eclipse.jgit.fnmatch;version="[5.4.0,5.5.0)",
diff --git a/org.eclipse.jgit.ssh.apache/pom.xml b/org.eclipse.jgit.ssh.apache/pom.xml
index 242957a..31bf6d7 100644
--- a/org.eclipse.jgit.ssh.apache/pom.xml
+++ b/org.eclipse.jgit.ssh.apache/pom.xml
@@ -75,7 +75,7 @@
 
     <dependency>
       <groupId>org.apache.sshd</groupId>
-      <artifactId>sshd-core</artifactId>
+      <artifactId>sshd-osgi</artifactId>
       <version>${apache-sshd-version}</version>
     </dependency>
 
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/CachingKeyPairProvider.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/CachingKeyPairProvider.java
index 1072f32..a1ec318 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/CachingKeyPairProvider.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/CachingKeyPairProvider.java
@@ -45,10 +45,13 @@
 import static java.text.MessageFormat.format;
 
 import java.io.IOException;
+import java.io.InputStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.security.GeneralSecurityException;
+import java.security.InvalidKeyException;
 import java.security.KeyPair;
+import java.security.PrivateKey;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -57,13 +60,20 @@
 import java.util.NoSuchElementException;
 import java.util.concurrent.CancellationException;
 
+import javax.security.auth.DestroyFailedException;
+
+import org.apache.sshd.common.NamedResource;
+import org.apache.sshd.common.config.keys.FilePasswordProvider;
+import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
+import org.apache.sshd.common.session.SessionContext;
+import org.apache.sshd.common.util.io.resource.IoResource;
+import org.apache.sshd.common.util.security.SecurityUtils;
 import org.eclipse.jgit.transport.sshd.KeyCache;
 
 /**
- * A {@link EncryptedFileKeyPairProvider} that uses an external
- * {@link KeyCache}.
+ * A {@link FileKeyPairProvider} that uses an external {@link KeyCache}.
  */
-public class CachingKeyPairProvider extends EncryptedFileKeyPairProvider
+public class CachingKeyPairProvider extends FileKeyPairProvider
 		implements Iterable<KeyPair> {
 
 	private final KeyCache cache;
@@ -71,7 +81,7 @@
 	/**
 	 * Creates a new {@link CachingKeyPairProvider} using the given
 	 * {@link KeyCache}. If the cache is {@code null}, this is a simple
-	 * {@link EncryptedFileKeyPairProvider}.
+	 * {@link FileKeyPairProvider}.
 	 *
 	 * @param paths
 	 *            to load keys from
@@ -85,36 +95,36 @@
 
 	@Override
 	public Iterator<KeyPair> iterator() {
+		return iterator(null);
+	}
+
+	private Iterator<KeyPair> iterator(SessionContext session) {
 		Collection<? extends Path> resources = getPaths();
 		if (resources.isEmpty()) {
 			return Collections.emptyListIterator();
 		}
-		return new CancellingKeyPairIterator(resources);
+		return new CancellingKeyPairIterator(session, resources);
 	}
 
 	@Override
-	public Iterable<KeyPair> loadKeys() {
-		return this;
+	public Iterable<KeyPair> loadKeys(SessionContext session) {
+		return () -> iterator(session);
 	}
 
-	@Override
-	protected KeyPair doLoadKey(Path resource)
+	private KeyPair loadKey(SessionContext session, Path path)
 			throws IOException, GeneralSecurityException {
-		if (!Files.exists(resource)) {
-			log.warn(format(SshdText.get().identityFileNotFound, resource));
+		if (!Files.exists(path)) {
+			log.warn(format(SshdText.get().identityFileNotFound, path));
 			return null;
 		}
-		// By calling doLoadKey(String, Path, FilePasswordProvider) instead of
-		// super.doLoadKey(Path) we can bypass the key caching in
-		// AbstractResourceKeyPairProvider, over which we have no real control.
-		String resourceId = resource.toString();
+		IoResource<Path> resource = getIoResource(session, path);
 		if (cache == null) {
-			return doLoadKey(resourceId, resource, getPasswordFinder());
+			return loadKey(session, resource, path, getPasswordFinder());
 		}
 		Throwable t[] = { null };
-		KeyPair key = cache.get(resource, p -> {
+		KeyPair key = cache.get(path, p -> {
 			try {
-				return doLoadKey(resourceId, p, getPasswordFinder());
+				return loadKey(session, resource, p, getPasswordFinder());
 			} catch (IOException | GeneralSecurityException e) {
 				t[0] = e;
 				return null;
@@ -130,18 +140,55 @@
 		return key;
 	}
 
+	private KeyPair loadKey(SessionContext session, NamedResource resource,
+			Path path, FilePasswordProvider passwordProvider)
+			throws IOException, GeneralSecurityException {
+		try (InputStream stream = Files.newInputStream(path)) {
+			Iterable<KeyPair> ids = SecurityUtils.loadKeyPairIdentities(session,
+					resource, stream, passwordProvider);
+			if (ids == null) {
+				throw new InvalidKeyException(
+						format(SshdText.get().identityFileNoKey, path));
+			}
+			Iterator<KeyPair> keys = ids.iterator();
+			if (!keys.hasNext()) {
+				throw new InvalidKeyException(format(
+						SshdText.get().identityFileUnsupportedFormat, path));
+			}
+			KeyPair result = keys.next();
+			if (keys.hasNext()) {
+				log.warn(format(SshdText.get().identityFileMultipleKeys, path));
+				keys.forEachRemaining(k -> {
+					PrivateKey pk = k.getPrivate();
+					if (pk != null) {
+						try {
+							pk.destroy();
+						} catch (DestroyFailedException e) {
+							// Ignore
+						}
+					}
+				});
+			}
+			return result;
+		}
+	}
+
 	private class CancellingKeyPairIterator implements Iterator<KeyPair> {
 
+		private final SessionContext context;
+
 		private final Iterator<Path> paths;
 
 		private KeyPair nextItem;
 
 		private boolean nextSet;
 
-		public CancellingKeyPairIterator(Collection<? extends Path> resources) {
+		public CancellingKeyPairIterator(SessionContext session,
+				Collection<? extends Path> resources) {
 			List<Path> copy = new ArrayList<>(resources.size());
 			copy.addAll(resources);
 			paths = copy.iterator();
+			context = session;
 		}
 
 		@Override
@@ -152,7 +199,7 @@
 			nextSet = true;
 			while (nextItem == null && paths.hasNext()) {
 				try {
-					nextItem = doLoadKey(paths.next());
+					nextItem = loadKey(context, paths.next());
 				} catch (CancellationException cancelled) {
 					throw cancelled;
 				} catch (Exception other) {
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/EncryptedFileKeyPairProvider.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/EncryptedFileKeyPairProvider.java
deleted file mode 100644
index ef8e611..0000000
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/EncryptedFileKeyPairProvider.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch>
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- *   copyright notice, this list of conditions and the following
- *   disclaimer in the documentation and/or other materials provided
- *   with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- *   names of its contributors may be used to endorse or promote
- *   products derived from this software without specific prior
- *   written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.eclipse.jgit.internal.transport.sshd;
-
-import static java.text.MessageFormat.format;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Path;
-import java.security.GeneralSecurityException;
-import java.security.InvalidKeyException;
-import java.security.KeyPair;
-import java.security.NoSuchProviderException;
-import java.security.PrivateKey;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-
-import javax.security.auth.DestroyFailedException;
-
-import org.apache.sshd.common.config.keys.FilePasswordProvider;
-import org.apache.sshd.common.config.keys.loader.KeyPairResourceParser;
-import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
-import org.apache.sshd.common.util.io.IoUtils;
-import org.apache.sshd.common.util.security.SecurityUtils;
-import org.eclipse.jgit.internal.transport.sshd.RepeatingFilePasswordProvider.ResourceDecodeResult;
-
-/**
- * A {@link FileKeyPairProvider} that asks repeatedly for a passphrase for an
- * encrypted private key if the {@link FilePasswordProvider} is a
- * {@link RepeatingFilePasswordProvider}.
- */
-public abstract class EncryptedFileKeyPairProvider extends FileKeyPairProvider {
-
-	// TODO: remove this class once we're based on sshd > 2.1.0. See upstream
-	// issue SSHD-850 https://issues.apache.org/jira/browse/SSHD-850 and commit
-	// https://github.com/apache/mina-sshd/commit/f19bd2e34
-
-	/**
-	 * Creates a new {@link EncryptedFileKeyPairProvider} for the given
-	 * {@link Path}s.
-	 *
-	 * @param paths
-	 *            to read keys from
-	 */
-	public EncryptedFileKeyPairProvider(List<Path> paths) {
-		super(paths);
-	}
-
-	@Override
-	protected KeyPair doLoadKey(String resourceKey, InputStream inputStream,
-			FilePasswordProvider provider)
-			throws IOException, GeneralSecurityException {
-		if (!(provider instanceof RepeatingFilePasswordProvider)) {
-			return super.doLoadKey(resourceKey, inputStream, provider);
-		}
-		KeyPairResourceParser parser = SecurityUtils.getKeyPairResourceParser();
-		if (parser == null) {
-			// This is an internal configuration error, thus no translation.
-			throw new NoSuchProviderException(
-					"No registered key-pair resource parser"); //$NON-NLS-1$
-		}
-		RepeatingFilePasswordProvider realProvider = (RepeatingFilePasswordProvider) provider;
-		// Read the stream now so that we can process the content several
-		// times.
-		List<String> lines = IoUtils.readAllLines(inputStream);
-		Collection<KeyPair> ids = null;
-		while (ids == null) {
-			try {
-				ids = parser.loadKeyPairs(resourceKey, realProvider, lines);
-				realProvider.handleDecodeAttemptResult(resourceKey, "", null); //$NON-NLS-1$
-				// No exception; success. Exit the loop even if ids is still
-				// null!
-				break;
-			} catch (IOException | GeneralSecurityException
-					| RuntimeException e) {
-				ResourceDecodeResult loadResult = realProvider
-						.handleDecodeAttemptResult(resourceKey, "", e); //$NON-NLS-1$
-				if (loadResult == null
-						|| loadResult == ResourceDecodeResult.TERMINATE) {
-					throw e;
-				} else if (loadResult == ResourceDecodeResult.RETRY) {
-					continue;
-				}
-				// IGNORE doesn't make any sense here, but OK, let's ignore it.
-				// ids == null, so we'll throw an exception below.
-				break;
-			}
-		}
-		if (ids == null) {
-			// The javadoc on loadKeyPairs says it might return null if no
-			// key pair found. Bad API.
-			throw new InvalidKeyException(
-					format(SshdText.get().identityFileNoKey, resourceKey));
-		}
-		Iterator<KeyPair> keys = ids.iterator();
-		if (!keys.hasNext()) {
-			throw new InvalidKeyException(format(
-					SshdText.get().identityFileUnsupportedFormat, resourceKey));
-		}
-		KeyPair result = keys.next();
-		if (keys.hasNext()) {
-			log.warn(format(SshdText.get().identityFileMultipleKeys,
-					resourceKey));
-			keys.forEachRemaining(k -> {
-				PrivateKey pk = k.getPrivate();
-				if (pk != null) {
-					try {
-						pk.destroy();
-					} catch (DestroyFailedException e) {
-						// Ignore
-					}
-				}
-			});
-		}
-		return result;
-	}
-}
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitClientSession.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitClientSession.java
index dcf330a..56f8ade 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitClientSession.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitClientSession.java
@@ -46,6 +46,7 @@
 
 import java.io.IOException;
 import java.net.SocketAddress;
+import java.security.GeneralSecurityException;
 import java.security.PublicKey;
 import java.util.ArrayList;
 import java.util.Iterator;
@@ -173,7 +174,8 @@
 	}
 
 	@Override
-	protected byte[] sendKexInit() throws IOException {
+	protected byte[] sendKexInit()
+			throws IOException, GeneralSecurityException {
 		StatefulProxyConnector proxy = proxyHandler;
 		if (proxy != null) {
 			try {
@@ -187,7 +189,7 @@
 				// This is called only from the ClientSessionImpl
 				// constructor, where the return value is ignored.
 				return null;
-			} catch (IOException e) {
+			} catch (IOException | GeneralSecurityException e) {
 				throw e;
 			} catch (Exception other) {
 				throw new IOException(other.getLocalizedMessage(), other);
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitHostConfigEntry.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitHostConfigEntry.java
index 7b22b88..21e8bea 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitHostConfigEntry.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitHostConfigEntry.java
@@ -53,28 +53,11 @@
  * A {@link HostConfigEntry} that provides access to the multi-valued keys as
  * lists of strings. The super class treats them as single strings containing
  * comma-separated lists.
- *
  */
 public class JGitHostConfigEntry extends HostConfigEntry {
 
 	private Map<String, List<String>> multiValuedOptions;
 
-	@Override
-	public String getProperty(String name, String defaultValue) {
-		// Upstream bug fix (SSHD-867): if there are _no_ properties at all, the
-		// super implementation returns always null even if a default value is
-		// given.
-		//
-		// See https://issues.apache.org/jira/projects/SSHD/issues/SSHD-867
-		//
-		// TODO: remove this override once we're based on sshd > 2.1.0
-		Map<String, String> properties = getProperties();
-		if (properties == null || properties.isEmpty()) {
-			return defaultValue;
-		}
-		return super.getProperty(name, defaultValue);
-	}
-
 	/**
 	 * Sets the multi-valued options.
 	 *
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthFactory.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthFactory.java
deleted file mode 100644
index 0b3de4a..0000000
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthFactory.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch>
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- *   copyright notice, this list of conditions and the following
- *   disclaimer in the documentation and/or other materials provided
- *   with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- *   names of its contributors may be used to endorse or promote
- *   products derived from this software without specific prior
- *   written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.eclipse.jgit.internal.transport.sshd;
-
-import java.util.List;
-
-import org.apache.sshd.client.auth.AbstractUserAuthFactory;
-import org.apache.sshd.client.auth.UserAuth;
-import org.apache.sshd.client.auth.pubkey.UserAuthPublicKeyFactory;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.signature.Signature;
-import org.apache.sshd.common.signature.SignatureFactoriesManager;
-
-/**
- * A customized authentication factory for public key user authentication. The
- * default implementation {@link UserAuthPublicKeyFactory} ends up doing some
- * crazy stream "magic" that loads too many keys too early.
- */
-public class JGitPublicKeyAuthFactory extends AbstractUserAuthFactory
-		implements SignatureFactoriesManager {
-
-	/** The singleton {@link JGitPublicKeyAuthFactory}. */
-	public static final JGitPublicKeyAuthFactory INSTANCE = new JGitPublicKeyAuthFactory();
-
-	private JGitPublicKeyAuthFactory() {
-		super(UserAuthPublicKeyFactory.NAME);
-	}
-
-	@Override
-	public UserAuth create() {
-		return new JGitPublicKeyAuthentication(getSignatureFactories());
-	}
-
-	@Override
-	public List<NamedFactory<Signature>> getSignatureFactories() {
-		return null;
-	}
-
-	@Override
-	public void setSignatureFactories(List<NamedFactory<Signature>> factories) {
-		throw new UnsupportedOperationException();
-	}
-}
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthentication.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthentication.java
deleted file mode 100644
index 63b3990..0000000
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthentication.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch>
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- *   copyright notice, this list of conditions and the following
- *   disclaimer in the documentation and/or other materials provided
- *   with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- *   names of its contributors may be used to endorse or promote
- *   products derived from this software without specific prior
- *   written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.eclipse.jgit.internal.transport.sshd;
-
-import java.util.List;
-
-import org.apache.sshd.client.auth.pubkey.UserAuthPublicKey;
-import org.apache.sshd.client.session.ClientSession;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.signature.Signature;
-
-/**
- * A specialized public key authentication handler that uses our own
- * {@link JGitPublicKeyIterator}. The super class creates in
- * {@link #init(ClientSession, String)} a
- * {@link org.apache.sshd.client.auth.pubkey.UserAuthPublicKeyIterator}, which
- * in its constructor does some strange {@link java.util.stream.Stream} "magic"
- * that ends up loading keys prematurely.
- */
-public class JGitPublicKeyAuthentication extends UserAuthPublicKey {
-
-	private ClientSession clientSession;
-
-	private String serviceName;
-
-	/**
-	 * Creates a new {@link JGitPublicKeyAuthentication}.
-	 *
-	 * @param factories
-	 *            signature factories to use
-	 */
-	public JGitPublicKeyAuthentication(
-			List<NamedFactory<Signature>> factories) {
-		super(factories);
-	}
-
-	@Override
-	public void init(ClientSession session, String service) throws Exception {
-		// Do *not* call super.init(); it'll create a UserAuthPublicKeyIterator
-		// and that's where things then go wrong. Instead, do the whole
-		// initialization directly here.
-		clientSession = session;
-		serviceName = service;
-		releaseKeys();
-		// Use our own iterator!
-		keys = new JGitPublicKeyIterator(session, this);
-	}
-
-	@Override
-	public ClientSession getClientSession() {
-		return clientSession;
-	}
-
-	@Override
-	public ClientSession getSession() {
-		return clientSession;
-	}
-
-	@Override
-	public String getService() {
-		return serviceName;
-	}
-}
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyIterator.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyIterator.java
deleted file mode 100644
index cda1262..0000000
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyIterator.java
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch>
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- *   copyright notice, this list of conditions and the following
- *   disclaimer in the documentation and/or other materials provided
- *   with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- *   names of its contributors may be used to endorse or promote
- *   products derived from this software without specific prior
- *   written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.eclipse.jgit.internal.transport.sshd;
-
-import java.io.IOException;
-import java.nio.channels.Channel;
-import java.security.KeyPair;
-import java.security.PublicKey;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.apache.sshd.agent.SshAgent;
-import org.apache.sshd.agent.SshAgentFactory;
-import org.apache.sshd.client.auth.pubkey.AbstractKeyPairIterator;
-import org.apache.sshd.client.auth.pubkey.KeyAgentIdentity;
-import org.apache.sshd.client.auth.pubkey.KeyPairIdentity;
-import org.apache.sshd.client.auth.pubkey.PublicKeyIdentity;
-import org.apache.sshd.client.config.hosts.HostConfigEntry;
-import org.apache.sshd.client.session.ClientSession;
-import org.apache.sshd.common.FactoryManager;
-import org.apache.sshd.common.keyprovider.KeyIdentityProvider;
-import org.apache.sshd.common.signature.SignatureFactoriesManager;
-
-/**
- * A new iterator over key pairs that we use instead of the default
- * {@link org.apache.sshd.client.auth.pubkey.UserAuthPublicKeyIterator}, which
- * in its constructor does some strange {@link java.util.stream.Stream} "magic"
- * that ends up loading keys prematurely. This class uses plain
- * {@link Iterator}s instead to avoid that problem. Used in
- * {@link JGitPublicKeyAuthentication}.
- *
- * @see <a href=
- *      "https://issues.apache.org/jira/projects/SSHD/issues/SSHD-860">Upstream
- *      issue SSHD-860</a>
- */
-public class JGitPublicKeyIterator
-		extends AbstractKeyPairIterator<PublicKeyIdentity> implements Channel {
-
-	// Re: the cause for the problem mentioned above has not been determined.
-	// It looks as if either the Apache code inadvertently calls
-	// GenericUtils.isEmpty() on all streams (which would load the first key
-	// of each stream), or the Java stream implementation does some prefetching.
-	// It's not entirely clear. Using Iterators we have more control over
-	// what happens when.
-
-	private final AtomicBoolean open = new AtomicBoolean(true);
-
-	private SshAgent agent;
-
-	private final List<Iterator<PublicKeyIdentity>> keys = new ArrayList<>(3);
-
-	private final Iterator<Iterator<PublicKeyIdentity>> keyIter;
-
-	private Iterator<PublicKeyIdentity> current;
-
-	private Boolean hasElement;
-
-	/**
-	 * Creates a new {@link JGitPublicKeyIterator}.
-	 *
-	 * @param session
-	 *            we're trying to authenticate
-	 * @param signatureFactories
-	 *            to use
-	 * @throws Exception
-	 *             if an {@link SshAgentFactory} is configured and getting
-	 *             identities from the agent fails
-	 */
-	public JGitPublicKeyIterator(ClientSession session,
-			SignatureFactoriesManager signatureFactories) throws Exception {
-		super(session);
-		boolean useAgent = true;
-		if (session instanceof JGitClientSession) {
-			HostConfigEntry config = ((JGitClientSession) session)
-					.getHostConfigEntry();
-			useAgent = !config.isIdentitiesOnly();
-		}
-		if (useAgent) {
-			FactoryManager manager = session.getFactoryManager();
-			SshAgentFactory factory = manager == null ? null
-					: manager.getAgentFactory();
-			if (factory != null) {
-				try {
-					agent = factory.createClient(manager);
-					keys.add(new AgentIdentityIterator(agent));
-				} catch (IOException e) {
-					try {
-						closeAgent();
-					} catch (IOException err) {
-						e.addSuppressed(err);
-					}
-					throw e;
-				}
-			}
-		}
-		keys.add(
-				new KeyPairIdentityIterator(session.getRegisteredIdentities(),
-						session, signatureFactories));
-		keys.add(new KeyPairIdentityIterator(session.getKeyPairProvider(),
-				session, signatureFactories));
-		keyIter = keys.iterator();
-	}
-
-	@Override
-	public boolean isOpen() {
-		return open.get();
-	}
-
-	@Override
-	public void close() throws IOException {
-		if (open.getAndSet(false)) {
-			closeAgent();
-		}
-	}
-
-	@Override
-	public boolean hasNext() {
-		if (!isOpen()) {
-			return false;
-		}
-		if (hasElement != null) {
-			return hasElement.booleanValue();
-		}
-		while (current == null || !current.hasNext()) {
-			if (keyIter.hasNext()) {
-				current = keyIter.next();
-			} else {
-				current = null;
-				hasElement = Boolean.FALSE;
-				return false;
-			}
-		}
-		hasElement = Boolean.TRUE;
-		return true;
-	}
-
-	@Override
-	public PublicKeyIdentity next() {
-		if (!isOpen() || hasElement == null && !hasNext()
-				|| !hasElement.booleanValue()) {
-			throw new NoSuchElementException();
-		}
-		hasElement = null;
-		PublicKeyIdentity result;
-		try {
-			result = current.next();
-		} catch (NoSuchElementException e) {
-			result = null;
-		}
-		return result;
-	}
-
-	private void closeAgent() throws IOException {
-		if (agent == null) {
-			return;
-		}
-		try {
-			agent.close();
-		} finally {
-			agent = null;
-		}
-	}
-
-	/**
-	 * An {@link Iterator} that maps the data obtained from an agent to
-	 * {@link PublicKeyIdentity}.
-	 */
-	private static class AgentIdentityIterator
-			implements Iterator<PublicKeyIdentity> {
-
-		private final SshAgent agent;
-
-		private final Iterator<? extends Map.Entry<PublicKey, String>> iter;
-
-		public AgentIdentityIterator(SshAgent agent) throws IOException {
-			this.agent = agent;
-			iter = agent == null ? null : agent.getIdentities().iterator();
-		}
-
-		@Override
-		public boolean hasNext() {
-			return iter != null && iter.hasNext();
-		}
-
-		@Override
-		public PublicKeyIdentity next() {
-			if (iter == null) {
-				throw new NoSuchElementException();
-			}
-			Map.Entry<PublicKey, String> entry = iter.next();
-			return new KeyAgentIdentity(agent, entry.getKey(),
-					entry.getValue());
-		}
-	}
-
-	/**
-	 * An {@link Iterator} that maps {@link KeyPair} to
-	 * {@link PublicKeyIdentity}.
-	 */
-	private static class KeyPairIdentityIterator
-			implements Iterator<PublicKeyIdentity> {
-
-		private final Iterator<KeyPair> keyPairs;
-
-		private final ClientSession session;
-
-		private final SignatureFactoriesManager signatureFactories;
-
-		public KeyPairIdentityIterator(KeyIdentityProvider provider,
-				ClientSession session,
-				SignatureFactoriesManager signatureFactories) {
-			this.session = session;
-			this.signatureFactories = signatureFactories;
-			keyPairs = provider == null ? null : provider.loadKeys().iterator();
-		}
-
-		@Override
-		public boolean hasNext() {
-			return keyPairs != null && keyPairs.hasNext();
-		}
-
-		@Override
-		public PublicKeyIdentity next() {
-			if (keyPairs == null) {
-				throw new NoSuchElementException();
-			}
-			KeyPair key = keyPairs.next();
-			return new KeyPairIdentity(signatureFactories, session, key);
-		}
-	}
-}
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshClient.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshClient.java
index b9ff5e5..98e71df 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshClient.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshClient.java
@@ -48,10 +48,12 @@
 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.net.Proxy;
+import java.net.SocketAddress;
 import java.nio.file.Files;
 import java.nio.file.InvalidPathException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.security.GeneralSecurityException;
 import java.security.KeyPair;
 import java.util.Arrays;
 import java.util.Iterator;
@@ -66,12 +68,14 @@
 import org.apache.sshd.client.future.DefaultConnectFuture;
 import org.apache.sshd.client.session.ClientSessionImpl;
 import org.apache.sshd.client.session.SessionFactory;
+import org.apache.sshd.common.AttributeRepository;
 import org.apache.sshd.common.config.keys.FilePasswordProvider;
 import org.apache.sshd.common.future.SshFutureListener;
 import org.apache.sshd.common.io.IoConnectFuture;
 import org.apache.sshd.common.io.IoSession;
 import org.apache.sshd.common.keyprovider.AbstractResourceKeyPairProvider;
-import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.apache.sshd.common.keyprovider.KeyIdentityProvider;
+import org.apache.sshd.common.session.SessionContext;
 import org.apache.sshd.common.session.helpers.AbstractSession;
 import org.apache.sshd.common.util.ValidateUtils;
 import org.eclipse.jgit.internal.transport.sshd.proxy.HttpClientConnector;
@@ -117,7 +121,8 @@
 	}
 
 	@Override
-	public ConnectFuture connect(HostConfigEntry hostConfig)
+	public ConnectFuture connect(HostConfigEntry hostConfig,
+			AttributeRepository context, SocketAddress localAddress)
 			throws IOException {
 		if (connector == null) {
 			throw new IllegalStateException("SshClient not started."); //$NON-NLS-1$
@@ -149,7 +154,7 @@
 			address = configureProxy(proxy, address);
 			proxy.clearPassword();
 		}
-		connector.connect(address).addListener(listener);
+		connector.connect(address, this, localAddress).addListener(listener);
 		return connectFuture;
 	}
 
@@ -263,16 +268,16 @@
 				identities, keyCache);
 		ourConfiguredKeysProvider.setPasswordFinder(passwordProvider);
 		if (hostConfig.isIdentitiesOnly()) {
-			session.setKeyPairProvider(ourConfiguredKeysProvider);
+			session.setKeyIdentityProvider(ourConfiguredKeysProvider);
 		} else {
-			KeyPairProvider defaultKeysProvider = getKeyPairProvider();
+			KeyIdentityProvider defaultKeysProvider = getKeyIdentityProvider();
 			if (defaultKeysProvider instanceof AbstractResourceKeyPairProvider<?>) {
 				((AbstractResourceKeyPairProvider<?>) defaultKeysProvider)
 						.setPasswordFinder(passwordProvider);
 			}
-			KeyPairProvider combinedProvider = new CombinedKeyPairProvider(
+			KeyIdentityProvider combinedProvider = new CombinedKeyIdentityProvider(
 					ourConfiguredKeysProvider, defaultKeysProvider);
-			session.setKeyPairProvider(combinedProvider);
+			session.setKeyIdentityProvider(combinedProvider);
 		}
 		return session;
 	}
@@ -363,39 +368,30 @@
 	}
 
 	/**
-	 * A {@link KeyPairProvider} that iterates over the {@link Iterable}s
-	 * returned by other {@link KeyPairProvider}s.
+	 * A {@link KeyIdentityProvider} that iterates over the {@link Iterable}s
+	 * returned by other {@link KeyIdentityProvider}s.
 	 */
-	private static class CombinedKeyPairProvider implements KeyPairProvider {
+	private static class CombinedKeyIdentityProvider
+			implements KeyIdentityProvider {
 
-		private final List<KeyPairProvider> providers;
+		private final List<KeyIdentityProvider> providers;
 
-		public CombinedKeyPairProvider(KeyPairProvider... providers) {
+		public CombinedKeyIdentityProvider(KeyIdentityProvider... providers) {
 			this(Arrays.stream(providers).filter(Objects::nonNull)
 					.collect(Collectors.toList()));
 		}
 
-		public CombinedKeyPairProvider(List<KeyPairProvider> providers) {
+		public CombinedKeyIdentityProvider(
+				List<KeyIdentityProvider> providers) {
 			this.providers = providers;
 		}
 
 		@Override
-		public Iterable<String> getKeyTypes() {
-			throw new UnsupportedOperationException(
-					"Should not have been called in a ssh client"); //$NON-NLS-1$
-		}
-
-		@Override
-		public KeyPair loadKey(String type) {
-			throw new UnsupportedOperationException(
-					"Should not have been called in a ssh client"); //$NON-NLS-1$
-		}
-
-		@Override
-		public Iterable<KeyPair> loadKeys() {
+		public Iterable<KeyPair> loadKeys(SessionContext context) {
 			return () -> new Iterator<KeyPair>() {
 
-				private Iterator<KeyPairProvider> factories = providers.iterator();
+				private Iterator<KeyIdentityProvider> factories = providers
+						.iterator();
 				private Iterator<KeyPair> current;
 
 				private Boolean hasElement;
@@ -407,7 +403,12 @@
 					}
 					while (current == null || !current.hasNext()) {
 						if (factories.hasNext()) {
-							current = factories.next().loadKeys().iterator();
+							try {
+								current = factories.next().loadKeys(context)
+										.iterator();
+							} catch (IOException | GeneralSecurityException e) {
+								throw new RuntimeException(e);
+							}
 						} else {
 							current = null;
 							hasElement = Boolean.FALSE;
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshConfig.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshConfig.java
index 9846439..6468b3e 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshConfig.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshConfig.java
@@ -47,11 +47,13 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.net.SocketAddress;
 import java.util.Map;
 import java.util.TreeMap;
 
 import org.apache.sshd.client.config.hosts.HostConfigEntry;
 import org.apache.sshd.client.config.hosts.HostConfigEntryResolver;
+import org.apache.sshd.common.AttributeRepository;
 import org.apache.sshd.common.util.net.SshdSocketAddress;
 import org.eclipse.jgit.annotations.NonNull;
 import org.eclipse.jgit.internal.transport.ssh.OpenSshConfigFile;
@@ -101,7 +103,8 @@
 
 	@Override
 	public HostConfigEntry resolveEffectiveHost(String host, int port,
-			String username) throws IOException {
+			SocketAddress localAddress, String username,
+			AttributeRepository attributes) throws IOException {
 		HostEntry entry = configFile.lookup(host, port, username);
 		JGitHostConfigEntry config = new JGitHostConfigEntry();
 		// Apache MINA conflates all keys, even multi-valued ones, in one map
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyVerifier.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyVerifier.java
index 4246fbe..381f7cf 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyVerifier.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyVerifier.java
@@ -672,7 +672,7 @@
 						continue;
 					}
 					try {
-						PublicKey serverKey = keyPart.resolvePublicKey(
+						PublicKey serverKey = keyPart.resolvePublicKey(null,
 								PublicKeyEntryResolver.IGNORING);
 						if (serverKey == null) {
 							LOG.warn(format(
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/PasswordProviderWrapper.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/PasswordProviderWrapper.java
index 93bd102..bec65f1 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/PasswordProviderWrapper.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/PasswordProviderWrapper.java
@@ -50,6 +50,8 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import org.apache.sshd.common.NamedResource;
+import org.apache.sshd.common.session.SessionContext;
 import org.eclipse.jgit.annotations.NonNull;
 import org.eclipse.jgit.transport.CredentialsProvider;
 import org.eclipse.jgit.transport.URIish;
@@ -83,10 +85,12 @@
 	}
 
 	@Override
-	public String getPassword(String resourceKey) throws IOException {
+	public String getPassword(SessionContext session, NamedResource resource,
+			int attemptIndex) throws IOException {
+		String key = resource.getName();
 		int attempt = counts
-				.computeIfAbsent(resourceKey, k -> new AtomicInteger()).get();
-		char[] passphrase = delegate.getPassphrase(toUri(resourceKey), attempt);
+				.computeIfAbsent(key, k -> new AtomicInteger()).get();
+		char[] passphrase = delegate.getPassphrase(toUri(key), attempt);
 		if (passphrase == null) {
 			return null;
 		}
@@ -98,21 +102,23 @@
 	}
 
 	@Override
-	public ResourceDecodeResult handleDecodeAttemptResult(String resourceKey,
+	public ResourceDecodeResult handleDecodeAttemptResult(
+			SessionContext session, NamedResource resource, int retryIndex,
 			String password, Exception err)
 			throws IOException, GeneralSecurityException {
-		AtomicInteger count = counts.get(resourceKey);
+		String key = resource.getName();
+		AtomicInteger count = counts.get(key);
 		int numberOfAttempts = count == null ? 0 : count.incrementAndGet();
 		ResourceDecodeResult result = null;
 		try {
-			if (delegate.keyLoaded(toUri(resourceKey), numberOfAttempts, err)) {
+			if (delegate.keyLoaded(toUri(key), numberOfAttempts, err)) {
 				result = ResourceDecodeResult.RETRY;
 			} else {
 				result = ResourceDecodeResult.TERMINATE;
 			}
 		} finally {
 			if (result != ResourceDecodeResult.RETRY) {
-				counts.remove(resourceKey);
+				counts.remove(key);
 			}
 		}
 		return result;
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/RepeatingFilePasswordProvider.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/RepeatingFilePasswordProvider.java
index e491cae..977f1a2 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/RepeatingFilePasswordProvider.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/RepeatingFilePasswordProvider.java
@@ -42,9 +42,6 @@
  */
 package org.eclipse.jgit.internal.transport.sshd;
 
-import java.io.IOException;
-import java.security.GeneralSecurityException;
-
 import org.apache.sshd.common.config.keys.FilePasswordProvider;
 
 /**
@@ -74,42 +71,4 @@
 		return 1;
 	}
 
-	// The following part of this interface is from the upstream resolution of
-	// SSHD-850. See https://github.com/apache/mina-sshd/commit/f19bd2e34 .
-	// TODO: remove this once we move to sshd > 2.1.0
-
-	/**
-	 * Result value of
-	 * {@link RepeatingFilePasswordProvider#handleDecodeAttemptResult(String, String, Exception)}.
-	 */
-	public enum ResourceDecodeResult {
-		/** Re-throw the decoding exception. */
-		TERMINATE,
-		/** Retry the decoding process - including password prompt. */
-		RETRY,
-		/** Skip attempt and see if we can proceed without the key. */
-		IGNORE;
-	}
-
-	/**
-	 * Invoked to inform the password provider about the decoding result.
-	 * <b>Note:</b> any exception thrown from this method (including if called
-	 * to inform about success) will be propagated instead of the original (if
-	 * any was reported)
-	 *
-	 * @param resourceKey
-	 *            The resource key representing the <U>private</U> file
-	 * @param password
-	 *            The password that was attempted
-	 * @param err
-	 *            The attempt result - {@code null} for success
-	 * @return How to proceed in case of error - <u>ignored</u> if invoked in
-	 *         order to report success. <b>Note:</b> {@code null} is same as
-	 *         {@link ResourceDecodeResult#TERMINATE}.
-	 * @throws IOException
-	 * @throws GeneralSecurityException
-	 */
-	ResourceDecodeResult handleDecodeAttemptResult(String resourceKey,
-			String password, Exception err)
-			throws IOException, GeneralSecurityException;
 }
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSessionFactory.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSessionFactory.java
index cdd47bf..2f9691e 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSessionFactory.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSessionFactory.java
@@ -64,18 +64,18 @@
 import org.apache.sshd.client.SshClient;
 import org.apache.sshd.client.auth.UserAuth;
 import org.apache.sshd.client.auth.keyboard.UserAuthKeyboardInteractiveFactory;
+import org.apache.sshd.client.auth.pubkey.UserAuthPublicKeyFactory;
 import org.apache.sshd.client.config.hosts.HostConfigEntryResolver;
 import org.apache.sshd.client.keyverifier.ServerKeyVerifier;
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.compression.BuiltinCompressions;
 import org.apache.sshd.common.config.keys.FilePasswordProvider;
-import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.apache.sshd.common.keyprovider.KeyIdentityProvider;
 import org.eclipse.jgit.annotations.NonNull;
 import org.eclipse.jgit.errors.TransportException;
 import org.eclipse.jgit.internal.transport.sshd.CachingKeyPairProvider;
 import org.eclipse.jgit.internal.transport.sshd.GssApiWithMicAuthFactory;
 import org.eclipse.jgit.internal.transport.sshd.JGitPasswordAuthFactory;
-import org.eclipse.jgit.internal.transport.sshd.JGitPublicKeyAuthFactory;
 import org.eclipse.jgit.internal.transport.sshd.JGitSshClient;
 import org.eclipse.jgit.internal.transport.sshd.JGitSshConfig;
 import org.eclipse.jgit.internal.transport.sshd.JGitUserInteraction;
@@ -211,7 +211,7 @@
 				}
 				HostConfigEntryResolver configFile = getHostConfigEntryResolver(
 						home, sshDir);
-				KeyPairProvider defaultKeysProvider = toKeyPairProvider(
+				KeyIdentityProvider defaultKeysProvider = toKeyIdentityProvider(
 						getDefaultKeys(sshDir));
 				KeyPasswordProvider passphrases = createKeyPasswordProvider(
 						credentialsProvider);
@@ -227,7 +227,7 @@
 				client.setUserInteraction(
 						new JGitUserInteraction(credentialsProvider));
 				client.setUserAuthFactories(getUserAuthFactories());
-				client.setKeyPairProvider(defaultKeysProvider);
+				client.setKeyIdentityProvider(defaultKeysProvider);
 				// JGit-specific things:
 				JGitSshClient jgitClient = (JGitSshClient) client;
 				jgitClient.setKeyCache(getKeyCache());
@@ -438,17 +438,18 @@
 
 	/**
 	 * Converts an {@link Iterable} of {link KeyPair}s into a
-	 * {@link KeyPairProvider}.
+	 * {@link KeyIdentityProvider}.
 	 *
 	 * @param keys
-	 *            to provide via the returned {@link KeyPairProvider}
-	 * @return a {@link KeyPairProvider} that provides the given {@code keys}
+	 *            to provide via the returned {@link KeyIdentityProvider}
+	 * @return a {@link KeyIdentityProvider} that provides the given
+	 *         {@code keys}
 	 */
-	private KeyPairProvider toKeyPairProvider(Iterable<KeyPair> keys) {
-		if (keys instanceof KeyPairProvider) {
-			return (KeyPairProvider) keys;
+	private KeyIdentityProvider toKeyIdentityProvider(Iterable<KeyPair> keys) {
+		if (keys instanceof KeyIdentityProvider) {
+			return (KeyIdentityProvider) keys;
 		}
-		return () -> keys;
+		return (session) -> keys;
 	}
 
 	/**
@@ -522,7 +523,7 @@
 		// Password auth doesn't have this problem.
 		return Collections.unmodifiableList(
 				Arrays.asList(GssApiWithMicAuthFactory.INSTANCE,
-						JGitPublicKeyAuthFactory.INSTANCE,
+						UserAuthPublicKeyFactory.INSTANCE,
 						JGitPasswordAuthFactory.INSTANCE,
 						UserAuthKeyboardInteractiveFactory.INSTANCE));
 	}
diff --git a/org.eclipse.jgit.test/BUILD b/org.eclipse.jgit.test/BUILD
index 95fb79b..b9fb89c 100644
--- a/org.eclipse.jgit.test/BUILD
+++ b/org.eclipse.jgit.test/BUILD
@@ -68,7 +68,7 @@
     deps = [
         "//lib:jsch",
         "//lib:junit",
-        "//lib:sshd-core",
+        "//lib:sshd-osgi",
         "//lib:sshd-sftp",
         "//org.eclipse.jgit:jgit",
         "//org.eclipse.jgit.junit:junit",
diff --git a/org.eclipse.jgit.test/tests.bzl b/org.eclipse.jgit.test/tests.bzl
index dc21029..6b5c7a1 100644
--- a/org.eclipse.jgit.test/tests.bzl
+++ b/org.eclipse.jgit.test/tests.bzl
@@ -45,7 +45,7 @@
             additional_deps = [
                 "//lib:jsch",
                 "//lib:jzlib",
-                "//lib:sshd-core",
+                "//lib:sshd-osgi",
                 "//lib:sshd-sftp",
                 ":sshd-helpers",
             ]
diff --git a/pom.xml b/pom.xml
index 314ab5e..5377b9e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -183,7 +183,7 @@
     <bundle-manifest>${project.build.directory}/META-INF/MANIFEST.MF</bundle-manifest>
 
     <jgit-last-release-version>5.3.0.201903130848-r</jgit-last-release-version>
-    <apache-sshd-version>2.0.0</apache-sshd-version>
+    <apache-sshd-version>2.2.0</apache-sshd-version>
     <jsch-version>0.1.55</jsch-version>
     <jzlib-version>1.1.1</jzlib-version>
     <javaewah-version>1.1.6</javaewah-version>