moonD4rk/HackBrowserData · error

ciphertext too short

Error message

ciphertext too short

What it means

errShortCiphertext means the input to a Chromium decryption routine (GCM or CBC) is smaller than the minimum structure of a version-prefixed encrypted blob: the 'v10'/'v20' 3-byte version prefix plus at least a GCM nonce (12B) or an AES-CBC block (16B). The library throws it before attempting decryption because such a blob cannot possibly be valid. It is a sentinel error returned from DecryptChromiumGCM, DecryptChromiumCBC, and AESGCMDecryptBlob.

Source

Thrown at crypto/errors.go:7

package crypto

import "errors"

// Sentinel errors for crypto operations.
var (
	errShortCiphertext   = errors.New("ciphertext too short")
	errInvalidBlockSize  = errors.New("ciphertext is not a multiple of the block size")
	errInvalidIVLength   = errors.New("IV length must equal block size")
	errInvalidPadding    = errors.New("invalid PKCS5 padding")
	errInvalidNonceLen   = errors.New("nonce length must equal GCM nonce size")
	errUnsupportedIVLen  = errors.New("unsupported IV length")
	errDecodeASN1        = errors.New("failed to decode ASN1 data")
	errDPAPINotSupported = errors.New("DPAPI not supported on this platform") //nolint:unused // used on darwin/linux only
)

View on GitHub (pinned to 0503d04d7a)

Solutions

  1. Check that the ciphertext actually begins with a version prefix ('v10' or 'v20') before calling decryption and skip plaintext rows.
  2. Verify the base64 decoding produced non-trivial bytes: log len(ciphertext) when the error occurs.
  3. Skip the record and continue extraction instead of failing the whole run; treat it as a plaintext/unencrypted value.
  4. Ensure the source database (Cookies/Login Data) was fully copied before reading; re-copy the DB if it may have been truncated.

Example fix

// before
decrypted, err := crypto.DecryptChromiumGCM(key, encValue)
if err != nil {
    return err
}
// after
decrypted, err := crypto.DecryptChromiumGCM(key, encValue)
if errors.Is(err, errShortCiphertext) || len(encValue) < 4 {
    return string(encValue), nil // treat as plaintext
}
if err != nil {
    return err
}
Defensive patterns

Strategy: validation

Validate before calling

func hasValidChromiumPrefix(ct []byte) bool {
    return len(ct) >= 3+12 && (bytes.HasPrefix(ct, []byte("v10")) || bytes.HasPrefix(ct, []byte("v20")))
}
if !hasValidChromiumPrefix(encValue) { /* treat as plaintext / skip */ }

Type guard

func isEncryptedBlob(b []byte) bool { return len(b) >= versionPrefixLen+gcmNonceSize }

Try / catch

dec, err := crypto.DecryptChromiumGCM(key, ct)
if errors.Is(err, crypto.ErrShortCiphertext) {
    dec = ct // plaintext fallback
} else if err != nil {
    return err
}

Prevention

When it happens

Trigger: Calling DecryptChromiumGCM with len(ciphertext) < versionPrefixLen+gcmNonceSize, or DecryptChromiumCBC/AESGCMDecryptBlob with len(ciphertext) < versionPrefixLen+aes.BlockSize. Typical cause: passing a raw base64-decoded value that was never encrypted (e.g. plaintext cookies or empty strings stored in the DB), or a truncated blob.

Common situations: Extracting cookies where Chromium stored unencrypted values in the 'value' column (older cookies with no v10 prefix); reading rows from an incomplete SQLite export; mis-decoded base64; pointing the tool at a corrupted database file.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of moonD4rk/HackBrowserData@0503d04d7a (2026-09-06). Data as JSON: /api/errors/b358040005a12c97. Report an issue: GitHub.