【问题标题】:how to extract DER encoded certificate from base64 string如何从base64字符串中提取DER编码证书
【发布时间】:2015-12-17 15:19:03
【问题描述】:

寻求有关如何解码以下 base64 MerkleTreeLeaf 字符串的帮助。

MerkleTreeLeaf 结构是一种复合数据结构,包含时间戳和数字证书。

该结构被编码为 Base64 编码的字节字符串。在这个字节字符串中,有一个以 DER 格式编码的实际证书。

我正在寻找一种 php 解决方案来提取 DER 编码的证书。

这是base64编码字符串的示例

AAAAAAFNDPxFcQAAAAUaMIIFFjCCBLygAwIBAgIQM+cDs5qlvsI+p1fkebkn3TAKBggqhkjOPQQDAjCBizELMAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMTwwOgYDVQQDEzNTeW1hbnRlYyBDbGFzcyAzIEVDQyAyNTYgYml0IEV4dGVuZGVkIFZhbGlkYXRpb24gQ0EwHhcNMTQxMjA4MDAwMDAwWhcNMTUxMjA4MjM1OTU5WjCCARExEzARBgsrBgEEAYI3PAIBAxMCVVMxGTAXBgsrBgEEAYI3PAIBAgwIRGVsYXdhcmUxGzAZBgsrBgEEAYI3PAIBAQwKV2lsbWluZ3RvbjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxHTAbBgNVBA8TFFByaXZhdGUgT3JnYW5pemF0aW9uMRAwDgYDVQQFEwcyMTU4MTEzMRYwFAYDVQQKDA1TeW1hbnRlYyBDb3JwMR0wGwYDVQQLDBRmb3IgY3QgdGVzdGluZy0tIGVjYzEgMB4GA1UEAwwXZXZwcm8xLmV2MS5zeW1hbnRlYy5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASdGXgRQD4CxlJr1QU7hZ86gbPxjlCHWDBZBSb5+vbo9bw2sZxaxwF15mHiSlEiaGVuwv2DxOPO+w/QVgMTggZ5o4ICdzCCAnMwIgYDVR0RBBswGYIXZXZwcm8xLmV2MS5zeW1hbnRlYy5jb20wCQYDVR0TBAIwADAOBgNVHQ8BAf8EBAMCB4AwZgYDVR0gBF8wXTBbBgtghkgBhvhFAQcXBjBMMCMGCCsGAQUFBwIBFhdodHRwczovL2Quc3ltY2IuY29tL2NwczAlBggrBgEFBQcCAjAZDBdodHRwczovL2Quc3ltY2IuY29tL3JwYTArBgNVHR8EJDAiMCCgHqAchhpodHRwOi8vc24uc3ltY2IuY29tL3NuLmNybDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwHwYDVR0jBBgwFoAUSBNlF5TsnhYqKnRc6FMttPuD644wVwYIKwYBBQUHAQEESzBJMB8GCCsGAQUFBzABhhNodHRwOi8vc24uc3ltY2QuY29tMCYGCCsGAQUFBzAChhpodHRwOi8vc24uc3ltY2IuY29tL3NuLmNydDCCAQIGCisGAQQB1nkCBAIEgfMEgfAA7gB1AKS5CZC0GFgUh7sTosxncAo8NZgE+RvfuON3zQ7IDdwQAAABSitKXtQAAAQDAEYwRAIgIQ2Dr+ktUJh1OFYAJxUqHwMjLmsMdvGToFaxSqEcAg8CIDjgHlQ8mV/NXsUC115hF5S7MZirjD7mdH52s6yv5JQiAHUAOTdvVF97Rgf1l0LXaM1dJDe/NHO2U0pINLz3Lmgcg8kAAAFKK0phCQAABAMARjBEAiA1GlOmlOeAP+uOmq+uPMVeN0TDsRZBxUE7oWUtZlKBOAIgFOoXuDXnAFALmW7CN66yrnHO7UyuMYy5t4oJqvgmzzowCgYIKoZIzj0EAwIDSAAwRQIgNqNb4f3YfKCvnkYjihpB9jGq0iUnfPclyD7mWxDJYt8CIQCJbJ48ZxGx2WYGRMXys52lxc/VxzzvdlSRto9y/jLhzAAA

如果我使用在线base64 convertors tool,它会显示一些细节,但显然不可读。如果我可以提取 DER 编码的证书,那么我可以使用 openssl 来解析它。

【问题讨论】:

  • 如果有帮助,我相信这里有一个 python 解决方案python script 可能会提供一些线索,但不确定我如何在 php 中做同样的事情

标签: php encoding certificate


【解决方案1】:

您可以像评论中的 Python 脚本一样使用它,只需将 Python unpack documentationthe one for PHP 进行比较。如果您只想要未解析的证书,则可以逃脱

<?php

function mtl_to_x509($base64str) {
    $raw = base64_decode($base64str);
    // Parse the decoded string
    $cert_length = unpack('N', chr(0).substr($raw, 12, 3))[1];
    $cert_as_asn1 = substr($raw, 15, $cert_length);
    return $cert_as_asn1;
}

$example = "AAAAAAFNDPxFcQAAAAUaMIIFFjCCBLygAwIBAgIQM+cDs5qlvsI+p1fkebkn3TAKBggqhkjOPQQDAjCBizELMAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMTwwOgYDVQQDEzNTeW1hbnRlYyBDbGFzcyAzIEVDQyAyNTYgYml0IEV4dGVuZGVkIFZhbGlkYXRpb24gQ0EwHhcNMTQxMjA4MDAwMDAwWhcNMTUxMjA4MjM1OTU5WjCCARExEzARBgsrBgEEAYI3PAIBAxMCVVMxGTAXBgsrBgEEAYI3PAIBAgwIRGVsYXdhcmUxGzAZBgsrBgEEAYI3PAIBAQwKV2lsbWluZ3RvbjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxHTAbBgNVBA8TFFByaXZhdGUgT3JnYW5pemF0aW9uMRAwDgYDVQQFEwcyMTU4MTEzMRYwFAYDVQQKDA1TeW1hbnRlYyBDb3JwMR0wGwYDVQQLDBRmb3IgY3QgdGVzdGluZy0tIGVjYzEgMB4GA1UEAwwXZXZwcm8xLmV2MS5zeW1hbnRlYy5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASdGXgRQD4CxlJr1QU7hZ86gbPxjlCHWDBZBSb5+vbo9bw2sZxaxwF15mHiSlEiaGVuwv2DxOPO+w/QVgMTggZ5o4ICdzCCAnMwIgYDVR0RBBswGYIXZXZwcm8xLmV2MS5zeW1hbnRlYy5jb20wCQYDVR0TBAIwADAOBgNVHQ8BAf8EBAMCB4AwZgYDVR0gBF8wXTBbBgtghkgBhvhFAQcXBjBMMCMGCCsGAQUFBwIBFhdodHRwczovL2Quc3ltY2IuY29tL2NwczAlBggrBgEFBQcCAjAZDBdodHRwczovL2Quc3ltY2IuY29tL3JwYTArBgNVHR8EJDAiMCCgHqAchhpodHRwOi8vc24uc3ltY2IuY29tL3NuLmNybDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwHwYDVR0jBBgwFoAUSBNlF5TsnhYqKnRc6FMttPuD644wVwYIKwYBBQUHAQEESzBJMB8GCCsGAQUFBzABhhNodHRwOi8vc24uc3ltY2QuY29tMCYGCCsGAQUFBzAChhpodHRwOi8vc24uc3ltY2IuY29tL3NuLmNydDCCAQIGCisGAQQB1nkCBAIEgfMEgfAA7gB1AKS5CZC0GFgUh7sTosxncAo8NZgE+RvfuON3zQ7IDdwQAAABSitKXtQAAAQDAEYwRAIgIQ2Dr+ktUJh1OFYAJxUqHwMjLmsMdvGToFaxSqEcAg8CIDjgHlQ8mV/NXsUC115hF5S7MZirjD7mdH52s6yv5JQiAHUAOTdvVF97Rgf1l0LXaM1dJDe/NHO2U0pINLz3Lmgcg8kAAAFKK0phCQAABAMARjBEAiA1GlOmlOeAP+uOmq+uPMVeN0TDsRZBxUE7oWUtZlKBOAIgFOoXuDXnAFALmW7CN66yrnHO7UyuMYy5t4oJqvgmzzowCgYIKoZIzj0EAwIDSAAwRQIgNqNb4f3YfKCvnkYjihpB9jGq0iUnfPclyD7mWxDJYt8CIQCJbJ48ZxGx2WYGRMXys52lxc/VxzzvdlSRto9y/jLhzAAA";

print mtl_to_x509($example);

?>

要查看它是否有效,请注意我们确实可以使用 openssl 解析它:

$ php mtl_to_x509.php | openssl x509 -inform der -noout -text | grep Subject:
        Subject: 1.3.6.1.4.1.311.60.2.1.3=US/1.3.6.1.4.1.311.60.2.1.2=Delaware/1.3.6.1.4.1.311.60.2.1.1=Wilmington, C=US, ST=California, L=Mountain View/businessCategory=Private Organization/serialNumber=2158113, O=Symantec Corp, OU=for ct testing-- ecc, CN=evpro1.ev1.symantec.com

如果您最终还需要数据结构的其余部分,相关的解包将如下所示:

$version = unpack('C', substr($raw, 0, 1))[1];
$ctype = unpack('C', substr($raw, 1, 1))[1];
$timestamp = unpack('J', substr($raw, 2, 8))[1];
$entry_type = unpack('n', substr($raw, 10, 2))[1];

【讨论】:

  • 这行得通!但是,对于 $version、ctype 等,我收到此消息“警告:unpack():64 位格式代码不适用于 32 位版本的 PHP”
  • 这可能是导致问题的$timestamp,因为解析 unsigned long long 在 32 位上不起作用。要查看值应该是多少,您可以使用print_r(unpack('C*', substr($raw, 2, 8)));:Array( [1] =&gt; 0 [2] =&gt; 0 [3] =&gt; 1 [4] =&gt; 77 [5] =&gt; 12 [6] =&gt; 52 [7] =&gt; 69 [8] =&gt; 113)。也就是时间戳应该是113*256^0 + 69*256^1 + 252*256^2 + 12*256^3 + 77*256^4 + 1\*256^5 = 1430441969009.
  • 或者就像两个 32 位整数:print_r(unpack('N*', substr($raw, 2, 8))); 给出 Array( [1] =&gt; 333 [2] =&gt; 217859441)。和217859441 + 333*256^4 = 1430441969009.
  • 在您的解决方案中,您是如何得出$cert_length 中的数字12、3 和$cert_as_asn1 中的15 - 我问的原因是因为我有另一个base64 字符串我正在尝试解析但是它不太管用。您可以在此处找到 base64 字符串:jpst.it/JgX9
  • @user3436467:我刚刚从原始帖子评论中提供的示例中获得它们,但您也可以在 CT RFC 中找到它们; ietf.org/rfc/rfc6962.txt
猜你喜欢
  • 2013-02-08
  • 1970-01-01
  • 2012-01-17
  • 2021-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-17
  • 2017-09-05
相关资源
最近更新 更多