如何使用Golang实现文件加密与解密_Golang crypto包操作示例

发布时间 - 2026-01-29 00:00:00    点击率:
用 aes.Encrypt 加密文件前必须用 PKCS#7 填充明文至 16 字节整数倍,且每次加密需生成唯一 nonce(GCM)或 IV(CBC),并将其与密文一同写入文件头部。

aes.Encrypt 做文件加密前必须补全明文长度

Go 的 crypto/aes 只提供底层分组密码操作,不自动处理填充(padding)。直接对任意长度文件调用 aes.Encrypt 会 panic:「crypto/aes: invalid buffer size」。这是因为 AES 是块密码(block cipher),要求输入长度必须是 16 字节的整数倍。

常见做法是使用 PKCS#7 填充(注意:Go 标准库没内置,需手动实现):

func pkcs7Pad(data []byte, blockSize int) []byte {
    padding := blockSize - len(data)%blockSize
    padtext := make([]byte, padding)
    for i := range padtext {
        padtext[i] = byte(padding)
    }
    return append(data, padtext...)
}
  • 填充字节值等于填充长度(如缺 3 字节,则填 \x03\x03\x03
  • 即使原文长度刚好是 16 的倍数,也要额外填充一整块(16 个 \x10),否则解密时无法区分“末尾是真实数据还是填充”
  • 读取大文件时别一次性读进内存,应分块填充 + 加密,避免 OO

    M

crypto/cipher.BlockMode 的两种典型模式:CBC 和 GCM

CBC(Cipher Block Chaining)和 GCM(Galois/Counter Mode)是 Go 中最常用的两种封装方式。它们不是互斥选项,而是安全模型的根本差异:

  • cipher.NewCBCEncrypter 只提供机密性,**不校验完整性**;攻击者可篡改密文导致解密后乱码甚至执行恶意代码
  • cipher.NewGCM 同时提供加密与认证(AEAD),解密时自动验证 nonce + 密文未被篡改,失败直接返回 error
  • GCM 要求 nonce 绝对唯一(推荐用随机 12 字节),而 CBC 的 IV 只需不可预测(可用 crypto/rand.Read 生成)

生产环境强烈优先选 GCM。示例初始化:

block, _ := aes.NewCipher(key)
gcm, _ := cipher.NewGCM(block)
nonce := make([]byte, gcm.NonceSize())
rand.Read(nonce) // 注意:此处应检查 error

文件加密时,IV/nonce 和密钥绝不能硬编码或复用

ivnonce 写死在代码里,等于把锁芯图纸贴门上。同样,同一密钥加密多个文件时若重复使用 nonce(GCM)或 IV(CBC),会导致密文可被分析破解。

  • GCM 下重复 nonce:直接泄露明文异或结果,可能恢复出全部内容
  • CBC 下重复 IV:首块密文失去随机性,且相同明文首块产生相同密文,暴露结构
  • 正确做法:每次加密生成新随机 nonce(GCM)或 iv(CBC),并将其**和密文一起写入输出文件头部**(如前 12/16 字节),解密时先读出再使用
  • 密钥本身不应出现在代码中;建议用 KMS、环境变量(os.Getenv("ENC_KEY"))或派生函数(scrypt.Key)生成

解密失败时,gcm.Open 返回的 error 不含具体原因

gcm.Open(dst, nonce, ciphertext, additionalData) 在认证失败(如 nonce 错、密文被改、密钥不对)时统一返回 cipher: message authentication failed。它**故意不说明是哪部分出错**,防止侧信道泄露信息(比如通过 error 类型判断密钥是否正确)。

  • 不要靠 error 字符串做逻辑分支(如 strings.Contains(err.Error(), "authentication")
  • 确保传入的 nonce 长度等于 gcm.NonceSize()(通常是 12),否则会 panic
  • 如果解密后数据为空但无 error,检查是否误把密文当成了明文——GCM 输出不含原始 IV/nonce,你得自己从文件头剥离后再传给 Open

最常被忽略的是:加密时写入了 nonce,解密时却忘了读出来,直接拿整个文件当密文传给 gcm.Open,结果必然失败。


# go  # golang  # 编码  # app  # 字节  # ai  # 环境变量  # 标准库  # crypto  # 封装  # Error  # 字符串  # padding  # 两种  # 不含  # 只提供  # 的是  # 文件加密  # 成了  # 多个  # 整数倍  # 也要  # 出现在 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 千问怎样用提示词获取健康建议_千问健康类提示词注意事项【指南】  JavaScript Ajax实现异步通信  如何用虚拟主机快速搭建网站?详细步骤解析  如何快速生成专业多端适配建站电话?  如何在IIS中新建站点并解决端口绑定冲突?  Android GridView 滑动条设置一直显示状态(推荐)  Laravel如何清理系统缓存命令_Laravel清除路由配置及视图缓存的方法【总结】  如何快速辨别茅台真假?关键步骤解析  Linux系统命令中tree命令详解  如何自定义safari浏览器工具栏?个性化设置safari浏览器界面教程【技巧】  如何在云指建站中生成FTP站点?  java获取注册ip实例  如何快速登录WAP自助建站平台?  如何使用 Go 正则表达式精准提取括号内首个纯字母标识符(忽略数字与嵌套)  如何实现建站之星域名转发设置?  Laravel如何生成PDF或Excel文件_Laravel文档导出工具与使用教程  如何在景安云服务器上绑定域名并配置虚拟主机?  如何快速生成橙子建站落地页链接?  Laravel如何处理JSON字段的查询和更新_Laravel JSON列操作与查询技巧  Claude怎样写约束型提示词_Claude约束提示词写法【教程】  小米17系列还有一款新机?主打6.9英寸大直屏和旗舰级影像  高性能网站服务器配置指南:安全稳定与高效建站核心方案  JS中页面与页面之间超链接跳转中文乱码问题的解决办法  Laravel如何使用软删除(Soft Deletes)功能_Eloquent软删除与数据恢复方法  郑州企业网站制作公司,郑州招聘网站有哪些?  如何在IIS中新建站点并配置端口与IP地址?  Windows11怎样设置电源计划_Windows11电源计划调整攻略【指南】  湖南网站制作公司,湖南上善若水科技有限公司做什么的?  如何用AI帮你把自己的生活经历写成一个有趣的故事?  北京网站制作费用多少,建立一个公司网站的费用.有哪些部分,分别要多少钱?  jQuery 常见小例汇总  网站建设保证美观性,需要考虑的几点问题!  装修招标网站设计制作流程,装修招标流程?  消息称 OpenAI 正研发的神秘硬件设备或为智能笔,富士康代工  通义万相免费版怎么用_通义万相免费版使用方法详细指南【教程】  JS实现鼠标移上去显示图片或微信二维码  实例解析Array和String方法  Angular 表单中正确绑定输入值以确保提交与验证正常工作  Python3.6正式版新特性预览  VIVO手机上del键无效OnKeyListener不响应的原因及解决方法  如何快速上传建站程序避免常见错误?  Win11怎么关闭透明效果_Windows11辅助功能视觉效果设置  猪八戒网站制作视频,开发一个猪八戒网站,大约需要多少?或者自己请程序员,需要什么程序员,多少程序员能完成?  宙斯浏览器视频悬浮窗怎么开启 边看视频边操作其他应用教程  Laravel怎么进行数据库回滚_Laravel Migration数据库版本控制与回滚操作  SQL查询语句优化的实用方法总结  Laravel如何构建RESTful API_Laravel标准化API接口开发指南  历史网站制作软件,华为如何找回被删除的网站?  香港服务器网站搭建教程-电商部署、配置优化与安全稳定指南  如何快速查询域名建站关键信息?