@nsec/keyring
v0.4.0
Published
OS Keyring and secure credential storage for NullSec / ZVault
Readme
@nsec/keyring
OS Keyring & Secure Credential Storage Provider for NullSec / ZVault
Overview • Installation • Storage Providers • Usage Examples • Security Model
Overview
@nsec/keyring manages secure storage and retrieval of private keys, identity pairs, and access tokens for developer workstations, headless CI/CD containers, and testing harnesses.
Key capabilities:
- Native OS Credential Stores: Direct integration with macOS Keychain, Windows Credential Manager, and Linux Secret Service / DBus via
@napi-rs/keyring. - Automatic Headless Fallback: Automatically falls back to a POSIX permission-hardened encrypted file store (
0o600on credentials file,0o700on directory) when running in SSH, Docker, or headless environments without DBus/X11. - In-Memory Store: Ephemeral credential store for hermetic automated tests and stateless operations.
Installation
# With npm
npm install @nsec/keyring
# With pnpm
pnpm add @nsec/keyring
# With yarn
yarn add @nsec/keyringStorage Providers
@nsec/keyring provides three implementations of the KeyringStorage interface:
| Provider | Backend | Typical Environment | Persistence |
|---|---|---|---|
| OSKeyringProvider | macOS Keychain, Windows Credential Vault, Linux Secret Service / KWallet | Developer workstations | Persistent |
| FileStorageProvider | ~/.nullsec/credentials.json (0o600 mode, atomic writes) | Headless servers, SSH sessions, Docker | Persistent |
| MemoryStorageProvider | JavaScript Map in memory | Unit & integration testing | Process lifetime |
Usage Examples
1. Unified Factory (createCredentialStore)
The recommended way to instantiate a store. By default, it attempts to use the OS Keyring and transparently falls back to FileStorageProvider if the OS Keyring is unavailable:
import { createCredentialStore } from '@nsec/keyring';
// Automatically selects OS Keyring with file fallback
const store = await createCredentialStore({
serviceName: 'nullsec',
fallbackToFile: true // default: true
});
// Save user credentials
await store.saveCredentials('[email protected]', {
keyId: 'id-alice',
privateKey: '-----BEGIN PRIVATE KEY-----\n...',
publicKey: '-----BEGIN PUBLIC KEY-----\n...',
email: '[email protected]',
serverUrl: 'https://vault.internal.net'
});
// Retrieve credentials
const creds = await store.getCredentials('[email protected]');
if (creds) {
console.log(`Loaded private key for ${creds.email}`);
}
// List all registered accounts
const accounts = await store.listAccounts();
// Delete credentials
await store.deleteCredentials('[email protected]');2. Explicit File Storage (FileStorageProvider)
Useful for Docker containers or custom CI machines where an explicit config path is desired:
import { FileStorageProvider } from '@nsec/keyring';
const fileStore = new FileStorageProvider('/custom/path/credentials.json');
await fileStore.saveCredentials('ci-runner', {
keyId: 'ci-runner',
privateKey: process.env.RUNNER_PRIVATE_KEY!
});3. Ephemeral Testing Store (MemoryStorageProvider)
import { MemoryStorageProvider } from '@nsec/keyring';
const memoryStore = new MemoryStorageProvider();
await memoryStore.saveCredentials('test-user', {
keyId: 'test-1',
privateKey: 'dummy-key'
});Security Model
- OS Keyring Priority: Where available, hardware-backed or OS-isolated credential vaults are prioritized so private keys remain protected behind OS user logins and biometric prompts (e.g. Touch ID).
- Hardened File Storage: In headless environments, credentials written by
FileStorageProviderare created via an atomic write-and-rename pattern with strict POSIX permissions:- Directory:
0o700(rwx------) - File:
0o600(rw-------) This prevents other non-root system users on shared Linux hosts from reading identity files.
- Directory:
