PEM, Not JPG: Spotting a Private Key Behind an Image Extension

Cryptography Level 2/4 ~3 min August 29, 2026

The challenge

A file named avatar.jpg was found in a web app's uploads folder, but it never renders as a photo. Open it in the hex viewer, read the first bytes as text, compare them to the reference signatures, and type the real file type.

What you'll learn

  • Read leading bytes as ASCII and recognise the '-----BEGIN' PEM header
  • Explain that PEM is a base64 text wrapper for keys, certificates, and CSRs
  • Recognise the 'MIIE' base64 prefix as the start of a DER-encoded key
  • Explain why a JPEG cannot start with printable text (it begins FF D8 FF)
  • Distinguish PEM from JPEG, PNG, and GZIP by their first bytes

Skills tested

PEM / private key recognitionASCII signature readingSecret-leak triage

Prerequisites

  • Basic familiarity with private keys and certificates
  • Comfort converting hex bytes to their ASCII characters

How it works

Not every signature is binary. PEM (Privacy-Enhanced Mail) is a text format that wraps binary cryptographic material - private keys, certificates, certificate signing requests - in base64 lines bracketed by human-readable header and footer lines. Every PEM block opens with five dashes, the word BEGIN, a label, and five more dashes, for example -----BEGIN PRIVATE KEY-----.

In this file the bytes 2D 2D 2D 2D 2D are five hyphens, 42 45 47 49 4E is BEGIN, and the rest spell PRIVATE KEY----- followed by a newline and a base64 line beginning MIIE. That MIIE prefix is the tell-tale start of a DER-encoded RSA/PKCS key once base64-encoded. So the whole file is printable text - a PEM-wrapped private key.

A real JPEG would start with FF D8 FF, bytes that are not printable text at all, so the .jpg name is a disguise. The reference list contrasts the PEM dash signature with JPEG (FF D8 FF), PNG (89 50 4E 47), and GZIP (1F 8B). Only the dashes match. A private key sitting in a web app's uploads folder is a serious exposure: anyone who can read it can impersonate the server or decrypt its traffic.

Common mistakes

  • Trusting the .jpg extension. The name says image, but JPEGs begin FF D8 FF, not printable dashes.
  • Reading only hex and skipping ASCII. The fastest path is to read the bytes as text, where -----BEGIN jumps out.
  • Calling it 'just a text file'. It is text, but the specific format with the BEGIN/END wrapper is PEM, and it contains a private key.
  • Confusing PEM with DER. DER is the raw binary; PEM is the base64-and-dashes text wrapper you are looking at here.

How to defend against it

Private keys must never live in user-reachable storage, and uploads must be validated by real content type.

  • Scan upload and asset directories for PEM headers (-----BEGIN) and other secret patterns, and alert on any match.
  • Validate uploads by magic bytes against the allowed types, rejecting anything that is not the expected image format.
  • Keep private keys in a secrets manager or restricted key store, never in a web-served folder, and rotate any key that has been exposed.
  • Serve user uploads from a separate domain or with a forced download content type so a leaked key is never executed or interpreted in app context.

Full solution

Pro and Max members unlock the complete step-by-step walkthrough.

Go Pro

Community stats

138 completions
88% success rate
Malekith First blood

Related Daily Hacks

23,000+ Hackers 100+ Labs & Courses Free
Start Hacking Free