微服务间通信应优先用rsa做身份认证和密钥交换,再用aes加密数据;jwt签名必须用rs256;配置文件加密密钥须通过kms管理,禁止硬编码。

微服务间通信该用RSA还是AES
微服务间通信优先选RSA做身份认证和密钥交换,别直接用AES加密整个请求体。AES适合加密数据本身(比如配置、数据库字段),但密钥分发是个死结——你没法安全地把AES密钥从服务A传到服务B,除非先用RSA把AES密钥“包一层”再传过去。
常见错误现象:crypto/aes: invalid key size 或服务启动时解密失败,往往是因为AES密钥硬编码在代码里,不同环境用了同一份密钥;而RSA私钥泄露后,所有用它加密的AES密钥都会失效。
- RSA用于:JWT签名验证、TLS证书交换、加密传输AES密钥
- AES用于:敏感配置文件加密、数据库字段加密、本地缓存加密
- 典型组合:用RSA公钥加密一个随机生成的AES-256密钥,再用该AES密钥加密实际业务数据(即“信封加密”)
为什么Golang里AES-GCM比CBC更值得默认选择
AES-GCM是Go标准库crypto/aes + crypto/cipher中唯一原生支持的AEAD(认证加密)模式,它把加密和完整性校验合二为一。而CBC必须额外拼接HMAC,否则无法防篡改——很多线上事故就出在这里。
性能影响:GCM在现代CPU上通常比CBC快10%~20%,尤其在启用AES-NI指令集的服务器上;兼容性无问题,Go 1.17+已全面支持。
- 使用
cipher.NewGCM(block)前,必须确保密钥长度为32字节(AES-256) - GCM需要Nonce(非重复数),长度建议12字节;重复使用同一Nonce+密钥会导致密文可被完全恢复
- 解密失败时,
gcm.Open()返回nil, cipher.ErrInvalidLength或crypto/aes: invalid key size,不是io.ErrUnexpectedEOF
JWT签名该用HS256还是RS256
微服务架构下必须用RS256。HS256要求所有服务共享同一个密钥,一旦任一服务被攻破,整个链路签名就失效;RS256则让每个服务只保管自己的RSA私钥,公钥可自由分发,天然支持密钥轮换。
容易踩的坑:jwt.Parse()默认不校验exp字段,必须显式传入jwt.WithValidator(jwt.Expected{TimeFunc: time.Now});另外github.com/golang-jwt/jwt/v5已废弃SigningMethodRSA常量,改用jwt.SigningMethodRS256。
- 生产环境私钥绝不能出现在代码或Git中,应通过KMS或Secret Manager注入
- 公钥加载时要用
x509.ParsePKIXPublicKey()而非rsa.ParsePKCS1PublicKey(),后者只支持PKCS#1格式,而云厂商签发的证书多为PKIX - Token解析失败常见报错:
token is expired、signature is invalid、key is not valid,三者原因完全不同
配置文件加密时密钥怎么存才安全
密钥永远不能和加密后的配置文件放在同一处。最简方案是开发环境用本地.key文件(权限设为600),生产环境强制走云KMS——AWS KMS、GCP KMS或阿里云KMS都提供Go SDK,调用kms.Decrypt()即可,密钥本身不出KMS服务边界。
如果硬要本地存密钥,务必避开以下做法:把密钥写进Viper的SetDefault()、用go:embed嵌入密钥字符串、在Dockerfile里用ENV传密钥明文。
- 推荐路径:启动时读取环境变量
KMS_KEY_ID,调KMS API解密获取AES密钥,再用该密钥解密配置 - Viper集成要点:重写
viper.DecoderConfigOption,在UnmarshalKey()前插入解密逻辑 - 加密后的配置文件可放心提交Git,但需确保
.gitignore排除了密钥文件和KMS凭证
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











