Back to Tauri

Stronghold

src/content/docs/plugin/stronghold.mdx

latest6.7 KB
Original Source

import PluginLinks from '@components/PluginLinks.astro'; import Compatibility from '@components/plugins/Compatibility.astro';

import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; import CommandTabs from '@components/CommandTabs.astro'; import PluginPermissions from '@components/PluginPermissions.astro';

<PluginLinks plugin={frontmatter.plugin} />

Store secrets and keys using the IOTA Stronghold secret management engine.

Supported Platforms

<Compatibility plugin={frontmatter.plugin} />

Setup

Install the stronghold plugin to get started.

<Tabs> <TabItem label="Automatic" > Use your project's package manager to add the dependency:
	{ ' ' }

	<CommandTabs
        npm="npm run tauri add stronghold"
        yarn="yarn run tauri add stronghold"
        pnpm="pnpm tauri add stronghold"
        bun="bun tauri add stronghold"
        deno="deno task tauri add stronghold"
        cargo="cargo tauri add stronghold"
	/>
</TabItem>

<TabItem label = "Manual">
	<Steps>

			1. Run the following command in the `src-tauri` folder to add the plugin to the project's dependencies in `Cargo.toml`:

				```sh frame=none
				cargo add tauri-plugin-stronghold
				```

			2. Modify `lib.rs` to initialize the plugin:

				```rust title="src-tauri/src/lib.rs" ins={4}
				#[cfg_attr(mobile, tauri::mobile_entry_point)]
				pub fn run() {
						tauri::Builder::default()
								.plugin(tauri_plugin_stronghold::Builder::new(|password| {}).build())
								.run(tauri::generate_context!())
								.expect("error while running tauri application");
				}
				```

			3. Install the JavaScript Guest bindings using your preferred JavaScript package manager:

				<CommandTabs
								npm = "npm install @tauri-apps/plugin-stronghold"
								yarn = "yarn add @tauri-apps/plugin-stronghold"
								pnpm = "pnpm add @tauri-apps/plugin-stronghold"
								deno = "deno add npm:@tauri-apps/plugin-stronghold"
								bun = "bun add @tauri-apps/plugin-stronghold"
				/>

	</Steps>
</TabItem>
</Tabs>

Due to an upstream bug we also recommend that you add this to your Cargo.toml file:

toml
[profile.dev.package.scrypt]
opt-level = 3

Usage

The plugin must be initialized with a password hash function, which takes the password string and must return a 32 bytes hash derived from it.

Initialize with argon2 password hash function

The Stronghold plugin offers a default hash function using the argon2 algorithm.

rust
use tauri::Manager;

pub fn run() {
    tauri::Builder::default()
        .setup(|app| {
            let salt_path = app
                .path()
                .app_local_data_dir()
                .expect("could not resolve app local data path")
                .join("salt.txt");
            app.handle().plugin(tauri_plugin_stronghold::Builder::with_argon2(&salt_path).build())?;
            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

Initialize with custom password hash function

Alternatively you can provide your own hash algorithm by using the tauri_plugin_stronghold::Builder::new constructor.

:::note The password hash must contain exactly 32 bytes. This is a Stronghold requirement. :::

rust
pub fn run() {
    tauri::Builder::default()
        .plugin(
            tauri_plugin_stronghold::Builder::new(|password| {
                // Hash the password here with e.g. argon2, blake2b or any other secure algorithm
                // Here is an example implementation using the `rust-argon2` crate for hashing the password
                use argon2::{hash_raw, Config, Variant, Version};

                let config = Config {
                    lanes: 4,
                    mem_cost: 10_000,
                    time_cost: 10,
                    variant: Variant::Argon2id,
                    version: Version::Version13,
                    ..Default::default()
                };
                let salt = "your-salt".as_bytes();
                let key = hash_raw(password.as_ref(), salt, &config).expect("failed to hash password");

                key.to_vec()
            })
            .build(),
        )
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

Usage from JavaScript

The stronghold plugin is available in JavaScript.

javascript
import { Client, Stronghold } from '@tauri-apps/plugin-stronghold';
// when using `"withGlobalTauri": true`, you may use
// const { Client, Stronghold } = window.__TAURI__.stronghold;
import { appDataDir } from '@tauri-apps/api/path';
// when using `"withGlobalTauri": true`, you may use
// const { appDataDir } = window.__TAURI__.path;

const initStronghold = async () => {
	const vaultPath = `${await appDataDir()}/vault.hold`;
	const vaultPassword = 'vault password';
	const stronghold = await Stronghold.load(vaultPath, vaultPassword);

	let client: Client;
	const clientName = 'name your client';
	try {
		client = await stronghold.loadClient(clientName);
	} catch {
		client = await stronghold.createClient(clientName);
	}

	return {
		stronghold,
		client,
	};
};

// Insert a record to the store
async function insertRecord(store: any, key: string, value: string) {
	const data = Array.from(new TextEncoder().encode(value));
	await store.insert(key, data);
}

// Read a record from store
async function getRecord(store: any, key: string): Promise<string> {
	const data = await store.get(key);
	return new TextDecoder().decode(new Uint8Array(data));
}

const { stronghold, client } = await initStronghold();

const store = client.getStore();
const key = 'my_key';

// Insert a record to the store
insertRecord(store, key, 'secret value');

// Read a record from store
const value = await getRecord(store, key);
console.log(value); // 'secret value'

// Save your updates
await stronghold.save();

// Remove a record from store
await store.remove(key);

Permissions

By default all potentially dangerous plugin commands and scopes are blocked and cannot be accessed. You must modify the permissions in your capabilities configuration to enable these.

See the Capabilities Overview for more information and the step by step guide to use plugin permissions.

json
{
	...,
	"permissions": [
		"stronghold:default",
	]
}
<PluginPermissions plugin={frontmatter.plugin} />