{"record":{"id":"02b82bea2a7e7bc5","repo":"beemdevelopment/Aegis","slug":"yandex-secret-checksum-invalid","errorCode":null,"errorMessage":"Yandex secret checksum invalid","messagePattern":"Yandex secret checksum invalid","errorType":"validation","errorClass":"OtpInfoException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/com/beemdevelopment/aegis/otp/YandexInfo.java","lineNumber":160,"sourceCode":"                inputTotalBitsAvailable -= bitsToRead;\n                requiredBits -= bitsToRead;\n                inputBitsAvailable -= bitsToRead;\n                accumBits += bitsToRead;\n\n                if (inputBitsAvailable == 0) {\n                    inputIndex += 1;\n                    inputBitsAvailable = 8;\n                }\n            }\n\n            if (accumBits == 13) {\n                accum ^= 0b1_1000_1111_0011;\n            }\n            accumBits = 16 - getNumberOfLeadingZeros(accum);\n        }\n\n        if (accum != originalChecksum) {\n            throw new OtpInfoException(\"Yandex secret checksum invalid\");\n        }\n    }\n\n    private static int getNumberOfLeadingZeros(char value) {\n        if (value == 0) {\n            return 16;\n        }\n\n        int n = 0;\n        if ((value & 0xFF00) == 0) {\n            n += 8;\n            value <<= 8;\n        }\n        if ((value & 0xF000) == 0) {\n            n += 4;\n            value <<= 4;\n        }\n        if ((value & 0xC000) == 0) {","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/app/src/main/java/com/beemdevelopment/aegis/otp/YandexInfo.java#L142-L178","documentation":"For full-length Yandex secrets, validateSecret recomputes the CRC-like checksum (accumulator over bits) and compares it to the embedded original checksum. A mismatch means the secret bytes are corrupted or altered, so OtpInfoException('Yandex secret checksum invalid') is thrown.","triggerScenarios":"Calling YandexInfo.validateSecret(byte[]) (via parseSecret) with a SECRET_FULL_LENGTH secret whose embedded checksum bits do not match the recomputed accumulator — e.g. one or more flipped bits in transmission/storage.","commonSituations":"Copy/paste corruption when manually transcribing Yandex secrets, encoding/decoding round-trip errors (case-sensitive base32 variants), secrets edited or truncated by intermediate tools.","solutions":["Re-obtain the secret from Yandex (fresh QR code or re-export) — the stored bytes are corrupt","Re-check the decoding path: ensure the same base32 alphabet/encoding was used as when the secret was created","Verify no characters were lost/altered during copy-paste (especially trailing characters)","If only the checksum is bad but codes otherwise work, treat the entry as untrusted and replace it rather than bypassing validation"],"exampleFix":"// before\ntry {\n    YandexInfo.validateSecret(secret);\n} catch (OtpInfoException e) {\n    secret = corruptSecret; // never reuse a checksum-failed secret\n}\n// after\ntry {\n    YandexInfo.validateSecret(secret);\n} catch (OtpInfoException e) {\n    Log.e(TAG, \"Yandex secret failed checksum; re-scan the QR code\", e);\n    throw new InvalidEntryException(\"Re-import the Yandex entry from a fresh QR code\");\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    YandexInfo.validateSecret(secret);\n} catch (OtpInfoException e) {\n    throw new InvalidEntryException(\"Yandex secret failed checksum; re-import from a fresh QR code\", e);\n}","preventionTips":["Treat checksum failure as data corruption: always re-obtain the secret, never bypass","Use round-trip-safe copy mechanisms (QR re-scan, not manual transcription)","Keep a consistent base32 alphabet through encode/decode","Back up secrets only through formats that preserve byte fidelity"],"tags":["otp","yandex","checksum","corruption","android"],"backgroundTag":"checksum-mismatch","analyzedSha":"d6f4e5925a97e4e91593f1542085eae03432a759","analyzedAt":"2026-09-08T00:46:31.111Z","contentChangedAt":"2026-09-08T00:46:31.111Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}