Skip to main content

verify_client

Function verify_client 

Source
pub fn verify_client(
    authorized_keys: &AuthorizedKeys,
    nonce: &[u8; 32],
    public_key: &[u8; 32],
    signature: &[u8; 64],
) -> Result<ClientRole<RoleId>, ClientAuthError>
Expand description

Decide a client’s challenge response: the key must be listed, under a role that may connect as a client, and must have signed nonce. Returns the connection’s role, as the runtime carries it: the operator, or an application role as its index in the role table.

nonce must be the one this listener sent the client for this connection, fresh from a cryptographic random source: a nonce reused across connections lets a recorded response be replayed.

The role is checked before the signature, so a refused key costs no verification; the answer the client sees is the same failure either way.

use base64::Engine;
use ed25519_dalek::{Signer, SigningKey};
use melin_app::auth::{AuthorizedKeys, NoRoles};
use melin_server_runtime::client_auth::{ClientAuthError, verify_client};

let client = SigningKey::from_bytes(&[7; 32]);
let public_key = client.verifying_key().to_bytes();
let listed = base64::engine::general_purpose::STANDARD.encode(public_key);
let keys = AuthorizedKeys::parse::<NoRoles>(&format!("operator {listed} ops\n")).unwrap();

// The listener sent this nonce; the client signed it.
let nonce = [0x5A; 32];
let signature = client.sign(&nonce).to_bytes();

let role = verify_client(&keys, &nonce, &public_key, &signature).unwrap();
assert!(role.is_operator());

let impostor = SigningKey::from_bytes(&[8; 32]).sign(&nonce).to_bytes();
assert!(matches!(
    verify_client(&keys, &nonce, &public_key, &impostor),
    Err(ClientAuthError::BadSignature(_))
));