I'm trying to authenticate a signature that clients generate from their private key and send to the server.
The only authenticator I could find in the library that sounded appropriate was the PublickeyAuthenticator
. Please correct me if this is the wrong class to do this.
I currently have:
this.sshServer.setPublickeyAuthenticator(new PublickeyAuthenticator() {
@Override
public boolean authenticate(String username, PublicKey key, ServerSession session) {
if (username.equals("client")) {
//if signature == valid??
return true;
}
}
});
Does anyone know if mina supports signature verification and if so, how can it be implemented?
My understanding is that I'd first have to assign/add the user public key to the server. If the client has provided a id_rsa.pub
file, how can I go about adding this file to the server as the public key?
Mina SSH has a few implementations of PublickeyAuthenticator
.
Look at
org.apache.sshd.server.config.keys.AuthorizedKeysAuthenticator
and
org.apache.sshd.server.auth.pubkey.KeySetPublickeyAuthenticator
.
Implementations of PublickeyAuthenticator
only check that the given public key is associated with the user.
The actual verification of the signature is handled internally to MINA SSH after the authentication.
The AuthorizedKeysAuthenticator
only supports one user(it doesnt check the username), but you could for example just point it at your id_rsa.pub
file and it should work.
this.sshServer.setPublickeyAuthenticator(
new AuthorizedKeysAuthenticator(new File("id_rsa.pub"));
You could write your own PublicKeyAuthenticator
that checks the keys against a map of users like so:
public class UserKeySetPublickeyAuthenticator implements PublickeyAuthenticator {
private final Map<String, Collection<? extends PublicKey>> userToKeySet;
public UserKeySetPublickeyAuthenticator(Map<String, Collection<? extends PublicKey>> userToKeySet) {
this.userToKeySet = userToKeySet;
}
@Override
public boolean authenticate(String username, PublicKey key, ServerSession session) {
return KeyUtils.findMatchingKey(key, userToKeySet.getOrDefault(username, Collections.emptyList())) != null;
}
}
You need to write some code to populate the map with your key data.
AuthorizedKeyEntry
has utility methods for doing this from files, inputstreams or strings.
An example of reading from user named authorized key files:
Map<String, List<PublicKey>> userKeysMap = new HashMap<>();
List<String> users = Arrays.asList("Jim", "Sally", "Bob");
for(String user : users){
List<PublicKey> usersKeys = new ArrayList<>();
for(AuthorizedKeyEntry ake : AuthorizedKeyEntry.readAuthorizedKeys(new File(user + "_authorized_keys"))){
PublicKey publicKey = ake.resolvePublicKey(PublicKeyEntryResolver.IGNORING);
if(publicKey != null){
usersKeys.add(publicKey);
}
}
userKeysMap.put(user, usersKeys);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With