ReadMyCert picoCTF 2023 Solution

Published: April 26, 2023

Description

A certificate signing request file hides the flag. Treat it as Base64 PEM data and decode the contents to recover the string.

Download the CSR. PEM is just Base64-wrapped DER, so the body decodes back to ASN.1 bytes.

Strip only the PEM tag lines, decode the body, then run the result through strings to ignore length-prefix bytes that surround the flag.

Cross-check with openssl req -text -noout so you know which Subject field hosts the flag.

bash
wget https://artifacts.picoctf.net/c/422/readmycert.csr
bash
sudo apt install -y binutils
bash
sed -n '/^-----/d;p' readmycert.csr | base64 --decode | strings
bash
openssl req -text -noout -in readmycert.csr

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it
Strip the PEM header/footer with sed, then base64-decode the body. For a no-terminal path, paste the middle block into the Base64 & Base32 Decoder. If you want a refresher on common encodings, the CTF encodings guide covers Base64, Hex, ASN.1 framing, and where each shows up in challenges.
  1. Step 1
    Strip the PEM tags and decode the body
    Observation
    I noticed the file extension was .csr and the challenge description mentioned 'Base64 PEM data,' which indicated the flag was encoded in the PEM body between the BEGIN/END marker lines and required stripping those markers before base64 decoding.
    Use sed to drop only the BEGIN/END marker lines, base64-decode the rest, and pipe through strings so the flag survives the binary ASN.1 framing.
    bash
    sed -n '/^-----/d;p' readmycert.csr | base64 --decode | strings | grep picoCTF

    Expected output

    Subject: CN=picoCTF{read_mycert...b0}
    What didn't work first

    Tried: Decode the entire CSR file including the BEGIN/END marker lines through base64 --decode

    The marker lines (-----BEGIN CERTIFICATE REQUEST-----) are not Base64 - they contain hyphens and spaces that are invalid Base64 characters. Feeding them to base64 --decode produces a 'invalid input' error or garbled output. Only the body lines between the markers are Base64-encoded DER, so the markers must be stripped first with sed or grep -v before decoding.

    Tried: Pipe the raw base64 --decode output directly to grep picoCTF without going through strings first

    The flag bytes in DER are prefixed with an ASN.1 tag-length header (e.g. 0c 24), which means the contiguous binary run before picoCTF is not printable. grep -a picoCTF may find the match but could print surrounding binary garbage or miss it entirely if the null-byte framing confuses line-based matching. Running through strings first isolates the printable run cleanly and avoids the binary artifact noise.

    Learn more

    A Certificate Signing Request (CSR) is a structured message sent to a Certificate Authority asking it to issue a TLS certificate. It contains the applicant's public key and identity fields (Common Name, Organization, Country, etc.) encoded in ASN.1 DER, a binary tag-length-value format. The CSR is then wrapped in PEM: Base64-encoded DER between -----BEGIN CERTIFICATE REQUEST----- and -----END CERTIFICATE REQUEST----- markers.

    The flag lives in one of the Subject fields (typically Common Name). When the parser stores that string in DER it prefixes the bytes with an ASN.1 tag and length, e.g. 0c 24 picoCTF{...}. Those framing bytes can crowd the flag in raw output, which is why strings is the right downstream filter: it skips short non-printable runs and surfaces the contiguous flag.

    Why sed -n '/^-----/d;p' instead of grep -v '-----'? The PEM marker lines start with five dashes at column 0. sed's anchored regex is precise; grep -v '-----' would also drop any data line that happens to contain that substring. PEM bodies almost never do, but the anchored form is the habit worth keeping.

  2. Step 2
    Sanity check with openssl
    Observation
    I noticed that piping through strings extracted the flag text but without field labels, which suggested running openssl req -text -noout to confirm exactly which Subject field (such as Common Name) contained the flag and to validate the decode was correct.
    openssl req -text -noout parses the ASN.1 properly and prints each field with its label, so you can confirm which Subject component holds the flag.
    bash
    openssl req -text -noout -in readmycert.csr
    What didn't work first

    Tried: Run openssl x509 -text -noout -in readmycert.csr to inspect the file

    openssl x509 expects a signed certificate (BEGIN CERTIFICATE), not a certificate signing request (BEGIN CERTIFICATE REQUEST). Running x509 on a CSR produces 'unable to load certificate' or a parsing error. The correct subcommand for CSRs is openssl req, which understands the PKCS#10 structure that wraps the Subject and public key.

    Tried: Omit the -noout flag and run openssl req -text -in readmycert.csr

    Without -noout, openssl also outputs the PEM block at the end of the text dump, which is harmless but clutters the terminal. More importantly, some users then try to re-decode that PEM output thinking it contains additional data - it does not, it is just the same CSR reprinted. The -noout flag suppresses this redundant PEM trailer and keeps the output focused on the human-readable field breakdown.

    Learn more

    Running the parsed view alongside the raw decode is the workflow worth internalising. openssl req -text -noout gives you the structured field names (CN, O, OU, emailAddress) so you know whether the flag was stored in the Common Name, an Organizational Unit, or an extension. That structural knowledge is what generalises to real PKI work, where you might be looking for a Subject Alternative Name in a certificate or a particular OID in a custom extension.

    Understanding PEM, DER, and ASN.1 pays off well beyond CTFs: TLS, code signing, SSH keys, JWTs, and S/MIME all sit on this stack. The openssl CLI inspects and converts between every variant.

  3. Step 3
    Alternate path: cfssl or browser export
    Observation
    I noticed that some environments may not have openssl installed, which suggested documenting cfssl certinfo as a drop-in alternative that parses the same PKCS#10 structure and emits the Subject fields in JSON.
    If openssl is not installed, cfssl certinfo -csr readmycert.csr also dumps the parsed fields. Browsers can export PEM-formatted certificates from any HTTPS site for practice.
    Learn more

    cfssl (CloudFlare's SSL toolkit) ships a certinfo subcommand that reads CSRs and certificates and emits JSON. cfssl certinfo -csr readmycert.csr gives you the same Subject breakdown openssl shows, in a format easy to grep or pipe into jq. The browser angle: in Firefox or Chrome the certificate viewer (lock icon → details) lets you export the live cert as PEM, then this same workflow inspects it.

Interactive tools
  • Base64 & Base32 DecoderDecode Base64 and Base32 strings with auto-detection. Multi-layer mode unwraps nested encodings automatically.
  • Recipe ChainStack decoders into a pipeline: Base64, hex, ROT, XOR, Morse, URL, Atbash, Vigenère, and more. Magic mode auto-discovers the chain. Bookmark the URL to save it.
  • Number Base ConverterConvert numbers between binary, octal, decimal, and hexadecimal instantly. Enter any value and see all four bases update in real time.

Flag

Reveal flag

picoCTF{read_mycert...b0}

No openssl tooling is required; basic Base64 decoding reveals the answer.

Key takeaway

X.509 certificates and certificate signing requests use a layered encoding stack: ASN.1 defines the data structure, DER serializes it to binary tag-length-value bytes, and PEM wraps those bytes in Base64 with BEGIN/END header lines for safe text transport. Every layer is reversible with standard tools, so any data embedded in a Subject field, extension, or public key component is fully recoverable from the file alone. This same stack underlies TLS, SSH keys, code signing, S/MIME, and JWTs, making PEM and openssl fluency broadly useful across real-world security work.

Related reading

Want more picoCTF 2023 writeups?

Useful tools for Cryptography

What to try next