moonD4rk/HackBrowserData · error

yandex: decrypted intermediate key shorter than 32 bytes

Error message

yandex: decrypted intermediate key shorter than 32 bytes

What it means

After stripping the protobuf signature from the decrypted Yandex intermediate-key plaintext, the remainder must contain at least yandexDataKeyLen (32) bytes of key material. If it is shorter, the decrypted key cannot be a valid 32-byte data key, so DecryptYandexIntermediateKey fails rather than returning truncated key bytes.

Source

Thrown at crypto/yandex.go:22

	"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
	}
	if !bytes.HasPrefix(plaintext, yandexSignature) {

View on GitHub (pinned to 0503d04d7a)

Solutions

  1. Re-copy the Yandex profile files to ensure the blob is not truncated.
  2. Verify the blob slice extends to the end of local_encryptor_data (no premature length cap).
  3. Confirm the Yandex version still wraps a 32-byte data key; adjust yandexDataKeyLen parsing if the format changed.
  4. Retry with a fresh master key to rule out partial decrypts producing malformed plaintext.

Example fix

// before: blob sliced with an arbitrary fixed length
blob := data[idx+len(localEncryptorPrefix) : idx+len(localEncryptorPrefix)+16]
// after: take everything after the marker
blob := data[idx+len(localEncryptorPrefix):]
Defensive patterns

Strategy: validation

Validate before calling

if len(blob) < 64 { return errors.New("yandex blob too short to hold a 32-byte data key") }

Try / catch

key, err := DecryptYandexIntermediateKey(masterKey, blob)
if errors.Is(err, errYandexKeyTooShort) {
    return nil, fmt.Errorf("yandex intermediate key truncated: %w", err)
}

Prevention

When it happens

Trigger: Calling DecryptYandexIntermediateKey where GCM decryption succeeds and the signature prefix matches, but the remaining plaintext is under 32 bytes — typically a truncated blob or a malformed protobuf body.

Common situations: Truncated copy of the Yandex profile database/Local State, slicing the blob short after the marker, or an altered Yandex format that stores fewer payload bytes than expected.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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