Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jsch 0.2.7 with bc-fips.jar gives NoClassDefFoundError for invalid private keys #289

Closed
HubertOT opened this issue Mar 13, 2023 · 4 comments

Comments

@HubertOT
Copy link

HubertOT commented Mar 13, 2023

Issue

During creating sFTPSession with public/private key authentication exception "NoClassDefFoundError: org/bouncycastle/crypto/params/Argon2Parameters$Builder" is thrown, if BCFIPS is used.

JSch 0.2.6 and before threw the more clear com.jcraft.jsch.JSchException: invalid privatekey.

Reproduction

Generate with PuttyGen a private key with passphrase and press the button "Save private key" and save it to a file. It will look like:

PuTTY-User-Key-File-3: ssh-rsa
Encryption: aes256-cbc
Comment: rsa-key-20230313
Public-Lines: 6
AAAAB3NzaC1yc2EAAAADAQABAAABAQC1fER5+0D1iplxuWje0hLi3gLX+7Idc2nG
...
...
Key-Derivation: Argon2id
Argon2-Memory: 8192
Argon2-Passes: 8
Argon2-Parallelism: 1
Argon2-Salt: 090ffb4de0f20f386d4acd213776ff35
Private-Lines: 14
uL33nk4bF9+pm9BDCL/gIy31wI73uqxnV960+f2fuLLp//v0WumFrvQ00FTVqRNI
...
...
Private-MAC: 3c03b...

Trying to create a sFTP session with the stored private key, with Jsch library 0.2.7 and bc-fips 1.0.2.3, results in an unclear exception:

java.lang.NoClassDefFoundError: org/bouncycastle/crypto/params/Argon2Parameters$Builder
at com.jcraft.jsch.bc.Argon2.init(Argon2.java:67)
at com.jcraft.jsch.KeyPair.loadPPK(KeyPair.java:1257)
at com.jcraft.jsch.KeyPair.load(KeyPair.java:695)
at com.jcraft.jsch.IdentityFile.newInstance(IdentityFile.java:46)
at com.jcraft.jsch.JSch.addIdentity(JSch.java:542)
at org.springframework.integration.sftp.session.DefaultSftpSessionFactory.initJschSession(DefaultSftpSessionFactory.java:433)
at org.springframework.integration.sftp.session.DefaultSftpSessionFactory.getSession(DefaultSftpSessionFactory.java:393)

Despite with Jsch library 0.2.6 it throws the clear and correct exception:

com.jcraft.jsch.JSchException: invalid privatekey
at com.jcraft.jsch.KeyPair.load(KeyPair.java:782)
at com.jcraft.jsch.IdentityFile.newInstance(IdentityFile.java:46)
at com.jcraft.jsch.JSch.addIdentity(JSch.java:530)
at org.springframework.integration.sftp.session.DefaultSftpSessionFactory.initJschSession(DefaultSftpSessionFactory.java:433)
at org.springframework.integration.sftp.session.DefaultSftpSessionFactory.getSession(DefaultSftpSessionFactory.java:393)

Cause

Cause of this is the multi jar construction of Jsch in relation with the used Java 8 and bc-fips library instead of Java 15 and/or bc-prov library. The bc-fips library doesn't contain (yet) the class Argon2Parameters. Also identical classes are located in a different package within bc-fips as within the bc-prov library. Package "org.bouncycastle.crypto.internal.params" vs "org.bouncycastle.crypto.params". So also when the class Argon2Parameters is added to the bc-fips library it still will give the NoClassDefFoundError exception.

Please check for the availability of the correct BouncyCastle libraries and wrap the NoClassDefFoundError exception to an applicable error message, e.g. "Invalid privatekey".

Workaround/Solution

Catch NoClassDefFoundError when calling JSch.addIdentity() (and perhaps other methods).

@norrisjeremy
Copy link
Contributor

Hi @HubertOT,

I've made changes in #290 to try and address this.
If you would like to test and confirm, you can download a snapshot build from here.

Thanks,
Jeremy

@HubertOT
Copy link
Author

Hello @norrisjeremy,

Thank you for the quick response. I will test with the provided jar file and come back to you.

With kind regards,
Hubert

@HubertOT
Copy link
Author

Hi @norrisjeremy,

Unfortunately I can still reproduce the issue. Debugging more into detail turned out the issue is on our side, which I overlooked. We searched within the stacktrace for the deepest (original) cause and throw that only up.
In relation with the concerning privatekey (which contained a public and private key):

  • The JSch 0.2.6 library can not retrieve the private key from the concerning privatekey string, hence throws exception "Invalid privatekey".
  • The JSch 0.2.7 library can extract the public and private key from the concerning privatekey string. However due to missing Argon2 algorithm/class can not load the privatekey, hence throws the exception "ClassNotFoundException: org.bouncycastle.crypto.params.Argon2Parameters$Builder".

As said, because our code only did throw the deepest exception, I draw the wrong conclusion based on "our" stacktrace.

Having said this, from JSch point of view no code modifications are needed, hence this Issue can be closed as knowledge issue.

Regards,
Hubert

@norrisjeremy
Copy link
Contributor

Hi @HubertOT,

In the 0.2.7 release, we added support for PuTTY's PPKv3 private key format, so what was previously an Invalid privatekey can now be handled by JSch.
However, for encrypted PPKv3 private keys, JSch requires the Bouncy Castle library in order to provide an Argon2 implementation.

You make a very good point however, in that JSch was throwing a NoClassDefFoundError when attempting to load a PPKv3 encrypted key without having Bouncy Castle available.
Part of #290 adds a change to correctly wrap that into a regular JSchException to prevent surprise runtime errors from leaking out of JSch.

Thanks,
Jeremy

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants