文件签章检查
在你的浏览器里读取文件开头的字节,判断它真正的格式,而不是副档名宣称的格式。附完整的 magic number 对照表。
在你的浏览器中运行
或把文件拖进来
- 文件
- —
- 大小
- —
- 浏览器猜的类型
- —
- 实际格式
- —
- 同时符合
- —
这是一种容器格式。字节认出来的是外层包装,不是里面的东西——.docx、.jar 与 .epub 都是 ZIP,前四个字节完全一样。
开头字节
| 偏移 | 十六进制 | ASCII |
|---|
文件签名对照表
| 格式 | 签名 | 扩展名 | MIME 类型 |
|---|---|---|---|
| PNG | 89 50 4E 47 0D 0A 1A 0A | .png | image/png |
| JPEG | FF D8 FF | .jpg .jpeg | image/jpeg |
| GIF (87a) | 47 49 46 38 37 61 | .gif | image/gif |
| GIF (89a) | 47 49 46 38 39 61 | .gif | image/gif |
| BMP | 42 4D | .bmp | image/bmp |
| WebP | 52 49 46 46 · 8: 57 45 42 50 | .webp | image/webp |
| TIFF (little-endian) | 49 49 2A 00 | .tif .tiff | image/tiff |
| TIFF (big-endian) | 4D 4D 00 2A | .tif .tiff | image/tiff |
| Photoshop | 38 42 50 53 | .psd | image/vnd.adobe.photoshop |
| Windows icon | 00 00 01 00 | .ico | image/x-icon |
| Windows cursor | 00 00 02 00 | .cur | image/x-icon |
| HEIC | 4: 66 74 79 70 · 8: 68 65 69 63 | .heic | image/heic |
| AVIF | 4: 66 74 79 70 · 8: 61 76 69 66 | .avif | image/avif |
| SVG | 3C 3F 78 6D 6C | .svg | image/svg+xml |
| WAV | 52 49 46 46 · 8: 57 41 56 45 | .wav | audio/wav |
| AVI | 52 49 46 46 · 8: 41 56 49 20 | .avi | video/x-msvideo |
| MP3 with ID3 tag | 49 44 33 | .mp3 | audio/mpeg |
| FLAC | 66 4C 61 43 | .flac | audio/flac |
| Ogg容器 | 4F 67 67 53 | .ogg .oga .opus | application/ogg |
| MP4容器 | 4: 66 74 79 70 | .mp4 .m4a .m4v | video/mp4 |
| Matroska / WebM容器 | 1A 45 DF A3 | .mkv .webm | video/x-matroska |
25 50 44 46 2D | application/pdf | ||
| RTF | 7B 5C 72 74 66 | .rtf | application/rtf |
| Legacy Office (.doc, .xls, .ppt)容器 | D0 CF 11 E0 A1 B1 1A E1 | .doc .xls .ppt .msi | application/x-ole-storage |
| PostScript | 25 21 | .ps .eps | application/postscript |
| ZIP (and .docx, .xlsx, .jar, .apk, .epub, .odt)容器 | 50 4B 03 04 | .zip .docx .xlsx .pptx .jar .apk .epub .odt | application/zip |
| ZIP (empty archive) | 50 4B 05 06 | .zip | application/zip |
| gzip容器 | 1F 8B | .gz .tgz | application/gzip |
| bzip2 | 42 5A 68 | .bz2 | application/x-bzip2 |
| xz | FD 37 7A 58 5A 00 | .xz | application/x-xz |
| Zstandard | 28 B5 2F FD | .zst | application/zstd |
| 7-Zip | 37 7A BC AF 27 1C | .7z | application/x-7z-compressed |
| RAR (1.5–4.x) | 52 61 72 21 1A 07 00 | .rar | application/vnd.rar |
| RAR (5.0+) | 52 61 72 21 1A 07 01 00 | .rar | application/vnd.rar |
| tar (POSIX)容器 | 257: 75 73 74 61 72 | .tar | application/x-tar |
| Debian package / ar archive容器 | 21 3C 61 72 63 68 3E | .deb .a | application/vnd.debian.binary-package |
| ELF (Linux executable) | 7F 45 4C 46 | — | application/x-elf |
| DOS / Windows executable | 4D 5A | .exe .dll | application/vnd.microsoft.portable-executable |
| Mach-O 64-bit | CF FA ED FE | — | application/x-mach-binary |
| Java class — or a Mach-O universal binary | CA FE BA BE | .class | application/java-vm |
| WebAssembly | 00 61 73 6D | .wasm | application/wasm |
| Script with a shebang | 23 21 | .sh .py .pl | text/x-shellscript |
| SQLite database | 53 51 4C 69 74 65 20 66 6F 72 6D 61 74 20 33 00 | .sqlite .db | application/vnd.sqlite3 |
| WOFF font | 77 4F 46 46 | .woff | font/woff |
| WOFF2 font | 77 4F 46 32 | .woff2 | font/woff2 |
| OpenType font | 4F 54 54 4F | .otf | font/otf |
| TrueType font | 00 01 00 00 00 | .ttf | font/ttf |
| Text with a UTF-8 byte order mark | EF BB BF | .txt | text/plain |
| Text with a UTF-16 LE byte order mark | FF FE | .txt | text/plain |
| Text with a UTF-16 BE byte order mark | FE FF | .txt | text/plain |
只读取开头 512 个字节,而且是在你的浏览器里读的。没有任何东西被上传。
副档名是说法,字节才是证据
档名结尾是 .jpg,只说明了有人决定这样叫它,完全没有说里面是什么。开头那几个字节通常会说:
大多数二进位格式的开头都是一段固定的样式,也就是 magic number,放在那里的用意正是让程序
不必相信档名就能认出文件。
把文件拖到上面,这个页面会读开头 512 个字节,告诉你它们说了什么。它不会多读,也不会把任何东西 送出去——这正是重点,因为你会想查一个文件的类型,通常就是因为你不信任它。
不一致代表什么,不代表什么
副档名与字节不一致时,页面会直说。无害的常见原因:
- 有人把
.png改名成.jpg,好通过上传限制。 - 下载时服务器送错
Content-Type,存下来的副档名就跟着错。 - 文件其实是
.docx,而.docx本来就是 ZIP。字节没错,是预期错了。
比较不无害的原因:披着图片副档名的脚本或执行档,或者刻意做成同时是两种合法格式的 polyglot 文件。 不一致是「值得看一下」的理由,不是判决。
而相符能证明的,比看起来少得多。 magic number 就只是开头那几个字节。一个文件可以用 %PDF-
开头,而其余几乎全是别的东西。签章检查是一道快速的筛子,不是验证器。
最容易搞错的几个情况
PK 不等于「一个 ZIP 档」
50 4B 03 04——PK 加两个控制字节,取自 Phil Katz——是每一个 ZIP 压缩包的开头。它同时也是
每一个 .docx、.xlsx、.pptx、.odt、.jar、.apk、.epub 的开头,因为这些本来就是
ZIP,只是内部有约定好的结构。再怎么读开头的字节都分不出来,只能把压缩包打开看里面有什么。
RIFF 与 ftyp 要看第二段
有些格式先放一个通用的容器标记,真正的格式在后面几个字节:
| 位移 0 | 位移 8 | 格式 |
|---|---|---|
RIFF | WEBP | WebP |
RIFF | WAVE | WAV |
RIFF | AVI | AVI |
ISO base media 也一样:ftyp 在位移 4,品牌代码在 8——所以 MP4、MOV、HEIC、AVIF 的前四个
字节完全相同。任何「一个格式一个样式」的对照表在这里都会出错。
CA FE BA BE 是两种东西
它是 Java .class 档的 magic number,1991 年选它是因为那是一个念得出来的十六进位单字。它同时
也是 macOS 上 Mach-O universal binary 的 magic number。两个都对;只挑一个讲的工具是在猜。
tar 的签章在第 257 个字节
ustar 出现在位移 257,不在开头,因为 tar 比「把头部放在文件最前面」这个惯例还早。只读前十六个
字节的话,每一个 tar 档都会认不出来。
根本没有签章的格式
纯文字、CSV、JSON、HTML、JavaScript、Markdown、大部分原始码——一个都没有,因为它们从来不是设计成 让机器读四个字节就认出来的。页面说「没有已知的文件签章」时,那往往是正确答案,不是失败。
例外是 byte order mark:文字档开头的 EF BB BF 是 UTF-8 BOM,也是 CSV 偶尔在第一格多出
 的原因。
相关
全部在你的浏览器里完成。若要验证文件的内容而不是类型, 杂凑产生器用同样的方式做指纹。