使用Golang的x509包解析私钥的方法
使用Golang的x509包解析私钥的方法
我正在使用 x509 包,并尝试使用 x509.ParsePKCS8PrivateKey 方法来解析存储在 .env 文件中的私钥。
该方法抛出以下错误:“asn1: structure error: tags don’t match (2 vs {class:0 tag:16 length:95 isCompound:true}) {optional:false explicit:false application:false private:false defaultValue: tag: stringType:0 timeType:0 set:false omitEmpty:false} int @2”。
我认为错误是由于 .env 文件中私钥的格式以及生成时使用了密码短语导致的。(我使用了 openssl 命令)。 .env 文件中私钥的格式如下: PRIVATE_KEY="-----BEGIN ENCRYPTED PRIVATE KEY----- blablablabla -----END ENCRYPTED PRIVATE KEY----- " 以下是我的代码:
privateKeyPEM := os.Getenv("PRIVATE_KEY")
// get private key from .env file
block, _ := pem.Decode([]byte(privateKeyPEM))
if block == nil {
http.Error(w, "{\"error\": \"Error decoding private key\"}", http.StatusBadRequest)
return
}
privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
fmt.Println(err.Error())
http.Error(w, "{\"error\": \"Error parsing private key\"}", http.StatusBadRequest)
return
}
这段代码的目标是在一个 HTTP 处理器中使用私钥,以解密来自客户端的一些数据。在我收到数据后,我调用 rsa.DecryptPKCS1v15(rand.Reader, privateKey, ecryptedData) 来解密数据,但代码从未执行到这一点。
任何建议都将不胜感激。我的 Go 版本是 1.21。
提前感谢。
更多关于使用Golang的x509包解析私钥的方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于使用Golang的x509包解析私钥的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
你的错误是因为使用了加密的PKCS#8私钥,而x509.ParsePKCS8PrivateKey无法直接解析加密的私钥。你需要先解密私钥。以下是修正后的代码示例:
import (
"crypto/x509"
"encoding/pem"
"os"
"fmt"
"net/http"
"crypto/rsa"
"crypto/rand"
"golang.org/x/crypto/pkcs12" // 需要安装:go get golang.org/x/crypto/pkcs12
)
func handler(w http.ResponseWriter, r *http.Request) {
privateKeyPEM := os.Getenv("PRIVATE_KEY")
password := os.Getenv("PRIVATE_KEY_PASSWORD") // 从环境变量获取密码
// 解码PEM块
block, _ := pem.Decode([]byte(privateKeyPEM))
if block == nil {
http.Error(w, "{\"error\": \"Error decoding private key\"}", http.StatusBadRequest)
return
}
// 检查是否为加密的私钥
if !x509.IsEncryptedPEMBlock(block) {
// 如果是未加密的PKCS#8私钥
privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
fmt.Println(err.Error())
http.Error(w, "{\"error\": \"Error parsing private key\"}", http.StatusBadRequest)
return
}
// 使用私钥进行解密
rsaPrivateKey, ok := privateKey.(*rsa.PrivateKey)
if !ok {
http.Error(w, "{\"error\": \"Not an RSA private key\"}", http.StatusBadRequest)
return
}
// 这里执行你的解密逻辑
decryptedData, err := rsa.DecryptPKCS1v15(rand.Reader, rsaPrivateKey, encryptedData)
if err != nil {
http.Error(w, "{\"error\": \"Decryption failed\"}", http.StatusBadRequest)
return
}
// 处理解密后的数据
fmt.Fprintf(w, "Decrypted: %s", decryptedData)
return
}
// 如果是加密的私钥,需要先解密
decryptedBlock, err := x509.DecryptPEMBlock(block, []byte(password))
if err != nil {
fmt.Println(err.Error())
http.Error(w, "{\"error\": \"Error decrypting private key\"}", http.StatusBadRequest)
return
}
// 解析解密后的PKCS#8私钥
privateKey, err := x509.ParsePKCS8PrivateKey(decryptedBlock)
if err != nil {
fmt.Println(err.Error())
http.Error(w, "{\"error\": \"Error parsing decrypted private key\"}", http.StatusBadRequest)
return
}
rsaPrivateKey, ok := privateKey.(*rsa.PrivateKey)
if !ok {
http.Error(w, "{\"error\": \"Not an RSA private key\"}", http.StatusBadRequest)
return
}
// 使用解密后的私钥
decryptedData, err := rsa.DecryptPKCS1v15(rand.Reader, rsaPrivateKey, encryptedData)
if err != nil {
http.Error(w, "{\"error\": \"Decryption failed\"}", http.StatusBadRequest)
return
}
fmt.Fprintf(w, "Decrypted: %s", decryptedData)
}
如果你的私钥是PKCS#1格式,可以使用以下替代方案:
// 对于PKCS#1格式的加密私钥
if block.Type == "RSA PRIVATE KEY" {
privateKey, err := x509.ParsePKCS1PrivateKey(decryptedBlock)
if err != nil {
fmt.Println(err.Error())
http.Error(w, "{\"error\": \"Error parsing PKCS1 private key\"}", http.StatusBadRequest)
return
}
// 使用privateKey进行解密
decryptedData, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, encryptedData)
// ... 后续处理
}
注意:x509.DecryptPEMBlock在Go 1.16中已被弃用。对于更新的Go版本,建议使用以下方法:
import "golang.org/x/crypto/pkcs12"
// 对于PKCS#12格式的加密私钥
privateKey, _, err := pkcs12.Decode(block.Bytes, password)
if err != nil {
fmt.Println(err.Error())
http.Error(w, "{\"error\": \"Error decoding PKCS12\"}", http.StatusBadRequest)
return
}
确保你的私钥密码存储在环境变量中,并且格式正确。如果问题仍然存在,检查你的私钥是否使用正确的算法加密(通常是AES-256-CBC)。

