无法解密的加密文件类型

December 20, 2025
2 min read
By devshan

Table of Contents

This is a list of all the sections in this post. Click on any of them to jump to that section.

背景

游离文件夹中可能存在一种特殊情况:文件以 .enc 结尾,但无法解密。原因可能是:

  • 文件损坏
  • 不是本系统加密的文件(来自其他工具或系统)
  • 密钥不匹配

这类文件不能简单归类为”加密的游离文件”,因为尝试收养时会失败。

设计决策

三种游离文件类型

类型判断条件显示文件名允许操作
加密的游离文件.enc 且可解密从尾部元数据提取的真实文件名下载、收养、删除
明文的游离文件.encS3 原始文件名下载、收养、删除
无法解密的加密文件.enc 但解密失败S3 原始文件名下载、删除(禁止收养)

检测机制

修改 extractOriginalName 函数,返回元组 (name, canDecrypt)

  • ("photo.jpg", true) → 可解密,提取到真实文件名
  • ("", true) → 可解密但没有嵌入文件名(理论上不应发生)
  • ("", false) → 无法解密

检测失败的情况:

  1. 文件太小(< 100 bytes)
  2. 元数据长度字段无效
  3. 密钥派生后解密失败(AEAD 认证失败)

数据结构变更

后端 OrphanFileInfo 新增字段:

type OrphanFileInfo struct {
    Key       string    `json:"key"`
    Name      string    `json:"name"`
    Size      int64     `json:"size"`
    Time      time.Time `json:"time"`
    Encrypted bool      `json:"encrypted"`
    Corrupted bool      `json:"corrupted"` // 新增
}

前端 FileMetadata 新增字段:

final bool isCorruptedOrphan;

收养拒绝

adoptOrphanFile API 中,对于加密文件先检测是否可解密:

if isEncrypted {
    _, canDecrypt := s.extractOriginalName(ctx, req.Key, fileSize)
    if !canDecrypt {
        c.JSON(http.StatusBadRequest, gin.H{
            "error": "cannot adopt corrupted file: decryption failed"
        })
        return
    }
}

前端处理

  1. 单个文件菜单:无法解密的文件不显示”收养”选项
  2. 多选操作:跳过无法解密的文件,提示”X 个无法解密已跳过”

使用体验

我在游离文件夹看到三种标签:

  • 512 KB · 加密的游离文件 → 可以收养
  • 1.2 MB · 明文的游离文件 → 可以收养(会自动加密)
  • 768 KB · 无法解密的加密文件 → 只能下载或删除

这样可以:

  1. 下载到本地用其他工具尝试恢复
  2. 确认无用后删除释放空间