diff --git a/package.json b/package.json index 7577f45..18a654a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "creddy", - "version": "0.5.0", + "version": "0.5.1", "scripts": { "dev": "vite", "build": "vite build", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 368dc7a..ac81551 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1196,7 +1196,7 @@ dependencies = [ [[package]] name = "creddy" -version = "0.4.9" +version = "0.5.0" dependencies = [ "argon2", "auto-launch", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 68c6d7c..31fb91f 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "creddy" -version = "0.5.0" +version = "0.5.1" description = "A friendly AWS credentials manager" authors = ["Joseph Montanaro"] license = "" diff --git a/src-tauri/src/app.rs b/src-tauri/src/app.rs index 2954f1e..c35e849 100644 --- a/src-tauri/src/app.rs +++ b/src-tauri/src/app.rs @@ -53,6 +53,7 @@ pub fn run() -> tauri::Result<()> { ipc::delete_credential, ipc::list_credentials, ipc::sshkey_from_file, + ipc::sshkey_from_private_key, ipc::get_config, ipc::save_config, ipc::launch_terminal, diff --git a/src-tauri/src/credentials/ssh.rs b/src-tauri/src/credentials/ssh.rs index 8f905c0..d6c5bbc 100644 --- a/src-tauri/src/credentials/ssh.rs +++ b/src-tauri/src/credentials/ssh.rs @@ -74,6 +74,21 @@ impl SshKey { }) } + pub fn from_private_key(private_key: &str, passphrase: &str) -> Result { + let mut privkey = PrivateKey::from_openssh(private_key)?; + if privkey.is_encrypted() { + privkey = privkey.decrypt(passphrase) + .map_err(|_| LoadSshKeyError::InvalidPassphrase)?; + } + + Ok(SshKey { + algorithm: privkey.algorithm(), + comment: privkey.comment().into(), + public_key: privkey.public_key().clone(), + private_key: privkey, + }) + } + pub async fn name_from_pubkey(pubkey: &[u8], pool: &SqlitePool) -> Result { let row = sqlx::query!( "SELECT c.name diff --git a/src-tauri/src/ipc.rs b/src-tauri/src/ipc.rs index a79fb05..6159654 100644 --- a/src-tauri/src/ipc.rs +++ b/src-tauri/src/ipc.rs @@ -142,6 +142,12 @@ pub async fn sshkey_from_file(path: &str, passphrase: &str) -> Result Result { + SshKey::from_private_key(private_key, passphrase) +} + + #[tauri::command] pub async fn get_config(app_state: State<'_, AppState>) -> Result { let config = app_state.config.read().await; diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 405ec8f..025b835 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -50,7 +50,7 @@ } }, "productName": "creddy", - "version": "0.5.0", + "version": "0.5.1", "identifier": "creddy", "plugins": {}, "app": { diff --git a/src/views/Approve.svelte b/src/views/Approve.svelte index 4be41fd..65c4f5a 100644 --- a/src/views/Approve.svelte +++ b/src/views/Approve.svelte @@ -9,7 +9,7 @@ // Extra 50ms so the window can finish disappearing before the redraw - const rehideDelay = Math.min(5000, $appState.config.rehide_ms + 50); + const rehideDelay = Math.min(5000, $appState.config.rehide_ms + 100); let alert; let success = false; diff --git a/src/views/credentials/EditSshKey.svelte b/src/views/credentials/EditSshKey.svelte index 5f29307..f046745 100644 --- a/src/views/credentials/EditSshKey.svelte +++ b/src/views/credentials/EditSshKey.svelte @@ -15,7 +15,6 @@ async function saveCredential() { await invoke('save_credential', {record: local}); dispatch('save', local); - showDetails = false; } async function copyText(evt) { diff --git a/src/views/credentials/NewSshKey.svelte b/src/views/credentials/NewSshKey.svelte index 8e19682..8854c4c 100644 --- a/src/views/credentials/NewSshKey.svelte +++ b/src/views/credentials/NewSshKey.svelte @@ -13,20 +13,23 @@ let name; let file; + let privateKey = ''; let passphrase = ''; let showDetails = true; + let mode = 'file'; const dispatch = createEventDispatcher(); let defaultPath = null; homeDir().then(d => defaultPath = `${d}/.ssh`); + let alert; let saving = false; async function saveCredential() { saving = true; try { - let key = await invoke('sshkey_from_file', {path: file.path, passphrase}); + let key = await getKey(); const payload = { id: record.id, name, @@ -41,9 +44,40 @@ } } + async function getKey() { + if (mode === 'file') { + return await invoke('sshkey_from_file', {path: file.path, passphrase}); + } + else { + return await invoke('sshkey_from_private_key', {privateKey, passphrase}); + } + } + +
+ + +
+ +
@@ -55,15 +89,20 @@ bind:value={name} > - File - name = file.name} /> + {#if mode === 'file'} + File + name = file.name} /> + {:else} + Private key + + {/if} Passphrase
- {#if file?.path} + {#if file?.path || privateKey !== ''}
{/if}