Skip to content

org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey cannot be cast to java.security.interfaces.ECPublicKey #356

Closed
@druhm

Description

@druhm

Hi,

I have a problem with SSJ when I connect to an OpenSSH server (6.6.1) with ECDSA keys (ecdsa-sha2-nistp256). While RSA and DSA keys work without any problems, ECDSA keys fail to authenticate a user. OpenSSH is well configured; using the very same keys with other tools (e.g. putty) I can successfully connect with ECDSA as well. Therefore I think its an SSHJ issue.

The problem is a bad cast from a private key to a public key in KeyType.java:133

@Override
protected boolean isMyType(Key key) {
   return ("ECDSA".equals(key.getAlgorithm()) && ECDSAVariationsAdapter.fieldSizeFromKey((ECPublicKey) key) == 256);
}

which results in the folloing error message.

org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey cannot be cast to java.security.interfaces.ECPublicKey

Root cause is that in KeyedAuthMethod.java:64 a call to KeyType.fromKey() uses a private key as parameter (created in KeyedAuthMethod.java:59), which basically leads to the ClassCastException later on.

[main] INFO net.schmizz.sshj.transport.random.BouncyCastleRandom - Generating random seed from SecureRandom.
[main] INFO net.schmizz.sshj.transport.TransportImpl - Client identity string: SSH-2.0-SSHJ_0.22.0
[main] INFO net.schmizz.sshj.transport.TransportImpl - Server identity string: SSH-2.0-OpenSSH_6.6.1
[reader] ERROR net.schmizz.sshj.transport.TransportImpl - Dying because - org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey cannot be cast to java.security.interfaces.ECPublicKey
java.lang.ClassCastException: org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey cannot be cast to java.security.interfaces.ECPublicKey
	at net.schmizz.sshj.common.KeyType$3.isMyType(KeyType.java:133)
	at net.schmizz.sshj.common.KeyType.fromKey(KeyType.java:297)
	at net.schmizz.sshj.userauth.method.KeyedAuthMethod.putSig(KeyedAuthMethod.java:64)
	at net.schmizz.sshj.userauth.method.AuthPublickey.sendSignedReq(AuthPublickey.java:74)
	at net.schmizz.sshj.userauth.method.AuthPublickey.handle(AuthPublickey.java:45)
	at net.schmizz.sshj.userauth.UserAuthImpl.handle(UserAuthImpl.java:142)
	at net.schmizz.sshj.transport.TransportImpl.handle(TransportImpl.java:500)
	at net.schmizz.sshj.transport.Decoder.decode(Decoder.java:102)
	at net.schmizz.sshj.transport.Decoder.received(Decoder.java:170)
	at net.schmizz.sshj.transport.Reader.run(Reader.java:59)
[reader] INFO net.schmizz.sshj.transport.TransportImpl - Disconnected - UNKNOWN
[main] ERROR net.schmizz.concurrent.Promise - <<authenticated>> woke to: net.schmizz.sshj.userauth.UserAuthException: org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey cannot be cast to java.security.interfaces.ECPublicKey
Exception in thread "main" net.schmizz.sshj.userauth.UserAuthException: Exhausted available authentication methods
	at net.schmizz.sshj.SSHClient.auth(SSHClient.java:230)
	at net.schmizz.sshj.SSHClient.authPublickey(SSHClient.java:345)
	at net.schmizz.sshj.SSHClient.authPublickey(SSHClient.java:364)
	at ecdsatester.EcdsaTesterMain.main(EcdsaTesterMain.java:46)
Caused by: net.schmizz.sshj.userauth.UserAuthException: org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey cannot be cast to java.security.interfaces.ECPublicKey
	at net.schmizz.sshj.userauth.UserAuthException$1.chain(UserAuthException.java:33)
	at net.schmizz.sshj.userauth.UserAuthException$1.chain(UserAuthException.java:26)
	at net.schmizz.concurrent.Promise.deliverError(Promise.java:96)
	at net.schmizz.sshj.userauth.UserAuthImpl.notifyError(UserAuthImpl.java:156)
	at net.schmizz.sshj.transport.TransportImpl.die(TransportImpl.java:601)
	at net.schmizz.sshj.transport.Reader.run(Reader.java:67)
Caused by: net.schmizz.sshj.common.SSHException: org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey cannot be cast to java.security.interfaces.ECPublicKey
	at net.schmizz.sshj.common.SSHException$1.chain(SSHException.java:36)
	at net.schmizz.sshj.common.SSHException$1.chain(SSHException.java:29)
	at net.schmizz.sshj.transport.TransportImpl.die(TransportImpl.java:595)
	... 1 more
Caused by: java.lang.ClassCastException: org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey cannot be cast to java.security.interfaces.ECPublicKey
	at net.schmizz.sshj.common.KeyType$3.isMyType(KeyType.java:133)
	at net.schmizz.sshj.common.KeyType.fromKey(KeyType.java:297)
	at net.schmizz.sshj.userauth.method.KeyedAuthMethod.putSig(KeyedAuthMethod.java:64)
	at net.schmizz.sshj.userauth.method.AuthPublickey.sendSignedReq(AuthPublickey.java:74)
	at net.schmizz.sshj.userauth.method.AuthPublickey.handle(AuthPublickey.java:45)
	at net.schmizz.sshj.userauth.UserAuthImpl.handle(UserAuthImpl.java:142)
	at net.schmizz.sshj.transport.TransportImpl.handle(TransportImpl.java:500)
	at net.schmizz.sshj.transport.Decoder.decode(Decoder.java:102)
	at net.schmizz.sshj.transport.Decoder.received(Decoder.java:170)
	at net.schmizz.sshj.transport.Reader.run(Reader.java:59)

There is a good change that I am using your API incorrectly here, since I have not found anything about this issue online and I somehow doubt that I would be the first to stumble across this.
If so please advise how to connect with a given private ECDSA key. But even if there is something wrong with the keys themselves (encoding etc), the code path that causes the exception is at least dubious, or am I wrong?
The keys in the sample below have been created for this issue and can be thrown away. I have locally updated java.security for BC and replaced local_policy.jar and US_export_policy.jar with their unlimited version.
I am using JRE1.8.0_144, SSHJ-0.22.0 and BC-158.

Here is a minimal sample that illustrates the problem.

package tester.sshj;
import java.net.Inet4Address;
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
import net.schmizz.sshj.userauth.keyprovider.KeyPairWrapper;
import net.schmizz.sshj.userauth.keyprovider.KeyProvider;
import net.schmizz.sshj.userauth.keyprovider.OpenSSHKeyFile;


public class EcdsaTesterMain
{

   public static void main(final String[] args) throws Exception
   {
	  final SSHClient sshClient = new SSHClient();
	  sshClient.addHostKeyVerifier( new PromiscuousVerifier() );
	  sshClient.connect( Inet4Address.getByName( "10.2.2.20" ) );

	  final String publicKey =
			"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAy"
			+ "NTYAAABBBA1ANSWFQ+1EUqDhncD8Y3mvhEw+iAATA/Qln5NzVUzZHbvyrJ+7l3"
			+ "C00IceDdes9SIFtm0W0m7JjPvlCl5nlso= SSH Key";

	  final String privateKey =
			"-----BEGIN EC PRIVATE KEY-----\n" +
			"MHcCAQEEIGhcvG8anyHew/xZJfozh5XIc1kmZZs6o2f0l3KFs4jgoAoGCCqGSM49\n" +
			"AwEHoUQDQgAEDUA1JYVD7URSoOGdwPxjea+ETD6IABMD9CWfk3NVTNkdu/Ksn7uX\n" +
			"cLTQhx4N16z1IgW2bRbSbsmM++UKXmeWyg==\n" +
			"-----END EC PRIVATE KEY-----\n";

	  final OpenSSHKeyFile keyFile = new OpenSSHKeyFile();
	  keyFile.init( privateKey, publicKey );

	  final KeyProvider keyProvider = new KeyPairWrapper( keyFile.getPublic(), keyFile.getPrivate());

	  sshClient.authPublickey
			( "username"
			, keyProvider
			);
	  
	  System.out.println( sshClient.isAuthenticated() );
	  sshClient.disconnect();
   }
}

Thanks for your time
Thomas

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions