moonD4rk/HackBrowserData · error

yandex: invalid protobuf signature on decrypted key

Error message

yandex: invalid protobuf signature on decrypted key

What it means

DecryptYandexIntermediateKey decrypts the intermediate key blob from Yandex's meta.local_encryptor_data with AES-GCM and expects the plaintext to start with a fixed protobuf signature prefix. When the decrypted plaintext does not begin with that signature, the blob is not the expected protobuf structure, so the function refuses to return a key. This guards against decrypting with the wrong master key or parsing garbage.

Source

Thrown at crypto/yandex.go:21

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-extract the master key for the exact Yandex profile being decrypted (keys are profile-specific).
  2. Verify the blob starts right after localEncryptorPrefix and contains the full protobuf body; re-locate the v10 marker with bytes.Index.
  3. Update/confirm yandexSignature against the current Yandex Browser version's protobuf layout.
  4. Check for profile corruption by re-copying the profile data and retrying.

Example fix

// before: master key copied from another profile's Local State
key, err := DecryptYandexIntermediateKey(otherProfileMasterKey, blob)
// after: resolve the master key for this specific profile
masterKey, err := GetMasterKey(yandexLocalStatePath)
key, err := DecryptYandexIntermediateKey(masterKey, blob)
Defensive patterns

Strategy: try-catch

Validate before calling

if len(masterKey) != 32 { return fmt.Errorf("master key must be 32 bytes, got %d", len(masterKey)) }
if len(blob) == 0 { return errors.New("empty yandex blob") }

Try / catch

key, err := DecryptYandexIntermediateKey(masterKey, blob)
if errors.Is(err, errYandexBadSignature) {
    // wrong master key or wrong blob region: re-extract and retry
    return nil, fmt.Errorf("yandex key unwrap failed (check master key): %w", err)
}

Prevention

When it happens

Trigger: Calling DecryptYandexIntermediateKey(masterKey, blob) where AES-GCM decryption of blob succeeds but the plaintext lacks the yandexSignature prefix — i.e. wrong master key, or the blob extracted from local_encryptor_data is not the protobuf-wrapped intermediate key (wrong offset / wrong bytes region).

Common situations: Extracting the blob at the wrong offset after the v10/localEncryptorPrefix marker, using a master key from a different browser profile, or a Yandex version change that alters the protobuf wrapping of the intermediate key.

Understand the failure class

Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.

Related errors


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