Files
HackBrowserData/crypto/version.go
Roger 2860bb82f9 docs: cross-host decryption guide and comment cleanup (#614)
* docs(readme): document cross-host decryption workflow

* docs: drop RFC citations and what-comments
2026-06-13 21:17:00 +08:00

56 lines
1.6 KiB
Go

package crypto
// CipherVersion represents the encryption version used by Chromium browsers.
type CipherVersion string
const (
// CipherV10 is Chrome 80+ encryption (AES-GCM on Windows, AES-CBC on macOS/Linux).
CipherV10 CipherVersion = "v10"
// CipherV11 is the Linux-only AES-CBC variant where the key comes from
// libsecret / kwallet. Same algorithm as CipherV10; only the key source differs.
CipherV11 CipherVersion = "v11"
// CipherV20 is Chrome 127+ App-Bound Encryption.
CipherV20 CipherVersion = "v20"
// CipherV12 is Chromium's SecretPortalKeyProvider (Flatpak / xdg-desktop-portal) tier —
// HKDF-SHA256 + AES-256-GCM with a secret retrieved via org.freedesktop.portal.Desktop.
// Recognized by DetectVersion so decryptValue can emit a known-gap error rather than a
// generic "unsupported cipher version" message; not yet implemented.
CipherV12 CipherVersion = "v12"
// CipherDPAPI is pre-Chrome 80 raw DPAPI encryption (no version prefix).
CipherDPAPI CipherVersion = "dpapi"
versionPrefixLen = 3
)
// DetectVersion identifies the encryption version from a ciphertext prefix.
func DetectVersion(ciphertext []byte) CipherVersion {
if len(ciphertext) < versionPrefixLen {
return CipherDPAPI
}
prefix := string(ciphertext[:versionPrefixLen])
switch prefix {
case "v10":
return CipherV10
case "v11":
return CipherV11
case "v12":
return CipherV12
case "v20":
return CipherV20
default:
return CipherDPAPI
}
}
func stripPrefix(ciphertext []byte) []byte {
ver := DetectVersion(ciphertext)
if ver == CipherV10 || ver == CipherV11 || ver == CipherV12 || ver == CipherV20 {
return ciphertext[versionPrefixLen:]
}
return ciphertext
}