sirthias / scala-ssh

Remote shell access via SSH for your Scala applications
Apache License 2.0
233 stars 52 forks source link

"SSHException: No provider available for PKCS8 key file" running basic example #6

Open gilbertw1 opened 12 years ago

gilbertw1 commented 12 years ago

Hi, I'm getting the above exception from sshj when trying to use key based authentication (full exception printed below) using a slightly modified version of the example in the Readme. I did some initial research and found in a source comment in sshj that this typically indicates that bouncy castle is not on the classpath. I've currently got this deployed using the one-jar sbt plugin and have verified that it does in fact include the bouncy castle library and have even added it manually when executing the jar using the -cp flag. I've also double checked to make sure that the key file is correct.

Code sample I'm running:

import com.decodified.scalassh._
import org.bouncycastle.jce.provider._

object SshClient extends App {

    SSH("myhost.net") { client =>
        client.exec("ls -a") match { 
            case Right(result) => println("Result: " + result.stdOutAsString())
            case Left(error) => println("Error: " + error)
        }
    }

}

With the following config (~/.scala-ssh/myhost.net):

login-type = keyfile
username = myhost-user
keyfile = ~/.ssh/ec2/myhostkey

SBT dependencies:

libraryDependencies ++= Seq (
    "com.decodified" % "scala-ssh" % "0.6.2",
    "org.bouncycastle" % "bcprov-jdk16" % "1.46",
    "com.jcraft" % "jzlib" % "1.1.1",
    "ch.qos.logback" % "logback-classic" % "1.0.3"
)

Running this application results in the following output:

14:52:51.240 [main] INFO  com.decodified.scalassh.SshClient - Authenticating to myhost.net:22 using PublicKeyLogin(sparcloud-boss,None,List(/Users/bgilbert/.ssh/ec2/myhostkey)) ...
Error: Could not authenticate (with keyfile) to myhost.net:22 due to net.schmizz.sshj.common.SSHException: No provider available for PKCS8 key file
14:52:51.245 [main] INFO  com.decodified.scalassh.SshClient - Closing connection to myhost.net:22 ...

Any ideas as to what the problem could be? Am I maybe missing something basic?

Thanks very much in advance!

sirthias commented 12 years ago

Brian,

hmm... I can't see something that's obviously wrong with your setup. I'm running very similar setups myself in numerous project successfully.

How about you distill a minimal full project that is failing for you and put it into a gist or a GH project, where I can check it out, change only the hostname and keyfile location and run it myself.

This way we should be able to pin down the issue relatively easily...

Cheers, Mathias


mathias@decodified.com http://www.decodified.com

On 12.07.2012, at 21:08, Bryan Gilbert wrote:

Hi, I'm getting the above exception from sshj when trying to use key based authentication (full exception printed below) using a slightly modified version of the example in the Readme. I did some initial research and found in a source comment in sshj that this typically indicates that bouncy castle is not on the classpath. I've currently got this deployed using the one-jar sbt plugin and have verified that it does in fact include the bouncy castle library and have even added it manually when executing the jar using the -cp flag. I've also double checked to make sure that the key file is correct.

Code sample I'm running:

import com.decodified.scalassh. import org.bouncycastle.jce.provider.

object SshClient extends App {

  SSH("myhost.net") { client =>
      client.exec("ls -a") match { 
          case Right(result) => println("Result: " + result.stdOutAsString())
          case Left(error) => println("Error: " + error)
      }
  }

}

With the following config (~/.scala-ssh/myhost.net):

login-type = keyfile username = myhost-user keyfile = ~/.ssh/ec2/myhostkey

SBT dependencies:

libraryDependencies ++= Seq ( "com.decodified" % "scala-ssh" % "0.6.2", "org.bouncycastle" % "bcprov-jdk16" % "1.46", "com.jcraft" % "jzlib" % "1.1.1", "ch.qos.logback" % "logback-classic" % "1.0.3" )

Running this application results in the following output:

14:52:51.240 [main] INFO com.decodified.scalassh.SshClient - Authenticating to myhost.net:22 using PublicKeyLogin(sparcloud-boss,None,List(/Users/bgilbert/.ssh/ec2/myhostkey)) ... Error: Could not authenticate (with keyfile) to myhost.net:22 due to net.schmizz.sshj.common.SSHException: No provider available for PKCS8 key file 14:52:51.245 [main] INFO com.decodified.scalassh.SshClient - Closing connection to myhost.net:22 ...

Any ideas as to what the problem could be? Am I maybe missing something basic?

Thanks very much in advance!


Reply to this email directly or view it on GitHub: https://github.com/sirthias/scala-ssh/issues/6

gilbertw1 commented 12 years ago

Hi Mathias,

Thank you for your quick response! I've created the following github repo that contains a minimum full project that I've experienced this problem with. It's located here:

https://github.com/gilbertw1/scala-ssh-example.git

You should be able to create the one-jar using the 'sbt one-jar' command. Also I've got the config file in the base directory of the repo, 'example.net', which is the file that I have placed in the '.scala-ssh' directory. Let me know if you have any questions about this project, and thanks again for looking at this.

Thanks! Bryan

sirthias commented 12 years ago

Ok, for me your sample project doesn't even run with sbt run. Can you apply this patch here and try again?

diff --git a/example.net b/example.net
deleted file mode 100644
index 1f40205..0000000
--- a/example.net
+++ /dev/null
@@ -1,3 +0,0 @@
-login-type = keyfile
-username = Ubuntu
-keyfile = ~/.ssh/ec2/example.net
\ No newline at end of file
diff --git a/src/main/resources/example.net b/src/main/resources/example.net
new file mode 100644
index 0000000..1f40205
--- /dev/null
+++ b/src/main/resources/example.net
@@ -0,0 +1,3 @@
+login-type = keyfile
+username = Ubuntu
+keyfile = ~/.ssh/ec2/example.net
\ No newline at end of file
diff --git a/src/main/scala/com/example/SshClient.scala b/src/main/scala/com/example/SshClient.scala
index 016628c..9717cc2 100644
--- a/src/main/scala/com/example/SshClient.scala
+++ b/src/main/scala/com/example/SshClient.scala
@@ -1,15 +1,16 @@
 package com.example

 import com.decodified.scalassh._
-import org.bouncycastle.jce.provider._

 object SshClient extends App {

+  println {
    SSH("example.net") { client =>
        client.exec("ls -a /") match { 
            case Right(result) => println("Result: " + result.stdOutAsString())
            case Left(error) => println("Error: " + error)
        }
    }
+  }

 }
\ No newline at end of file
joakim666 commented 11 years ago

I got the same error using the assembly:single goal of the maven assembly plugin to produce one big executable jar file. Changing to use the appassembler maven plugin which uses separate jar files and a start script instead made it work without any code changes.

So something goes wrong when combining all needed classes into a big jar file and that for unknown reasons breaks the public key based authentication.

Good to know!

eyalkaspi commented 10 years ago

Posting more details here to help anyone having the same problem. When using maven to package a single jar, for instance using the maven shade plugin, bouncycastle get altered and sshj fails registering it with the following exception:

java.security.NoSuchProviderException: JCE cannot authenticate the provider BC

in

net.schmizz.sshj.common.SecurityUtils.register()

This is because the BC signature is invalid. Given that sshj only has a optional dependency to BC, it does not fail but logs an info message (BouncyCastle not registered, using the default JCE provider).

The solution consists in having an version of the bouncycastle jar which is not altered in the classpath. If the application is launched with "java -jar" this is a little tricky as one can only specify one jar. One can either have the manifest of the "main" jar reference bouncycastle or add bouncycastle to the JRE extension library (in jre/lib/ext/bcprov-jdk15on-1.49.jar for instance.)

yarinzimmerman commented 9 years ago

Hi,

is it possible to pass a username and pwd without a keyfile or a HostConfig?

Thanks, Yarin.

tekumara commented 9 years ago

Had this problem when including the bouncy castle classes were packaged up into my uber jar. As mentioned by eyalkaspi, bouncy castle doesn't like this unless the jar is signed. I removed the bouncy castle jars from my uber jar and included it on the classpath and it worked:

java -cp bcprov-ext-jdk16-1.46.jar:pvt.jar org.test.Main