Single-device mode is the default PPS authentication mode.
It uses one registered device key and automatic forward-secure key rotation.
1. Server creates a challenge with a nonce.
2. Client increments the counter.
3. Client generates the next key pair.
4. Client signs the Pulse payload with the current key.
5. Client includes the next public key in the payload.
6. Server verifies the signature.
7. Server verifies the counter and rotation sequence.
8. Server updates the stored public key to the next public key.
use Pps\Client\AuthenticatorClient;
use Pps\Server\AuthenticationHandler;
use Pps\Server\ChallengeGenerator;
use Pps\Storage\InMemoryStorage;
$storage = new InMemoryStorage();
$rpId = 'example.com';
$generator = new ChallengeGenerator();
$challenge = $generator->create($rpId);
$client = new AuthenticatorClient($clientState);
$pulse = $client
->rpId($rpId)
->nonce($challenge->nonceB64u)
->createPulse();
$handler = new AuthenticationHandler($storage);
$result = $handler->verify(
pulseToken: $pulse['token'],
rpId: $rpId,
nonceB64u: $challenge->nonceB64u,
trustCode: $pulse['trust_code']
);
if ($result->ok) {
$clientState = $pulse['new_client_state'];
}
After successful verification, the server updates:
current_pk = next_pk
key_seq = rot_seq
last_counter = pulse_counter
The client updates:
current_seed = next_seed
counter = pulse_counter
key_seq = rot_seq
pending_certs = pending_certs + new_rotation_certificate
After the server acknowledges success, the client may clear pending certificates.