{"record":{"id":"9483419f5719f243","repo":"jumpserver/jumpserver","slug":"empty-plaintext-after-decrypt","errorCode":null,"errorMessage":"empty plaintext after decrypt","messagePattern":"empty plaintext after decrypt","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"apps/common/sdk/gm/sctu/session_mixin.py","lineNumber":41,"sourceCode":"def zero_pad(data: bytes, block_size: int = 16) -> bytes:\n    pad_len = (-len(data)) % block_size\n    if pad_len == 0:\n        return data\n    return data + b\"\\x00\" * pad_len\n\n\ndef zero_unpad(data: bytes) -> bytes:\n    return data.rstrip(b\"\\x00\")\n\n\ndef pkcs7_pad(data: bytes, block_size: int = 16) -> bytes:\n    pad_len = block_size - (len(data) % block_size)\n    return data + bytes([pad_len]) * pad_len\n\n\ndef pkcs7_unpad(data: bytes, block_size: int = 16) -> bytes:\n    if not data:\n        raise ValueError(\"empty plaintext after decrypt\")\n\n    pad_len = data[-1]\n    if pad_len < 1 or pad_len > block_size:\n        raise ValueError(\"invalid pkcs7 padding\")\n\n    if data[-pad_len:] != bytes([pad_len]) * pad_len:\n        raise ValueError(\"bad pkcs7 padding\")\n\n    return data[:-pad_len]\n\n\nclass SM4Mixin(BaseMixin):\n    \"\"\"\n    SM4 外部明文 key 加解密。\n\n    注意：\n    1. 按当前 SDK 实测，key 允许 16 字节的整数倍。\n    2. CBC 模式 iv 必须是 16 字节。","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/jumpserver/jumpserver/blob/6ec464fabd61b95912d539455a3a5f15f5c59fe0/apps/common/sdk/gm/sctu/session_mixin.py#L23-L59","documentation":"pkcs7_unpad raises ValueError when the decrypted buffer handed to it is empty. In PKCS7 the last byte encodes the pad length (1..block_size), so an empty buffer has no padding byte to read and cannot be valid plaintext.","triggerScenarios":"Decrypting with padding=PADDING_PKCS7 when the driver returned 0 output bytes — typically because empty ciphertext was passed in, or the device wrote no output due to an earlier error path.","commonSituations":"Round-tripping empty payloads, upstream code returning b'' for missing data, length variables (temp_data_length.value) coming back 0 from the HSM.","solutions":["Check that ciphertext is non-empty before calling decrypt with PKCS7 padding","Inspect temp_data_length handling: if the driver legitimately produced 0 bytes, skip unpadding and return b''","Use PADDING_NONE for raw block operations where empty output is expected"],"exampleFix":"# before\nplain = session.decrypt(cipher, key, padding=PADDING_PKCS7)\n\n# after\nif not cipher:\n    return b''\nplain = session.decrypt(cipher, key, padding=PADDING_PKCS7)","handlingStrategy":"validation","validationCode":"if not cipher:\n    return b''  # or raise a domain-specific error before decrypt","typeGuard":null,"tryCatchPattern":"try:\n    pt = session.decrypt(cipher, key, padding=PADDING_PKCS7)\nexcept ValueError as e:\n    if 'empty' in str(e):\n        return b''\n    raise","preventionTips":["Treat empty ciphertext as a no-op upstream","Log temp_data_length after device decrypt when debugging"],"tags":["gm","crypto","sm4","pkcs7","padding"],"backgroundTag":"crypto-padding-error","analyzedSha":"6ec464fabd61b95912d539455a3a5f15f5c59fe0","analyzedAt":"2026-08-28T11:33:00.925Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}