peass-ng/PEASS-ng · error · System.ArgumentException
Invalid encryption version prefix.
Error message
Invalid encryption version prefix.
What it means
DecryptWithAESGCM expects Google Chrome app-bound encrypted tokens to start with a known ASCII version prefix (e.g. 'v10'/'v20'). If the ciphertext is shorter than the prefix or does not begin with it, decryption cannot proceed and ArgumentException is thrown. This prevents attempting AES-GCM decryption on data in an unexpected format.
Source
Thrown at winPEAS/winPEASexe/winPEAS/Info/CloudInfo/GWorkspaceInfo.cs:263
Beaprint.PrintException("Error extracting refresh tokens (If Chrome is running the DB is probably locked but you could dump Chrome's procs and search it there or go around this lock): " + ex.Message);
return refreshTokens.ToArray();
}
}
public static string DecryptWithAESGCM(byte[] ciphertext, byte[] key)
{
// Constants
int nonceLength = 12; // GCM standard nonce length
int macLength = 16; // GCM authentication mac length
string versionPrefix = "v10"; // Matching kEncryptionVersionPrefix
// Convert prefix to byte array
byte[] versionPrefixBytes = Encoding.ASCII.GetBytes(versionPrefix);
// Check the prefix
if (ciphertext.Length < versionPrefixBytes.Length ||
!IsPrefixMatch(ciphertext, versionPrefixBytes))
{
throw new ArgumentException("Invalid encryption version prefix.");
}
// Extract the nonce from the ciphertext (after the prefix)
byte[] nonce = new byte[nonceLength];
Array.Copy(ciphertext, versionPrefixBytes.Length, nonce, 0, nonceLength);
// Extract the actual encrypted data (after the prefix and nonce)
int encryptedDataStartIndex = versionPrefixBytes.Length + nonceLength;
byte[] encryptedData = new byte[ciphertext.Length - encryptedDataStartIndex];
Array.Copy(ciphertext, encryptedDataStartIndex, encryptedData, 0, encryptedData.Length);
// Split the mac and actual ciphertext
byte[] mac = new byte[macLength];
Array.Copy(encryptedData, encryptedData.Length - macLength, mac, 0, macLength);
byte[] actualCiphertext = new byte[encryptedData.Length - macLength];
Array.Copy(encryptedData, 0, actualCiphertext, 0, actualCiphertext.Length);
View on GitHub (pinned to 53fb989abc)
Solutions
- Inspect the first bytes of the ciphertext (hex dump) and confirm they match the expected versionPrefix
- Re-read the correct source: the app-bound encrypted key from the right registry key/value for the installed browser version
- Update the versionPrefix constant to match the browser version's actual format (e.g. v20 for newer Chrome app-bound encryption)
- Add a length/format check and log a descriptive error distinguishing 'no prefix' from 'corrupt data'
Example fix
// before
byte[] plain = DecryptWithAESGCM(blob, key, "v10");
// after
if (blob == null || blob.Length < 3 || Encoding.ASCII.GetString(blob, 0, 3) != "v20")
throw new InvalidOperationException("Token blob does not carry v20 app-bound prefix; check browser version/source.");
byte[] plain = DecryptWithAESGCM(blob, key, "v20"); Defensive patterns
Strategy: validation
Validate before calling
static bool HasVersionPrefix(byte[] ct, string prefix)
{
var p = Encoding.ASCII.GetBytes(prefix);
return ct != null && ct.Length >= p.Length &&
ct.AsSpan(0, p.Length).SequenceEqual(p);
} Try / catch
try { return DecryptWithAESGCM(ct, key, prefix); }
catch (ArgumentException) { log.Error("Token blob missing expected version prefix; wrong source or browser format changed."); return null; } Prevention
- Hex-dump the first bytes of ciphertext and match against the prefix constant before decrypting
- Keep versionPrefix in sync with the browser version's app-bound encryption format
- Always preserve tokens as raw byte[]; never round-trip through string encodings that alter leading bytes
- Read from the documented registry/file source for the specific Chromium flavor and version
When it happens
Trigger: Calling decryptedToken with ciphertext whose first bytes are not the expected version prefix: the value was read from the wrong registry value/file, the prefix constant was changed, or the byte array was sliced incorrectly (e.g. off-by-one or including a BOM).
Common situations: Chrome changed its app-bound encryption format in newer versions; copying the wrong registry blob (DPAPI-encrypted instead of app-bound); reading the value with wrong offsets so the prefix is missing; handling Firefox or non-Chromium data with this routine.
Related errors
- Decryption failed due to MAC mismatch
- Keys > 32 are not supported
- Invalid digest length (required: 1 - 32)
- Salt length must be exactly 8 bytes
- Personalization length must be exactly 8 bytes
AI-assisted analysis of peass-ng/PEASS-ng@53fb989abc (2026-09-02).
Data as JSON: /api/errors/b9d0df28b7a6bdc2.
Report an issue: GitHub.