使用 x509.ParseCertificateRequest 解组失败但 openssl 可以吗?
Unmarshal with x509.ParseCertificateRequest fails but openssl is ok?
当我尝试加载 PEM 编码的 CSR 时,Golang 没有正确解析 CSR 中的 ASN.1 数据。它吐出序列被截断。
另一方面,OpenSSL 可以处理 CSR 并打印出正确的 CN。
这是生成代码(在 c# 中):
public string generateCSR(string cn)
{
try
{
AsymmetricCipherKeyPair pair = this.keyHolder.keypair;
var subject = new X509Name("CN=" + cn);
var pkcs10CertificationRequest = new Pkcs10CertificationRequest
(PkcsObjectIdentifiers.Sha256WithRsaEncryption.Id, subject, pair.Public, null, pair.Private);
string csr = Convert.ToBase64String(pkcs10CertificationRequest.GetDerEncoded());
Debug.Log(csr);
return csr;
} catch(Exception e)
{
Debug.LogError(e);
}
return null;
}
直接通过 HTTP 发送到 Golang 服务(没有任何 URL 编码等)
Golang 服务器端:
// Try to parse CSR
bytes := make([]byte, base64.StdEncoding.DecodedLen(len(csrData)))
n, err := base64.StdEncoding.Decode(bytes, csrData)
if err != nil {
fmt.Printf("Error whilst parsing PEM: %v\n", err)
resp.WriteHeader(http.StatusBadRequest)
return
}
_, err = x509.ParseCertificateRequest(bytes[:n])
if err != nil {
fmt.Printf("Error whilst parsing ASN.1/REQ CSR: %v\n", err)
resp.WriteHeader(http.StatusBadRequest)
return
}
测试 CSR(在 PEM 中):
MIIEWTCCAkECAQAwFjEUMBIGA1UEAwwLdGVzdEFjY291bnQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCHu2/2GXBGlEuIWAjhBHXRnT17Pod9aPbTnLwfVSD+1xjchsu2rB83LtSWlfRXoIs4geUTvr2io0iP/kU+IzVZwL/CMzPWoWwq4VH5nQ5QMqCCMEF2g90BmIlLgaopNuQPfAEO64d+3dSFnha3QLbmv2xXe3WwYJ+RTvf+Kij0jgeB3MGzEmlVDiVWlaH4TO5LzY5/CbQgtfDHmhp4LDGe+9vbSkX/m4TXMEg4//21oe7YKO4spM1z9pIUsk8vBb0jDwRFnYRhRjHY5JTzOOM6lewjciOIlOKiBBPb4xSGJeRexZZvl111L/chhLQR701XvSyEn8MQRC6U3/BAhdvvwROPfJoEkbpf5vPYGfmsRr4iwci7XBFlw7q1iJZ6Jk4T4iYaPXl2HF0x9kpbA6eDDKkdJvM0Z6X61Eir6hI8xsyAoTEh4pBRyypl+tTLl1vK1BNEZhaPatTj5N0glCxa/MxODDDri6aobU5mjbYfp1FMdpSYiJub0l7tZvgSCv82ANxjPvT4HLge658C7VOfAQj+kdeGzNgJRSA8/FwJGsbl0RyB0Yn82HrYKB+YQy/e79+i/BIm9yAmBsEjTgrjkNF1izl5PrwQBc/lU9gVbONNvryODV4pG7NrNERSsiwN5YXFWDElDZjO3TaFwbz67raRgX7aBIHlCeINzBVuzwIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQBFZmrjbbqxerp5oLbmW91fBzinXKLmP8E1bsIyh4GSsWxnN13a9Srbq/VEaNJm+vucAFrptleMCz8GAO5Gm8XobhnMzr6uotn8b2rEDZvo9UHuyqu2H8wI2Te5sqjBjnbH/KOTN83uYLQVODkVve/9VW7e0xxjG8i/OCmyVjVY0sc4U06LRJw4LVqeeOFWJcv0yjxEucwLNodlzm0S3t9Cx0Vkd3cVzq/lwcBTEDHzcfgleOUcOCgbOZF6NDvyuB5VLsS+HwJeIm8tiBF9yqT+RYFKYQjvDy1XT9a1sNqn7jmiV3zwb4vcy16vgAakjyBeWnK87UJQI4XiCyGP61Xchlo5p5yyIu09iJeAN5pHuKCQAYmvEjTF630O5i/e0UHWhIZA0PnG1xAksVv9FpoQh8LjfnG7+XkAYWFxAbiIG/x8rQsyZie9SSvW2hbRykGpNdQYy4wiwt/dx/UaZI3/n24/dE50NWckP8fLeGWqqej0mYWCLjzxult0xELRiVvjNfuHwcfTPBrqmQqG16PII7tjhv0bhszRrIAkcVMpTM0RV/jcSVc4aMLpDRVLElDtaG2qCaJWq5a8MBk1BiYLjI8i8f0cMBXJ2dq9sjzEwl0vGObBui5my9jHgwzY7aPqIO0mgZm5sEpisBZMgCJ9AmK36u7wjqZZC6jnuxYoWg==
Go 中的 ASN 解析器中是否有任何我遗漏的选项?为什么 OpenSSL 可以处理该输入?
我找到了这个问题的答案。
Bouncycastle 不会在没有给定属性实例(空)时将 a0:00 添加到属性。这导致不完整的编码数据。
“如果你刚刚看到:
属性:
那么 SET OF 丢失并且编码在技术上是无效的(但它是可以容忍的)。”
- https://www.openssl.org/docs/man1.0.2/man1/openssl-req.html
解决方案是向 CSR 提供一个空的 DerSet,这会导致 a0:00 生成表明不存在任何属性。
当我尝试加载 PEM 编码的 CSR 时,Golang 没有正确解析 CSR 中的 ASN.1 数据。它吐出序列被截断。
另一方面,OpenSSL 可以处理 CSR 并打印出正确的 CN。
这是生成代码(在 c# 中):
public string generateCSR(string cn)
{
try
{
AsymmetricCipherKeyPair pair = this.keyHolder.keypair;
var subject = new X509Name("CN=" + cn);
var pkcs10CertificationRequest = new Pkcs10CertificationRequest
(PkcsObjectIdentifiers.Sha256WithRsaEncryption.Id, subject, pair.Public, null, pair.Private);
string csr = Convert.ToBase64String(pkcs10CertificationRequest.GetDerEncoded());
Debug.Log(csr);
return csr;
} catch(Exception e)
{
Debug.LogError(e);
}
return null;
}
直接通过 HTTP 发送到 Golang 服务(没有任何 URL 编码等)
Golang 服务器端:
// Try to parse CSR
bytes := make([]byte, base64.StdEncoding.DecodedLen(len(csrData)))
n, err := base64.StdEncoding.Decode(bytes, csrData)
if err != nil {
fmt.Printf("Error whilst parsing PEM: %v\n", err)
resp.WriteHeader(http.StatusBadRequest)
return
}
_, err = x509.ParseCertificateRequest(bytes[:n])
if err != nil {
fmt.Printf("Error whilst parsing ASN.1/REQ CSR: %v\n", err)
resp.WriteHeader(http.StatusBadRequest)
return
}
测试 CSR(在 PEM 中):
MIIEWTCCAkECAQAwFjEUMBIGA1UEAwwLdGVzdEFjY291bnQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCHu2/2GXBGlEuIWAjhBHXRnT17Pod9aPbTnLwfVSD+1xjchsu2rB83LtSWlfRXoIs4geUTvr2io0iP/kU+IzVZwL/CMzPWoWwq4VH5nQ5QMqCCMEF2g90BmIlLgaopNuQPfAEO64d+3dSFnha3QLbmv2xXe3WwYJ+RTvf+Kij0jgeB3MGzEmlVDiVWlaH4TO5LzY5/CbQgtfDHmhp4LDGe+9vbSkX/m4TXMEg4//21oe7YKO4spM1z9pIUsk8vBb0jDwRFnYRhRjHY5JTzOOM6lewjciOIlOKiBBPb4xSGJeRexZZvl111L/chhLQR701XvSyEn8MQRC6U3/BAhdvvwROPfJoEkbpf5vPYGfmsRr4iwci7XBFlw7q1iJZ6Jk4T4iYaPXl2HF0x9kpbA6eDDKkdJvM0Z6X61Eir6hI8xsyAoTEh4pBRyypl+tTLl1vK1BNEZhaPatTj5N0glCxa/MxODDDri6aobU5mjbYfp1FMdpSYiJub0l7tZvgSCv82ANxjPvT4HLge658C7VOfAQj+kdeGzNgJRSA8/FwJGsbl0RyB0Yn82HrYKB+YQy/e79+i/BIm9yAmBsEjTgrjkNF1izl5PrwQBc/lU9gVbONNvryODV4pG7NrNERSsiwN5YXFWDElDZjO3TaFwbz67raRgX7aBIHlCeINzBVuzwIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQBFZmrjbbqxerp5oLbmW91fBzinXKLmP8E1bsIyh4GSsWxnN13a9Srbq/VEaNJm+vucAFrptleMCz8GAO5Gm8XobhnMzr6uotn8b2rEDZvo9UHuyqu2H8wI2Te5sqjBjnbH/KOTN83uYLQVODkVve/9VW7e0xxjG8i/OCmyVjVY0sc4U06LRJw4LVqeeOFWJcv0yjxEucwLNodlzm0S3t9Cx0Vkd3cVzq/lwcBTEDHzcfgleOUcOCgbOZF6NDvyuB5VLsS+HwJeIm8tiBF9yqT+RYFKYQjvDy1XT9a1sNqn7jmiV3zwb4vcy16vgAakjyBeWnK87UJQI4XiCyGP61Xchlo5p5yyIu09iJeAN5pHuKCQAYmvEjTF630O5i/e0UHWhIZA0PnG1xAksVv9FpoQh8LjfnG7+XkAYWFxAbiIG/x8rQsyZie9SSvW2hbRykGpNdQYy4wiwt/dx/UaZI3/n24/dE50NWckP8fLeGWqqej0mYWCLjzxult0xELRiVvjNfuHwcfTPBrqmQqG16PII7tjhv0bhszRrIAkcVMpTM0RV/jcSVc4aMLpDRVLElDtaG2qCaJWq5a8MBk1BiYLjI8i8f0cMBXJ2dq9sjzEwl0vGObBui5my9jHgwzY7aPqIO0mgZm5sEpisBZMgCJ9AmK36u7wjqZZC6jnuxYoWg==
Go 中的 ASN 解析器中是否有任何我遗漏的选项?为什么 OpenSSL 可以处理该输入?
我找到了这个问题的答案。
Bouncycastle 不会在没有给定属性实例(空)时将 a0:00 添加到属性。这导致不完整的编码数据。
“如果你刚刚看到: 属性: 那么 SET OF 丢失并且编码在技术上是无效的(但它是可以容忍的)。” - https://www.openssl.org/docs/man1.0.2/man1/openssl-req.html
解决方案是向 CSR 提供一个空的 DerSet,这会导致 a0:00 生成表明不存在任何属性。