jumpserver/jumpserver · error · UKeyCertNormalizationError
Invalid certificate format
Error message
Invalid certificate format
What it means
UKeyCertNormalizationError raised when writing the submitted cert_pem to a temp file and importing it via Sm2Certificate().import_pem fails with any exception — the PEM is not a parseable SM2/CSR certificate (wrong format, corrupted, or an RSA/standard X.509 PEM handed to the GM parser).
Source
Thrown at apps/authentication/backends/ukey/backends.py:103
self._verify_cert_cn(sm2_cert.get_subject().get('commonName'), username)
self._verify_sm2_signature(sm2_cert.get_subject_public_key(), signature, challenge)
return user
@staticmethod
def _load_sm2_cert(cert_pem):
"""将 PEM 字符串写入临时文件,加载为 Sm2Certificate 对象后立即删除临时文件。"""
from common.utils.gmssl_python import Sm2Certificate
fd, cert_file = tempfile.mkstemp(suffix='.crt')
try:
os.close(fd)
with open(cert_file, 'w', encoding='utf-8') as f:
f.write(cert_pem)
sm2_cert = Sm2Certificate()
sm2_cert.import_pem(cert_file)
except Exception as e:
logger.error('UKeyBackend: failed to load SM2 cert: %s', e)
raise UKeyCertNormalizationError()
finally:
if os.path.exists(cert_file):
os.unlink(cert_file)
return sm2_cert
@staticmethod
def _verify_sm2_cert_validity(sm2_cert):
"""校验 SM2 证书有效期(not_before / not_after)。"""
try:
validity = sm2_cert.get_validity()
except Exception as e:
logger.error('UKeyBackend: failed to get SM2 cert validity: %s', e)
raise UKeyCertExpiredError()
UKeyBackend._check_validity_period(validity.not_before, validity.not_after, 'SM2')
@staticmethod
def _verify_sm2_cert_chain(sm2_cert):
"""调用 Sm2Certificate.verify_by_ca_certificate 验证 SM2 证书链。"""View on GitHub (pinned to 6ec464fabd)
Solutions
- Inspect the submitted cert_pem (log length/head/tail) and confirm it begins with BEGIN CERTIFICATE and is intact.
- Ensure the client sends the SM2 certificate PEM verbatim with real newlines.
- Route non-SM2 certificates to _authenticate_other instead of the SM2 branch.
Example fix
# before cert_pem = base64.b64encode(raw_der).decode() # DER b64, not PEM # after cert_pem = raw_der.decode() if b'BEGIN CERTIFICATE' in raw_der else pem_encode(raw_der)
Defensive patterns
Strategy: validation
Validate before calling
def is_valid_pem(cert_pem: str) -> bool:
return isinstance(cert_pem, str) and '-----BEGIN CERTIFICATE-----' in cert_pem \
and '-----END CERTIFICATE-----' in cert_pem
if not is_valid_pem(cert_pem):
return error_response('Invalid certificate payload', code='BAD_CERT') Type guard
def is_sm2_pem(cert_pem: str) -> bool:
return (isinstance(cert_pem, str)
and cert_pem.lstrip().startswith('-----BEGIN CERTIFICATE-----')
and '\n' in cert_pem) Try / catch
try:
sm2_cert = UKeyBackend._load_sm2_cert(cert_pem)
except UKeyCertNormalizationError:
return error_response('Certificate could not be parsed', status=400) Prevention
- Client sends PEM untouched (no newline escaping/base64 double-encoding)
- Validate PEM markers server-side before tempfile round-trip
- Route RSA/X.509 certs to the non-SM2 branch
When it happens
Trigger: _authenticate_sm2 receives cert_pem that gmssl cannot import: truncated payload, base64/DER instead of PEM, or a non-SM2 certificate submitted on the SM2 path.
Common situations: Client sends the wrong certificate slot, frontend mangles newlines in the PEM, double-encoded base64, or an RSA UKey user routed into the SM2 branch.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- Certificate has expired or is not yet valid
- gmssl reqsign failed: {}
- Certificate chain verification failed
- AUTH_UKEY_CA_CERT_CONTENT not configured
- This account is inactive.
AI-assisted analysis of jumpserver/jumpserver@6ec464fabd (2026-08-28).
Data as JSON: /api/errors/558e9defdacdff76.
Report an issue: GitHub.