微信原图到底在救人,还是在泄露隐私?取决于你怎么用!

安全 应用安全
最近又看到有人在讨论,微信原图泄露隐私的事情。起因好像是有人在社交媒体上发布了一张照片,然后被网友定位到具体的生活范围,甚至直接定位到居住的小区,楼层门牌号等信息,想想还是很可怕的。

 [[284396]]

一. 序

最近又看到有人在讨论,微信原图泄露隐私的事情。起因好像是有人在社交媒体上发布了一张照片,然后被网友定位到具体的生活范围,甚至直接定位到居住的小区,楼层门牌号等信息,想想还是很可怕的。

在这个事件中的「网友定位」过程,其实很大一部分信息来自照片内容本身泄露的信息。各种警匪片大家应该也看过,专业人士可以通过一张照片分析出很多有用的信息,例如从窗户阳光的晒入角度,就可以分析出房间的朝向,有一些镜面的反光,也可以分析拍照环境的更多信息等等。

但这里说到微信原图暴露的信息,其实就是我们拍照时,在照片中携带的 Exif 信息。这个 Exif 信息是相机在拍照时,专门记录的一些属性信息和拍摄数据。例如 GPS 定位数据、拍摄时间、拍摄时相机的方向等。

Exif 信息只是拍摄图片文件的固有信息,不光微信原图分享,其实你通过任何形式,将源文件分享出去,都是会携带这些信息。但其中 GPS 涉及到定位,而定位信息又是一个在某些人看来,比较「敏感」的信息。

为什么说是某些人呢?图片携带的定位信息,暴露出去确实可能会造成困扰,但是某些时刻,这又是可以救命的,例如《民警巧用图片定位,解救被骗 CX 组织受害人》之类的新闻,我想大家应该也看过。另外也有很多人反映,不使用原图会导致接收到的图片模糊(被压缩),这也是一部分人偏爱发送「原图」的原因。

一边确实有隐私保护的需求,另一边也有发送无损原图的需要。微信是怎么解决的呢?在发送图片的时候,提供了一个「原图」的选项,将是否发送图片源文件的选择权,交到了用户自己的手里。值得一提的是,微信发送图片,为了传输效率以及隐私的考虑,默认是发送压缩后的图片的,在压缩的过程中,会清理 EXIF 信息,所以如果你找不到「原图」的选项,那么就说明这里只支持发送「压缩图」,例如微信朋友圈。

到这就清晰了,所谓微信原图泄露的隐私,只是图片在拍摄时存入的固有信息 EXIF,而只要通过处理 EXIF 信息就会被抹去。所以如果想对方接收到 EXIF 信息,就发送原图,反之则可以通过压缩处理一下再发送。

本来到这里就算完了,不过作为一个技术向的公众号,我们再继续科普一下照片 EXIF 信息以及在 Android 开发时如何读取和修改它。

二. 图片的 EXIF

2.1 什么是 Exif?

Exif(Exchangeable image file format)表示可交换图像文件格式,是专门记录数码相机拍照时的一些参数,例如定位信息、拍摄设备方向、曝光、色彩等信息,并将这些信息写入图片文件中,以保证在传输时保留这些信息。

Exif 可以被附加到 JPEG、TIFF、RIFF 等文件中,简单来说,图片文件中有一块特殊的区域,可以存放一些额外的 Exif 信息,以保证我们在使用图片时更方便。

这本身没什么坏处,除了 GPS 定位信息会让我们敏感之外,其他信息更多的是为了辅助我们使用。例如前面提到的拍摄照片时,设备的方向信息,就可以保证无论我们拍照时,手机的方向是侧着的或者是倒着的,拍照后在相册中预览时,永远保持正着的原因。

一般的图片处理软件,都可以读取出图片的 Exif 信息,并且支持修改。随便找一个在线查看 Exif 信息的工具网站,就可以查看到我上传图片的 Exif 信息。

 

图片的 Exif 信息,没有任何的保护,我们可以对其任意的修改。但是这些信息你也看到了,没有修改的意义,通常就是压缩时直接抹去。

2.2 压缩会损失 Exif

压缩会损失掉 Exif 信息,这也就是为什么在不发送原图的时候,接收者是读取不到 Exif 信息的。这很好理解,以现在图片手机摄像头支持的像素来说,一张大画幅的照片,随随便便就是上十 MB 甚至几十 MB,这对发送的网络和存储都是有压力的,所以通常 App 的做法是在发送前,本地做一次图片压缩。

前面提到,Exif 信息会记录拍照时,拍照设备持握的方向,例如有时我们会将手机倒过来拍全身照。这照片在相册展示时,永远都是正确的方向,我不会得到一个头朝下的照片。

如果压缩会导致 Exif 丢失,为什么压缩后的图片,在显示时依然可以保证显示方向的正确?

这就要说到图片压缩时的策略,我们就拿 Android 下比较出名的开源图片压缩库 Luban 举例,Github 上很多图片压缩库都是借鉴或者引用它来实现的。

在 Luban 的 Engine.java 文件中,可以找到相关的代码,逻辑很简单,就是在压缩前,先将图片按照 Exif 中记录的方向,旋转后再进行处理。

 

这也就是为什么图片压缩时,虽然抹去了 Exif 信息,但是图片显示的方向依然是正确的原因。

2.3 压缩后保留 Exif 信息

保留 Exif 信息这种需求,我确实想不到有什么场景需要在压缩后,保留此信息的。

但是如果有必要的话,最简单的处理方式,就是在压缩前,将图片的 Exif 读取存储,压缩后再写入图片中。

那么这就又涉及到,我们如何编码读取和写入图片的 Exif 信息。

三. 操作 Exif 信息

3.1 使用 ExifInterface

在 Android 中,需要 ExifInterface 来读取 Exif 信息,如果你直接在 AS 中搜索这个类,可以发现在 android.media 包下,确实有一个 ExifInterface,但是我不建议使用它。

自从 Android Support 25.1.0 开始,又添加了一个新的支持库:ExifInterface。这是由于 Android 7.1 对 ExifInterface 做了重大修改,因此建议使用此 Support 包,它最低支持到 Api 9+。

随着 AndroidX 的发布,对 ExifInterface 也做了迁移支持,只不过现在的版本还是 Beta01。

 

使用方式并没有什么太大的差异,完全取决于你项目的要求,这里举例就使用最新的 28.+ 了

  1. api "com.android.support:exifiinterface:28.+" 

Support 包和 android.media 中的 ExifInterface 基本操作,都是类似的,都提供了对指定图片的 Exif 信息进行读写的功能,区别在于 Support 包中包含了 140 多个不同的属性,而其中近 100 个是 android 7.1 中新增的。

3.2 获取 ExifInterface

ExifInterface 存在两个构造函数,可以传递一个图片文件路径或者图片的 InputStream。

 

上面两种构造方式,都可以获取到一个 ExifInterface 对象。它们之间有些差异:

1、使用 InputStream 获得的 ExifInterface 无法被修改,而直接读取的图片文件,则可以修改。

2、ExifInterface 无法处理远端的 InputStream,例如是从 HttpURIConnection 返回的输入流,所以这里建议使用 content:// 或者file:// 这种 Uri 路径。

3.3 读取 Exif 信息

获得 ExifInterface 对象之后,就可以对其进行操作。

大多数的 Exif 属性,只需要视情况使用 getAttributeInt() 、getAttributeDouble()、getAttribute()(适用于 String)。它们分别表示不同类型的属性。这些方法接收一个 String 类型的参数,这些参数都以常量的形式,以 TAG_Xxx 为开头,被标记在 ExifInterface 中。

具体想知道不同的 TAG_Xxx 需要使用什么方法获取,可以直接看文档。

 

其中注释就已经标记了该属性代表的类型。

下面举个最常见的例子,获取图片的拍摄方向,用于在显示的时候进行旋转。

 

当然,还有一些其它比较重要的信息,例如谣传微信原图暴露的位置信息,可以通过 getLatLong() 方法获取到一个 float 的数组,分别表示经度和维度,getAltitude() 获取拍摄的海拔高度,单位是 米 。还有一些图片,如果自带缩略图,可以使用 getThumbnail() 方法获取到。更多操作,详见代码文档,这里就不一一举例了。

需要注意的是,Exif 是一个不严谨的数据,它不存在任何必须的标记字段,每个标记字段值,都是可选的,所以我们在读取的时候,一定要考虑读取时的异常处理。

3.4 写入 Exif 信息

ExifInterface 其实是不可信的,它只能作为一个参考。因为任何程序都可以对它进行修改。

修改 Exif 信息可以使用 setAttribute() 方法,它接收一个 key-value 的键值对。用于标记待修改的 Tag 和最终修改后的值。在修改完成之后,还需调用saveAttributes() 方法,否者不会将设置的 Exif 信息写入到图片文件中。

还有一点需要注意,虽然文档中表明,Exif 信息是一个弱校验的数据,但是它对 TAG 的值是有要求的,如果不是它本身定义的值,保存并不会报错,但是读取的时候,会返回 null 。

四. 小结时刻

到这里你应该就清楚了,微信原图泄露的只是照相机 App 在拍照时,对图片写入的固有信息,并没有什么太多的秘密,这些信息在图片压缩时就会被抹去。

最后再总结一下:

图片在拍照时,会写入 Exif 信息到图片文件中,直接发送文件会保留此信息。

99% 的图片压缩,都会抹去 Exif 信息。

Android 下读取 Exif 信息,可以使用 ExifInterface。

【本文为51CTO专栏作者“张旸”的原创稿件,转载请通过微信公众号联系作者获取授权】 

戳这里,看该作者更多好文

 

责任编辑:武晓燕 来源: 51CTO专栏
相关推荐

2019-06-27 15:35:13

多云云计算DevOps

2019-12-09 10:48:11

腾讯微信Exif信息

2021-12-08 13:55:22

加密货币比特币金融

2019-07-04 11:56:17

大数据智慧城市开发

2020-03-09 16:43:06

脚本语言浏览器JavaScript

2012-12-24 11:09:34

云计算基因

2019-12-20 17:48:34

工业物联网可穿戴设备物联网

2010-10-12 13:02:09

Wi-Fi无线传输速

2023-03-02 14:32:21

CIO数字化转型

2010-09-06 14:25:16

无线局域网

2010-03-25 13:07:05

无线信号家庭无线局域网

2019-07-17 10:10:34

Netty版本Event

2023-06-11 17:02:24

数字化转型数字经济

2021-07-07 10:47:46

物联网区块链安全硬件

2022-01-05 07:07:37

混合办公模式

2018-02-06 22:46:46

IT加薪职场

2021-03-22 16:05:05

比特币区块链安全

2021-05-12 14:53:39

UiPathrpa

2023-07-06 22:42:55

AIGC工具变革者

2020-11-02 12:47:56

性能优化
点赞
收藏

51CTO技术栈公众号