深度解析

EXIF 元数据详解:照片如何泄露你的隐私

koboshiCo-founder
·4 分钟阅读
EXIF 元数据详解:照片如何泄露你的隐私
概述

每一张手机或相机拍出的照片,内部都藏着第二个文件:拍摄参数、时间戳、序列号,往往还有 GPS 坐标。本文讲清 EXIF 的字节级结构、如何查看它、它会暴露什么,以及格式转换如何把它抹除。

用 iPhone 拍一张照片,再用十六进制编辑器打开这个 JPEG。从 FF D8 起始标记往后数几百字节,你会看到这段内容:

FF E1 1C 24 45 78 69 66 00 00 4D 4D 00 2A 00 00 00 08

FF E1 是 APP1 段标记。它后面的两个字节是段长度。接着六个字节拼出 Exif\0\0,紧随其后的是一个 TIFF 头(4D 4D 00 2A 表示大端序)。你的 JPEG 里还装着第二个更小的文件,它透露出的关于你的信息,往往比图像本身还多。

EXIF 到底是什么

EXIF 是 Exchangeable Image File Format(可交换图像文件格式)的缩写。JEIDA(日本电子工业振兴协会)于 1995 年发布了 1.0 版本。如今该标准由 JEITA 和 CIPA 维护,EXIF 3.0 于 2023 年发布。

从结构上看,EXIF 就是一个 TIFF。Exif\0\0 头之后是字节序标记,然后是一串图像文件目录(Image File Directory,IFD)。每个 IFD 条目固定十二字节:

Bytes 0-1:   标签 ID(如 0x010F = Make)
Bytes 2-3:   数据类型(ASCII、rational、short、long)
Bytes 4-7:   值的数量
Bytes 8-11:  内联值,或指向值的偏移量

有两个子目录和隐私直接相关。EXIF SubIFD(由标签 0x8769 指向)保存相机参数、序列号和时间戳。GPS IFD(标签 0x8825)把纬度和经度各存为三个有理数:度、分、秒。

IFD1 里通常还存着一张缩略图,一张嵌在元数据里的小 JPEG。先记住这一点,后面会用到。

哪些容器携带 EXIF:

格式EXIF 位置说明
JPEGAPP1 段EXIF 的发源地
HEICmeta box 中的 Exif自 iOS 11 起的 iPhone 默认
WebPVP8X 内的 EXIF chunk可选,常常不存在
PNGeXIf chunk2017 年才加入规范
TIFF文件本身就是 TIFFEXIF 的母格式
BMP/ICO不支持完全没有元数据结构

相机为什么开始写入它

九十年代中期要解决的问题很琐碎,也很实际。数码相机产生的文件没有任何上下文信息。胶片摄影师有底片、印着冲印日期的相馆信封和笔记,数码相机用户有的只是一个装满 DSC_0042.JPG 的文件夹,别的什么都没有。

EXIF 解决了三个具体需求:

  • 曝光记录。光圈、快门速度、ISO 和焦距,摄影师可以回看一张照片为什么拍得好,然后重复同样的设置。
  • 打印下单。DPOF(Digital Print Order Format,数码打印命令格式)让你在相机上选好照片,之后由冲印店的自助机打印,其中会用到旋转等 EXIF 字段。
  • 方向与预览。Orientation 标签让竖拍的照片保持竖直显示,内嵌缩略图让相机液晶屏上的浏览足够快。

注意这背后的前提:照片始终留在主人手里。在 EXIF 设计的世界里,一张照片的路径是从 CF 卡到硬盘再到冲印亭。1995 年的 JEIDA,没有人会想到有一天你每天会往公共服务器上传十几张照片。

里面到底装了什么

用任何一个元数据读取工具打开一张手机照片,标签列表都会很长。其中和隐私相关的字段:

标签示例值泄露了什么
Make / ModelApple, iPhone 15 Pro你的硬件
BodySerialNumber / LensSerialNumber每台设备唯一你相机的指纹
DateTimeOriginal + OffsetTime2026:06:30 18:42:11 +09:00时间,精确到秒
GPSLatitude / GPSLongitude37°46'29" N, 122°25'10" W地点,精确到米
GPSAltitude14.2 m大致哪一层楼
SoftwareInstagram, Photoshop 26.1哪些软件动过这个文件
Artist / Copyright自由文本有时是真名
IFD1 缩略图第二个 JPEG未经编辑的原图副本

下面是一张真实 iPhone 照片的 exiftool 输出,为简洁起见做了删减:

$ exiftool IMG_4021.HEIC
Make                            : Apple
Camera Model Name               : iPhone 15 Pro
Serial Number                   : F2LX8A1BCD
Date/Time Original              : 2026:06:30 18:42:11
GPS Latitude                    : 37 deg 46' 29.28" N
GPS Longitude                   : 122 deg 25' 10.41" W
GPS Altitude                    : 14.2 m Above Sea Level

花三十秒读完,一个陌生人就能知道你用什么设备拍、什么时候在那里,以及"那里"具体是哪里,误差不过几米。

在自己的电脑上查看 EXIF

Windows

右键点击文件,打开"属性",切换到"详细信息"选项卡。制造商、型号、日期和 GPS 坐标都列在里面。选项卡底部有一个"删除属性和个人信息"链接,点开是一个简单的元数据清除对话框。

想在 PowerShell 里直接读原始数据:

Add-Type -AssemblyName System.Drawing
$img = [System.Drawing.Image]::FromFile("C:\photos\IMG_4021.jpg")
$img.PropertyItems | ForEach-Object {
    $text = [System.Text.Encoding]::ASCII.GetString($_.Value).Trim([char]0)
    "Tag 0x{0:X4} (len {1}): {2}" -f $_.Id, $_.Len, $text
}
$img.Dispose()

数值字段读出来是原始字节,但 Make、Software 这类 ASCII 标签能正常显示出文字。

macOS

用"预览"打开图片,在"工具"菜单中选择"显示检查器",查看 EXIF 和 GPS 选项卡。GPS 选项卡甚至会把拍摄位置直接标在地图上。

在终端里,mdls 会列出 Spotlight 索引到的全部信息:

mdls IMG_4021.jpg | grep -iE "gps|latitude|longitude|model"

或者用 brew install exiftool 安装 ExifTool,查看完整的标签列表。

Linux

ExifTool 是标准工具:

exiftool IMG_4021.jpg

更轻量的替代方案:exiv2 IMG_4021.jpg,或者 ImageMagick 的 identify -verbose IMG_4021.jpg | grep -i exif

在浏览器里,用二十行 TypeScript

想自己找到 APP1 段,需要沿着 JPEG 的标记链遍历一遍:

async function findExifSegment(file: File): Promise<number> {
  const bytes = new Uint8Array(await file.slice(0, 128 * 1024).arrayBuffer())
  if (bytes[0] !== 0xff || bytes[1] !== 0xd8) return -1 // not a JPEG

  let offset = 2
  while (offset < bytes.length - 12) {
    if (bytes[offset] !== 0xff) break
    const marker = bytes[offset + 1]
    const length = (bytes[offset + 2] << 8) | bytes[offset + 3]
    if (
      marker === 0xe1 &&
      String.fromCharCode(...bytes.slice(offset + 4, offset + 10)) ===
        "Exif\0\0"
    ) {
      return offset
    }
    offset += 2 + length
  }
  return -1
}

EXIF 如何泄露你的隐私

GPS 坐标暴露你的位置

只要相机应用有定位权限,手机拍照时就会记录 GPS,而这个权限是大多数人随手点过一次就忘掉的默认设置。把阳台、书桌或者孩子学校作业的照片发到论坛或二手交易平台,你就以米级精度公布了自己的住址。

最有名的例子是 John McAfee。2012 年 12 月,他在逃亡途中藏身危地马拉。Vice 发布了一张用 iPhone 4S 为他拍摄的照片,EXIF 数据里带着完整的 GPS 坐标,任何人都能读出他在危地马拉的确切位置。几天后,他被危地马拉警方拘押。

序列号把你的账号关联起来

BodySerialNumber 和 LensSerialNumber 每台设备唯一。两个匿名账号如果发布的是同一台相机拍的照片,就几乎可以被确定地关联起来。有研究者正是出于这个原因爬取图片网站,按相机序列号给照片聚类。你可以在网上把不同身份分开,你的相机却不分这些。

时间戳勾勒出你的作息

DateTimeOriginal,再加上时区偏移。单个时间戳说明不了什么,但一年的上传记录足以看出你几点起床、几点出门、什么时候旅行。

缩略图会出卖你

IFD1 缩略图是元数据里一张独立的 JPEG。把人脸或文件从主图中裁掉,很多编辑器并不会同步更新原始缩略图。谁把它提取出来,谁就拿到了未裁剪的原图。2003 年,一位 TechTV 主持人发布了裁剪过的个人照片,读者从 EXIF 缩略图中还原出了完整画面。这个教训流传至今,因为工具一直在犯同样的错误。

哪些上传渠道会留下 EXIF

大型社交平台(Facebook、Instagram、X)会在上传时剥离图片的 EXIF。其余渠道大多不会:邮件附件、论坛上传、交易平台商品图、网盘分享链接、AirDrop,以及任何设置为发送原图的即时通讯工具。只要文件原样离开你的设备,元数据就跟着一起走。

转换格式时会发生什么

转换照片格式并不自动等于清除元数据。转换器分两种:

  1. 元数据搬运工。重新编码但刻意把标签带过去的工具:ExifTool、ffmpeg,以及大多数默认勾选"保留元数据"的图形界面转换器。用这类工具把 JPEG 转成 WebP,你的 GPS 坐标会原封不动地搬进 WebP 的 EXIF chunk。
  2. 像素重编码器。先把文件解码成原始像素,再从像素编码出一个全新的文件。输出里只有图像数据,因为元数据从来就不是像素的一部分。

手动清除的话,两种方式都只需要一条命令:

# ExifTool: wipe every tag, keep the image
exiftool -all= -overwrite_original photo.jpg

# ImageMagick 7: re-encode without metadata
magick photo.jpg -strip photo-clean.jpg

这里有一个细节需要注意:方向。EXIF Orientation(标签 0x0112)告诉查看器把图像旋转一定角度,通常是 90 度。如果清除标签时没有把这个旋转烘焙进像素,每张竖拍照片导出来都是横躺的。正确的顺序是先按方向信息解码,再丢弃元数据。一个只清除不旋转的工具,比完全不清除还糟糕。

我们的转换器如何处理 EXIF

本站所有转换器都是像素重编码器,处理流程完全一致:

  1. 在你的浏览器中把源文件解码为原始像素(HEIC 使用 libheif 的 WebAssembly 版本,其余格式使用浏览器原生解码器)。
  2. 把像素绘制到画布上,EXIF 方向已在解码时应用完毕。
  3. 把画布编码为目标格式。

输出文件里只有压缩后的像素,别的什么都没有。没有 APP1 段,没有 EXIFeXIf chunk,没有 GPS IFD,没有序列号,没有内嵌缩略图。代码里根本不存在复制元数据的路径,因为内存里就没有元数据可复制。而且整个流程都在客户端运行,文件从不离开你的设备,也没有任何服务器会看到原图。

选择你的源格式:

把文件拖进来,下载转换后的副本,分享这个副本。像素一模一样,元数据已经没了。

简而言之

  • 在把照片分享到任何 EXIF 能保留下来的渠道(邮件、论坛、交易平台、直链)之前,先检查一遍。Windows 用"属性",macOS 用"检查器",Linux 用 exiftool
  • 如果文件带着 GPS 数据,而你并不希望如此,转换一下。上面链接的每个工具都只输出像素。
  • 如果你用不同的身份发帖,相机序列号可能把这些身份关联起来。清除元数据同样能解决。
  • 原图保持原样。在你自己的档案库里,EXIF 确实有用。需要干净的,是你发布出去的那些副本。

更多推荐阅读