uv/crates/uv-keyring
John Mumm 880eb286e8
Add new uv-keyring crate that vendors the keyring-rs crate (#14725)
This PR is a first step toward support for storing credentials in the
system keyring. The `keyring-rs` crate is the best option for system
keyring integration, but the latest version (v4) requires either that
Linux users have `libdbus` installed or that it is built with `libdbus`
vendored in. This is because v4 depends on
[dbus-secret-service](https://github.com/open-source-cooperative/dbus-secret-service),
which was created as an alternative to
[secret-service](https://github.com/open-source-cooperative/secret-service-rs)
so that users are not required to use an async runtime. Since uv does
use an async runtime, this is not a good tradeoff for uv.

This PR:
* Vendors `keyring-rs` crate into a new `uv-keyring` workspace crate
* Moves to the async `secret-service` crate that does not require
clients on Linux to have `libdbus` on their machines. This includes
updating `CredentialsAPI` trait (and implementations) to use async
methods.
* Adds `uv-keyring` tests to `cargo test` jobs. For `cargo test |
ubuntu`, this meant setting up secret service and priming gnome-keyring
as an earlier step.
* Removes iOS code paths
* Patches in @oconnor663 's changes from his [`keyring-rs`
PR](https://github.com/open-source-cooperative/keyring-rs/pull/261)
* Applies many clippy-driven updates
2025-08-15 15:57:56 +02:00
..
src Add new uv-keyring crate that vendors the keyring-rs crate (#14725) 2025-08-15 15:57:56 +02:00
tests Add new uv-keyring crate that vendors the keyring-rs crate (#14725) 2025-08-15 15:57:56 +02:00
Cargo.toml Add new uv-keyring crate that vendors the keyring-rs crate (#14725) 2025-08-15 15:57:56 +02:00
README.md Add new uv-keyring crate that vendors the keyring-rs crate (#14725) 2025-08-15 15:57:56 +02:00

uv-keyring

This is vendored from keyring-rs crate commit 9635a2f53a19eb7f188cdc4e38982dcb19caee00.

A cross-platform library to manage storage and retrieval of passwords (and other secrets) in the underlying platform secure store, with a fully-developed example that provides a command-line interface.

Usage

You can use the Entry::new function to create a new keyring entry. The new function takes a service name and a user's name which together identify the entry.

Passwords (strings) or secrets (binary data) can be added to an entry using its set_password or set_secret methods, respectively. (These methods create or update an entry in the underlying platform's persistent credential store.) The password or secret can then be read back using the get_password or get_secret methods. The underlying credential (with its password/secret data) can then be removed using the delete_credential method.

use keyring::{Entry, Result};

fn main() -> Result<()> {
    let entry = Entry::new("my-service", "my-name")?;
    entry.set_password("topS3cr3tP4$$w0rd").await?;
    let password = entry.get_password().await?;
    println!("My password is '{}'", password);
    entry.delete_credential().await?;
    Ok(())
}

Errors

Creating and operating on entries can yield a keyring::Error which provides both a platform-independent code that classifies the error and, where relevant, underlying platform errors or more information about what went wrong.

Platforms

This crate provides built-in implementations of the following platform-specific credential stores:

  • Linux, FreeBSD, OpenBSD: The DBus-based Secret Service.
  • macOS: Keychain Services.
  • Windows: The Windows Credential Manager.

It can be built and used on other platforms, but will not provide a built-in credential store implementation; you will have to bring your own.

Platform-specific issues

If you use the Secret Service as your credential store, be aware that every call to the Secret Service is done via an inter-process call, which takes time (typically tens if not hundreds of milliseconds).

If you use the Windows-native credential store, be careful about multi-threaded access, because the Windows credential store does not guarantee your calls will be serialized in the order they are made. Always access any single credential from just one thread at a time, and if you are doing operations on multiple credentials that require a particular serialization order, perform all those operations from the same thread.

The macOS credential store does not allow service names or usernames to be empty, because empty fields are treated as wildcards on lookup. Use some default, non-empty value instead.