From 901d9c257d4840725f8778323312009abdd8ae4c Mon Sep 17 00:00:00 2001 From: Vantz Stockwell Date: Tue, 17 Mar 2026 11:39:24 -0400 Subject: [PATCH] =?UTF-8?q?fix:=20SSH=20key=20double-base64=20encoding=20?= =?UTF-8?q?=E2=80=94=20PEM=20was=20corrupted=20during=20storage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause: frontend btoa() encoded the PEM before sending to Go []byte parameter. Wails already base64-encodes []byte over JSON bridge, so the vault stored base64(base64(pem)) — garbage. Fix: Go method now accepts string, frontend sends raw PEM. Keys must be re-added after this update. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../src/components/connections/ConnectionEditDialog.vue | 6 ++---- internal/app/app.go | 7 +++---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/frontend/src/components/connections/ConnectionEditDialog.vue b/frontend/src/components/connections/ConnectionEditDialog.vue index 241ca19..05a78d8 100644 --- a/frontend/src/components/connections/ConnectionEditDialog.vue +++ b/frontend/src/components/connections/ConnectionEditDialog.vue @@ -447,14 +447,12 @@ async function saveNewCredential(): Promise { "", // domain — not collected in this form ) as Credential; } else { - // SSH Key: CreateSSHKeyCredential(name, username string, privateKeyPEM []byte, passphrase string) - // Wails serialises []byte as base64. We encode the raw PEM string with btoa(). - const pemBase64 = btoa(newCred.value.privateKeyPEM.trim()); + // SSH Key: CreateSSHKeyCredential(name, username, privateKeyPEM string, passphrase string) created = await Call.ByName( `${APP}.CreateSSHKeyCredential`, newCred.value.name.trim(), newCred.value.username.trim(), - pemBase64, + newCred.value.privateKeyPEM.trim(), newCred.value.passphrase, ) as Credential; } diff --git a/internal/app/app.go b/internal/app/app.go index 7a1fa65..7adffdc 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -490,13 +490,12 @@ func (a *WraithApp) CreatePassword(name, username, password, domain string) (*cr } // CreateSSHKeyCredential imports an SSH private key and creates a Credential -// record referencing it. privateKeyPEM is the raw PEM bytes (Wails serialises -// []byte as base64 over the JSON bridge, so the frontend passes btoa(pem)). -func (a *WraithApp) CreateSSHKeyCredential(name, username string, privateKeyPEM []byte, passphrase string) (*credentials.Credential, error) { +// record referencing it. privateKeyPEM is the raw PEM string (NOT base64 encoded). +func (a *WraithApp) CreateSSHKeyCredential(name, username string, privateKeyPEM string, passphrase string) (*credentials.Credential, error) { if a.Credentials == nil { return nil, fmt.Errorf("vault is locked") } - return a.Credentials.CreateSSHKeyCredential(name, username, privateKeyPEM, passphrase) + return a.Credentials.CreateSSHKeyCredential(name, username, []byte(privateKeyPEM), passphrase) } // DeleteCredential removes a credential by ID.