hierynomus / sshj

ssh, scp and sftp for java
Apache License 2.0
2.51k stars 601 forks source link

net.schmizz.sshj.common.SSHRuntimeException: no such algorithm: X25519 for provider BC #895

Open leefine opened 1 year ago

leefine commented 1 year ago

when i use sftp transfer the file ,the lib give me this error:

net.schmizz.sshj.common.SSHRuntimeException: no such algorithm: X25519 for provider BC

exceptionfactory commented 1 year ago

@leefine Can you provide the version of Bouncy Castle you are using? The X25519 algorithm should be supported since version 1.61 of Bouncy Castle.

devaskim commented 1 year ago

The X25519 algorithm should be supported since version 1.61 of Bouncy Castle.

Didn't help

exceptionfactory commented 1 year ago

@devaskim and @leefine, please provide more details on the runtime dependency configuration and Java version if you would like to receive additional help on this issue. The specific Java version and Bouncy Castle version, as well as the stack trace associated with the error, are necessary to track down the problem.

devaskim commented 1 year ago

@exceptionfactory Thanks for your time. Java 8 and BC 1.61

devaskim commented 1 year ago

@exceptionfactory Forgot to mention.

Our application has a lot of dependencies and BC is common for part of them (now we use 1.60 version). When I add the latest version of sshj (0.36), I got no such algorithm: X25519 for provider BC error. If I bump BC version to 1.61, I got class signature error (sorry, don't remember exactly). Seems like we need to use the same or upper version of BC as sshj uses at the moment.

exceptionfactory commented 1 year ago

Thanks for the additional details @devaskim. If you could provide the details of the class signature error, that would be helpful. The latest version of the Bouncy Castle Provider library is 1.76, and I recommend using that version. However, it sounds like Bouncy Castle could be a transitive or platform dependency. Is this running in the context of a web application container? Either way, the stack trace details would be helpful. I recommend evaluating the deployed JAR files to ensure the expected version.

hfhbd commented 1 year ago

I got the same problem:

Exception in thread "sshj-Reader-MYSERVER/MYIP:22-123456" java.lang.NoClassDefFoundError: org/bouncycastle/asn1/x509/AlgorithmIdentifier
    at org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey.getEncoded(Unknown Source)
    at net.schmizz.sshj.transport.verification.OpenSSHKnownHosts$HostEntry.getKeyString(OpenSSHKnownHosts.java:471)
    at net.schmizz.sshj.transport.verification.OpenSSHKnownHosts$HostEntry.verify(OpenSSHKnownHosts.java:453)
    at net.schmizz.sshj.transport.verification.OpenSSHKnownHosts.verify(OpenSSHKnownHosts.java:132)
    at net.schmizz.sshj.transport.KeyExchanger.verifyHost(KeyExchanger.java:218)
    at net.schmizz.sshj.transport.KeyExchanger.handle(KeyExchanger.java:401)
    at net.schmizz.sshj.transport.TransportImpl.handle(TransportImpl.java:485)
    at net.schmizz.sshj.transport.Decoder.decode(Decoder.java:113)
    at net.schmizz.sshj.transport.Decoder.received(Decoder.java:200)
    at net.schmizz.sshj.transport.Reader.run(Reader.java:60)

BC 1.75, which is used by sshj 0.36:

+--- com.hierynomus:sshj:0.36.0
|    +--- org.slf4j:slf4j-api:2.0.7
|    +--- org.bouncycastle:bcprov-jdk18on:1.75
|    +--- org.bouncycastle:bcpkix-jdk18on:1.75
|    |    +--- org.bouncycastle:bcprov-jdk18on:1.75
|    |    \--- org.bouncycastle:bcutil-jdk18on:1.75
|    |         \--- org.bouncycastle:bcprov-jdk18on:1.75
|    +--- com.hierynomus:asn-one:0.6.0
|    |    \--- org.slf4j:slf4j-api:1.7.13 -> 2.0.7
|    \--- net.i2p.crypto:eddsa:0.3.0

mention this in the release notehttps://www.[bouncycastle.org](https://www.bouncycastle.org/releasenotes.html#r1rv75)/releasenotes.html#r1rv75s: The ASN.1 core package has had some dead and retired methods cleaned up and removed. MAYBE this cleanup went wrong. Or it is unrelated.

exceptionfactory commented 1 year ago

Thanks for the note and stack trace @hfhbd.

The NoClassDefFoundError indicates that the Bouncy Castle AlgorithmIdentifier is not available at runtime. This class is in the bcutil-jdk18on library. Although the dependency tree you provided is correct, it sounds like something else is overriding the Bouncy Castle version, causing the bcutil-jdk18on to be missing at runtime. Is this a web application, a standalone Java program, or something else? I recommend reviewing the final build artifacts to determine the actual versions of Bouncy Castle included.

hfhbd commented 1 year ago

It is a Gradle plugin using an isolated classloader (Worker api) and these dependencies:

runtimeClasspath - Runtime classpath of null/main.
+--- com.hierynomus:sshj:0.36.0
|    +--- org.slf4j:slf4j-api:2.0.7
|    +--- org.bouncycastle:bcprov-jdk18on:1.75
|    +--- org.bouncycastle:bcpkix-jdk18on:1.75
|    |    +--- org.bouncycastle:bcprov-jdk18on:1.75
|    |    \--- org.bouncycastle:bcutil-jdk18on:1.75
|    |         \--- org.bouncycastle:bcprov-jdk18on:1.75
|    +--- com.hierynomus:asn-one:0.6.0
|    |    \--- org.slf4j:slf4j-api:1.7.13 -> 2.0.7
|    \--- net.i2p.crypto:eddsa:0.3.0
+--- org.jetbrains.kotlin:kotlin-stdlib:1.9.20-Beta2
|    \--- org.jetbrains:annotations:13.0
+--- net.java.dev.jna:jna:5.13.0
\--- net.java.dev.jna:jna-platform:5.13.0
     \--- net.java.dev.jna:jna:5.13.0

It does work with 0.35.0 though.

exceptionfactory commented 1 year ago

SSHJ Pull Request #838 replaced a custom class with the standard X25519 implementation available through configured Java Security Providers. This is available by default on Java 11 and following, but Bouncy Castle provides the implementation for Java 8.

As mentioned, the NoClassDefFoundError indicates that the runtime environment cannot find the bcutil-jdk18on JAR.

Reviewing the Gradle 8.3 dependencies, it packages an older version of Bouncy Castle 1.68:

gradle-8.3/lib/plugins/bcpg-jdk15on-1.68.jar  
gradle-8.3/lib/plugins/bcpkix-jdk15on-1.68.jar  
gradle-8.3/lib/plugins/bcprov-jdk15on-1.68.jar  

At runtime, Gradle apparently registers the older version of the Bouncy Castle Provider, but the custom plugin seems to be conflicting. Based on Gradle including Bouncy Castle, one potential solution is to mark the bcprov-jdk18on and bcpkix-jdk18on dependencies as provided.

j0kkeri commented 5 months ago

I had the "classic" cause for this; another dependency which had transitive dependency to BC 1.60. Fixed by excluding the old version.