背景
游离文件夹中可能存在一种特殊情况:文件以 .enc 结尾,但无法解密。原因可能是:
- 文件损坏
- 不是本系统加密的文件(来自其他工具或系统)
- 密钥不匹配
这类文件不能简单归类为”加密的游离文件”,因为尝试收养时会失败。
设计决策
三种游离文件类型
| 类型 | 判断条件 | 显示文件名 | 允许操作 |
|---|---|---|---|
| 加密的游离文件 | .enc 且可解密 | 从尾部元数据提取的真实文件名 | 下载、收养、删除 |
| 明文的游离文件 | 非 .enc | S3 原始文件名 | 下载、收养、删除 |
| 无法解密的加密文件 | .enc 但解密失败 | S3 原始文件名 | 下载、删除(禁止收养) |
检测机制
修改 extractOriginalName 函数,返回元组 (name, canDecrypt):
("photo.jpg", true)→ 可解密,提取到真实文件名("", true)→ 可解密但没有嵌入文件名(理论上不应发生)("", false)→ 无法解密
检测失败的情况:
- 文件太小(< 100 bytes)
- 元数据长度字段无效
- 密钥派生后解密失败(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
}
}前端处理
- 单个文件菜单:无法解密的文件不显示”收养”选项
- 多选操作:跳过无法解密的文件,提示”X 个无法解密已跳过”
使用体验
我在游离文件夹看到三种标签:
512 KB · 加密的游离文件→ 可以收养1.2 MB · 明文的游离文件→ 可以收养(会自动加密)768 KB · 无法解密的加密文件→ 只能下载或删除
这样可以:
- 下载到本地用其他工具尝试恢复
- 确认无用后删除释放空间