revault_api 0.3.12 copy "revault_api: ^0.3.12" to clipboard
revault_api: ^0.3.12 copied to clipboard

Typed Dart FFI bindings for encrypted reVault lockboxes, credentials, keys, form records, and local vault metadata on Linux, macOS, and Windows.

reVault for Dart #

revault_api provides typed Dart bindings for creating and opening encrypted reVault Lockbox archives and managing the user's persistent local Vault. The native core is implemented in Rust, while the public API uses Dart classes and explicitly owned secret values.

The Dart package supports Dart and Flutter desktop applications on Linux, macOS, and Windows, on both x86-64 and ARM64. It does not currently support Dart web applications: this binding uses dart:ffi and dart:io. Projects targeting browsers or WebAssembly should use the JavaScript/WASM package.

Installation #

Add the current package from pub.dev:

dart pub add revault_api

Then load the bundled native runtime once during application startup:

import 'package:revault_api/revault_api.dart';

Future<void> main() async {
  await Revault.load();
  // Vault, Lockbox, and AgentSession are now ready to use.
}

The current release is 0.3.12. Normal applications do not need to download a native library or set an environment variable; the package build hook bundles the correct native carrier.

Create a Vault and Lockbox in Dart #

The following setup creates or opens a Vault, creates a password-protected Lockbox, and stores the Lockbox password inside the encrypted Vault. It uses SecretString.fromString to keep the example self-contained. A production password prompt should supply owned UTF-8 bytes to SecretString.takeUtf8 so the original input buffer can also be wiped.

import 'dart:io';

import 'package:revault_api/revault_api.dart';

Future<void> main() async {
  await Revault.load();

  final workspace = Directory('.revault-example')..createSync();
  final vaultPassphrase = SecretString.fromString('replace-this-passphrase');
  final lockboxPassword = SecretString.fromString('replace-this-password');
  final vault = Vault.openOrCreate(
    pathTo: '${workspace.path}/vault',
    passphrase: vaultPassphrase,
  );

  try {
    final path = '${workspace.path}/team-secrets.lbox';
    final lockbox = File(path).existsSync()
        ? Lockbox.open(path, password: lockboxPassword)
        : Lockbox.create(path, password: lockboxPassword);
    try {
      lockbox.setDescription('Team deployment credentials');
      lockbox.commit();
      vault.rememberPassword(lockbox.id, lockboxPassword);
    } finally {
      lockbox.close();
    }
  } finally {
    vault.close();
    lockboxPassword.close();
    vaultPassphrase.close();
  }
}

A complete runnable version with interactive password prompts is included in example/getting_started.dart.

Create a Vault and Lockbox with the CLI #

The reVault CLI and Dart binding use the same Vault and Lockbox formats. Install the CLI, initialize the default Vault and profile, and create a Lockbox for that profile:

cargo install revault_cli
lbx vault init
lbx team-secrets.lbox create \
  --description 'Team deployment credentials'

The CLI prints recovery material during Vault initialization. Store that material securely: losing both the Vault and its recovery material can make profile-protected Lockboxes unrecoverable.

The Dart application can then open the CLI-created Vault and Lockbox using the Vault passphrase:

import 'package:revault_api/revault_api.dart';

Future<void> openExisting(SecretString vaultPassphrase) async {
  await Revault.load();
  final vault = Vault.open(passphrase: vaultPassphrase);
  try {
    final lockbox = Lockbox.open('team-secrets.lbox', vault: vault);
    try {
      print(lockbox.description);
      print(lockbox.list('/', recursive: true));
    } finally {
      lockbox.close();
    }
  } finally {
    vault.close();
  }
}

Core API concepts #

  • Revault loads the process-wide native runtime and provides key-generation, import, export, and format utilities.
  • Vault is the persistent encrypted store for profiles, private keys, contacts, signing keys, and remembered Lockbox credentials and metadata.
  • Lockbox is a portable encrypted .lbox archive containing files, variables, secrets, and structured forms.
  • AgentSession controls the optional session-agent process and its temporary cache of decrypted Lockbox content keys.

Passwords and passphrases use SecretString; binary keys use SecretBytes. Both own wipeable byte storage and must be closed. SecretString.fromString cannot erase the immutable Dart String used to create it, so password-input adapters should return owned UTF-8 bytes for SecretString.takeUtf8 whenever possible.

Use the optional session agent #

Ordinary Lockbox.open calls are process-local and never start or contact the agent. Use AgentSession explicitly for CLI-style or multi-process workflows:

final agent = AgentSession.instance;
agent.start();
agent.keepOpenWithPassword(
  'team-secrets.lbox',
  lockboxPassword,
  duration: const Duration(minutes: 30),
);

final lockbox = agent.acquireOpenLockbox('team-secrets.lbox');
try {
  print(lockbox.list('/', recursive: true));
} finally {
  lockbox.close();
}

agent.closeLockbox('team-secrets.lbox');

The agent stores a temporary content key, not an open file handle. Acquiring a Lockbox does not extend the agent entry's lifetime. The returned process-local handle owns an independent key and remains usable after agent expiry until it is closed.

Lockbox descriptions #

A Lockbox can carry a human-readable description of its purpose. The text is stored inside the encrypted archive rather than its public header, so it can be read only after the Lockbox is opened.

lockbox.setDescription(
  'Production deployment credentials and recovery material',
);
lockbox.commit();
print(lockbox.description);

lockbox.clearDescription();
lockbox.commit();

Platform credentials and unattended access #

Vault.rememberPassphrase stores the Vault passphrase in the operating-system credential store. On platforms without per-use user-presence enforcement, any process able to access that user's platform credentials may be able to retrieve it. This grants unattended access to the Vault and every Lockbox for which the Vault contains a usable credential.

Remembered Lockbox passwords remain encrypted inside the Vault; they are not stored as independent operating-system credentials. With no explicit credential, Lockbox.open(path) opens the default Vault using its platform-stored passphrase and asks the Vault for a matching Lockbox password or profile key. It does not persist a raw content key or contact the session agent.

Agent expiry and AgentSession.closeAll() are therefore not authentication boundaries while the Vault passphrase remains retrievable without interaction. The agent provides stronger isolation when the user unlocks the Vault interactively, retains only selected Lockbox keys in the agent, and then closes the Vault.

For services launched with sudo, see Opening a reVault Vault after sudo.

Native library loading #

Revault.load() normally loads the target-specific carrier supplied by the package. An application installer that deliberately maintains one shared carrier can provide its path explicitly:

await Revault.load(
  nativeLibraryPath: '/opt/my_app/lib/librevault_api.so',
);

Resolution order is an explicit path, a non-empty inherited REVAULT_LIBRARY, and then the package carrier. A library name rather than a path delegates lookup to the operating system's normal library search rules.

More information #

0
likes
0
points
701
downloads

Publisher

unverified uploader

Weekly Downloads

Typed Dart FFI bindings for encrypted reVault lockboxes, credentials, keys, form records, and local vault metadata on Linux, macOS, and Windows.

Homepage
Repository (GitHub)
View/report issues

Topics

#encryption #credentials #archive #security #ffi

License

unknown (license)

Dependencies

code_assets, ffi, flat_buffers, hooks

More

Packages that depend on revault_api