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的讨论可以看出社区对这个需求的渴望已经很久,但官方并没有太多关注。

参考链接

相关推荐
直奔標竿9 小时前
SpringAI + RAG + MCP + Agent 零基础全栈实战(完结篇)| 27课完整汇总,Java开发者AI转型必看
java·开发语言·人工智能·spring boot·后端·spring
枫叶林FYL10 小时前
项目八 云资源成本优化与治理平台
后端·python·自然语言处理·flask
SamDeepThinking10 小时前
第1篇-开篇词:几亿用户规模下,我们是怎么做C端高并发商品系统的
java·后端·架构
代码丰11 小时前
一文讲清楚: SSE、WebSocket 与 HTTP的关系
后端
代码丰11 小时前
java 21虚拟线程vs传统线程 原理分析以及具体测试例子去分析性能提升
后端
用户05343693807311 小时前
langchainrust:Rust 版 LangChain 框架(LLM+Agent+RAG)
后端
fox_lht11 小时前
第十章 通用集合
开发语言·后端·算法·rust
悟空聊架构11 小时前
GStack的26种专家角色,真正实现一人成军!
后端
counting money11 小时前
Spring框架基础(依赖注入-半注解形式)
java·后端·spring