Saturday, June 15, 2024
Ana SayfaCosmic Meta QAProgramming QuestionsTroubleshooting SSH Key Authentication for an Android App

Troubleshooting SSH Key Authentication for an Android App

Question

I am unable to login to my server using key authentication from my Android app. However, I am able to login to the server from my app using password authentication. Additionally, I can login to the server using key authentication from other clients on my network.

Here’s a snippet of my code:

protected String sshConnect() {

    String stdoutString = null;
    String alias = "KEYPAIRTEST";

    KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
    keyStore.load(null);
    KeyStore.Entry entry = keyStore.getEntry(alias, null);
    PrivateKey privateKey = ((KeyStore.PrivateKeyEntry) entry).getPrivateKey();
    PublicKey publicKey = keyStore.getCertificate(alias).getPublicKey();
    KeyPair keyPair = new KeyPair(publicKey, privateKey);

    // create a client instance
    try (SshClient client = SshClient.setUpDefaultClient()) {

        client.setServerKeyVerifier(AcceptAllServerKeyVerifier.INSTANCE);
        client.start();

        // connection and authentication
        try (ClientSession session = client.connect(username, host, port).verify(TimeUnit.SECONDS.toMillis(defaultTimeoutSeconds)).getSession()) {

            session.auth().verify(TimeUnit.SECONDS.toMillis(defaultTimeoutSeconds));

            // create a channel to communicate
            ClientChannel channel = session.createExecChannel(this.command);

            ByteArrayOutputStream stdoutStream = new ByteArrayOutputStream();
            channel.setOut(stdoutStream);

            // open channel
            channel.open().verify(5, TimeUnit.SECONDS);

            // close channel
            channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED),
                    TimeUnit.SECONDS.toMillis(5));

            // output after converting to string type
            stdoutString = stdoutStream.toString();

        } catch (Exception e) {
            Log.d(TAG, "sshConnect(): client.connect(): Exception: " + e);
        }
    } catch (Exception e) {
        Log.d(TAG, "sshConnect(): client.start(): Exception: " + e);
    }
    return stdoutString;
}

I generated and stored the keys in the Android KeyStore using the following code:

KeyPairGenerator kpg = KeyPairGenerator.getInstance(
                        KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");

kpg.initialize(new KeyGenParameterSpec.Builder(
                        alias,
                        KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
                        .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
                        .setKeySize(2048)
                        .build());

kpg.generateKeyPair();

I extracted the public key and added it to the server’s ~/.ssh/authorized_keys file. Despite this, the login fails with the following warnings and exception in my client logs:

WARN org.apache.sshd.client.keyverifier.AcceptAllServerKeyVerifier - Server at /192.168.13.4:22 presented unverified EC key: SHA256:nNMe+ZsasdILlkGIZfcLwl41ZvVTzTaEOeA
Exception: org.apache.sshd.common.SshException: No more authentication methods available

What am I doing wrong?

Answer

To troubleshoot your issue with SSH key authentication from your Android app, you need to ensure that your key pair generation, public key formatting, and SSH client configuration are all correctly set up. Here’s a comprehensive guide to address these aspects and resolve your problem.

Detailed Description

When attempting to use SSH key authentication from an Android app, several steps must be verified to ensure the process works correctly. This includes generating and storing key pairs, ensuring the public key is correctly formatted and placed, and configuring the SSH client properly. Let’s go through these steps in detail.

Step 1: Key Pair Generation and Storage

Ensure your key generation and storage process is correct. Here’s how you can do it:

KeyPairGenerator kpg = KeyPairGenerator.getInstance(
        KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");

kpg.initialize(new KeyGenParameterSpec.Builder(
        alias,
        KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
        .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
        .setKeySize(2048)
        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
        .build());

kpg.generateKeyPair();

Ensure you include the necessary encryption paddings and key sizes for secure key generation.

Step 2: Public Key Format and Placement

Ensure the public key is correctly formatted and placed in the ~/.ssh/authorized_keys file on the server. The key should start with ssh-rsa followed by a space and the base64-encoded key.

Example of correct formatting:

ssh-rsa AAAAB3...base64_encoded_key... rest_of_key== user@host

Also, check the permissions of the ~/.ssh/authorized_keys file and the ~/.ssh directory:

chmod 600 ~/.ssh/authorized_keys
chmod 700 ~/.ssh

Step 3: SSH Client Configuration and Authentication Process

Ensure your SSH client is correctly configured to use the generated key pair. Here’s a refined version of your sshConnect method:

protected String sshConnect() {

    String stdoutString = null;
    String alias = "KEYPAIRTEST";

    try {
        KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
        keyStore.load(null);
        KeyStore.Entry entry = keyStore.getEntry(alias, null);
        PrivateKey privateKey = ((KeyStore.PrivateKeyEntry) entry).getPrivateKey();
        PublicKey publicKey = keyStore.getCertificate(alias).getPublicKey();
        KeyPair keyPair = new KeyPair(publicKey, privateKey);

        try (SshClient client = SshClient.setUpDefaultClient()) {
            client.setServerKeyVerifier(AcceptAllServerKeyVerifier.INSTANCE);
            client.start();

            try (ClientSession session = client.connect(username, host, port).verify(defaultTimeoutSeconds, TimeUnit.SECONDS).getSession()) {
                session.addPublicKeyIdentity(keyPair);
                session.auth().verify(defaultTimeoutSeconds, TimeUnit.SECONDS);

                try (ClientChannel channel = session.createExecChannel(this.command)) {
                    ByteArrayOutputStream stdoutStream = new ByteArrayOutputStream();
                    channel.setOut(stdoutStream);

                    channel.open().verify(5, TimeUnit.SECONDS);
                    channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), TimeUnit.SECONDS.toMillis(5));

                    stdoutString = stdoutStream.toString();
                }
            } catch (Exception e) {
                Log.d(TAG, "sshConnect(): client.connect(): Exception: " + e);
            }
        } catch (Exception e) {
            Log.d(TAG, "sshConnect(): client.start(): Exception: " + e);
        }
    } catch (Exception e) {
        Log.d(TAG, "sshConnect(): KeyStore Exception: " + e);
    }
    return stdoutString;
}

Additional Checks

  1. Server Logs: Check the server’s SSH logs (/var/log/auth.log or /var/log/secure) for any relevant error messages when the authentication fails. This can provide clues about why the key authentication is not working.
  2. Key Fingerprint Verification: Ensure the key fingerprint matches on both sides. The warning about the server presenting an unverified EC key may indicate a mismatch or an issue with the server’s host key verification process.
  3. Network Configuration: Verify that there are no network issues or firewalls blocking the key-based authentication.

Conclusion

By ensuring the correct generation and storage of key pairs, proper formatting and placement of the public key, and verifying the SSH client configuration and server logs, you should be able to diagnose and resolve the key authentication issue from your Android app. If you continue to face problems, detailed logs from both the client and server side will be crucial in further troubleshooting.

Useful Links

Cosmic Meta
Cosmic Metahttps://cosmicmeta.io
Cosmic Meta Digital is your ultimate destination for the latest tech news, in-depth reviews, and expert analyses. Our mission is to keep you informed and ahead of the curve in the rapidly evolving world of technology, covering everything from programming best practices to emerging tech trends. Join us as we explore and demystify the digital age.
RELATED ARTICLES

CEVAP VER

Lütfen yorumunuzu giriniz!
Lütfen isminizi buraya giriniz

- Advertisment -

Most Popular

Recent Comments