moonD4rk/HackBrowserData · error

yandex: encrypted intermediate key truncated

Error message

yandex: encrypted intermediate key truncated

What it means

errYandexBlobShort is returned by DecryptYandexIntermediateKey when the bytes after the v10 marker are shorter than yandexIntKeyBlobLen (96 bytes: 12B nonce + 68B ciphertext + 16B GCM tag). A truncated payload cannot contain a complete encrypted intermediate key, so the function refuses to attempt GCM decryption.

Source

Thrown at crypto/yandex.go:20

import (
	"bytes"
	"errors"
)

// yandexSignature is the protobuf wire-format header (field1 varint=1, field2 len=32) on every wrapped key.
var yandexSignature = []byte{0x08, 0x01, 0x12, 0x20}

var localEncryptorPrefix = []byte("v10")

const (
	yandexIntKeyBlobLen = 96 // 12B nonce + 68B ciphertext + 16B GCM tag
	yandexDataKeyLen    = 32
)

var (
	errYandexMarkerNotFound = errors.New("yandex: v10 marker not found in local_encryptor_data")
	errYandexBlobShort      = errors.New("yandex: encrypted intermediate key truncated")
	errYandexBadSignature   = errors.New("yandex: invalid protobuf signature on decrypted key")
	errYandexKeyTooShort    = errors.New("yandex: decrypted intermediate key shorter than 32 bytes")
)

// DecryptYandexIntermediateKey unwraps the per-DB data key from meta.local_encryptor_data.
func DecryptYandexIntermediateKey(masterKey, blob []byte) ([]byte, error) {
	idx := bytes.Index(blob, localEncryptorPrefix)
	if idx < 0 {
		return nil, errYandexMarkerNotFound
	}
	payload := blob[idx+len(localEncryptorPrefix):]
	if len(payload) < yandexIntKeyBlobLen {
		return nil, errYandexBlobShort
	}

	plaintext, err := AESGCMDecryptBlob(masterKey, payload[:yandexIntKeyBlobLen], nil)
	if err != nil {
		return nil, err

View on GitHub (pinned to 0503d04d7a)

Solutions

  1. Re-copy the Yandex profile with the browser fully closed and re-run extraction.
  2. Validate len(payload) >= 96 at the call site and skip short records with a warning.
  3. Ensure the correct marker occurrence is used if multiple markers could appear in the blob.
  4. Check for database locks/corruption (integrity check on the SQLite file) if many records are short.

Example fix

// before
key, err := crypto.DecryptYandexIntermediateKey(masterKey, blob)
// after
idx := bytes.Index(blob, prefix)
if idx < 0 || len(blob)-idx-len(prefix) < 96 {
    return nil, fmt.Errorf("truncated record: %w", errYandexBlobShort)
}
key, err := crypto.DecryptYandexIntermediateKey(masterKey, blob)
Defensive patterns

Strategy: validation

Validate before calling

const yandexIntKeyBlobLen = 96
idx := bytes.Index(blob, markerPrefix)
if idx >= 0 && len(blob)-idx-len(markerPrefix) < yandexIntKeyBlobLen {
    return errors.New("yandex payload truncated")
}

Type guard

func yandexPayloadComplete(blob, prefix []byte, need int) bool {
    i := bytes.Index(blob, prefix)
    return i >= 0 && len(blob)-i-len(prefix) >= need
}

Try / catch

key, err := crypto.DecryptYandexIntermediateKey(master, blob)
if errors.Is(err, crypto.ErrYandexBlobShort) {
    log.Warnf("yandex intermediate key truncated (%d bytes); skipping", len(blob))
    return nil
}

Prevention

When it happens

Trigger: Calling DecryptYandexIntermediateKey where len(payload after marker) < 96 — typically a truncated DB value, a partially copied meta file, or the marker appearing near the end of a different structure by coincidence.

Common situations: Incompletely copied Yandex Browser profile (meta file truncated); reading the DB while the browser still writes it; slicing the payload at the wrong marker occurrence; SQLite reads from a locked/torn database.

Understand the failure class

Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.

Related errors


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