package keyretriever import ( "errors" "fmt" ) // KeyRetriever retrieves the master encryption key for a Chromium-based browser. // Each platform has different implementations: // - macOS: Keychain access (security command) or gcoredump exploit // - Windows: DPAPI decryption of Local State file // - Linux: D-Bus Secret Service or fallback to "peanuts" password type KeyRetriever interface { RetrieveKey(storage, localStatePath string) ([]byte, error) } // ChainRetriever tries multiple retrievers in order, returning the first success. // Used on macOS (gcoredump → password → security) and Linux (D-Bus → peanuts). type ChainRetriever struct { retrievers []KeyRetriever } // NewChain creates a ChainRetriever that tries each retriever in order. func NewChain(retrievers ...KeyRetriever) KeyRetriever { return &ChainRetriever{retrievers: retrievers} } func (c *ChainRetriever) RetrieveKey(storage, localStatePath string) ([]byte, error) { var errs []error for _, r := range c.retrievers { key, err := r.RetrieveKey(storage, localStatePath) if err == nil && len(key) > 0 { return key, nil } if err != nil { errs = append(errs, fmt.Errorf("%T: %w", r, err)) } } return nil, fmt.Errorf("all retrievers failed: %w", errors.Join(errs...)) }