{"record":{"id":"13da27a225a6e36e","repo":"lcobucci/jwt","slug":"invalid-data-should-start-with-a-sequence","errorCode":null,"errorMessage":"Invalid data. Should start with a sequence.","messagePattern":"Invalid data\\. Should start with a sequence\\.","errorType":"exception","errorClass":"Lcobucci\\JWT\\Signer\\Ecdsa\\ConversionFailed","httpStatus":null,"severity":"error","filePath":"src/Signer/Ecdsa/MultibyteStringConverter.php","lineNumber":100,"sourceCode":"        }\n\n        while (\n            substr($data, 0, self::BYTE_SIZE) === self::ASN1_NEGATIVE_INTEGER\n            && substr($data, 2, self::BYTE_SIZE) <= self::ASN1_BIG_INTEGER_LIMIT\n        ) {\n            $data = substr($data, 2, null);\n        }\n\n        return $data;\n    }\n\n    public function fromAsn1(string $signature, int $length): string\n    {\n        $message  = bin2hex($signature);\n        $position = 0;\n\n        if (self::readAsn1Content($message, $position, self::BYTE_SIZE) !== self::ASN1_SEQUENCE) {\n            throw ConversionFailed::incorrectStartSequence();\n        }\n\n        // @phpstan-ignore-next-line\n        if (self::readAsn1Content($message, $position, self::BYTE_SIZE) === self::ASN1_LENGTH_2BYTES) {\n            $position += self::BYTE_SIZE;\n        }\n\n        $pointR = self::retrievePositiveInteger(self::readAsn1Integer($message, $position));\n        $pointS = self::retrievePositiveInteger(self::readAsn1Integer($message, $position));\n\n        $points = hex2bin(str_pad($pointR, $length, '0', STR_PAD_LEFT) . str_pad($pointS, $length, '0', STR_PAD_LEFT));\n        assert(is_string($points));\n        assert($points !== '');\n\n        return $points;\n    }\n\n    private static function readAsn1Content(string $message, int &$position, int $length): string","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/lcobucci/jwt/blob/375813049c24c7111bda8b6884c57b071ceb2fe7/src/Signer/Ecdsa/MultibyteStringConverter.php#L82-L118","documentation":"Thrown by MultibyteStringConverter::fromAsn1 when the input does not begin with the ASN.1 SEQUENCE tag (0x30). DER-encoded ECDSA signatures must start with a SEQUENCE; this guard rejects input that is already in raw r||s concatenation form or otherwise corrupted.","triggerScenarios":"Calling fromAsn1() with a raw (non-DER) r||s signature string, or with a base64/hex string that was never decoded to binary, so the first byte is not 0x30.","commonSituations":"Feeding a JWS/compact signature (raw r||s) into fromAsn1 by mistake, double-decoding base64, or receiving truncated signatures over the wire.","solutions":["Confirm the input is DER-encoded (starts with byte 0x30) before calling fromAsn1","If the signature is raw r||s form, do not call fromAsn1 — use it directly","Decode base64/hex input fully before conversion","Check the transport layer for truncation or corruption of the signature"],"exampleFix":"// before\n$raw = $converter->fromAsn1($compactJwsSignature, 32);\n// after\n$der = base64_decode($derBase64Signature, true);\nif (ord($der[0]) === 0x30) {\n    $raw = $converter->fromAsn1($der, 32);\n}","handlingStrategy":"validation","validationCode":"if (strlen($signature) < 1 || ord($signature[0]) !== 0x30) { throw new InvalidArgumentException('Not a DER sequence'); }","typeGuard":null,"tryCatchPattern":"try { $raw = $converter->fromAsn1($der, 32); } catch (\\Jose\\Component\\Signature\\Exception\\ConversionFailed $e) { /* treat as raw or reject */ }","preventionTips":["Know your input format: DER only for fromAsn1, raw r||s otherwise","Wrap decoding (base64/hex) and conversion in one helper with checks","Log the first byte when conversion fails to spot format mix-ups"],"tags":["ecdsa","asn1","der","signature"],"backgroundTag":"invalid-argument-format","analyzedSha":"375813049c24c7111bda8b6884c57b071ceb2fe7","analyzedAt":"2026-09-14T11:12:28.004Z","contentChangedAt":"2026-09-14T11:12:28.004Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}