F-Droid 中文文档 下载 App

F-Droid 仓库索引签名与防篡改机制

仓库索引是什么

每个 F-Droid 仓库都有一个索引文件(通常是 index-v1.jar),它是该仓库的「目录清单」:

F-Droid 客户端同步仓库时,首先下载这个索引文件,然后根据索引内容去下载具体的 APK。

索引签名如何防篡改

假设一个攻击者想破坏 F-Droid 的信任链。他可以尝试:

场景一:替换仓库服务器上的文件

攻击者入侵了 f-droid.org 服务器,替换了某个 APK 文件。结果:

  1. F-Droid 下载该 APK
  2. 验证 APK 的签名哈希 → 哈希值和索引中记录的不一致
  3. F-Droid 拒绝安装

攻击者也需要同时篡改索引文件——但索引文件有 GPG 签名,攻击者没有私钥,签不出合法签名。所以索引改不了,APK 替换也就无效。

场景二:中间人攻击

攻击者在网络中拦截了 F-Droid 的仓库请求,返回了伪造的索引文件。结果:

  1. F-Droid 下载伪造的索引文件
  2. 用内置公钥验证 GPG 签名 → 签名不匹配
  3. F-Droid 拒绝同步,显示「仓库签名无效」

场景三:DNS 劫持

攻击者劫持 DNS 请求,让 f-droid.org 解析到自己的服务器。结果和场景二一样——伪造的索引过不了 GPG 签名验证。

官方仓库的镜像

F-Droid 官方仓库(f-droid.org)有多个全球镜像节点:

所有镜像节点使用完全相同的签名密钥——这就是为什么添加第三方仓库时需要单独确认密钥信任。镜像节点不能独立签名,它们只是分发主仓库的内容。

多仓库的安全隔离

F-Droid 可以同时连接多个仓库(官方 + IzzyOnDroid + Guardian Project 等),每个仓库有自己的签名密钥。当添加新仓库时:

  1. F-Droid 下载新仓库的索引
  2. 显示新仓库的签名指纹
  3. 让你确认是否信任这个密钥
  4. 确认后才会把该仓库的应用纳入搜索范围

重要:添加第三方仓库是一个安全决策。不要随便从网上搜仓库地址添加——确认来源可信。

仓库刷新频率

F-Droid 客户端默认每天刷新一次仓库索引。你可以手动触发刷新(设置 → 手动刷新)。

刷新频率不需要太高——F-Droid 官方仓库每周新增/更新几十个应用,每天查一次足够及时。

索引文件的格式

索引文件内部是一个 JSON 结构(index.json),包含:

{
  "repo": {
    "name": "F-Droid",
    "address": "https://f-droid.org/repo",
    "timestamp": 1728950000,
    "apkversion": 11,
    "apps": [
      {
        "packageName": "org.fdroid.fdroid",
        "name": "F-Droid",
        "summary": "Free and open source Android app store",
        "categories": ["System"],
        "versions": {
          "2000051": {
            "versionName": "2.0.1",
            "hash": "sha256:abc123...",
            "sig": "abc123def456...",
            "apkName": "org.fdroid.fdroid_2000051.apk"
          }
        }
      }
    ]
  }
}

F-Droid 客户端和 fdroidserver 工具链都使用这个 JSON 格式。索引文件打包成 JAR 格式(带压缩),外部附带 GPG 签名文件(.asc)。

索引签名的局限性

GPG 签名可以防篡改,但不能防止索引本身的内容有问题——如果索引中某个应用的 APK URL 指向了恶意服务器,签名机制无法检测(虽然 F-Droid 会在下载 APK 后验证哈希)。

这也是为什么 F-Droid 有严格的准入审核——防的是「坏人混进来」,而签名防的是「坏人篡改已有内容」。