I built NovaKey because I wanted a better answer to a deceptively simple security problem: how do I use a high-value secret on a computer without routinely typing that secret on the computer keyboard or placing it into the workstation clipboard as part of the normal workflow?
The obvious examples are master passwords, recovery keys, long administrative credentials, API tokens, and other secrets that are both difficult to memorize and expensive to expose. A password manager solves the storage problem very well, but the moment a secret is needed by an application, the secret still has to cross a boundary from secure storage into the destination process. That transition is where the architecture becomes interesting.
NovaKey approaches the problem by treating the phone as the trusted secret origin and the desktop as the delivery target. The iOS application stores secrets in the iOS Keychain, requires explicit user authentication before release, and sends the selected secret directly to a paired NovaKey daemon running on the computer. The daemon then evaluates a series of security controls before attempting to place the secret into the focused application.
NovaKey is designed to reduce unnecessary secret handling on the workstation, protect secrets in transit, require explicit user intent, and constrain where delivery can occur. It does not claim that a secret remains safe after delivery to a fully compromised computer.
The Security Problem I Wanted to Solve
High-value secrets are awkward because security and usability pull in opposite directions. The strongest password is useless if I cannot reliably enter it when I need it. The easiest secret to type is often the easiest secret to guess, reuse, observe, or capture. Clipboard-based workflows are convenient, but they deliberately place the secret into a shared operating-system facility that other software may be able to inspect.
A different approach is to keep the secret on a device that already has strong local security controls and release it only at the moment of use. Modern phones are well suited to that role because they provide secure key storage, biometric or passcode authorization, and an interface that is physically separate from the computer receiving the secret.
That does not remove the destination computer from the trust model. The computer ultimately needs the plaintext secret in order to submit it to an application. The goal is therefore narrower: minimize how long and how broadly the secret is exposed, authenticate the path used to deliver it, and create controls around the final injection action.
Start With the Threat Model
One of the most important decisions I made was to document the threat model instead of allowing the cryptography to become the threat model by implication. Strong algorithms do not automatically produce a secure system. The system has to define what it trusts, what it distrusts, and what happens when one of those assumptions fails.
iOS Device
The phone is the root of trust for secret storage and user intent. Secrets are protected by iOS Keychain controls and release is gated by Face ID or the device passcode.
Paired Daemon
The daemon is explicitly paired and trusted to receive a secret, evaluate local policy, and inject it into the active application. Pairing credentials are protected locally where the OS allows it.
Network
The local network is treated as untrusted. Passive capture, active tampering, replay attempts, unauthorized clients, and opportunistic pairing are all threats the protocol is intended to resist.
Compromised Endpoint
A fully compromised host operating system, same-user malware, a hardware keylogger, or a compromised build pipeline is outside the daemon threat model. If the destination host is fully controlled by an attacker, the delivered secret can ultimately be captured there.
This distinction matters. A statement such as "the desktop may be hostile" can easily be interpreted too broadly. NovaKey reduces exposure to some desktop-side threats and avoids ordinary keyboard entry, but a host with sufficient privileges can observe application memory, hook input paths, capture the screen, or interfere with the daemon itself. The daemon security policy deliberately describes a fully compromised host as game-over.
Architecture at a Glance
The current design is intentionally local. NovaKey does not require a vendor-operated cloud service for its core secret-delivery path. The phone connects directly to the paired computer, and the daemon listens for two protocol routes on a single TCP listener: pairing traffic and encrypted message traffic.
The separation between these stages is important. Storage security, user authentication, transport security, message authentication, authorization, and secret injection are different problems. NovaKey treats them as different control layers instead of expecting one cryptographic operation to solve all of them.
The Phone as the Secret Origin
On iOS, NovaKey stores saved secrets in the Keychain. After a secret is saved, the application does not display it back to the user as ordinary plaintext. Copying or sending a secret requires Face ID or the device passcode. Pairing credentials are also stored in the Keychain.
This creates a useful trust boundary. The secret is not sitting in a configuration file on the workstation waiting to be used, and the user does not need to repeatedly type a master secret on the desktop keyboard. The phone becomes the place where the user makes the release decision.
The security benefit comes from reducing exposure paths, not from moving all trust to the phone. A compromised or jailbroken phone is outside the iOS threat model. The application also cannot protect a secret after a correctly authenticated release if the receiving endpoint is malicious or fully compromised.
Pairing: Establishing Trust Before Sending Secrets
Secret delivery only makes sense if the phone knows which computer it is talking to and the computer knows which phone is authorized to send messages. NovaKey establishes that relationship through an explicit pairing process instead of relying on LAN discovery or an unauthenticated first connection.
When the daemon has no paired devices, it can enter pairing mode and generate a QR code. The pairing flow uses the same TCP listener as normal messages, but the connection begins with a route preface identifying it as pairing traffic:
NOVAK/1 /pair
At a high level, the pairing sequence works like this:
- The phone obtains a one-time pairing token from the QR workflow and connects to the daemon.
- The daemon provides its ML-KEM public key, an expiration time, and a short fingerprint.
- The client verifies that the fingerprint of the public key matches the fingerprint associated with the QR pairing data.
- The phone creates a device identifier and a 32-byte per-device key.
- The registration payload is protected using ML-KEM-768, HKDF-SHA-256, and XChaCha20-Poly1305.
- The daemon stores the paired device credential and the iOS application stores the pairing information in the Keychain.
The one-time pairing token is 128 bits, expires, and is consumed during a successful pairing handshake. The daemon also limits pairing hello attempts by source IP. These controls are intended to make opportunistic pairing by another system on the same network significantly harder.
The iOS application also binds pairing to a specific server address. After pairing, the host or IP cannot simply be edited in place; moving to a different address requires creating a new listener and pairing again. That is a deliberate tradeoff against silent redirection.
Protocol v3: Key Establishment Is Not Payload Encryption
NovaKey protocol v3 uses three cryptographic building blocks for normal /msg traffic. I think it is worth being precise about what each one does because phrases like "post-quantum encryption" often collapse several different operations into one marketing sentence.
ML-KEM is a key-encapsulation mechanism. It is used to establish shared key material; it is not what directly encrypts the password string. NIST standardized ML-KEM in FIPS 203 in August 2024, with ML-KEM-512, ML-KEM-768, and ML-KEM-1024 as the standardized parameter sets. NovaKey uses ML-KEM-768.
For each normal message, the client performs an ML-KEM encapsulation against the daemon's public key. The resulting KEM shared secret becomes input to HKDF-SHA-256. The paired device's 32-byte device key is used as the HKDF salt and a protocol-specific information string separates this derivation from other potential uses of the same material.
K = HKDF-SHA256(
IKM = kemShared,
salt = deviceKey,
info = "NovaKey v3 AEAD key",
outLen = 32 bytes
)
That derived key is then used with XChaCha20-Poly1305. XChaCha20-Poly1305 provides confidentiality and integrity: an attacker who modifies the protected data cannot simply create a different valid plaintext without causing authentication to fail.
The outer protocol header is also supplied as authenticated associated data. This means fields required for routing and parsing can remain outside the encrypted plaintext while still being integrity protected by the AEAD operation.
Typed Messages Instead of an Untyped Secret Blob
After decryption, NovaKey does not treat every valid packet as "type these bytes." Protocol v3 requires a versioned inner message frame containing the device identifier, a message type, and an optional payload. The daemon currently understands four message types:
- Inject - deliver a secret payload.
- Approve - satisfy the optional two-man approval gate.
- Arm - open a time-limited injection window.
- Disarm - close the armed state.
The device identifier inside the authenticated plaintext is validated against the outer device identity. This is a small but useful example of defensive protocol design: do not assume that because two fields arrived together they are automatically consistent.
Freshness, Replay Resistance, and Abuse Controls
Encryption alone does not stop an attacker from recording a valid encrypted packet and replaying it later. A password injection protocol needs to care about message freshness because a perfectly authentic old "inject" command may still be dangerous if it can be reused.
NovaKey includes a Unix timestamp in the encrypted plaintext, applies freshness checks on the daemon, tracks nonces for replay protection, and applies per-device rate limiting. These controls operate in addition to the authenticated encryption rather than as a substitute for it.
The result is a layered validation path. Before the daemon considers injection, it has already checked protocol framing, cryptographic authenticity, device identity consistency, freshness, replay state, and rate limits.
Cryptography Is Not Authorization
One of my favorite architectural properties in the daemon is this rule: successful cryptographic validation does not imply injection will occur.
A message can be completely valid from a cryptographic perspective and still be rejected by local policy. The daemon evaluates independent safety gates after decryption but before secret delivery. Depending on configuration, those controls can include:
- Arming / push-to-type
- Two-man approval
- Maximum injection length
- Newline restrictions
- Allowed process names
- Denied process names
- Allowed window-title rules
- Denied window-title rules
- Clipboard fallback policy
- Auto-typing fallback policy
The arming gate can require the daemon to be placed into a time-limited armed state before an injection is accepted. A successful injection can consume that state. This helps prevent an unattended client from continuously sending secrets into whichever application happens to be focused.
Two-man mode adds a separate approval window. An Approve message must be received before an Inject message is accepted, and approval can be scoped per device and consumed after use. This is particularly useful as an example of authorization layered on top of authentication: proving who sent a command is different from deciding whether the command is currently permitted.
Injection Is Where Security Becomes an Operating-System Problem
Transporting the secret securely is only half of the problem. Eventually the secret has to cross into the application that needs it, and Windows, macOS, X11, and Wayland do not expose identical mechanisms for doing that.
The daemon prioritizes direct injection into the focused control. If direct injection is not possible, optional fallback behavior can be enabled. The important point is that fallback is part of policy and the client receives a distinct outcome instead of the daemon silently changing security behavior.
| Outcome | Behavior | Security Consideration |
|---|---|---|
| Direct injection | The daemon inserts the secret into the focused control without using clipboard or auto-typing fallback. | Preferred path where supported, although the destination application still receives plaintext. |
| Auto-typing fallback | The daemon generates synthetic input using operating-system APIs. | May be visible to keyloggers or software with sufficient privileges. Can be disabled. |
| Clipboard paste injection | The daemon places the secret on the clipboard and performs a paste action. | Expands exposure to clipboard-accessible processes. Requires explicit policy. |
| Clipboard-only fallback | The secret is copied locally and the user performs the paste. | Degraded path is explicit and visible rather than silently presented as direct injection. |
Wayland is a good example of the tension between platform security and automation. Wayland intentionally restricts many global input and window-inspection behaviors that are common under X11. When NovaKey cannot determine or inject into the active target under Wayland, it fails deterministically and can use a clipboard fallback only when that behavior has been explicitly enabled.
Clipboard Fallback Is a Policy Decision
I did not want clipboard usage to become an invisible implementation detail. If the architecture is intended to reduce unnecessary secret exposure, silently copying every secret into the clipboard whenever injection becomes inconvenient would undermine the design goal.
The daemon therefore separates two clipboard decisions. One setting controls whether the clipboard may be used when delivery is blocked by an arming gate or target policy. Another controls whether clipboard fallback may occur after an otherwise authorized injection attempt fails. Both can be disabled.
The iOS app also treats clipboard use as a distinct user action rather than background behavior. This does not make the clipboard inherently safe. It makes the security transition visible and configurable, which is an architectural improvement over an implicit fallback.
Protecting Paired Device Credentials on the Daemon
Pairing creates a per-device static secret used as part of subsequent authentication and key derivation. That credential becomes sensitive local state on the computer, so the daemon has to protect more than the secrets being delivered.
On Windows, NovaKey seals the device store using DPAPI and ties it to the local user context. On macOS and Linux, the preferred path is a sealed wrapper encrypted with XChaCha20-Poly1305 using a sealing key obtained through the operating-system keyring.
Linux services complicate this. A headless service, hardware-token-backed login, or session without usable keyring access may prevent the daemon from retrieving the sealing key. The configuration therefore exposes the tradeoff rather than hiding it. An environment can require a sealed store and fail closed when secure storage is unavailable, or explicitly permit a plaintext device file protected with strict file permissions when operational requirements demand it.
Cross-Platform Engineering Changes the Threat Surface
NovaKey-Daemon is written in Go, but secret injection is necessarily platform-specific. Networking, protocol validation, policy evaluation, configuration, logging, and much of the security logic can remain shared. The final interaction with the focused application cannot.
Windows, macOS, Linux/X11, and Linux/Wayland have different APIs, permission models, and automation constraints. That means "cross-platform" security software should not pretend every platform provides the same guarantees. A direct injection path on one operating system may require auto-typing or clipboard fallback on another. Focused-window detection may be reliable in one session type and unavailable in another.
The daemon reports those outcomes differently so the client can distinguish a successful direct injection from a degraded clipboard path. That is both a usability feature and a security control because the user is not forced to infer which mechanism actually handled the secret.
Why the Cryptographic Protocol Logic Lives in Go
NovaKey also has an implementation problem that is easy to overlook: the iOS client is written in Swift, while the daemon is written in Go. Reimplementing a custom binary protocol and its cryptographic framing independently in two languages creates an obvious opportunity for drift, parsing bugs, or subtly different security behavior.
I created NovaKeyKEMBridge to keep the client-side protocol construction in Go and expose it to the iOS application as an XCFramework generated with golang.org/x/mobile/bind. The bridge builds inject, approve, arm, disarm, and pairing frames using the same protocol rules and cryptographic libraries used by the Go ecosystem.
This does not eliminate the need for testing at the Swift boundary, but it reduces the number of independent implementations of the security-critical framing logic. It also creates a clean architectural boundary: Swift manages the application experience, Keychain interaction, biometrics, listeners, and user intent while the Go bridge handles the wire-format cryptography.
Why I Made the Security-Critical Components Open Source
NovaKey is handling exactly the kind of data where "trust me" is not a satisfying architecture. The daemon, iOS client, and KEM bridge are public so the behavior can be reviewed. The protocol and security documents are also published alongside the code.
Open source does not make a binary trustworthy by itself. It does not prevent a compromised build pipeline, guarantee that a distributed binary matches the source, or protect a user who installs a malicious fork. What it does provide is auditability. Reviewers can inspect whether the application is making unexpected network calls, whether secrets are logged, how pairing is performed, what the fallback behavior actually does, and whether the documented cryptographic design matches the implementation.
For NovaKey specifically, open source reinforces another design choice: the core workflow does not require a NovaKey account, analytics service, or vendor-operated secret relay. The trust relationship is between the user's phone and the computer the user explicitly paired.
What NovaKey Does Not Protect Against
Security writing becomes less useful when every control is described as if it provides absolute protection. NovaKey has explicit non-goals and failure boundaries.
- Fully compromised desktop: malware with sufficient privilege can observe or alter what happens after the secret arrives. The daemon threat model considers a compromised host game-over.
- Fully compromised or jailbroken iPhone: the phone is a root of trust. If that root is lost, NovaKey cannot restore it through network cryptography.
- Malicious paired listener: pairing authorizes a destination to receive secrets. A user who deliberately pairs with an attacker has authorized the wrong trust relationship.
- Compromised build pipeline: open source improves reviewability but does not automatically guarantee the integrity of every produced artifact.
- Pairing QR exposure during its valid window: pairing material is security-sensitive and must be treated that way.
- Destination application compromise: the application receiving the secret eventually possesses that secret in plaintext.
These limitations do not make the architecture pointless. They define the set of risks NovaKey is actually trying to reduce: keyboard exposure, unnecessary clipboard use, unauthenticated network delivery, message tampering, replay, unauthorized senders, and unintended injection into disallowed targets.
Security Architecture Lessons From Building NovaKey
The most valuable part of building NovaKey was not selecting cryptographic algorithms. It was forcing every part of the workflow to answer a different security question.
- Where should the secret live? On the trusted phone in the iOS Keychain during normal storage.
- Who is allowed to release it? The user, after local biometric or passcode authorization.
- Which destination is trusted? A computer established through explicit pairing and server-key fingerprint verification.
- How is the network treated? As untrusted, with authenticated encryption and freshness controls around every message.
- Does an authentic command automatically execute? No. Local authorization and safety policy are evaluated after cryptographic validation.
- What happens when the preferred injection method is unavailable? The daemon reports a different outcome and only uses enabled fallbacks.
- Where do the guarantees end? At the point where a fully compromised trusted endpoint controls the secret's execution environment.
That is the broader pattern I would reuse in other security-sensitive systems. Separate authentication from authorization. Separate key establishment from payload encryption. Separate transport security from endpoint security. Treat fallback behavior as part of the threat model. Document residual risk instead of burying it.
NovaKey Project Repositories
The security-critical components discussed in this article are available publicly for review:
Additional daemon installation and pairing documentation is available through the NovaKey App documentation.
Final Thoughts
NovaKey started as a solution to a personal workflow problem, but building it became a much broader security architecture exercise. The difficult questions were not "which cipher should I use?" They were questions about trust, user intent, pairing, endpoint behavior, degraded operating modes, secure local state, and the point at which the system should refuse to continue.
The resulting architecture uses modern cryptography, including ML-KEM-768 for per-message key establishment, but the cryptography is only one layer. The more important pattern is defense in depth: Keychain storage, biometric release, explicit pairing, authenticated messages, freshness and replay controls, rate limiting, local authorization gates, focused-target policy, configurable injection behavior, secure device-store handling, and a documented threat model around all of it.
A security system is not defined by its strongest primitive. It is defined by the complete path a secret takes, the trust decisions made along that path, and what the system does when one of those assumptions fails.
That is the part of NovaKey I consider most valuable as an engineering project: not that it moves a secret from a phone to a computer, but that the entire path can be reasoned about as a security architecture.
Tags: NovaKey, security architecture, post-quantum cryptography, ML-KEM-768, XChaCha20-Poly1305, secure pairing, secret management, iOS Keychain, threat modeling, CISSP
Published & Last Updated: August 22, 2026
Author: Robert H. Osborne