go解析含passphrase的pem秘钥

背景

在编写TLS配置时需要用到需要用到一串包含passphrase的RSA秘钥,本想通过官方库的方式解析使用,但由于安全因素,官方已经禁用了DecryptPEMBlockEncryptPEMBlockIsEncryptedPEMBlock等函数,导致无法通过官方库去实现这个需求。

解决方案

最终通过pkcs8库来完成需求,代码如下:

go 复制代码
package main

import (
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"os"

	"github.com/youmark/pkcs8"
)

func main() {
	pem, err := getTlsConfig()
	if err != nil {
		panic(err)
	}
	fmt.Println("无加密的pem:", string(pem))
}

func getTlsConfig() ([]byte, error) {
	passphrase := "test123"
	keyFilePaaht := "./key"

	keyPEMByte, err := os.ReadFile(keyFilePaaht)
	if err != nil {
		err = fmt.Errorf("read %s failed! err: %s", keyFilePaaht, err)
		return nil, err
	}

	keyPEMBlock, rest := pem.Decode(keyPEMByte)
	if len(rest) > 0 {
		err := fmt.Errorf("decode key failed! rest: %s", rest)
		return nil, err
	}

	// 解析pem
	key, err := pkcs8.ParsePKCS8PrivateKey(keyPEMBlock.Bytes, []byte(passphrase))
	if err != nil {
		err = fmt.Errorf("parse PKCS8 private key err: %s", err)
		return nil, err
	}

	// 解析出其中的RSA 私钥
	keyBytes, err := x509.MarshalPKCS8PrivateKey(key)
	if err != nil {
		err = fmt.Errorf("MarshalPKCS8PrivateKey failed! %s", err)
		return nil, err
	}
	// 编码成新的PEM 结构
	newKey := pem.EncodeToMemory(
		&pem.Block{
			Type:  "PRIVATE KEY",
			Bytes: keyBytes,
		},
	)

	return newKey, nil
}

为什么GO不支持pem的加密?

GO团队的Commit Message

crypto/x509: deprecate legacy PEM encryption

It's unfortunate that we don't implement PKCS#8 encryption (#8860)

so we can't recommend an alternative but PEM encryption is so broken

that it's worth deprecating outright.

官方库x509

Deprecated: Legacy PEM encryption as specified in RFC 1423 is insecure by design. Since it does not authenticate the ciphertext, it is vulnerable to padding oracle attacks that can let an attacker recover the plaintext.

GO团队认为PEM encryption的实现是不好的,不够安全的,因此官方移除了实现,并且也不推荐相关的外部实现的库。

从这个Issue的讨论可以看出社区对这个需求的渴望已经很久,但官方并没有太多关注。

参考链接

相关推荐
有来技术15 分钟前
Spring Boot 4 + Vue3 企业级多租户 SaaS:从共享 Schema 架构到商业化套餐设计
java·vue.js·spring boot·后端
东东5161 小时前
学院个人信息管理系统 (springboot+vue)
vue.js·spring boot·后端·个人开发·毕设
三水不滴2 小时前
Redis缓存更新策略
数据库·经验分享·redis·笔记·后端·缓存
小邓吖3 小时前
自己做了一个工具网站
前端·分布式·后端·中间件·架构·golang
大爱编程♡3 小时前
SpringBoot统一功能处理
java·spring boot·后端
码界奇点4 小时前
基于Gin与GORM的若依后台管理系统设计与实现
论文阅读·go·毕业设计·gin·源代码管理
迷迭香与樱花5 小时前
Gin 框架
go·gin
好好研究6 小时前
总结SSM设置欢迎页的方式
xml·java·后端·mvc
小马爱打代码6 小时前
Spring Boot:第三方 API 调用的企业级容错设计
java·spring boot·后端
csdn2015_7 小时前
springboot task
java·spring boot·后端