Files
HackBrowserData/crypto/keyretriever/keyretriever_linux.go
T
Roger 410bffe643 refactor: naming cleanup and crypto package improvements (#551)
* refactor: naming cleanup across all packages
2026-04-05 16:51:56 +08:00

88 lines
2.1 KiB
Go

//go:build linux
package keyretriever
import (
"crypto/sha1"
"fmt"
"github.com/godbus/dbus/v5"
keyring "github.com/ppacher/go-dbus-keyring"
)
// https://source.chromium.org/chromium/chromium/src/+/main:components/os_crypt/os_crypt_linux.cc
var linuxParams = pbkdf2Params{
salt: []byte("saltysalt"),
iterations: 1,
keySize: 16,
hashFunc: sha1.New,
}
// DBusRetriever queries GNOME Keyring / KDE Wallet via D-Bus Secret Service.
type DBusRetriever struct{}
func (r *DBusRetriever) RetrieveKey(storage, _ string) ([]byte, error) {
conn, err := dbus.SessionBus()
if err != nil {
return nil, fmt.Errorf("dbus session: %w", err)
}
svc, err := keyring.GetSecretService(conn)
if err != nil {
return nil, fmt.Errorf("secret service: %w", err)
}
session, err := svc.OpenSession()
if err != nil {
return nil, fmt.Errorf("open session: %w", err)
}
defer session.Close()
collections, err := svc.GetAllCollections()
if err != nil {
return nil, fmt.Errorf("get collections: %w", err)
}
for _, col := range collections {
items, err := col.GetAllItems()
if err != nil {
continue
}
for _, item := range items {
label, err := item.GetLabel()
if err != nil {
continue
}
if label == storage {
secret, err := item.GetSecret(session.Path())
if err != nil {
return nil, fmt.Errorf("get secret for %s: %w", storage, err)
}
if len(secret.Value) > 0 {
return linuxParams.deriveKey(secret.Value), nil
}
}
}
}
return nil, fmt.Errorf("secret %q not found in keyring", storage)
}
// FallbackRetriever uses the hardcoded "peanuts" password when D-Bus is unavailable.
// https://source.chromium.org/chromium/chromium/src/+/main:components/os_crypt/os_crypt_linux.cc;l=100
type FallbackRetriever struct{}
func (r *FallbackRetriever) RetrieveKey(_, _ string) ([]byte, error) {
return linuxParams.deriveKey([]byte("peanuts")), nil
}
// DefaultRetriever returns the Linux retriever chain:
// D-Bus Secret Service first, then "peanuts" fallback.
// The keychainPassword parameter is unused on Linux.
func DefaultRetriever(_ string) KeyRetriever {
return NewChain(
&DBusRetriever{},
&FallbackRetriever{},
)
}