Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions src/main/java/com/trilead/ssh2/auth/AuthenticationManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import com.trilead.ssh2.signature.Ed25519Verify;
import com.trilead.ssh2.signature.RSASHA1Verify;
import com.trilead.ssh2.signature.SSHSignature;
import com.trilead.ssh2.signature.SkPublicKey;
import com.trilead.ssh2.transport.MessageHandler;
import com.trilead.ssh2.transport.TransportManager;

Expand Down Expand Up @@ -339,6 +340,45 @@ else if ("EdDSA".equals(publicKey.getAlgorithm()))

tm.sendMessage(ua.getPayload());
}
else if (publicKey instanceof SkPublicKey)
{
// FIDO2 Security Key (SK) authentication
// SK keys require external signing via SignatureProxy
if (signatureProxy == null)
{
throw new IOException("SK key authentication requires a SignatureProxy for signing.");
}

SkPublicKey skPublicKey = (SkPublicKey) publicKey;
final String algo = skPublicKey.getSshKeyType();

// Get the encoded public key (includes key type, key data, and application)
byte[] pk_enc = skPublicKey.getEncoded();

byte[] msg = this.generatePublicKeyUserAuthenticationRequest(user, algo, pk_enc);

// Determine the hash algorithm based on key type
// sk-ssh-ed25519@openssh.com uses SHA512 (same as Ed25519)
// sk-ecdsa-sha2-nistp256@openssh.com uses SHA256
String hashAlgorithm;
if (algo.contains("ed25519"))
{
hashAlgorithm = SignatureProxy.SHA512;
}
else
{
hashAlgorithm = SignatureProxy.SHA256;
}

// The SignatureProxy.sign() for SK keys must return the complete
// signature blob including flags and counter, not just the raw signature
byte[] sk_sig_enc = signatureProxy.sign(msg, hashAlgorithm);

PacketUserauthRequestPublicKey ua = new PacketUserauthRequestPublicKey("ssh-connection", user,
algo, pk_enc, sk_sig_enc);

tm.sendMessage(ua.getPayload());
}
else
{
throw new IOException("Unknown public key type.");
Expand Down
43 changes: 43 additions & 0 deletions src/main/java/com/trilead/ssh2/signature/SkPublicKey.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@

package com.trilead.ssh2.signature;

import java.security.PublicKey;

/**
* Interface for FIDO2 Security Key (SK) public keys used in SSH authentication.
*
* SK keys are hardware-backed keys where the private key never leaves the device.
* The signature format includes additional fields (flags, counter) beyond the
* raw cryptographic signature.
*
* Implementations should provide:
* - sk-ssh-ed25519@openssh.com for Ed25519-based SK keys
* - sk-ecdsa-sha2-nistp256@openssh.com for ECDSA P-256 SK keys
*/
public interface SkPublicKey extends PublicKey {

/**
* Get the SSH key type identifier.
*
* @return The key type string, e.g., "sk-ssh-ed25519@openssh.com" or
* "sk-ecdsa-sha2-nistp256@openssh.com"
*/
String getSshKeyType();

/**
* Get the application ID (relying party ID) for this key.
* Typically "ssh:" for SSH authentication.
*
* @return The application ID string
*/
String getApplication();

/**
* Get the underlying key data (without the key type prefix).
* For Ed25519, this is the 32-byte public key.
* For ECDSA, this is the uncompressed EC point.
*
* @return The raw key bytes
*/
byte[] getKeyData();
}
Loading
Loading