{"record":{"id":"1704ea84b0355096","repo":"jumpserver/jumpserver","slug":"invalid-sm3-digest-size","errorCode":null,"errorMessage":"Invalid SM3 digest size","messagePattern":"Invalid SM3 digest size","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"apps/common/utils/gmssl_python.py","lineNumber":485,"sourceCode":"\t\tfp = libc.fopen(path.encode('utf-8'), 'wb')\n\t\tif gmssl.sm2_public_key_info_to_pem(byref(self), c_void_p(fp)) != 1:\n\t\t\traise NativeError('libgmssl inner error')\n\t\tlibc.fclose(c_void_p(fp))\n\n\tdef import_public_key_info_pem(self, path):\n\t\tlibc.fopen.restype = c_void_p\n\t\tfp = libc.fopen(path.encode('utf-8'), 'rb')\n\t\tif gmssl.sm2_public_key_info_from_pem(byref(self), c_void_p(fp)) != 1:\n\t\t\traise NativeError('libgmssl inner error')\n\t\tlibc.fclose(c_void_p(fp))\n\t\tself._has_public_key = True\n\t\tself._has_private_key = False\n\n\tdef sign(self, dgst):\n\t\tif self._has_private_key == False:\n\t\t\traise TypeError('has no private key')\n\t\tif len(dgst) != SM3_DIGEST_SIZE:\n\t\t\traise ValueError('Invalid SM3 digest size')\n\t\tsig = create_string_buffer(SM2_MAX_SIGNATURE_SIZE)\n\t\tsiglen = c_size_t()\n\t\tif gmssl.sm2_sign(byref(self), dgst, sig, byref(siglen)) != 1:\n\t\t\traise NativeError('libgmssl inner error')\n\t\treturn sig[:siglen.value]\n\n\tdef verify(self, dgst, signature):\n\t\tif self._has_public_key == False:\n\t\t\traise TypeError('has no public key')\n\t\tif len(dgst) != SM3_DIGEST_SIZE:\n\t\t\traise ValueError('Invalid SM3 digest size')\n\t\tif gmssl.sm2_verify(byref(self), dgst, signature, c_size_t(len(signature))) != 1:\n\t\t\treturn False\n\t\treturn True\n\n\tdef encrypt(self, data):\n\t\tif self._has_public_key == False:\n\t\t\traise TypeError('has no public key')","sourceCodeStart":467,"sourceCodeEnd":503,"githubUrl":"https://github.com/jumpserver/jumpserver/blob/6ec464fabd61b95912d539455a3a5f15f5c59fe0/apps/common/utils/gmssl_python.py#L467-L503","documentation":"ValueError raised by sign when the digest argument is not exactly SM3_DIGEST_SIZE (32) bytes. SM2 signs an SM3 digest, so the input must be the fixed 32-byte SM3 output; the wrapper enforces this before invoking the native signer.","triggerScenarios":"Calling sign(dgst) with a SHA-256 digest (32 bytes but semantically wrong is still accepted-length-wise; a 16/20/64-byte digest raises), with a hex-encoded digest string (64 chars), or with a raw message instead of its digest.","commonSituations":"Hashing with SHA-1/SHA-512 instead of SM3; passing hex digests from logs; signing the message itself rather than sm3(msg); using str instead of bytes.","solutions":["Hash with SM3 first: dgst = SM3().update(msg).finish() (or the module's sm3 helper) yielding 32 bytes","Pass bytes, not hex strings: bytes.fromhex(hex_digest) if you only have hex","Double-check the digest pipeline length: assert len(dgst) == 32 before signing"],"exampleFix":"// before\nsig = sm2.sign('a1b2...32-byte-hex-string...')   # 64-char str -> ValueError\n// after\nfrom gmssl_python import SM3\ndgst = SM3(bytes(msg, 'utf-8')).finish() if hasattr(SM3, '__call__') else sm3_digest(msg)\nsig = sm2.sign(dgst)  # exactly 32 bytes","handlingStrategy":"validation","validationCode":"from gmssl_python import SM3_DIGEST_SIZE\ndgst = bytes.fromhex(dgst_hex) if isinstance(dgst, str) else dgst\nassert len(dgst) == SM3_DIGEST_SIZE, f'digest must be {SM3_DIGEST_SIZE} bytes'","typeGuard":"def is_sm3_digest(d) -> bool:\n    return isinstance(d, (bytes, bytearray)) and len(d) == 32","tryCatchPattern":"try:\n    sig = sm2.sign(dgst)\nexcept ValueError as e:\n    if 'digest size' in str(e):\n        raise ValueError('hash the message with SM3 before signing') from None\n    raise","preventionTips":["Always hash with SM3, not SHA-256, in SM2 workflows","Keep digests as bytes; convert hex only at display boundaries","Assert len(digest)==32 in helper functions"],"tags":["gmssl","sm2","sm3","digest","signing","validation","python"],"backgroundTag":"invalid-digest-size","analyzedSha":"6ec464fabd61b95912d539455a3a5f15f5c59fe0","analyzedAt":"2026-08-28T11:33:00.925Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}