如何创建可由 OpenSSL 命令行工具解析的单行 x509 证书
How to create a single line x509 certificate that can be parsed by OpenSSL commandline tool
我想准备一个可以被 OpenSSL 命令行实用程序解析的单行 x509 证书字符串。
我使用 OpenSSL 命令行实用程序创建了私钥,
openssl genrsa -out privatekey.pem 1024
然后创建了一个public键,
openssl req -new -x509 -key privatekey.pem -out publickey.cer -days 1825
证书内容为,
$ openssl x509 -in publickey.cer
-----BEGIN CERTIFICATE-----
MIICZjCCAc+gAwIBAgIUUnH/2DwpRMsAkWtkE1jccev9FtwwDQYJKoZIhvcNAQEL
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xOTA5MTAxMTE0NDRaFw0yNDA5
MDgxMTE0NDRaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwgZ8wDQYJKoZIhvcNAQEB
BQADgY0AMIGJAoGBAJ1Z9/FRGmzCCB1F6txz2JMpHy+WNgvtPfyRQh6vjC3g7mcD
CHOPORT9vg/9ye2smr0gcPnkJwzA6ftaw0fWvHCXtVcb+cFs7xL3JbC7HexJQWFT
4fcQ6KhckTfn8qvkHdSMEX1y6+sFKFgftUgAtWmhRNnYTPaFEjFEjc8MVeM9AgMB
AAGjUzBRMB0GA1UdDgQWBBQ+mp9v3pEw5Oy4FiE3Go9vs/56zzAfBgNVHSMEGDAW
gBQ+mp9v3pEw5Oy4FiE3Go9vs/56zzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
DQEBCwUAA4GBAAlemG77/vf1bvGlADLc+/sPeZ6ppuMz/y3qVRqfFJ+78RMTSrLW
SPGUyDFauTAvf7fNj+D/Pt+OrMue+AK+PCi0JxIWxIIv+XJqoSxHTwoBqujn93Xs
+vm03hED1aoCs/s7rSsckAR/OjkMtQDoVer/F0izuE7ebAh4IFYXYTUD
-----END CERTIFICATE-----
然后我使用下面的 awk command、
将换行符转换为 \n
$ awk 'NF {sub(/\r/, ""); printf "%s\n",[=13=];}' publickey.cer | tee single_line_publickey.cer
转换后的证书是,
-----BEGIN CERTIFICATE-----\nMIICZjCCAc+gAwIBAgIUUnH/2DwpRMsAkWtkE1jccev9FtwwDQYJKoZIhvcNAQEL\nBQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM\nGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xOTA5MTAxMTE0NDRaFw0yNDA5\nMDgxMTE0NDRaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw\nHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwgZ8wDQYJKoZIhvcNAQEB\nBQADgY0AMIGJAoGBAJ1Z9/FRGmzCCB1F6txz2JMpHy+WNgvtPfyRQh6vjC3g7mcD\nCHOPORT9vg/9ye2smr0gcPnkJwzA6ftaw0fWvHCXtVcb+cFs7xL3JbC7HexJQWFT\n4fcQ6KhckTfn8qvkHdSMEX1y6+sFKFgftUgAtWmhRNnYTPaFEjFEjc8MVeM9AgMB\nAAGjUzBRMB0GA1UdDgQWBBQ+mp9v3pEw5Oy4FiE3Go9vs/56zzAfBgNVHSMEGDAW\ngBQ+mp9v3pEw5Oy4FiE3Go9vs/56zzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3\nDQEBCwUAA4GBAAlemG77/vf1bvGlADLc+/sPeZ6ppuMz/y3qVRqfFJ+78RMTSrLW\nSPGUyDFauTAvf7fNj+D/Pt+OrMue+AK+PCi0JxIWxIIv+XJqoSxHTwoBqujn93Xs\n+vm03hED1aoCs/s7rSsckAR/OjkMtQDoVer/F0izuE7ebAh4IFYXYTUD\n-----END CERTIFICATE-----\n
但是 OpenSSL 命令行工具无法解析这个单行证书,
$ openssl x509 -in single_line_publickey.cer
unable to load certificate
140671947637184:error:0909006C:PEM routines:get_name:no start line:../crypto/pem/pem_lib.c:745:Expecting: TRUSTED CERTIFICATE
看起来无法找到封装边界 -----BEGIN CERTIFICATE-----
和 -----END CERTIFICATE-----
。从 RFC7468: Textual Encodings of PKIX, PKCS, and CMS Structures 标准中,我发现 BEGIN CERTIFICATE
和 END CERTIFICATE
标签需要用换行符分隔。这里看起来 \n
不起作用。我尝试 \r\n
模拟 CR+LF 但我仍然遇到同样的问题。
我观察到,当我在换行符中保留 BEGIN CERTIFICATE
和 END CERTIFICATE
标签时,OpenSSL 命令行工具能够解析证书。
证书文件是,
$ cat multi_line_publickey.cer
-----BEGIN CERTIFICATE-----
MIICZjCCAc+gAwIBAgIUUnH/2DwpRMsAkWtkE1jccev9FtwwDQYJKoZIhvcNAQELBQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xOTA5MTAxMTE0NDRaFw0yNDA5MDgxMTE0NDRaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJ1Z9/FRGmzCCB1F6txz2JMpHy+WNgvtPfyRQh6vjC3g7mcDCHOPORT9vg/9ye2smr0gcPnkJwzA6ftaw0fWvHCXtVcb+cFs7xL3JbC7HexJQWFT4fcQ6KhckTfn8qvkHdSMEX1y6+sFKFgftUgAtWmhRNnYTPaFEjFEjc8MVeM9AgMBAAGjUzBRMB0GA1UdDgQWBBQ+mp9v3pEw5Oy4FiE3Go9vs/56zzAfBgNVHSMEGDAWgBQ+mp9v3pEw5Oy4FiE3Go9vs/56zzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GBAAlemG77/vf1bvGlADLc+/sPeZ6ppuMz/y3qVRqfFJ+78RMTSrLWSPGUyDFauTAvf7fNj+D/Pt+OrMue+AK+PCi0JxIWxIIv+XJqoSxHTwoBqujn93Xs+vm03hED1aoCs/s7rSsckAR/OjkMtQDoVer/F0izuE7ebAh4IFYXYTUD
-----END CERTIFICATE-----
并且 OpenSSL 工具能够解析它,
$ openssl x509 -in multi_line_publickey.cer -noout -subject
subject=C = AU, ST = Some-State, O = Internet Widgits Pty Ltd
但是这里我有三行。如何以 OpenSSL 命令行实用程序可以解析的方式将此证书准备为一行?
你可以施展 bash 黑魔法来得到你想要的。如果你看到你的 single_line_publickey.cer
,它也有 \n
个字符,当你回显时它也会出现。这意味着您可以强制 echo 将它们打印为换行符。
如果您尝试类似的操作:
echo -ne $(cat single_line_publickey.cer) | openssl x509 -noout -text
应该没问题。
I wanted to prepare a single line x509 Certificate string which can be parsed by OpenSSL command-line utility...
-----BEGIN CERTIFICATE-----
MIICZjCCAc+gAwIBAgIUUnH/2DwpRMsAkWtkE1jccev9FtwwDQYJKoZIhvcNAQELBQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xOTA5MTAxMTE0NDRaFw0yNDA5MDgxMTE0NDRaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJ1Z9/FRGmzCCB1F6txz2JMpHy+WNgvtPfyRQh6vjC3g7mcDCHOPORT9vg/9ye2smr0gcPnkJwzA6ftaw0fWvHCXtVcb+cFs7xL3JbC7HexJQWFT4fcQ6KhckTfn8qvkHdSMEX1y6+sFKFgftUgAtWmhRNnYTPaFEjFEjc8MVeM9AgMBAAGjUzBRMB0GA1UdDgQWBBQ+mp9v3pEw5Oy4FiE3Go9vs/56zzAfBgNVHSMEGDAWgBQ+mp9v3pEw5Oy4FiE3Go9vs/56zzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GBAAlemG77/vf1bvGlADLc+/sPeZ6ppuMz/y3qVRqfFJ+78RMTSrLWSPGUyDFauTAvf7fNj+D/Pt+OrMue+AK+PCi0JxIWxIIv+XJqoSxHTwoBqujn93Xs+vm03hED1aoCs/s7rSsckAR/OjkMtQDoVer/F0izuE7ebAh4IFYXYTUD
-----END CERTIFICATE-----
PEM 编码在 RFC 1421 中有详细说明,Privacy Enhancement for Internet Electronic Mail。在规格中,它说:
- 封装边界各自为政,
- 邮件是Base64编码的,
- 行限制为 64 个字符,
- 行尾是 CR ('\r') 和 LF ('\n')
OpenSSL 从未很好地处理格式错误的证书。从我记事起就是这样。相当多的图书馆不能很好地处理 EOL。他们也会在 CRLF 行结尾处窒息。
相比之下,OpenSSH 文件格式 RFC RFC 4716 表示实现必须处理 CR、LF 或 CRLF 的 eol。 RFC 还表示证书和密钥应使用本机平台约定编写,因此您将在该字段中看到所有三个。
如果您不介意黑暗的 awk 魔法,请继续。
没有 -----BEGIN CERTIFICATE-----
,-----END CERTIFICATE-----
新行:
awk 'NR>2 { sub(/\r/, ""); printf "%s",last} { last=[=10=] }' ca.crt
证书包括页眉、页脚,无换行符:
awk 'NF {sub(/\r/, ""); printf "%s",[=11=];}' ca.crt
证书包括页眉、页脚和换行符 \n
awk 'NF {sub(/\r/, ""); printf "%s\n",[=12=];}'
我想准备一个可以被 OpenSSL 命令行实用程序解析的单行 x509 证书字符串。
我使用 OpenSSL 命令行实用程序创建了私钥,
openssl genrsa -out privatekey.pem 1024
然后创建了一个public键,
openssl req -new -x509 -key privatekey.pem -out publickey.cer -days 1825
证书内容为,
$ openssl x509 -in publickey.cer
-----BEGIN CERTIFICATE-----
MIICZjCCAc+gAwIBAgIUUnH/2DwpRMsAkWtkE1jccev9FtwwDQYJKoZIhvcNAQEL
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xOTA5MTAxMTE0NDRaFw0yNDA5
MDgxMTE0NDRaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwgZ8wDQYJKoZIhvcNAQEB
BQADgY0AMIGJAoGBAJ1Z9/FRGmzCCB1F6txz2JMpHy+WNgvtPfyRQh6vjC3g7mcD
CHOPORT9vg/9ye2smr0gcPnkJwzA6ftaw0fWvHCXtVcb+cFs7xL3JbC7HexJQWFT
4fcQ6KhckTfn8qvkHdSMEX1y6+sFKFgftUgAtWmhRNnYTPaFEjFEjc8MVeM9AgMB
AAGjUzBRMB0GA1UdDgQWBBQ+mp9v3pEw5Oy4FiE3Go9vs/56zzAfBgNVHSMEGDAW
gBQ+mp9v3pEw5Oy4FiE3Go9vs/56zzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
DQEBCwUAA4GBAAlemG77/vf1bvGlADLc+/sPeZ6ppuMz/y3qVRqfFJ+78RMTSrLW
SPGUyDFauTAvf7fNj+D/Pt+OrMue+AK+PCi0JxIWxIIv+XJqoSxHTwoBqujn93Xs
+vm03hED1aoCs/s7rSsckAR/OjkMtQDoVer/F0izuE7ebAh4IFYXYTUD
-----END CERTIFICATE-----
然后我使用下面的 awk command、
将换行符转换为\n
$ awk 'NF {sub(/\r/, ""); printf "%s\n",[=13=];}' publickey.cer | tee single_line_publickey.cer
转换后的证书是,
-----BEGIN CERTIFICATE-----\nMIICZjCCAc+gAwIBAgIUUnH/2DwpRMsAkWtkE1jccev9FtwwDQYJKoZIhvcNAQEL\nBQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM\nGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xOTA5MTAxMTE0NDRaFw0yNDA5\nMDgxMTE0NDRaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw\nHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwgZ8wDQYJKoZIhvcNAQEB\nBQADgY0AMIGJAoGBAJ1Z9/FRGmzCCB1F6txz2JMpHy+WNgvtPfyRQh6vjC3g7mcD\nCHOPORT9vg/9ye2smr0gcPnkJwzA6ftaw0fWvHCXtVcb+cFs7xL3JbC7HexJQWFT\n4fcQ6KhckTfn8qvkHdSMEX1y6+sFKFgftUgAtWmhRNnYTPaFEjFEjc8MVeM9AgMB\nAAGjUzBRMB0GA1UdDgQWBBQ+mp9v3pEw5Oy4FiE3Go9vs/56zzAfBgNVHSMEGDAW\ngBQ+mp9v3pEw5Oy4FiE3Go9vs/56zzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3\nDQEBCwUAA4GBAAlemG77/vf1bvGlADLc+/sPeZ6ppuMz/y3qVRqfFJ+78RMTSrLW\nSPGUyDFauTAvf7fNj+D/Pt+OrMue+AK+PCi0JxIWxIIv+XJqoSxHTwoBqujn93Xs\n+vm03hED1aoCs/s7rSsckAR/OjkMtQDoVer/F0izuE7ebAh4IFYXYTUD\n-----END CERTIFICATE-----\n
但是 OpenSSL 命令行工具无法解析这个单行证书,
$ openssl x509 -in single_line_publickey.cer
unable to load certificate
140671947637184:error:0909006C:PEM routines:get_name:no start line:../crypto/pem/pem_lib.c:745:Expecting: TRUSTED CERTIFICATE
看起来无法找到封装边界 -----BEGIN CERTIFICATE-----
和 -----END CERTIFICATE-----
。从 RFC7468: Textual Encodings of PKIX, PKCS, and CMS Structures 标准中,我发现 BEGIN CERTIFICATE
和 END CERTIFICATE
标签需要用换行符分隔。这里看起来 \n
不起作用。我尝试 \r\n
模拟 CR+LF 但我仍然遇到同样的问题。
我观察到,当我在换行符中保留 BEGIN CERTIFICATE
和 END CERTIFICATE
标签时,OpenSSL 命令行工具能够解析证书。
证书文件是,
$ cat multi_line_publickey.cer
-----BEGIN CERTIFICATE-----
MIICZjCCAc+gAwIBAgIUUnH/2DwpRMsAkWtkE1jccev9FtwwDQYJKoZIhvcNAQELBQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xOTA5MTAxMTE0NDRaFw0yNDA5MDgxMTE0NDRaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJ1Z9/FRGmzCCB1F6txz2JMpHy+WNgvtPfyRQh6vjC3g7mcDCHOPORT9vg/9ye2smr0gcPnkJwzA6ftaw0fWvHCXtVcb+cFs7xL3JbC7HexJQWFT4fcQ6KhckTfn8qvkHdSMEX1y6+sFKFgftUgAtWmhRNnYTPaFEjFEjc8MVeM9AgMBAAGjUzBRMB0GA1UdDgQWBBQ+mp9v3pEw5Oy4FiE3Go9vs/56zzAfBgNVHSMEGDAWgBQ+mp9v3pEw5Oy4FiE3Go9vs/56zzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GBAAlemG77/vf1bvGlADLc+/sPeZ6ppuMz/y3qVRqfFJ+78RMTSrLWSPGUyDFauTAvf7fNj+D/Pt+OrMue+AK+PCi0JxIWxIIv+XJqoSxHTwoBqujn93Xs+vm03hED1aoCs/s7rSsckAR/OjkMtQDoVer/F0izuE7ebAh4IFYXYTUD
-----END CERTIFICATE-----
并且 OpenSSL 工具能够解析它,
$ openssl x509 -in multi_line_publickey.cer -noout -subject
subject=C = AU, ST = Some-State, O = Internet Widgits Pty Ltd
但是这里我有三行。如何以 OpenSSL 命令行实用程序可以解析的方式将此证书准备为一行?
你可以施展 bash 黑魔法来得到你想要的。如果你看到你的 single_line_publickey.cer
,它也有 \n
个字符,当你回显时它也会出现。这意味着您可以强制 echo 将它们打印为换行符。
如果您尝试类似的操作:
echo -ne $(cat single_line_publickey.cer) | openssl x509 -noout -text
应该没问题。
I wanted to prepare a single line x509 Certificate string which can be parsed by OpenSSL command-line utility...
-----BEGIN CERTIFICATE----- MIICZjCCAc+gAwIBAgIUUnH/2DwpRMsAkWtkE1jccev9FtwwDQYJKoZIhvcNAQELBQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xOTA5MTAxMTE0NDRaFw0yNDA5MDgxMTE0NDRaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJ1Z9/FRGmzCCB1F6txz2JMpHy+WNgvtPfyRQh6vjC3g7mcDCHOPORT9vg/9ye2smr0gcPnkJwzA6ftaw0fWvHCXtVcb+cFs7xL3JbC7HexJQWFT4fcQ6KhckTfn8qvkHdSMEX1y6+sFKFgftUgAtWmhRNnYTPaFEjFEjc8MVeM9AgMBAAGjUzBRMB0GA1UdDgQWBBQ+mp9v3pEw5Oy4FiE3Go9vs/56zzAfBgNVHSMEGDAWgBQ+mp9v3pEw5Oy4FiE3Go9vs/56zzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GBAAlemG77/vf1bvGlADLc+/sPeZ6ppuMz/y3qVRqfFJ+78RMTSrLWSPGUyDFauTAvf7fNj+D/Pt+OrMue+AK+PCi0JxIWxIIv+XJqoSxHTwoBqujn93Xs+vm03hED1aoCs/s7rSsckAR/OjkMtQDoVer/F0izuE7ebAh4IFYXYTUD -----END CERTIFICATE-----
PEM 编码在 RFC 1421 中有详细说明,Privacy Enhancement for Internet Electronic Mail。在规格中,它说:
- 封装边界各自为政,
- 邮件是Base64编码的,
- 行限制为 64 个字符,
- 行尾是 CR ('\r') 和 LF ('\n')
OpenSSL 从未很好地处理格式错误的证书。从我记事起就是这样。相当多的图书馆不能很好地处理 EOL。他们也会在 CRLF 行结尾处窒息。
相比之下,OpenSSH 文件格式 RFC RFC 4716 表示实现必须处理 CR、LF 或 CRLF 的 eol。 RFC 还表示证书和密钥应使用本机平台约定编写,因此您将在该字段中看到所有三个。
如果您不介意黑暗的 awk 魔法,请继续。
没有 -----BEGIN CERTIFICATE-----
,-----END CERTIFICATE-----
新行:
awk 'NR>2 { sub(/\r/, ""); printf "%s",last} { last=[=10=] }' ca.crt
证书包括页眉、页脚,无换行符:
awk 'NF {sub(/\r/, ""); printf "%s",[=11=];}' ca.crt
证书包括页眉、页脚和换行符 \n
awk 'NF {sub(/\r/, ""); printf "%s\n",[=12=];}'