{"record":{"id":"4a4c066ac1ebf5fc","repo":"aio-libs/aiohttp","slug":"md5-and-sha1-are-insecure-and-not-supported-use-s","errorCode":null,"errorMessage":"md5 and sha1 are insecure and not supported. Use sha256.","messagePattern":"md5 and sha1 are insecure and not supported\\. Use sha256\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"aiohttp/client_reqrep.py","lineNumber":189,"sourceCode":"        return tuple.__new__(\n            cls, (url, method, headers, url if real_url is sentinel else real_url)\n        )\n\n\nclass Fingerprint:\n    HASHFUNC_BY_DIGESTLEN = {\n        16: md5,\n        20: sha1,\n        32: sha256,\n    }\n\n    def __init__(self, fingerprint: bytes) -> None:\n        digestlen = len(fingerprint)\n        hashfunc = self.HASHFUNC_BY_DIGESTLEN.get(digestlen)\n        if not hashfunc:\n            raise ValueError(\"fingerprint has invalid length\")\n        elif hashfunc is md5 or hashfunc is sha1:\n            raise ValueError(\"md5 and sha1 are insecure and not supported. Use sha256.\")\n        self._hashfunc = hashfunc\n        self._fingerprint = fingerprint\n\n    @property\n    def fingerprint(self) -> bytes:\n        return self._fingerprint\n\n    def check(self, transport: asyncio.Transport) -> None:\n        if not transport.get_extra_info(\"sslcontext\"):\n            return\n        sslobj = transport.get_extra_info(\"ssl_object\")\n        cert = sslobj.getpeercert(binary_form=True)\n        got = self._hashfunc(cert).digest()\n        if got != self._fingerprint:\n            host, port, *_ = transport.get_extra_info(\"peername\")\n            raise ServerFingerprintMismatch(self._fingerprint, got, host, port)\n\n","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/client_reqrep.py#L171-L207","documentation":"Raised by Fingerprint.__init__ when the fingerprint length maps to md5 (16 bytes) or sha1 (20 bytes). Both algorithms are cryptographically broken, so aiohttp refuses to use them for certificate pinning and directs the caller to SHA-256 (32 bytes). This is a deliberate hard security policy, not a capability gap.","triggerScenarios":"Calling Fingerprint(b'<16 bytes>') or Fingerprint(b'<20 bytes>') — i.e. supplying an MD5 or SHA-1 digest of the server certificate. Construction fails before any request is made.","commonSituations":"Legacy pinning config generated with md5/sha1; tutorials/examples predating the deprecation; tooling that defaults to sha1 for certificate digests; copying a fingerprint from an old openssl output.","solutions":["Recompute the fingerprint as SHA-256 of the DER certificate and pass the 32-byte digest.","Regenerate via: openssl x509 -in cert.pem -noout -pubkey | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary.","Remove any md5/sha1 fingerprint from config files and replace with the sha256 value.","Do not attempt to bypass; md5/sha1 pinning is insecure."],"exampleFix":"# before\nimport hashlib\nfp = Fingerprint(hashlib.md5(der_cert).digest())  # 16 bytes -> ValueError\n\n# after\nfp = Fingerprint(hashlib.sha256(der_cert).digest())  # 32 bytes","handlingStrategy":"validation","validationCode":"import hashlib\n\ndef sha256_fingerprint(der_cert: bytes) -> bytes:\n    # always produce a supported 32-byte sha256 fingerprint\n    return hashlib.sha256(der_cert).digest()","typeGuard":"def is_secure_fingerprint(fp: bytes) -> bool:\n    # 32 bytes => sha256 (the only secure length aiohttp accepts)\n    return isinstance(fp, (bytes, bytearray)) and len(fp) == 32","tryCatchPattern":"from aiohttp import Fingerprint\n\ntry:\n    fp = Fingerprint(raw)\nexcept ValueError as e:\n    if 'insecure' in str(e):\n        raise ValueError('Recompute the fingerprint with SHA-256 (32 bytes)')\n    raise","preventionTips":["Regenerate all existing md5/sha1 pins as sha256.","Audit config for 16- or 20-byte fingerprint values.","Use openssl with -sha256 when extracting cert digests."],"tags":["ssl","tls","fingerprint","security","deprecation","client"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}