How to create a single line x509 certificate that can be parsed by OpenSSL commandline tool

14,145

Solution 1

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 encoding is detailed in RFC 1421, Privacy Enhancement for Internet Electronic Mail. Among the specifications, it says:

  • Encapsulation boundaries are on their own lines,
  • The message is Base64 encoded,
  • Lines are limited to 64 characters,
  • End-of-line is CR ('\r') and LF ('\n')

OpenSSL has never handled ill-formed certificates well. It has been that way as long as I can remember. A fair number of libraries don't handle EOL well. They choke on CRLF line endings as well.

In contrast, the OpenSSH file format RFC, RFC 4716, say an implementation must handle an eol that is CR, LF, or CRLF. The RFC also says certificates and keys should be written using native platform conventions, so you will see all three in the field.

Solution 2

You can do some bash dark magic to get what you want. If you see your single_line_publickey.cer, it has the \n chars too that show up when you echo. Which means you can force echo to print them as newlines.

If you try something like:

echo -ne $(cat single_line_publickey.cer) | openssl x509 -noout -text

It should work out just fine.

Share:
14,145
anoop.babu
Author by

anoop.babu

Updated on June 05, 2022

Comments

  • anoop.babu
    anoop.babu almost 2 years

    I wanted to prepare a single line x509 Certificate string which can be parsed by OpenSSL command-line utility.

    I created a private key using OpenSSL command-line utility,

    openssl genrsa -out privatekey.pem 1024
    

    And then created a public key,

    openssl req -new -x509 -key privatekey.pem -out publickey.cer -days 1825
    

    The contents of the certificate is,

    $ 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-----
    

    I then converted the newline symbols to \n using below awk command,

    $ awk 'NF {sub(/\r/, ""); printf "%s\\n",$0;}' publickey.cer  | tee single_line_publickey.cer
    

    The transformed certificate is,

    -----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
    

    But OpenSSL command line tool is failing to parse this single line certificate,

    $ 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
    

    Looks like it is not able to find the encapsulation boundaries -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----. From the RFC7468: Textual Encodings of PKIX, PKCS, and CMS Structures standard, I found that BEGIN CERTIFICATE and END CERTIFICATE labels needs to be separated by newline. Here looks like \n is not working. I tried \r\n to simulate CR+LF but still I had the same problem.

    What I observed is the OpenSSL command-line tool is able to parse the certificate when I keep BEGIN CERTIFICATE and END CERTIFICATE labels in newlines. The certificate file is,

    $ 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-----
    

    And the OpenSSL tool is able to parse it,

    $ openssl x509 -in multi_line_publickey.cer -noout -subject
    subject=C = AU, ST = Some-State, O = Internet Widgits Pty Ltd
    

    But here I have three lines. How to prepare this certificate as one line in a way that OpenSSL Command Line utility can parse it?

    • CristiFati
      CristiFati over 4 years
      What's the reasoning behind the "single line"?
    • anoop.babu
      anoop.babu over 4 years
      I have a web front-end which takes only strings as input. I wanted the users to pass certificates through this front-end. The frontend then passes this single line certificate as a parameter to openstack heat stack creation. The front end has pretty basic Javascript support with very limited modules.
    • bartonjs
      bartonjs over 4 years
      Sounds like you should just transport the base64, then write the PEM header and footer yourself.
  • anoop.babu
    anoop.babu over 4 years
    OpenSSL CLI is not recognizing CR ('\r') or LF ('\n'). I tried, -----BEGIN CERTIFICATE-----\rBASE64Certificate\r-----END CERTIFICATE----- but OpenSSL CLI is not able to recognize the newline. Not sure OpenSSL treats which symbol as a newline. I am using Ubuntu 18.04.3 LTS.
  • Jakub Jabłoński
    Jakub Jabłoński almost 2 years
    From what I saw it will also replace also values like "\w" into "w" which breaks pem file