Golang如何将PKCS#12格式的JAVA证书转换为JKS格式

Golang如何将PKCS#12格式的JAVA证书转换为JKS格式 我理解大多数人认为JKS不安全且/或已过时,但事实是许多现代软件仍然依赖Java密钥库来运行。

我已经掌握了加载、解码和解析我的CA证书、服务器证书以及PKCS#12证书的代码。

有人有关于如何将.P12文件转换为.JKS的实际示例吗?

最终,我也可以直接使用exec.Command("keytool", ...),但这意味着每次我通过RPM/DEB/APK打包自己的工具时,都需要某个版本的Java作为依赖项以提供keytool,而这里的目标是完全避免使用Java。

func main() {
    fmt.Println("hello world")
}

更多关于Golang如何将PKCS#12格式的JAVA证书转换为JKS格式的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang如何将PKCS#12格式的JAVA证书转换为JKS格式的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go中实现PKCS#12到JKS的转换需要处理两种不同的密钥库格式。以下是完整的示例代码:

package main

import (
    "crypto/rsa"
    "crypto/x509"
    "encoding/pem"
    "fmt"
    "io/ioutil"
    "os"
    "software.sslmate.com/src/go-pkcs12"
    "github.com/pavel-v-chernykh/keystore-go/v4"
)

func convertP12ToJKS(p12Path, jksPath, p12Password, jksPassword string) error {
    // 读取PKCS#12文件
    p12Data, err := ioutil.ReadFile(p12Path)
    if err != nil {
        return fmt.Errorf("读取P12文件失败: %v", err)
    }

    // 解码PKCS#12
    privateKey, certificate, caCerts, err := pkcs12.Decode(p12Data, p12Password)
    if err != nil {
        return fmt.Errorf("解码PKCS#12失败: %v", err)
    }

    // 创建JKS密钥库
    ks := keystore.New()

    // 将私钥和证书转换为JKS条目
    rsaKey, ok := privateKey.(*rsa.PrivateKey)
    if !ok {
        return fmt.Errorf("不支持的私钥类型")
    }

    // 创建证书链
    certChain := make([]keystore.Certificate, 0, len(caCerts)+1)
    certChain = append(certChain, keystore.Certificate{
        Type:    "X509",
        Content: certificate.Raw,
    })

    for _, caCert := range caCerts {
        certChain = append(certChain, keystore.Certificate{
            Type:    "X509",
            Content: caCert.Raw,
        })
    }

    // 创建私钥条目
    privateKeyEntry := keystore.PrivateKeyEntry{
        CreationTime:     keystore.Now(),
        PrivateKey:      rsaKey,
        CertificateChain: certChain,
    }

    // 将条目添加到密钥库
    err = ks.SetPrivateKeyEntry("mykey", privateKeyEntry, []byte(jksPassword))
    if err != nil {
        return fmt.Errorf("添加私钥条目失败: %v", err)
    }

    // 保存JKS文件
    jksFile, err := os.Create(jksPath)
    if err != nil {
        return fmt.Errorf("创建JKS文件失败: %v", err)
    }
    defer jksFile.Close()

    err = ks.Store(jksFile, []byte(jksPassword))
    if err != nil {
        return fmt.Errorf("保存JKS文件失败: %v", err)
    }

    return nil
}

// 如果需要处理证书链的单独保存
func saveCertificateChain(cert *x509.Certificate, caCerts []*x509.Certificate, basePath string) error {
    // 保存主证书
    certFile, err := os.Create(basePath + ".crt")
    if err != nil {
        return err
    }
    defer certFile.Close()

    pem.Encode(certFile, &pem.Block{
        Type:  "CERTIFICATE",
        Bytes: cert.Raw,
    })

    // 保存CA证书链
    for i, caCert := range caCerts {
        caFile, err := os.Create(fmt.Sprintf("%s-ca-%d.crt", basePath, i))
        if err != nil {
            return err
        }
        defer caFile.Close()

        pem.Encode(caFile, &pem.Block{
            Type:  "CERTIFICATE",
            Bytes: caCert.Raw,
        })
    }

    return nil
}

func main() {
    // 使用示例
    err := convertP12ToJKS(
        "server.p12",
        "server.jks",
        "p12password",
        "jkspassword",
    )
    
    if err != nil {
        fmt.Printf("转换失败: %v\n", err)
        return
    }
    
    fmt.Println("转换成功")
}

需要安装的依赖:

go get software.sslmate.com/src/go-pkcs12
go get github.com/pavel-v-chernykh/keystore-go/v4

这个实现完全避免了Java依赖,直接处理PKCS#12解码和JKS格式生成。keystore-go库提供了完整的JKS格式支持,包括正确的加密和存储格式。

回到顶部