Golang中处理SOAP和x509编码的问题求助

Golang中处理SOAP和x509编码的问题求助 你好

我需要以某种方式编码这样的消息体。我拥有私钥和公钥,但不太清楚具体该如何操作。 谢谢!

<soap:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-11055">
        <xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="EncDataId-11056" Type="http://www.w3.org/2001/04/xmlenc#Content">
            <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" />
            <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
                <wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
                    <wsse:Reference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" URI="#EncKeyId-9E76CD1FC968BE065E155231051099013820" />
                </wsse:SecurityTokenReference>
            </ds:KeyInfo>
            <xenc:CipherData>
                <xenc:CipherValue>7Z+sDZXhoUkeLZTCpKNe34Ee0FzPWII4SOvZkCa5QgnJXZakGWnb9+/8nvhn4bZXIALAaM0sELYe
TG4c2l1sOM8HF5mdn4hVCfY9/fS2zZabHuO8LQtJgt5Ce0igmv8aDlji17vr855VGObzvSS4ZBOp
bHjOiZ5AoEGZToIFORxTyqfmNgWosc1kfVze5v9n9DkYVgmtDnRp4IEZtTIVliAU8FRXKCeaJw+1
l9ebqS5PhlPJDpIsb+94nYLpb1O7Xi4XDwI5tVGysf4QtsZQ3bwE1qLCwEqqJXp7gtz0y02eKs/a
rRHZQIuP7gSBLwMvpgAgzsTAJbX0TSP7oVGKvNS6QtLRwYHz4Nwz3vAvgvdO8TlYLg/7QMc4u9T4
1zDuKaouLPdxMzu3qIWKuCdplLwCpXjyKbACz0C3O1aMdyHtto6SKO3L3GaRplo61b1eHv0aZIUi
trtJMqO4osaLmFF3oI8DdSV4DpR+lLuFyLs86jHpadS+SyHF5wgA/x9wos7zTyZHkVuhptabhqBL
eJX9gyP5X2wEKIJV4mgBxtRSfSDqfkhV/uPiCqcNshFBRM-qZq79W1r9gVOCZx+2b3ZQPYjNcSxh
BXVzam1BsVjlVzlunxXvYY06pwPMyQgSQth3ItRRl9rTr/N+LCZpzucv305KIsD4Y2rRJiCBdDVB
uhRWh4GxLbF7AZQkvbBzzOhzmRICu92Bb8so1LSMgWkU/XG7zVgVLD+fKkJ1zCENdHS+kbn9sHsI
MwJrLlKO</xenc:CipherValue>
            </xenc:CipherData>
        </xenc:EncryptedData>
    </soap:Body>

更多关于Golang中处理SOAP和x509编码的问题求助的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

我建议将密钥保存在单独的文件中,然后读取为[]byte类型。这样您就可以将它们添加到消息中,并根据需要输出。

希望这对您有所帮助。我本人不使用SOAP,只使用TLS。

更多关于Golang中处理SOAP和x509编码的问题求助的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go中处理SOAP消息的加密和解密通常涉及使用XML加密标准(XML Encryption)和x509证书。以下是一个示例,展示如何使用etree包构建SOAP体,并使用crypto/x509crypto/rsa处理x509编码的密钥对进行加密操作。假设你已经有了私钥和公钥文件(例如,private.pempublic.pem),我们将模拟一个简单的加密过程,但注意:实际SOAP加密可能需要更复杂的XML处理,例如使用专门的库如 github.com/moov-io/signedxml 或手动构建XML结构。

首先,确保安装必要的包:

go get github.com/beevik/etree

以下是一个示例代码,演示如何生成一个基本的SOAP体结构,并使用RSA公钥加密数据(这里简化了加密部分,实际中你可能需要处理AES密钥和XML加密规范):

package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/base64"
	"encoding/pem"
	"fmt"
	"log"
	"os"

	"github.com/beevik/etree"
)

func main() {
	// 加载公钥(用于加密)
	publicKey, err := loadPublicKey("public.pem")
	if err != nil {
		log.Fatalf("Failed to load public key: %v", err)
	}

	// 原始数据(例如SOAP体内容)
	originalData := "Your SOAP body data here"
	encryptedData, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, []byte(originalData))
	if err != nil {
		log.Fatalf("Encryption failed: %v", err)
	}
	encodedData := base64.StdEncoding.EncodeToString(encryptedData)

	// 创建SOAP体XML结构
	doc := etree.NewDocument()
	doc.CreateProcInst("xml", `version="1.0" encoding="UTF-8"`)

	soapBody := doc.CreateElement("soap:Body")
	soapBody.CreateAttr("xmlns:wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd")
	soapBody.CreateAttr("wsu:Id", "id-11055")

	encryptedDataElem := soapBody.CreateElement("xenc:EncryptedData")
	encryptedDataElem.CreateAttr("xmlns:xenc", "http://www.w3.org/2001/04/xmlenc#")
	encryptedDataElem.CreateAttr("Id", "EncDataId-11056")
	encryptedDataElem.CreateAttr("Type", "http://www.w3.org/2001/04/xmlenc#Content")

	encryptionMethod := encryptedDataElem.CreateElement("xenc:EncryptionMethod")
	encryptionMethod.CreateAttr("Algorithm", "http://www.w3.org/2001/04/xmlenc#aes128-cbc")

	keyInfo := encryptedDataElem.CreateElement("ds:KeyInfo")
	keyInfo.CreateAttr("xmlns:ds", "http://www.w3.org/2000/09/xmldsig#")

	securityTokenRef := keyInfo.CreateElement("wsse:SecurityTokenReference")
	securityTokenRef.CreateAttr("xmlns:wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd")

	reference := securityTokenRef.CreateElement("wsse:Reference")
	reference.CreateAttr("xmlns:wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd")
	reference.CreateAttr("URI", "#EncKeyId-9E76CD1FC968BE065E155231051099013820")

	cipherData := encryptedDataElem.CreateElement("xenc:CipherData")
	cipherValue := cipherData.CreateElement("xenc:CipherValue")
	cipherValue.SetText(encodedData) // 使用base64编码的加密数据

	// 输出XML
	doc.Indent(2)
	xmlStr, err := doc.WriteToString()
	if err != nil {
		log.Fatalf("Failed to generate XML: %v", err)
	}
	fmt.Println(xmlStr)
}

// loadPublicKey 从PEM文件加载公钥
func loadPublicKey(filename string) (*rsa.PublicKey, error) {
	keyData, err := os.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	block, _ := pem.Decode(keyData)
	if block == nil {
		return nil, fmt.Errorf("failed to decode PEM block")
	}
	pub, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return nil, err
	}
	return pub.(*rsa.PublicKey), nil
}

// 注意:实际应用中,你可能需要处理私钥解密,使用类似函数加载私钥
func loadPrivateKey(filename string) (*rsa.PrivateKey, error) {
	keyData, err := os.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	block, _ := pem.Decode(keyData)
	if block == nil {
		return nil, fmt.Errorf("failed to decode PEM block")
	}
	priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	if err != nil {
		return nil, err
	}
	return priv, nil
}

这个示例生成了一个SOAP体,其中包含加密数据部分。在实际场景中,你可能需要:

  • 使用AES加密实际数据,然后用RSA加密AES密钥(符合XML加密标准)。
  • 处理完整的SOAP信封和头部。
  • 使用更专业的库来处理XML签名和加密,例如 signedxml

如果你有具体的加密数据需要解密,可以使用私钥进行RSA解密:

// 解密示例函数
func decryptData(privateKey *rsa.PrivateKey, encryptedBase64 string) (string, error) {
	encryptedData, err := base64.StdEncoding.DecodeString(encryptedBase64)
	if err != nil {
		return "", err
	}
	decryptedData, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, encryptedData)
	if err != nil {
		return "", err
	}
	return string(decryptedData), nil
}

运行代码前,请确保替换文件路径和实际数据。如果遇到具体错误,请提供更多细节以便进一步调试。

回到顶部