moonD4rk/HackBrowserData · error

yandex: v10 marker not found in local_encryptor_data

Error message

yandex: v10 marker not found in local_encryptor_data

What it means

errYandexMarkerNotFound is returned by DecryptYandexIntermediateKey when the v10 marker (localEncryptorPrefix) cannot be located in the local_encryptor_data blob. The Yandex v10 format requires a fixed prefix inside the blob to locate the encrypted intermediate key; without it the payload offset cannot be determined.

Source

Thrown at crypto/yandex.go:19

package crypto

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 {

View on GitHub (pinned to 0503d04d7a)

Solutions

  1. Verify the blob actually comes from Yandex's local_encryptor_data and contains the v10 marker prefix; inspect the raw bytes.
  2. Check you selected the correct SQLite field — not a cookie value or an empty cell.
  3. Handle older/newer Yandex formats separately; add a branch if the marker changed between Yandex Browser versions.
  4. Skip such records and log a warning instead of failing the whole extraction run.

Example fix

// before
key, err := crypto.DecryptYandexIntermediateKey(masterKey, blob)
// after
if !bytes.Contains(blob, localEncryptorPrefix) {
    return nil, fmt.Errorf("skipping record: %w", errYandexMarkerNotFound)
}
key, err := crypto.DecryptYandexIntermediateKey(masterKey, blob)
Defensive patterns

Strategy: validation

Validate before calling

if !bytes.Contains(blob, markerPrefix) {
    return fmt.Errorf("v10 marker absent; len=%d", len(blob))
}

Type guard

func hasYandexMarker(blob, prefix []byte) bool { return bytes.Index(blob, prefix) >= 0 }

Try / catch

key, err := crypto.DecryptYandexIntermediateKey(master, blob)
if errors.Is(err, crypto.ErrYandexMarkerNotFound) {
    log.Warnf("yandex record lacks v10 marker; skipping")
    return nil
}

Prevention

When it happens

Trigger: Calling DecryptYandexIntermediateKey with a blob that does not contain the v10 marker — e.g. an empty DB field, a Chromium-style v10 cookie value passed by mistake, or a Yandex database using an older/newer storage format without the prefix.

Common situations: Reading a Yandex Browser profile whose local_encryptor_data format differs (pre-v10 or updated versions); selecting the wrong column/row from the SQLite DB; pointing the Yandex path at a plain Chromium profile by accident.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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