Android SSHJ connection exception () - "KeyFactory ECDSA implementation not found"

I am trying to open an SSH client session from my Android application. Trying to connect to a device on a local network (Raspberry Pi). I am using SSHJ library version 0.10.0. It does not work when calling ssh.connect() with TransportException , which is ultimately NoSuchAlgorithmException by NoSuchAlgorithmException . See Exception Tree below.

 SSHClient ssh = new SSHClient(new AndroidConfig()); Session session = null; try { //ssh.loadKnownHosts(); // Exception thrown on this line ssh.connect("192.168.1.109", 22); // Doesn't reach below ssh.authPassword("user", "password"); session = ssh.startSession(); } catch (net.schmizz.sshj.transport.TransportException ex) { ; } 

Exception Tree:

 net.schmizz.sshj.transport.TransportException net.schmizz.sshj.common.SSHException net.schmizz.sshj.common.SSHRuntimeException java.security.GeneralSecurityException: java.security.NoSuchAlgorithmException: KeyFactory ECDSA implementation not found java.security.NoSuchAlgorithmException: KeyFactory ECDSA implementation not found 

Other system information:

 SSHJ library : v0.10.0 Android device : Galaxy Note 3 running Android 4.4.2 

I used maven dependency support in Android Studio to enable the SSHJ JAR, and it pulled into the following three libraries in addition to the SSHJ v0.10.0 jar ...

 bouncy castle... bcpkix-jdk15on-1.50.jar bcprov-jdk15on-1.50.jar logging.... slf4j-api-1.7.7.jar 

I don't know where to start this exception ... any suggestions are appreciated! Thanks.

UPDATE: 31-Oct-2014

As suggested by LeeDavidPainter , I included the SpongyCastle 1.51.0 JAR and added this line at the top:

 Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1); 

Now I get another exception on one line:

 net.schmizz.sshj.transport.TransportException net.schmizz.sshj.common.SSHException net.schmizz.sshj.common.SSHRuntimeException java.security.GeneralSecurityException: java.security.spec.InvalidKeySpecException: key spec not recognised java.security.spec.InvalidKeySpecException: key spec not recognised 

Also note that I tried the following line, with the same result:

 Security.addProvider(new org.spongycastle.jce.provider.BouncyCastleProvider()); 

I have another application on my phone that basically does exactly what I want to achieve - its called RaspberryPiController - it connects to your RPi via SSH with username and password auth. This works great, so it seems like this is not a network issue.

+6
source share
5 answers

I could not find a niche with this problem in SSHJ, so I decided to give JSch an attempt that offers the same functionality. Its available as a maven repository - I used jsch version 0.1.51 ('com.jcraft: jsch: 0.1.51').

He worked for the first time with this piece of code;

 import com.jcraft.jsch.ChannelExec; import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSchException; import java.io.ByteArrayOutputStream; import java.util.Properties; JSch jsch = new JSch(); com.jcraft.jsch.Session session = null; String result = ""; try { session = jsch.getSession("user", "192.168.1.109", 22); session.setPassword("password"); // Avoid asking for key confirmation Properties prop = new Properties(); prop.put("StrictHostKeyChecking", "no"); session.setConfig(prop); session.connect(); // SSH Channel ChannelExec channel = (ChannelExec)session.openChannel("exec"); ByteArrayOutputStream stream = new ByteArrayOutputStream(); channel.setOutputStream(stream); // Execute command channel.setCommand("ls -ltr"); channel.connect(1000); java.lang.Thread.sleep(500); // this kludge seemed to be required. channel.disconnect(); result = stream.toString(); } catch (JSchException ex) { String s = ex.toString(); System.out.println(s); } catch (InterruptedException ex) { String s = ex.toString(); System.out.println(s); } finally { if (session != null) session.disconnect(); } 

This seems like a more reliable implementation when used compared to SSHJ - or this impression may be due to the fact that they choose rather conservative timeouts. For example, if the target device is turned off, the session.connect () call by default will try to connect for about 20 seconds until failure.

0
source

Android comes with a stripped-down version of BouncyCastle that doesn't include ECDSA algorithms. Thus, even if you include the full version in your class path, the Android version will be selected and used.

You might want to take a look at the http://rtyley.imtqy.com/spongycastle/ that was created to get around this, its repackaged version of Bouncycastle, which can be installed as a standalone JCE provider on Android. Just set it as your default JCE provider before trying to connect via SSHJ (not verified).

 Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1); 
+5
source

Switching to sshj 0.9.0 here: http://mvnrepository.com/artifact/net.schmizz/sshj/0.9.0

The problem seems to have been introduced in 0.10.x. Also, I tried another JCE provider, but got into the same problem.

+2
source

Jsch most likely worked because it does not support elliptic curve algorithms for SSH AFAIK. If you do not need elliptic curve algorithms, then your answer.

0
source

Based on LeeDavidPainter's solution,

 /** * Creates a new SSH client stub */ public SSH(final String host, final int port) { SecurityUtils.setSecurityProvider(SecurityUtils.BOUNCY_CASTLE); //<-- Here Security.insertProviderAt(new BouncyCastleProvider(), 1); //<-- Here this.ssh.addHostKeyVerifier(new PromiscuousVerifier()); this.shell = new SSHShellSession(); this.ssh = new SSHClient(); this.connected = false; this.initiated = false; this.host = host; this.port = port; } 

The two commented areas above // โ€‹โ€‹<is the solution.

0
source

Source: https://habr.com/ru/post/977471/


All Articles