You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golang中正确解码asn1.RawValue的方法(X509证书解析场景)

Go解析X509证书AIA扩展时的乱码解决方法

问题背景

我正在使用Golang实现证书解析,需要获取父证书链接。执行openssl x509 -in certificate.pem -text -noout可查看证书的**Authority Information Access(AIA)**扩展,其中包含OCSP和CA Issuers的URI。

我的Go项目代码如下:

package main

import (
	"encoding/asn1"
	"encoding/pem"
	"fmt"
	"crypto/x509"
)

func main() {
	content := `-----BEGIN CERTIFICATE-----
MIIJxDCCCKygAwIBAgINfEbzVUOoCNMWumANCjANBgkqhkiG9w0BAQsFADBqMQsw
CQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2Vj
IEx0ZC4xFDASBgNVBAsMC2UtU3ppZ25vIENBMRowGAYDVQQDDBFlLVN6aWdubyBU
ZXN0IENBMzAeFw0yMzAxMjQxMjQxNTBaFw0yNDAxMjQxMjQxNTBaMIHQMRMwEQYL
KwYBBAGCNzwCAQMTAkVFMRgwFgYLKwYBBAGCNzwCAQEMB1RhbGxpbm4xHTAbBgNV
BA8MFFByaXZhdGUgT3JnYW5pemF0aW9uMREwDwYDVQQFEwgxMjI2ODQ3NTELMAkG
A1UEBhMCRUUxEDAOBgNVBAcMB1RhbGxpbm4xFzAVBgNVBAoMDk1ha3Nla2Vza3Vz
IEFTMRswGQYDVQRhDBJQU0RFRS1GU0EtMTIyNjg0NzUxGDAWBgNVBAMMD21ha2Vj
b21tZXJjZS5sdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJFyj3sS
xev2yHbGXNmqw8e+ZqFvrb1+UHlsm7c65HSjwAVjheHNV1cufilRf5X1PuBDmXtC
XpwD7FmOc7h++BAEdapv/XcWkMqUgbkfwhaZPkjbXIQBH7jbe4D+3pxn+ZDlq/1b
Wi6dJhGHN+Ydgw6x+qGBOVzaFlprFdOYQXDw8yMc/iQMBahzzQApe2EwW1XRgyaT
DNE5t2T7uWC05qDYgi1HI50WGoezx7A7CDSjwG+kFvczleY+4H73aPiGH1f0q+EC
POZsoot12CWspBwZB9G03S5IoIipJPoQmIvnKGgeGbbY16P3VQ/78w9XjPy0dwid
x2CfPlPLTa8eJF0CAwEAAaOCBgAwggX8MA4GA1UdDwEB/wQEAwIFoDCBiQYKKwYB
BAHWeQIEAgR7BHkAdwB1AKoeeAQ/gGSCK+VMtcHKwuMu5FDmczAqSLwmlwubLAgd
AAABhePMiCsAAAQDAEYwRAIgMbv+IXdcxOgT9VPPUIuuHajA08AiGnQMKnSsYHPl
4egCICQN64jfx+fitpnfxb6u531tA3VkjmMmLOkvN5b2vj4wMB0GA1UdJQQWMBQG
CCsGAQUFBwMBBggrBgEFBQcDAjCCAyQGA1UdIASCAxswggMXMIIDEwYMKwYBBAGB
qBgCAQFkMIIDATAmBggrBgEFBQcCARYaaHR0cDovL2NwLmUtc3ppZ25vLmh1L3Fj
cHMwgb8GCCsGAQUFBwICMIGyDIGvVGVzdCBxdWFsaWZpZWQgY2VydGlmaWNhdGUg
Zm9yIHdlYnNpdGUgYXV0aGVudGljYXRpb24gYW5kIGNsaWVudCBhdXRoZW50aWNh
dGlvbi4gVGhlIHByb3ZpZGVyIHByZXNlcnZlcyByZWdpc3RyYXRpb24gZGF0YSBm
b3IgMTAgeWVhcnMgYWZ0ZXIgdGhlIGV4cGlyYXRpb24gb2YgdGhlIGNlcnRpZmlj
YXRlLjCBlQYIKwYBBQUHAgIwgYgMgYVURVNUIGNlcnRpZmljYXRlIGlzc3VlZCBv
bmx5IGZvciB0ZXN0aW5nIHB1cnBvc2VzLiBUaGUgaXNzdWVyIGlzIG5vdCBsaWFi
bGUgZm9yIGFueSBkYW1hZ2VzIGFyaXNpbmcgZnJvbSB0aGUgdXNlIG9mIHRoaXMg
Y2VydGlmaWNhdGUhMIHMBggrBgEFBQcCAjCBvwyBvFRlc3p0IG1pbsWRc8OtdGV0
dCB3ZWJvbGRhbC1oaXRlbGVzw610xZEgw6lzIMO8Z3lmw6lsLWhpdGVsZXPDrXTF
kSB0YW7DunPDrXR2w6FueS4gQSByZWdpc3p0csOhY2nDs3MgYWRhdG9rYXQgYSBz
em9sZ8OhbHRhdMOzIGEgdGFuw7pzw610dsOhbnkgbGVqw6FydMOhdMOzbCBzesOh
bcOtdG90dCAxMCDDqXZpZyDFkXJ6aSBtZWcuMIGtBggrBgEFBQcCAjCBoAyBnVRl
c3p0ZWzDqXNpIGPDqWxyYSBraWFkb3R0IFRFU1pUIHRhbsO6c8OtdHbDoW55LiBB
IGhhc3puw6FsYXTDoXZhbCBrYXBjc29sYXRvc2FuIGZlbG1lcsO8bMWRIGvDoXJv
a8OpcnQgYSBTem9sZ8OhbHRhdMOzIHNlbW1pbHllbiBmZWxlbMWRc3PDqWdldCBu
ZW0gdsOhbGxhbCEwHQYDVR0OBBYEFFpdJ86Z7qiDATzBzLvlL+6RLl12MB8GA1Ud
IwQYMBaAFNzmAijvNzCPiT6grSBV8+826PDNMBoGA1UdEQQTMBGCD21ha2Vjb21t
ZXJjZS5sdDAyBgNVHR8EKzApMCegJaAjhiFodHRwOi8vdGVzenQuZS1zemlnbm8u
aHUvVENBMy5jcmwwbwYIKwYBBQUHAQEEYzBhMDAGCCsGAQUFBzABhiRodHRwOi8v
dGVzenQuZS1zemlnbm8uaHUvdGVzdGNhM29jc3AwLQYIKwYBBQUHMAKGIWh0dHA6
Ly90ZXN6dC5lLXN6aWduby5odS9UQ0EzLmNydDCCARQGCCsGAQUFBwEDBIIBBjCC
AQIwCAYGBACORgEBMAsGBgQAjkYBAwIBCjBTBgYEAI5GAQUwSTAkFh5odHRwczov
L2NwLmUtc3ppZ25vLmh1L3FjcHNfZW4TAkVOMCEWG2h0dHBzOi8vY3AuZS1zemln
bm8uaHUvcWNwcxMCSFUwEwYGBACORgEGMAkGBwQAjkYBBgMwfwYGBACBmCcCMHUw
JjARBgcEAIGYJwECDAZQU1BfUEkwEQYHBACBmCcBAwwGUFNQX0FJDENFRSAtIEVz
dG9uaWFuIEZpbmFuY2lhbCBTdXBlcnZpc2lvbiBBdXRob3JpdHkgLyBGaW5hbnRz
aW5zcGVrdHNpb29uDAZFRS1GU0EwDQYJKoZIhvcNAQELBQADggEBAHZXm9440SvU
cpZLshQ3oKOOeU4fTrP0KQkvzmBkmf+yct80vartjnIaDk5rk6HQRJRjcuDI9+Hj
ep9nzwkN+BUVwc2EV+M7i35pCK+dvNMTcgXTo2qGVznoSVjFuzshoC4mFIfxNczo
2NE2uTfU2wyWzQPYNcwFMZ7AoUXylGofEfS13mdH5dET++nWoAOD8ABZZqAeYsk9
R1fCxRThpldxjiJdDUZpzcVw+obyjRhKIm6zAHd6R0E6KB9I+feevF8IwgnTSozE
Zflb6EvyjuizsyqGteLrjim4ALu1+pA/2zhLZm55PWj1kM8PiWYqIGla0dKOzF4+
OTNNT6RR7bU=
-----END CERTIFICATE-----`
	certDERBlock, _ := pem.Decode([]byte(content))
	x509Cert, err := x509.ParseCertificate(certDERBlock.Bytes)
	if err != nil {
		fmt.Println("Parse certificate error:", err)
		return
	}
	for _, extension := range x509Cert.Extensions {
		if extension.Id.Equal(asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 1}) {
			var collExts []asn1.RawValue
			asn1.Unmarshal(extension.Value, &collExts)
			for _, collExt := range collExts {
				fmt.Println(string(collExt.Bytes))
			}
		}
	}
}

运行后输出带乱码的内容:

+0�#http://teszt.e-szigno.hu/testca3ocsp
+0�0http://teszt.e-szigno.hu/TCA3.crt

虽然可以自行提取链接,但希望了解如何正确解码asn1.RawValue或其Bytes字段,得到可读的文本内容。查阅了asn1包,未找到对应的解码函数。

解决方案

AIA扩展的ASN.1结构包含多个条目,每个条目由OID和IA5String类型的URI组成。直接将RawValue的Bytes转字符串会包含ASN.1的类型标签和长度信息,导致乱码。正确的做法是定义匹配ASN.1结构的Go结构体,通过asn1.Unmarshal完成解码。

修改后的代码

package main

import (
	"encoding/asn1"
	"encoding/pem"
	"fmt"
	"crypto/x509"
	"log"
)

// AIAEntry 表示AIA扩展中的单个条目
type AIAEntry struct {
	OID asn1.ObjectIdentifier
	URI string `asn1:"ia5string"`
}

// AIAContent 表示整个AIA扩展的内容
type AIAContent struct {
	Entries []AIAEntry `asn1:"sequence"`
}

func main() {
	content := `-----BEGIN CERTIFICATE-----
MIIJxDCCCKygAwIBAgINfEbzVUOoCNMWumANCjANBgkqhkiG9w0BAQsFADBqMQsw
CQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2Vj
IEx0ZC4xFDASBgNVBAsMC2UtU3ppZ25vIENBMRowGAYDVQQDDBFlLVN6aWdubyBU
ZXN0IENBMzAeFw0yMzAxMjQxMjQxNTBaFw0yNDAxMjQxMjQxNTBaMIHQMRMwEQYL
KwYBBAGCNzwCAQMTAkVFMRgwFgYLKwYBBAGCNzwCAQEMB1RhbGxpbm4xHTAbBgNV
BA8MFFByaXZhdGUgT3JnYW5pemF0aW9uMREwDwYDVQQFEwgxMjI2ODQ3NTELMAkG
A1UEBhMCRUUxEDAOBgNVBAcMB1RhbGxpbm4xFzAVBgNVBAoMDk1ha3Nla2Vza3Vz
IEFTMRswGQYDVQRhDBJQU0RFRS1GU0EtMTIyNjg0NzUxGDAWBgNVBAMMD21ha2Vj
b21tZXJjZS5sdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJFyj3sS
xev2yHbGXNmqw8e+ZqFvrb1+UHlsm7c65HSjwAVjheHNV1cufilRf5X1PuBDmXtC
XpwD7FmOc7h++BAEdapv/XcWkMqUgbkfwhaZPkjbXIQBH7jbe4D+3pxn+ZDlq/1b
Wi6dJhGHN+Ydgw6x+qGBOVzaFlprFdOYQXDw8yMc/iQMBahzzQApe2EwW1XRgyaT
DNE5t2T7uWC05qDYgi1HI50WGoezx7A7CDSjwG+kFvczleY+4H73aPiGH1f0q+EC
POZsoot12CWspBwZB9G03S5IoIipJPoQmIvnKGgeGbbY16P3VQ/78w9XjPy0dwid
x2CfPlPLTa8eJF0CAwEAAaOCBgAwggX8MA4GA1UdDwEB/wQEAwIFoDCBiQYKKwYB
BAHWeQIEAgR7BHkAdwB1AKoeeAQ/gGSCK+VMtcHKwuMu5FDmczAqSLwmlwubLAgd
AAABhePMiCsAAAQDAEYwRAIgMbv+IXdcxOgT9VPPUIuuHajA08AiGnQMKnSsYHPl
4egCICQN64jfx+fitpnfxb6u531tA3VkjmMmLOkvN5b2vj4wMB0GA1UdJQQWMBQG
CCsGAQUFBwMBBggrBgEFBQcDAjCCAyQGA1UdIASCAxswggMXMIIDEwYMKwYBBAGB
qBgCAQFkMIIDATAmBggrBgEFBQcCARYaaHR0cDovL2NwLmUtc3ppZ25vLmh1L3Fj
cHMwgb8GCCsGAQUFBwICMIGyDIGvVGVzdCBxdWFsaWZpZWQgY2VydGlmaWNhdGUg
Zm9yIHdlYnNpdGUgYXV0aGVudGljYXRpb24gYW5kIGNsaWVudCBhdXRoZW50aWNh
dGlvbi4gVGhlIHByb3ZpZGVyIHByZXNlcnZlcyByZWdpc3RyYXRpb24gZGF0YSBm
b3IgMTAgeWVhcnMgYWZ0ZXIgdGhlIGV4cGlyYXRpb24gb2YgdGhlIGNlcnRpZmlj
YXRlLjCBlQYIKwYBBQUHAgIwgYgMgYVURVNUIGNlcnRpZmljYXRlIGlzc3VlZCBv
bmx5IGZvciB0ZXN0aW5nIHB1cnBvc2VzLiBUaGUgaXNzdWVyIGlzIG5vdCBsaWFi
bGUgZm9yIGFueSBkYW1hZ2VzIGFyaXNpbmcgZnJvbSB0
相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 23:55:28