使用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

1 回复

更多关于使用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)。

回到顶部