Wheel归档与RECORD核验
核对本地wheel文件名、元数据、标签与每个RECORD哈希和大小,明确区分完整性失败、不支持的哈希和未验证签名。
- 1添加输入
- 2调整设置
- 3获取结果
工具输入和文件在当前浏览器处理,不会上传。
开始之前
安装未知wheel前,先查看归档声明与字节是否一致。此任务只读取文件,不导入包;坏哈希交付失败报告,不能用“已生成报告”代替“核验通过”。
如何使用
- 选择保留原文件名的wheel,或加载固定小文件示例。
- 查看完整性状态、已核验文件、失败、未知哈希与未验证签名。
- 下载全部核验报告,并用可信生产者核对失败项;不要将报告当作安全或安装许可。
支持范围与限制
只选择1个32 MiB以内的.whl文件,不接受粘贴。ZIP最多10000项、展开后64 MiB、每项压缩比200;危险路径、重复、CRC错误、加密、多卷和ZIP64拒绝。JSON报告最多200000值,全部下载合计10 MiB;任一预算超限原子拒绝,不输出部分核验。
支持Wheel-Version 1.0与Metadata-Version 1.1、1.2、2.1–2.6。必须恰有对应文件名分发名称和字面版本的dist-info目录及METADATA/WHEEL/RECORD。名称按连字符、下划线和点规范化比较,版本按字面比较,不推断PEP440等价。可选build和压缩标签与WHEEL逐项核对。折行/重复头、描述正文和入口点保留为文本。
核验每个归档文件的RECORD URL安全规范Base64 SHA256/384/512及大小;未列出、缺失、哈希或大小不符、元数据不一致均为integrityStatus=failed。SHA224及其他未知算法为unsupported_hash/incomplete;MD5/SHA1禁止并记为失败。失败仍交付完整诊断报告,不宣称通过。
RECORD自身必须空哈希/大小;旧RECORD.jws/p7s签名文件明确signature_not_verified,不执行验签。verified_recorded_payload只描述已列出负载的核验,不证明包真实性、安装安全、主机ABI或平台适用性。不安装、导入、执行入口点或向磁盘解包。
报告预览最多200行,每个超过2000字符的单元格只显示前2000字符加省略号。报告超过20000字符时文本/复制为摘要预览;完整JSON、CSV、HTML始终在下载文件中,未知哈希和例外可见。
操作示例
示例输入
Selected file: demo_pkg-1.2.3-py2.py3-none-any.whl (1461 bytes)
示例参数
{"secondary":"","params":{"spreadsheetSafe":true},"files":[{"name":"demo_pkg-1.2.3-py2.py3-none-any.whl","type":"application/zip","base64":"UEsDBBQAAAAIADOQRl2Z6IfyFgAAABQAAAAUAAAAZGVtb19wa2cvX19pbml0X18ucHkrKMrMK9FQcvFX8PMPUQgK9VPS5AIAUEsDBBQAAAAIADOQRl2sis5GCQAAAAcAAAAYAAAAZGVtb19wa2cvZGF0YSxxdW90ZWQudHh0y0jNycnn5QIAUEsDBBQAAAAIADOQRl14NdQjlgAAANUAAAAhAAAAZGVtb19wa2ctMS4yLjMuZGlzdC1pbmZvL01FVEFEQVRBXYy9CoMwFEb3PMXFPQF1KWl1crVDC13LRS821Pw0uRZ9+ypCB8fDd87XEmOPjPJBMRnvNBQqF1e0pKEn62V4D+K/5apQpbjRZzKRkmxMYg1xRUqc6qo4Q1j45d3zuxd1lZXqlB0LXoJxg6SZyW1aOnaXPbtP1mJcNNCMNowkoPOOjZuQV0mIhlIXTdgAwojGAa+fSvwAUEsDBBQAAAAIADOQRl0x1dR9WgAAAGkAAAAeAAAAZGVtb19wa2ctMS4yLjMuZGlzdC1pbmZvL1dIRUVMRcg7CoAwEAXAPqfIBVb8dLmA2ImI1lGeGpBd2UTQ22sjljPjBuw0QGMQdrbIclODoT6JOquI8DpvtIQrnQrTiSRqIrUv9jA5m/SE6f3q7HGXxMIgz/c31T8PUEsDBBQAAAAIADOQRl1s0YtXKgAAACsAAAApAAAAZGVtb19wa2ctMS4yLjMuZGlzdC1pbmZvL2VudHJ5X3BvaW50cy50eHSLTs7PK87PSY0vTi7KLCgpjuVKSc3NV7BVAFHxBdnpesk5mVa5iZl5XABQSwMEFAAAAAgAM5BGXe4nb4A4AQAAzAEAAB8AAABkZW1vX3BrZy0xLjIuMy5kaXN0LWluZm8vUkVDT1JEfdDLtkJQAMbxeY/ReJNLLg3OANsldCpJNLFkE6lN7E54+rPOwLDzAr//tz6UPeq4qa6LOC5xSeKYbgbQFQkniF+GnHLjLtBgYtm7wtjY+1bT7uc1WcF3zCzDKxcWsuzKZOwAx8zmaLJQQhLwfNUkQzTpyXwCx4PkfPsBYw1Z3VYQmu9eZZVAzPDLc8at0JKiKpC19nAEpNnEUSzN0TyNyo5QJc7rxUb3Faj4ysQe+iK1sSeprhXh2Bwj/8B39sZx71sBmXu+Fx5UQC1XlqkDjuU/wydL191JvekwYBj1+JMzj/ypQdEQ3IS/peFR0LgVV7MGS50yN0zyDrCM8FnNMGmHuKlLTLq/O6bAWgvKS4VzIXg1t8h8e0gy1XPLi8pYhMZwVND3Dl5c596lYPnPak/Xth4EYPYLUEsBAhQDFAAAAAgAM5BGXZnoh/IWAAAAFAAAABQAAAAAAAAAAAAAALSBAAAAAGRlbW9fcGtnL19faW5pdF9fLnB5UEsBAhQDFAAAAAgAM5BGXayKzkYJAAAABwAAABgAAAAAAAAAAAAAALSBSAAAAGRlbW9fcGtnL2RhdGEscXVvdGVkLnR4dFBLAQIUAxQAAAAIADOQRl14NdQjlgAAANUAAAAhAAAAAAAAAAAAAAC0gYcAAABkZW1vX3BrZy0xLjIuMy5kaXN0LWluZm8vTUVUQURBVEFQSwECFAMUAAAACAAzkEZdMdXUfVoAAABpAAAAHgAAAAAAAAAAAAAAtIFcAQAAZGVtb19wa2ctMS4yLjMuZGlzdC1pbmZvL1dIRUVMUEsBAhQDFAAAAAgAM5BGXWzRi1cqAAAAKwAAACkAAAAAAAAAAAAAALSB8gEAAGRlbW9fcGtnLTEuMi4zLmRpc3QtaW5mby9lbnRyeV9wb2ludHMudHh0UEsBAhQDFAAAAAgAM5BGXe4nb4A4AQAAzAEAAB8AAAAAAAAAAAAAALSBYwIAAGRlbW9fcGtnLTEuMi4zLmRpc3QtaW5mby9SRUNPUkRQSwUGAAAAAAYABgDHAQAA2AMAAAAA"}]}示例输出
{"format":"Wheel1.0 archive and RECORD audit","summary":{"files":6,"zipEntries":6,"expandedBytes":848,"verifiedFiles":5,"integrityFailures":0,"unsupportedHashes":0,"unverifiedSignatures":0,"integrityStatus":"verified_recorded_payload","metadataVersion":"2.1","distribution":"demo-pkg","version":"1.2.3","build":null,"packageAuthenticityVerified":false},"filename":"demo_pkg-1.2.3-py2.py3-none-any.whl","distInfo":"demo_pkg-1.2.3.dist-info","filenameTags":["py2-none-any","py3-none-any"],"declaredTags":["py2-none-any","py3-none-any"],"expandedTags":["py2-none-any","py3-none-any"],"metadata":{"headers":[{"key":"Metadata-Version","value":"2.1"},{"key":"Name","value":"demo-pkg"},{"key":"Version","value":"1.2.3"},{"key":"Requires-Dist","value":"requests>=2; python_version>=\"3.8\""},{"key":"Requires-Dist","value":"typing-extensions; python_version<\"3.8\""},{"key":"Summary","value":"example\n continuation"}],"body":"Description plain text.\n"},"wheel":{"headers":[{"key":"Wheel-Version","value":"1.0"},{"key":"Generator","value":"research-fixture"},{"key":"Root-Is-Purelib","value":"true"},{"key":"Tag","value":"py2-none-any"},{"key":"Tag","value":"py3-none-any"}],"body":""},"checks":[{"path":"demo_pkg/__init__.py","status":"verified","algorithm":"sha256","recordedBytes":"20","actualBytes":20,"expectedHash":"sha256=F8c2zPVCDaHJPhFMJQrCClZIt9Dw_04Xg2Xh88L8tzs","actualHash":"sha256=F8c2zPVCDaHJPhFMJQrCClZIt9Dw_04Xg2Xh88L8tzs","sizeMatches":true},{"path":"demo_pkg/data,quoted.txt","status":"verified","algorithm":"sha256","recordedBytes":"7","actualBytes":7,"expectedHash":"sha256=zS7KNTV0HyeorkDDGwxB1AV6enuRKzO5rthkhdHIRnY","actualHash":"sha256=zS7KNTV0HyeorkDDGwxB1AV6enuRKzO5rthkhdHIRnY","sizeMatches":true},{"path":"demo_pkg-1.2.3.dist-info/METADATA","status":"verified","algorithm":"sha256","recordedBytes":"213","actualBytes":213,"expectedHash":"sha256=SxhcJnR7BLHYn_GzYTS3sJMKLlO5dGQ3x5m-V-49HGE","actualHash":"sha256=SxhcJnR7BLHYn_GzYTS3sJMKLlO5dGQ3x5m-V-49HGE","sizeMatches":true},{"path":"demo_pkg-1.2.3.dist-info/WHEEL","status":"verified","algorithm":"sha256","recordedBytes":"105","actualBytes":105,"expectedHash":"sha256=jEDV00BUvf0mfqCD6F5La3jcXU5C292o1F1-WeLXafs","actualHash":"sha256=jEDV00BUvf0mfqCD6F5La3jcXU5C292o1F1-WeLXafs","sizeMatches":true},{"path":"demo_pkg-1.2.3.dist-info/entry_points.txt","status":"verified","algorithm":"sha256","recordedBytes":"43","actualBytes":43,"expectedHash":"sha256=ICVibknf5VupjYGwRd7GBZr36AzhXFyUAdNPDbLKlsc","actualHash":"sha256=ICVibknf5VupjYGwRd7GBZr36AzhXFyUAdNPDbLKlsc","sizeMatches":true},{"path":"demo_pkg-1.2.3.dist-info/RECORD","status":"record_self_unhashed","algorithm":null,"recordedBytes":null,"actualBytes":460,"expectedHash":null,"actualHash":null,"sizeMatches":null}],"issues":[],"entryPoints":"[console_scripts]\ndemo = demo_pkg.cli:main\n","files":[{"path":"demo_pkg/__init__.py","bytes":20},{"path":"demo_pkg/data,quoted.txt","bytes":7},{"path":"demo_pkg-1.2.3.dist-info/METADATA","bytes":213},{"path":"demo_pkg-1.2.3.dist-info/WHEEL","bytes":105},{"path":"demo_pkg-1.2.3.dist-info/entry_points.txt","bytes":43},{"path":"demo_pkg-1.2.3.dist-info/RECORD","bytes":460}],"unverifiedExceptions":["RECORD self entry has no hash/size","legacy signatures are not verified","no package authenticity/ABI/security/installation verdict"]}出现问题时
使用生产者导出的完整原wheel与原文件名;检查唯一dist-info、必需头、标签、规范RECORD CSV和路径。失败哈希应向可信来源重新获取文件,不改哈希掩盖差异。超限请在生产者侧生成更小归档。
常见问题
哈希失败为什么仍有下载?
下载的是失败诊断,integrityStatus明确为failed;每个原声明与实际值可用于查错。
能证明wheel安全吗?
不能。RECORD不是可信签名。本工具不验证代码安全、作者身份或当前机器的ABI。
为什么不支持SHA224?
合同只实现SHA256/384/512。SHA224明确标成不支持,不能据此宣称全部文件已核验。