Cover image for How to anonymise sensitive data in PDF documents with Python

Jason Farrar

你是否曾经需要与他人分享银行对账单?也许你需要你的项目用户与你分享一份以便排查问题。

我遇到了完全相同的问题。我一直在构建一个可扩展工具,用于将英国银行对账单转换为关系数据库,但我只能获取自己银行的对账单。如何在不要求人们向我发送敏感的个人身份信息的情况下获取其他银行的对账单?

我需要保留布局和字体编码的匿名化银行对账单,以便这些对账单能够以与原始文件完全相同的方式进行处理。我还希望默认情况下对所有内容进行混淆,但能够保留日期和交易类型的保护。最后,如果能将来自同一账户的多份对账单配置为始终混淆为相同的假值,那就太有帮助了!

因此我构建了一个能正确完成这项工作的 Python 工具——在保持 PDF 外观完全相同的同时混淆敏感数据。

PDF 涂黑的问题

传统的涂黑工具通常做两件事中的其中一件:

  1. 黑色方块 — 叠加不透明矩形。文本仍然存在于下方(只要我的解析器处理它就能看到)。实际上并不安全。
  2. 文本替换 — 交换文本,但会破坏字体编码、布局或两者兼有。PDF 不仅看起来不对,而且对账单构成的 slightest 变化都可能使我的配置文件失效并使其变得无用。

两者都不理想。我需要的是实际替换 PDF 内容流中的字节——告诉 PDF 查看器要绘制什么的原始指令——同时保留字体编码和定位。

为什么选择 pikepdf?

我查看了三个 Python PDF 库:

级别 为什么不适用
PyPDF2 高级 合并、拆分、提取——没有内容流访问
pdfplumber 高级 我已经在使用它进行文本提取,但它不修改内容流
pikepdf 低级 直接访问内容流操作符和字体编码

pikepdf 为你提供对原始 PDF 操作符的访问——Tj(显示文本)、TJ(显示带定位的文本)、Tm(设置文本矩阵)。这是实际文本存在的地方,也是我需要进行更改的地方。

工作原理

核心思路很简单:

  1. 解析 PDF 的内容流为操作符
  2. 扫描 敏感模式(排序码、账号、IBAN、卡号)
  3. 替换 匹配的字节为混淆的替代内容
  4. 写回 修改后的内容流

这里有一个棘手的部分:PDF 字体编码。不同的银行使用不同的编码策略:

  • Latin-1(单字节,简单明了)
  • ToUnicode CMap(将字符代码映射到 Unicode——现代 PDF 中常见)
  • Identity-H(CID 字体,多字节——某些银行软件使用)

该工具处理所有三种情况,因此无论银行的 PDF 生成器如何,混淆后的文本都能正确渲染。

用法

一个函数,一个导入:

from bank_statement_anonymiser import anonymise_pdf

anonymise_pdf("statement.pdf", "anonymised.pdf")

Enter fullscreen mode Exit fullscreen mode

就是这样。输出 PDF 看起来与输入完全相同,但敏感数据已被混淆。

哪些内容会被匿名化

该工具针对这些模式:

  • 排序码(英国特有:XX-XX-XX 格式)
  • 账号(8 位英国账号)
  • IBAN(国际银行账号)
  • 卡号(Visa、Mastercard 模式)
  • 商户名称(可通过配置文件配置)

哪些内容不会被匿名化

  • 交易金额(因为我的依赖项目会根据对账单总变动验证交易行的金额)
  • 日期(涵盖交易日期和对账单日期的各种格式)
  • 交易类型(在 never_anonymise_system.toml 中指定,包含支持银行的已知交易类型)

配置

你可以通过传入自己的 TOML 配置文件进一步自定义要匿名化的内容:

# always_anonymise.toml — 强制替换这些模式
"12-12-12" = "99-99-99"
"Jason Farrar" = "John Doe"

Enter fullscreen mode Exit fullscreen mode

# never_anonymise.toml — 保护这些短语
exclude = [
    "Balance Brought Forward",
    "Account Summary",
]

Enter fullscreen mode Exit fullscreen mode

该系统使用基于排除的方法:默认情况下所有内容都会被混淆,然后你指定要保护的内容。

局限性

这是针对英国的。排序码、账号和 IBAN 格式的正则表达式模式已包含英国银行。目前已在以下银行上成功测试:

  • HSBC
  • Natwest
  • TSB
  • Halifax

它也可能适用于其他银行,所以请尝试一下并告诉我!
其他银行可能需要添加新的正则表达式模式,并且几乎肯定会使用不同的交易类型。可能还会有我尚未遇到过的其他字体编码。
非常欢迎所有贡献!

安装

pip install uk-bank-statement-anonymiser

Enter fullscreen mode Exit fullscreen mode

安装和使用的进一步说明可在 README 中找到

开源

采用 MIT 许可。所有处理均为本地进行——无网络请求、无账户、无数据收集。

GitHub: github.com/boscorat/uk-bank-statement-anonymiser

你是否遇到过类似的 PDF 匿名化挑战?我有兴趣了解其他银行的 PDF 格式——我能添加的模式越多,这个工具就越有用。

任何问题或评论都非常欢迎。我很想听听你是否认为有更好的方法来解决这个问题,或者我可以对结构进行哪些更改以扩大这个项目的实用范围。