Time-bound asymmetric authentication proofs for offline, OTP-style, transaction-signing, duress-aware, and multi-device authentication flows.
PulseProof Sentinel Protocol, abbreviated PPS, is an experimental authentication protocol that replaces shared-secret TOTP-style codes with signed, time-bound, asymmetric proofs called Pulses.
Instead of sharing a secret between client and server, the user’s device holds a private key. The server stores only the corresponding public key.
A Pulse can be bound to:
- a relying party identifier
- a time epoch
- a monotonic counter
- a server nonce
- a security policy
- a transaction hash
- environmental or proximity context
- an optional human-visible Trust Code and AmountMark
PPS is designed to be implementable across many technologies, including PHP, JavaScript, TypeScript, Python, Go, Rust, Java, Swift, Kotlin, and constrained embedded environments.
PulseProof Sentinel is not intended to replace WebAuthn/FIDO2.
WebAuthn/FIDO2 is an excellent protocol for browser-based, origin-bound, phishing-resistant authentication. Where a full WebAuthn ceremony is available, it is usually the preferred choice.
PPS targets operational gaps where WebAuthn is unavailable, insufficient, or difficult to deploy:
- offline or semi-offline authentication
- legacy OTP input forms
- QR-code and deep-link authentication
- hardware terminals and point-of-sale devices
- IoT and constrained devices
- systems without a full WebAuthn client stack
- human-visible transaction confirmation
- silent duress signaling
- offline multi-device threshold approval
In short:
WebAuthn is ideal for browser passkeys.
PPS is designed for OTP-like, offline, terminal, transaction, and constrained-device flows.
Traditional TOTP has several limitations:
TOTP = HMAC(shared_secret, time)
The server knows the shared secret. If the server database is compromised, OTP secrets may be exposed.
PPS changes the model:
Pulse = Sign(private_key, time + rp + nonce + counter + context + policy)
The server verifies using a public key.
This gives PPS several advantages:
- no shared OTP secret stored on the server
- stronger cryptographic proof than a 6-digit code
- replay protection using nonce, epoch, expiration, and counter
- service binding using RP identifier hash
- policy binding using dynamic policy negotiation
- transaction binding using transaction hash and AmountMark
- optional forward-secure key rotation
- optional silent duress signaling
- optional offline threshold co-signing
Each authentication event produces a signed Pulse.
The verifier stores only public keys.
PPS can generate and verify Pulses without requiring a live network round-trip, although nonce-based online mode is recommended when possible.
PPS can produce human-visible Trust Codes for legacy OTP-style input flows.
However, the full Pulse Token is strongly preferred over manual code entry.
For transaction signing, PPS can embed a two-digit amount checksum into the Trust Code.
Example:
Amount: 2,500,067 IRR
Trust Code: 49371867
The last two digits, 67, are derived from the transaction amount.
This helps users detect transaction tampering.
PPS supports an optional duress key.
If a user authenticates under coercion, the device can sign with a hidden duress key.
The server can return a normal-looking success response while internally:
- limiting sensitive operations
- blocking high-value transactions
- triggering a silent alert
- delaying settlement
- requesting step-up verification later
The attacker should not be able to distinguish a duress authentication from a normal one.
PPS supports optional offline multi-device approval.
Example:
Phone signs transaction
Watch signs transaction
Server requires both signatures
This is useful for high-value fintech, banking, crypto withdrawal, and administrative approval flows.
The server can issue a policy object:
{
"min_trust_digits": 8,
"require_biometric": true,
"require_secure_enclave": true,
"threshold": 2,
"max_amount_minor": 10000000,
"require_proximity": true
}The Pulse is cryptographically bound to the policy hash.
A Pulse can be bound to context such as:
- session identifier
- transaction hash
- BLE proximity beacon hash
- acoustic nonce hash
- device integrity hash
- application-specific context hash
This can increase resistance to relay and phishing attacks.
| Capability | SMS OTP | TOTP | Push 2FA | Challenge-Response OTP | WebAuthn / FIDO2 | PulseProof Sentinel |
|---|---|---|---|---|---|---|
| Server stores shared secret | Usually | Yes | Usually | Sometimes | No | No |
| Primary proof | Possession of SIM | HMAC shared secret | Proprietary app/server channel | HMAC or asymmetric challenge | Public-key signature | Public-key signature |
| Offline capable | No | Yes | No | Sometimes | Limited | Yes |
| Works with legacy OTP input fields | Yes | Yes | No | Sometimes | No | Yes |
| Phishing resistance | Low | Low | Medium | Medium | High | High when full Pulse Token is used |
| Replay protection | Weak | Time-window based | Server-controlled | Challenge-based | Strong | Strong |
| Transaction amount confirmation | No | No | Sometimes | Rare | Possible with payment extensions | Yes, with AmountMark |
| Silent duress support | No | No | Rare | No | No standard mechanism | Optional |
| Offline multi-device threshold approval | No | No | No | No | Limited | Optional |
| Suitable for constrained terminals | Low | High | Low | Medium | Low | High |
| Suitable for browser passkey flows | No | No | No | No | Excellent | Possible, but WebAuthn preferred |
| Open wire format | No | RFC 6238 | Usually proprietary | Varies | W3C standard | Yes |
PPS is not claiming to be better than WebAuthn for browser authentication.
WebAuthn is preferred when:
- the user is in a browser
- the RP can use platform authenticators
- passkeys are supported
- origin binding is available
PPS is designed for cases where WebAuthn is not enough or not practical.
A simplified PPS flow:
1. Relying Party creates a challenge
- nonce
- rp_id
- optional transaction hash
- optional policy object
2. Authenticator receives challenge
- via QR code, deep link, SDK, or manual context
3. Authenticator signs a Pulse
- time epoch
- rp_id hash
- nonce
- counter
- policy hash
- context hash
- next public key, if ratcheting
4. Authenticator displays optional Trust Code / AmountMark
5. Relying Party verifies:
- signature
- rp binding
- nonce
- epoch
- expiration
- counter
- policy
- context
- amount mark
- rotation state
6. Authentication or transaction approval succeeds
Website:
Sign in to example.com
Scan this QR code with your PPS authenticator.
Authenticator app:
Login request
Service: example.com
Device: Phone
Risk: Normal
Trust Code: 493718
Trust Phrase: river bronze lantern
[Reject] [Approve]
Authenticator app:
Withdrawal request
Amount: 2,500,067 IRR
To: IR820540102680020817909002
Service: example.com
Trust Code: 49371867
[Reject] [Approve Withdrawal]
The last two digits of the Trust Code match the last two digits of the amount.
| Module | Description | Status |
|---|---|---|
| Core Pulse | Ed25519-signed time-bound authentication proof | Specified |
| Verifiable Ratchet | Forward-secure key rotation using signed next public key | Specified |
| Silent Duress | Hidden duress key producing Honey-Pulse | Specified |
| Threshold Mode | Offline n-of-m multisig approval | Specified |
| Context Binding | Bind Pulse to session, transaction, BLE, acoustic, or device context | Specified |
| Policy Binding | Bind Pulse to dynamic server policy | Specified |
| AmountMark | Embed transaction amount checksum into Trust Code | Specified |
| Trust Phrase | Optional human-friendly word phrase | Specified |
The mandatory profile for PPS version 1 is:
PPS-ED25519-CBOR30
It uses:
| Component | Value |
|---|---|
| Signature algorithm | Ed25519 |
| Hash algorithm | SHA-256 |
| KDF | HKDF-SHA256 |
| Canonical encoding | Deterministic CBOR |
| Text encoding | base64url without padding |
| Default epoch length | 30 seconds |
Optional post-quantum and hybrid profiles may be defined in future revisions.
PPS is currently an experimental specification.
Reference implementations are planned or in progress.
| Language | Package / Directory | Status |
|---|---|---|
| PHP | pps-php |
Planned |
| JavaScript | pps-js |
Planned |
| Python | pps-python |
Planned |
| Go | pps-go |
Planned |
| Rust | pps-rust |
Planned |
Implementers should not use PPS in production without independent security review.
Implementations should use well-reviewed cryptographic libraries.
ext-sodium
paragonie/sodium_compat
spomky-labs/cbor-php
ext-gmp
@noble/ed25519
@noble/hashes
cbor-x
Web Crypto API where appropriate
cryptography
cbor2
crypto/ed25519
fxamacker/cbor
ed25519-dalek
sha2
hkdf
ciborium
Do not implement Ed25519, HKDF, SHA-256, or CBOR from scratch unless absolutely necessary.
This repository currently contains or will contain:
.
├── README.md
├── SPEC.md
├── SECURITY.md
├── LICENSE
├── CONTRIBUTING.md
├── CODE_OF_CONDUCT.md
├── CHANGELOG.md
├── docs/
│ ├── overview.md
│ ├── comparison.md
│ ├── threat-model.md
│ ├── implementers-guide.md
│ ├── faq.md
│ └── ietf.md
├── cddl/
│ └── pps.cddl
├── examples/
│ ├── php/
│ ├── js/
│ └── python/
├── test-vectors/
│ └── README.md
└── interop/
└── README.md
If you want to implement PPS:
- Read
SPEC.md. - Implement deterministic CBOR encoding.
- Implement Ed25519 signing and verification.
- Implement HKDF-based Trust Code derivation.
- Implement nonce, epoch, counter, and expiration validation.
- Implement policy and context hash verification.
- Add rate limiting and secure key storage.
- Test against published test vectors.
For high-security deployments, prefer full Pulse Token transmission over manual Trust Code entry.
PPS is experimental.
It has not been independently audited.
Do not use it in production systems without:
- cryptographic review
- security audit
- interoperability testing
- threat modeling
- key-management review
- operational rate limiting
- secure key storage
- duress-response testing
PPS is designed to improve security against:
- shared-secret database leakage
- TOTP replay within time windows
- simple OTP phishing
- transaction tampering
- lack of silent duress signaling
- single-device compromise in high-value flows
PPS does not magically prevent:
- malware that tricks users into approving malicious transactions
- full device compromise with live key extraction
- coercion where the user reveals all secrets
- social engineering
- poor implementation
- weak key storage
- missing rate limiting
Security depends on implementation and deployment.
PulseProof Sentinel builds on many existing ideas and standards, including:
- TOTP / HOTP
- OATH OCRA
- WebAuthn / FIDO2
- Ed25519
- CBOR
- HKDF
- Signal-style ratcheting concepts
- threshold signatures and multisignatures
- duress PIN and hidden-account concepts
- transaction signing in banking and payment systems
PPS does not claim that these individual mechanisms are new.
Its contribution is an interoperable protocol profile that combines them into a compact, technology-agnostic wire format for offline, OTP-like, transaction-signing, duress-aware, and threshold authentication flows.
PPS is submitted as an individual Internet-Draft:
draft-hezami-pulseproof-sentinel
Datatracker:
https://datatracker.ietf.org/doc/draft-hezami-pulseproof-sentinel/
Feedback is welcome, especially on:
- scope relative to WebAuthn/FIDO2
- forward-secure ratchet design
- duress signaling model
- threshold mode
- CBOR wire format
- Trust Code derivation
- transaction binding
- implementation feasibility across languages
Contributions are welcome.
Please read:
For security vulnerabilities, do not open a public issue. Please follow the private reporting process described in SECURITY.md.
Unless otherwise noted:
- Code in this repository is licensed under the Apache License 2.0.
- Documentation is licensed under CC-BY 4.0.
- Internet-Draft text is subject to IETF Trust provisions.
See LICENSE for details.
“PulseProof Sentinel” is the name of this protocol project.
This project is independent and is not affiliated with any existing product or service using a similar name.
If you believe there is a naming conflict, please open an issue or contact the maintainers.
This protocol is experimental and provided as-is.
Use at your own risk.