# 隐写术是什么？把数据藏进图片的原理

隐写术（steganography）是把一条信息藏起来，让没有人怀疑有信息存在的做法。加密是把信息打乱，让它无法被读懂；隐写术则是把它藏进某个普通的东西里，比如一张度假照片或一段语音备忘，让没人想到去查看。这个词来自希腊语，意思是“被遮盖的书写”。

数字隐写术主要围绕图片，因为一张照片里有几百万个数字，可以在没人看得出差别的情况下被轻微改动。本指南介绍实际存在的方法，从修改像素的最后一位，到在 JPEG 压缩内部做手脚；说明为什么大多数“图片里藏文件”（常说的“图种”）的做法其实比真正的隐写术简单；为什么通过聊天 App 发送照片常常会抹掉隐藏的部分；以及寻找隐藏数据的人，也就是隐写分析者，是怎么做的。

## 什么是隐写术

每个隐写系统都有同样的三个部分。**载荷**（payload）是秘密本身：一条信息、一个文件、一个文件夹。**载体**（carrier），也叫封面，是装着它的无害文件：一个 PNG、一个 JPEG、一段 WAV 录音。结果，也就是里面带着载荷的载体，叫作隐写文件或隐写包。Wikipedia 上的相关文章还补充了一个有用的第四个术语：**嵌入密度**（encoding density），即载体中被改动的比例。密度越低，改动越难被察觉，能放进去的数据也越少。

按 Wikipedia 的说法，相对于加密的优势在于，秘密“does not attract attention to itself as an object of scrutiny”（不会让自己成为被审视的对象而引起注意）。一个加密文件会宣告有东西在被保护。一张小狗的照片什么也不会宣告。这也是它的弱点：一旦有人怀疑这张照片，隐写术本身就什么也保护不了，所以严肃的工具会先加密载荷、再隐藏它。隐藏换来的是“不显眼”。当“不显眼”失效时，保护内容安全的是加密。

## 这个想法比计算机早了 2500 年

最古老的故事是实物的。希罗多德描述过一条信息被纹在信使剃光的头上，等头发长回来之后再派他出发。后来的几个世纪里，人们用过遇热显现的隐形墨水，到了二十世纪，微缩点把一页文字缩到一个印刷句号那么大。这个词本身最早出现在 1499 年，在约翰内斯·特里特米乌斯（Johannes Trithemius）的《Steganographia》中，那是一本伪装成魔法书的密码学和隐写术论著。

数字版本沿用同样的逻辑，只是把头皮换成了文件格式。载体只需要两个属性：它的某一部分可以在人察觉不到的情况下改变，而且知道去哪里找的程序能把这个改变读回来。图像在这两点上都极为充足。

## LSB 隐写：改动每种颜色的最后一位

教科书上的方法是最低有效位（LSB）嵌入。典型图像中的一个像素，把红、绿、蓝存成 0 到 255 之间的数字，每个都写成八位二进制。最后一位恰好代表一个单位的变化。把它翻转，红色值 200 就变成 201。没有任何屏幕、任何眼睛能显示出这个差别。

<figure><img src="/docs/guides/img/stego/lsb-bits.svg" alt="一个红 200、绿 117、蓝 54 的像素，以二进制表示。把每个值的最后一位换成信息位 1、0、1，得到 201、116 和 55。两个色块看起来一模一样。" loading="lazy" width="100%"><figcaption>三个信息位存进一个像素。每个值最多只变动 255 级中的一级。</figcaption></figure>

对图片里的每个值都这样做，容量就累积起来了。一张 1200 万像素的照片有 3600 万个颜色值，每个存一位就是 3600 万位，理论上约 4.5 MB。真实的工具用得少得多，一方面是为了保持不显眼，另一方面是因为它们会按由密码得出的伪随机顺序分散这些位，这样载荷就不会是图像顶部一整块整齐的区域。

LSB 只适用于无损格式，如 PNG 和 BMP，这些格式会精确存储每个像素值。把同一张图存成 JPEG，压缩器会对数值取整，打乱最后几位，信息也随之被打乱。

它也是隐写分析者最了解的方法。自然照片的低位有一种特有的噪声模式，用看起来完全随机的加密数据覆盖这些位，就会改变这个模式。Westfeld 和 Pfitzmann 在 2000 年发表了针对 LSB 嵌入的统计攻击，Fridrich、Goljan 和 Du 在 2001 年表明，在彩色图像中，嵌入会增加“非常接近”的颜色对的数量。Wikipedia 报告说，仅改动 LSB 的做法“在某些情况下能以合理的可靠度检测出低至 1% 的嵌入密度”（“in some cases detecting encoding densities as low as 1% with reasonable reliability”），不过那里这个数字没有引用来源。在 Hacker News 上，有位评论者说得更直白：朴素的 LSB 替换引入的噪声“VERY easy to detect”（非常容易检测）。

## JPEG 隐写在压缩内部工作

手机和网络上的大多数照片都是 JPEG，所以工具必须找到办法挺过 JPEG 的取整。答案是在取整之后而不是之前藏数据。

JPEG 编码器把图像切成 8×8 像素的块，并用一种叫离散余弦变换（DCT）的变换，把每个块转成 64 个频率系数：一个数代表块的平均亮度，其他的代表粗略和精细的细节。然后它把这些系数除以一张质量表并取整，损失就发生在这里。JPEG 隐写直接编辑取整后的系数本身，所以编码器之后做的任何事，都不会把信息取整抹掉。

早期的工具做得很朴素。JSteg 和 JPHide 是 Provos 和 Honeyman 在 2001 年测试检测的两个程序，它们改动系数低位的方式会让整体直方图发生偏移，统计检验能抓到。OutGuess 由 Niels Provos 在 1999 年编写，它把位嵌入伪随机选择的系数，然后调整其他系数，让全局直方图与原图一致，专门用来对付卡方攻击。

这没能持续：Fridrich、Goljan 和 Hogea 在 2002 年的一次攻击，测量了 JPEG 块边缘的“块状度”（blockiness），攻破了 OutGuess，甚至估算出了隐藏信息的长度。steghide 是最著名的命令行工具，它对 JPEG 和音频走了另一条路：用密码短语选出数值对进行交换，使每种颜色或采样值的计数保持不变，其作者称这能抵抗“first-order statistical tests”（一阶统计检验）。

这场军备竞赛仍是这个领域的形态。Fridrich、Pevny 和 Kodovsky 在 2007 年把统计上不可检测的 JPEG 隐写称为一个满是“dead ends”（死胡同）的研究难题，到 2012 年，隐写分析已转向在数千个图像特征上训练的机器学习分类器。读者在网上会看到的两种说法，隐写术“很容易被检测”和“很难被检测”，都是对的。分界线在算法上，而不在这个想法本身。

## 大多数“图片里藏文件”，是追加的数据，不是真正的隐写术

在 YouTube 上搜“怎么把文件藏进图片”，最常见的演示根本不是 LSB。它是 Windows 上的一行命令：

<ol>
<li>把一张照片和一个 zip 压缩包放在同一个文件夹里。</li>
<li>在命令提示符里运行 <code>copy /b photo.jpg + archive.zip combined.jpg</code>。在 macOS 或 Linux 上，<code>cat photo.jpg archive.zip &gt; combined.jpg</code> 效果相同。</li>
<li>打开 <code>combined.jpg</code>：它显示的是那张照片。把它改名为 <code>.zip</code>，很多压缩工具就能打开里面的文件。</li>
</ol>

这能行得通，是因为格式的结尾方式。JPEG 以一个图像结束标记收尾，PNG 以一个叫 IEND 的数据块收尾，PNG 规范把它定义为“the last chunk in a PNG datastream”（PNG 数据流中的最后一个数据块）。图像查看器读到那里就停止，忽略后面的任何东西。相反，zip 读取器会在文件末尾寻找压缩包的目录，并往回读。一个能被两个不同程序都当作有效文件读取的文件，叫作**多态文件**（polyglot），而“old RAR trick”（古老的 RAR 把戏），正如 r/Steganography 上一位 Reddit 用户所称，就是最常见的例子，也就是常说的“图种”。

<figure><img src="/docs/guides/img/stego/three-ways.svg" alt="在文件中隐藏数据的三种方式的示意图：改动图像数据内部像素的低位、在结束标记之后追加字节、在结束标记之前加入格式允许的额外记录。" loading="lazy" width="100%"><figcaption>隐藏数据可以放的三个位置。只有第一种改变了图片本身。</figcaption></figure>

还有第三类介于两者之间。大多数格式都是带标签数据块的容器，并定义了添加自定义数据块的办法：PNG 有辅助数据块，JPEG 有应用段，MP4 有用户自定义的 box，PDF 允许注释。不认识某个数据块的查看器会跳过它，所以文件保持完全有效，在任何地方都能正常打开。容量很大，视频里可达数 GB，而图片本身没有任何变化。

后两种严格说来都不是隐写术，因为它们既没有碰像素，也没有设法让自己在统计上看起来正常。文件只是携带了超出画面所需的东西。在近期一批样本里，r/Steganography 上获赞最多的帖子，把数据藏进 BMP 扫描行的填充字节里，而它自己的评论者就看出了破绽：有人算了容量账，另一人说他们会“be immediately suspicious if someone sent me an image that's not png or jpg”（如果有人给我发的图片不是 png 或 jpg，我会立刻起疑）。追加和插入的数据能瞒过看图片的人，却瞒不过读取整个文件的程序，而且这个文件明显比同样尺寸的普通照片大。

## 分享照片常常会毁掉载荷

隐藏的数据只有在原样的字节都保留下来时才能存活，而人们分享照片的许多方式并不会保留它们。

聊天 App、社交网络或图片托管服务收到一张照片时，往往并不会保存你发出的那个文件。它会把图像解码成像素，经常还会缩小尺寸，并为了节省带宽写出一个全新的压缩文件。像素里的 LSB 位会被新的压缩打乱。系数级的 JPEG 载荷在质量改变时被取整抹去。追加的字节和额外的格式记录通常不会被复制，因为 App 是只根据像素写出新文件的。

<figure><img src="/docs/guides/img/stego/recompression.svg" alt="流程图：带有隐藏数据的图片，通过 U 盘、云盘、电子邮件附件或“以文档发送”作为文件复制，会原样到达，数据得以保留。作为照片发送时，App 会解码、缩放并写出新文件，所以像素位被打乱，额外的字节和记录根本不会被写入。" loading="lazy" width="100%"><figcaption>只有逐字节复制文件时，隐藏的部分才会跟着走。</figcaption></figure>

目前没有可靠的公开测试说明哪些 App 会这么做，而且行为会随版本以及“照片”与“文档”发送模式而变化，所以在被证明无损之前，请把任何分享都当作有损的。这些轶事都指向同一个方向。r/Steganography 上有位 Reddit 用户发现，某个工具的载荷只在从 Reddit 下载的 PNG 里存活，在 Reddit 提供的 WebP 版本里则没有。Hacker News 上有位评论者回忆起较早的一次尝试：“most image hosts were smart enough to detect the sub-optimal encoding and 'helpfully' fix it”（大多数图片托管服务足够聪明，能检测到次优的编码并‘好心地’修复它）。安全的习惯很简单：把文件当作文件来发送，并在删除原件之前，先检查收到的那份副本还能打开。

## 隐写分析，是找出隐藏数据的手艺

Wikipedia 把隐写分析定义为“the study of detecting messages hidden using steganography”（研究如何检测用隐写术隐藏的信息），与密码分析相对。它的目标分三步：发现可疑文件，判断它们是否带有载荷，并在可能时恢复它。前两步是统计和文件检查。第三步通常需要密码，这就是为什么即使隐藏已被看穿，加密仍然重要。

最著名的实地研究说明了第三步在实践中有多难。2001 年，Niels Provos 和 Peter Honeyman 扫描了 eBay 拍卖中的两百万张图片。他们的检测器标记了约 17,000 张，对这些做字典攻击，却一条隐藏信息也没找到。Wikipedia 的文章警告说，只凭隐写分析采取行动是“a very dicey proposition unless a payload has been completely recovered and decrypted”（除非载荷已被完全恢复并解密，否则是非常冒险的），因为否则分析者只有“a statistic indicating that a file may have been modified”（一个表明文件可能被修改过的统计数字）。检测是什么样子、它的局限，完整的故事见[隐藏的照片能被发现吗](/zh/guides/can-hidden-photos-be-detected)。双方的工具，连同它们的年龄和弱点，在[隐写术工具对比](/zh/guides/steganography-tools)中做了比较。

## HideFile 能帮上什么

大多数搜索隐写术的人并不需要隐蔽信道。他们只是想让几张私密照片或几个文件，在别人会拿起的手机或笔记本电脑上不再显眼。对这个目的，经典工具很别扭：steghide 在 JPEG 和 WAV 里只能放小载荷，LSB 工具需要 PNG，而且没有一个能给你一个可以浏览的图库。

HideFile 采用的是上面示意图里的第三种办法。在 [hidefile.app](https://hidefile.app)，在任何现代浏览器里，你选一张普通的照片、视频或 PDF 作为封面，添加私密文件，并设置密码。HideFile 在浏览器里加密这些文件，并把它们存成文件格式所允许的记录，所以封面在其他任何地方仍然是一张正常的图片、视频或文档。到 hidefile.app 输入密码打开，文件就出现了。不会上传到 HideFile 的服务器，也不需要安装任何东西。

它是“隐蔽加加密”，并且坦率地说明是哪一部分在起作用。HideFile 不改动像素，也不试图骗过统计检验。专门的工具能看出封面里被加了数据；它做不到的是在没有密码时读出内容。这使它适合让东西避开浏览你设备的人，而对于训练有素的检查人员、边境检查或法律压力，它不合适。

密码无法找回，而且会重新编码照片的 App 可能会把隐藏的部分去掉，所以请把封面当作文件来保存和分享。想全面了解各种隐藏技巧能骗过谁，见[怎么把文件藏在眼皮底下](/zh/guides/how-to-hide-files-in-plain-sight)；照片保险箱 App 的对比，见[照片保险箱 App 安全吗](/zh/guides/is-photo-vault-safe)。

## 资料来源

- Wikipedia：[Steganography](https://en.wikipedia.org/wiki/Steganography)（2026-10-13 的修订版，核对于 2026-10-14）
- Wikipedia：[Steganalysis](https://en.wikipedia.org/wiki/Steganalysis)（核对于 2026-10-14）
- Wikipedia：[OutGuess](https://en.wikipedia.org/wiki/OutGuess)（核对于 2026-10-14）
- Provos and Honeyman，[Detecting Steganographic Content on the Internet](http://www.citi.umich.edu/techreports/reports/citi-tr-01-11.pdf)，CITI Technical Report 01-11，2001
- Westfeld and Pfitzmann，“Attacks on Steganographic Systems”，Information Hiding (LNCS)，2000，[doi:10.1007/10719724_5](https://doi.org/10.1007/10719724_5)
- Fridrich, Goljan and Du，“Detecting LSB steganography in color and gray-scale images”，IEEE Multimedia，2001，[doi:10.1109/93.959097](https://doi.org/10.1109/93.959097)
- Fridrich, Pevny and Kodovsky，“Statistically undetectable JPEG steganography: dead ends, challenges, and opportunities”，ACM MM&amp;Sec 2007，[doi:10.1145/1288869.1288872](https://doi.org/10.1145/1288869.1288872)
- Fridrich and Kodovsky，“Rich Models for Steganalysis of Digital Images”，IEEE TIFS，2012，[doi:10.1109/tifs.2012.2190402](https://doi.org/10.1109/tifs.2012.2190402)
- W3C：[PNG Specification (Third Edition)](https://www.w3.org/TR/png-3/)，IEND 数据块
- steghide：[project home](https://steghide.sourceforge.net/)
- Microsoft Learn：[copy command](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/copy)
- Reddit，r/Steganography：[hiding .txt files in images?](https://www.reddit.com/comments/1p032xi/)
- Reddit，r/Steganography：[BMP scan-line padding post](https://www.reddit.com/comments/1nn7l5v/)
- Reddit，r/Steganography：[PNG download keeps the data, WebP does not](https://www.reddit.com/comments/1lho85i/)
- Hacker News：[comment on naive LSB detection](https://news.ycombinator.com/item?id=11581277)
- Hacker News：[comment on image hosts re-encoding](https://news.ycombinator.com/item?id=11582783)
