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

参考链接

相关推荐
Java小混子9 小时前
golang项目CRUD示例
开发语言·后端·golang
想搞艺术的程序员9 小时前
Go 优雅关闭实践指南:从原理到框架落地
开发语言·后端·golang
JohnYan9 小时前
Bun技术评估 - 29 Docker集成
javascript·后端·docker
华仔啊9 小时前
MyBatis-Plus 让你开发效率翻倍!新手也能5分钟上手!
java·后端·mybatis
绝无仅有9 小时前
某东互联网大厂的Redis面试知识点分析
后端·面试·架构
乌暮10 小时前
JavaEE入门--计算机是怎么工作的
java·后端·java-ee
前端世界10 小时前
ASP.NET 实战:用 CSS 选择器打造一个可搜索、响应式的书籍管理系统
css·后端·asp.net
Java水解10 小时前
MySQL 正则表达式:REGEXP 和 RLIKE 操作符详解
后端·mysql
金銀銅鐵10 小时前
[Java] 用 Swing 生成一个最大公约数计算器(展示计算过程)
java·后端·数学
知其然亦知其所以然10 小时前
面试官笑了:我用这套方案搞定了“2000w vs 20w”的Redis难题!
redis·后端·面试