jumpserver/jumpserver · error · ValueError

empty plaintext after decrypt

Error message

empty plaintext after decrypt

What it means

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.

Source

Thrown at apps/common/sdk/gm/sctu/session_mixin.py:41

def zero_pad(data: bytes, block_size: int = 16) -> bytes:
    pad_len = (-len(data)) % block_size
    if pad_len == 0:
        return data
    return data + b"\x00" * pad_len


def zero_unpad(data: bytes) -> bytes:
    return data.rstrip(b"\x00")


def pkcs7_pad(data: bytes, block_size: int = 16) -> bytes:
    pad_len = block_size - (len(data) % block_size)
    return data + bytes([pad_len]) * pad_len


def pkcs7_unpad(data: bytes, block_size: int = 16) -> bytes:
    if not data:
        raise ValueError("empty plaintext after decrypt")

    pad_len = data[-1]
    if pad_len < 1 or pad_len > block_size:
        raise ValueError("invalid pkcs7 padding")

    if data[-pad_len:] != bytes([pad_len]) * pad_len:
        raise ValueError("bad pkcs7 padding")

    return data[:-pad_len]


class SM4Mixin(BaseMixin):
    """
    SM4 外部明文 key 加解密。

    注意:
    1. 按当前 SDK 实测,key 允许 16 字节的整数倍。
    2. CBC 模式 iv 必须是 16 字节。

View on GitHub (pinned to 6ec464fabd)

Solutions

  1. Check that ciphertext is non-empty before calling decrypt with PKCS7 padding
  2. Inspect temp_data_length handling: if the driver legitimately produced 0 bytes, skip unpadding and return b''
  3. Use PADDING_NONE for raw block operations where empty output is expected

Example fix

# before
plain = session.decrypt(cipher, key, padding=PADDING_PKCS7)

# after
if not cipher:
    return b''
plain = session.decrypt(cipher, key, padding=PADDING_PKCS7)
Defensive patterns

Strategy: validation

Validate before calling

if not cipher:
    return b''  # or raise a domain-specific error before decrypt

Try / catch

try:
    pt = session.decrypt(cipher, key, padding=PADDING_PKCS7)
except ValueError as e:
    if 'empty' in str(e):
        return b''
    raise

Prevention

When it happens

Trigger: 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.

Common situations: Round-tripping empty payloads, upstream code returning b'' for missing data, length variables (temp_data_length.value) coming back 0 from the HSM.

Related errors


AI-assisted analysis of jumpserver/jumpserver@6ec464fabd (2026-08-28). Data as JSON: /api/errors/9483419f5719f243. Report an issue: GitHub.