Biterra Labs preview / Intro to Cryptography
Before ciphers and encryption, you need encoding. Encoding is not encryption. It is a way to write the same bytes as text so they can travel through systems that expect text.
In CTFs, a lot of "crypto" is one or two clean decodes.
Start by identifying how the data is written. A string is encoding-shaped when its characters, length, or padding match a known format:
626974637466 is hex-shaped because it uses only 0-9 and a-f and splits into pairs.Yml0Y3Rm is Base64-shaped because it uses the Base64 alphabet; longer values may end with = padding.meet at nine is already readable text, so there is no reason to decode it as hex or Base64.These clues identify the outer representation, not what the bytes mean. Base64 or hex can contain readable text, encrypted data, compressed data, or a file. Decode one layer, inspect the result, and then decide what the bytes are.
If the characters and padding match a known encoding, test that representation before assuming encryption.
| Pattern | Likely format | Why | First test |
|---|---|---|---|
Yml0Y3Rme3tleGFtcGxlfX0= | Standard Base64 | Uses letters and digits and ends with = padding | Decode once with Base64 |
eyJyb2xlIjoidmlld2VyIn0 | URL-safe or unpadded Base64 | Looks Base64-shaped but omits padding; URL-safe values may also use - and _ | Add padding if required and use a URL-safe decoder |
6269746374667b7b6578616d706c657d7d | Hex | Uses only 0-9 and a-f, has even length, and splits into byte pairs | Decode once as hex |
These patterns suggest a format; they do not prove it. Decode one layer and inspect the result before choosing another operation.
Standard Base64 uses A-Z, a-z, 0-9, +, /, and = padding. It turns binary into text for things like cookies, JSON, and email. URL-safe Base64 (sometimes called base64url) uses - and _ instead of + and /, and may omit the = padding.
+ / or - _.= only appears at the end (= or ==).=.Yml0Y3Rme3tleGFtcGxlfX0= decodes to bitctf{{example}}.If the string matches these clues, decode it once and inspect the result.
echo Yml0Y3Rme3tleGFtcGxlfX0= | base64 -d
atob("Yml0Y3Rme3tleGFtcGxlfX0=")
import base64
base64.b64decode("Yml0Y3Rme3tleGFtcGxlfX0=")
The Bash command works with GNU coreutils and current macOS; older macOS versions use base64 -D. Browser atob(...) handles the standard alphabet but not - and _. In Python, use base64.urlsafe_b64decode(...) for URL-safe input and add = padding until the length is a multiple of 4 if required.
In CyberChef, add From Base64 to the recipe.
Hex writes each byte as two characters from 0-9 and a-f (or A-F). You will see it in dumps, some challenge files, and hash output.
0-9 and a-f (or A-F). One byte is written as two hex characters, so a value representing whole bytes has even length.6269746374667b7b6578616d706c657d7d decodes to bitctf{{example}}.Split the example into pairs to see the bytes:
62 69 74 63 74 66 7b 7b 65 78 61 6d 70 6c 65 7d 7d
A long hex string is "hex-shaped." After one decode it might be readable text, another encoding, a hash, or binary. The decode tells you which.
echo 6269746374667b7b6578616d706c657d7d | xxd -r -p
const hex = "6269746374667b7b6578616d706c657d7d";
const bytes = Uint8Array.from(
hex.match(/../g).map(byte => Number.parseInt(byte, 16)),
);
new TextDecoder().decode(bytes);
bytes.fromhex("6269746374667b7b6578616d706c657d7d").decode()
Use .decode() when the resulting bytes contain text.
In CyberChef, add From Hex to the recipe. You can also inspect individual values with a hex-to-ASCII converter.
The output decides your next move:
| Result | What it may mean | Next move |
|---|---|---|
| Readable text or a complete flag | The encoding layer is removed | Read it and stop if the task is solved |
| Another Base64- or hex-shaped string | The challenge may contain another encoding layer | Classify and decode the new layer once |
A file signature such as PK or \x89PNG | The decoded bytes belong to a file | Save the bytes and inspect the file type |
| Unreadable bytes | The decode may be wrong, or the result may be compressed, encrypted, or binary data | Recheck the format and challenge clues before trying another operation |
A challenge gives you:
NmM2MTc5NjU3MjczNWY2MTcyNjU1ZjYzNmM3NTY1NzM=
Work through the evidence in order:
= make standard Base64 a reasonable first test.6c61796572735f6172655f636c756573
layers_are_clues
Each operation was supported by the current value. You did not decide in advance to "decode twice"; you classified the output after the first decode.
base64 docsA cookie contains:
eyJyb2xlIjoidmlld2VyIn0
It has letters and numbers but no =, +, or /. Is Base64 still a reasonable first test?
Answer: yes. URL-safe Base64 may omit padding. Add = until the length is a multiple of 4 if the decoder complains, then see whether the bytes look like JSON or other text.
National Treasure Fragment
Classify the representation first.