A system may need to carry file bytes through a place that accepts text. An encoding gives those bytes a form that can travel there. Decoding reverses that representation. You will follow one declared Base64 decode and keep the operation separate from a claim of secrecy.
Hex writes each byte as two hex digits. Base64 groups the bits into six-bit values and looks each value up in an alphabet of 64 symbols. A six-bit group is sometimes called a sextet. Standard Base64 uses letters, digits, +, and /; = can appear at the end as padding to complete a group.
Percent-encoding is another representation used in a URI, a structured identifier such as a web address. It writes a byte, also called an octet, as % followed by two hex digits. Thus %20 represents the space byte. A form may represent a space with + under a different rule. Always identify the declared operation before reversing a string.
Before you begin
- Recommended first
- An editor that works under pressure, Reading and making files, A script that does one real chore, ASCII and Unicode
- Estimated time
- 15 min reading, 15 min activity. Setup and optional practice may take longer.
- Where you work
- Read and trace the supplied source and input in your browser. A later optional run uses Python 3.12 and its standard library in a fresh directory under your own ~/yanosec-lab. The ~ means your home directory. Keep paired files together and avoid overwriting existing work. No extra packages or network calls are required.
- Without a lab
- Follow each source line against the supplied input and predicted trace. You can complete the same reasoning without running Python; the practical run can wait. Earlier recorded Python results are labeled separately from predictions. Reading works without JavaScript. Answer checking needs JavaScript and a secure context; saving additionally needs usable browser storage.
After this lesson you can:
- Decode a short value whose operation is declared.
- Name hex, Base64, and URI percent-encoding as representations.
- Explain why a public reverse step does not provide secrecy.
01Example
The worked input is the two ASCII bytes 68 69, the letters hi. Their sixteen bits are grouped into six-bit values for Base64; the final group is filled with zero bits to reach six. The alphabet maps indexes 26, 6, and 36 to a, G, and k, and = records the padding. This is a hand grouping, not a tool transcript.
Bytes: 68 69
UTF-8 letters: hi
Bits: 01101000 01101001
Sextets: 011010 000110 100100
Indexes: 26, 6, 36
Base64: aGk=
Percent-encoding is a different operation. %20 means the space octet, not these two bytes.02Encoding is reversible on purpose
Encoding is useful because its reverse rule is available to anyone who needs the bytes. In Base64, knowing the alphabet and padding rules is enough to decode. Encryption serves a different purpose: it uses a key to protect a message. Reversing Base64 is decoding, even if the original text was unfamiliar.
The declared variant matters. Standard Base64 and URL-safe Base64 use different symbols for two alphabet entries. Some systems omit padding because their surrounding format already determines the length. For this activity, use the standard alphabet and the padding as supplied. A failed decode is a reason to inspect that declaration before trying unrelated transforms.
The hi bytes 68 69 regroup into Base64 sextets and aGk=; two added zero bits and the = padding notation remain explicit.Model. A teaching model drawn by hand. It shows the idea, not real tool output.
Read the full explanation below.
Playback is optional. Step through at your own pace.
Source bytes
68 69011010index 26a000110index 6G100100index 36k2 pad bitsaGk=bytes
UTF-8 hi is two source bytes 68 69.
Follow the explanation
- UTF-8 hi is two source bytes 68 69.
- Expand the bytes to 01101000 01101001, retaining their boundaries.
- Six-bit groups cross the byte boundary: 011010 000110 100100; last two bits are padding.
- The sextet indices are 26, 6 and 36.
- Indices select a, G and k; = marks padding, giving aGk=.
- The public reverse rule recovers 68 69 and hi; this is not secrecy.
Read every state and value
1. UTF-8 hi is two source bytes 68 69.
- Stage
- bytes
- Selected Group
- Not established
2. Expand the bytes to 01101000 01101001, retaining their boundaries.
- Stage
- bits
- Selected Group
- Not established
3. Six-bit groups cross the byte boundary: 011010 000110 100100; last two bits are padding.
- Stage
- sextets
- Selected Group
- 2
4. The sextet indices are 26, 6 and 36.
- Stage
- indices
- Selected Group
- 1
5. Indices select a, G and k; = marks padding, giving aGk=.
- Stage
- encoded
- Selected Group
- 2
6. The public reverse rule recovers 68 69 and hi; this is not secrecy.
- Stage
- reverse
- Selected Group
- Not established
03Decode one declared Base64 value
Use b2s= as the fresh input. The worksheet supplies its alphabet values and the regrouped bits. Cover the result lines while you make your prediction. The optional CyberChef card names the same operation, but no application is required.
YanoSec / Code
Hand grouping from RFC 4648 and RFC 3986.
A six-bit group is a sextet. Regroup into eight-bit bytes after decoding.
Worked bytes: 68 69
UTF-8 letters: hi
Standard Base64 of those bytes: aGk=
The final = is padding. It is not a third letter of hi.
URI percent-encoding: %20 is the octet 20 hex, which is a space in US-ASCII.
That is a URI rule. It is not a rule for every form body.
Activity input: b2s=
Operation name: standard Base64 decode. This is not decryption.
b is 011011, 2 is 110110, s is 101100
Regrouped bytes: 01101111 01101011
Hex: 6f 6b
UTF-8 letters: ok
Record the input, the named operation, and the recovered bytes.
YanoSec / Code
Optional helper card. You can finish this recipe on paper.
The full CyberChef lesson is Stage 08.
Operation name in the CyberChef source: From Base64
Input: b2s=
Alphabet: standard Base64, with digits, letters, +, /, and = padding
Do not select an encryption operation and do not change the alphabet.
If a later build uses another name, stop and use the hand grouping in encoding-cards.txt.
- Write the operation beside b2s=: standard Base64 decode. This fixes the alphabet you will use.
- Read the supplied six-bit groups for b, 2, and s. Join them, then keep the first sixteen bits because the final = marks a padded group. Split them into two groups of eight.
- Compare your result with 01101111 01101011, or hex 6f 6b. These ASCII bytes spell ok. The byte interpretation follows the Base64 operation; it is a separate step.
- Record the input, operation, and resulting bytes, then stop. A previous Python 3.12.3 run recorded the same bytes with base64.b64decode; the worksheet remains enough to follow the reasoning.
04Optional challenge
Spend about ten extra minutes grouping the declared hex 6f6b into pairs. It should give 6f 6b, the same two bytes as the Base64 activity. Explain why two different written representations can recover identical data.
05Fresh cases for the checks
Use these fictional cases for the checks below. They have different inputs from the worked examples. Read them here or make notes; no installation or external service is needed.
Encoding case AOwned fixture. An original file made for this course. Follow the activity's instructions in your own lab.
Declared operation: standard Base64 decode. Input: dXA=.
d = 011101; X = 010111; A = 000000.
Join these groups and keep the first sixteen bits because the final = marks padding.
Byte table: 01110101 is hex 75 and ASCII u; 01110000 is hex 70 and ASCII p.
Encoding case BOwned fixture. An original file made for this course. Follow the activity's instructions in your own lab.
An independent exported field is %2F. Its source declares URI percent-encoding, where each % followed by two hex digits represents that byte. Byte 2f is the slash character. No key is used.
06Explain your prediction
Optional written self-check: Record the exact input, declared operation and recovered bytes. Explain any later text interpretation separately, and do not infer authenticity or secrecy merely from a successful decode.
07Common mistakes
If a decoder gives an unexpected result, compare the declared alphabet, copied characters, and padding first. Changing operations until something looks readable does not establish which encoding the source used.
If you count = as a message character after Base64 decoding, revisit the final bit group. The equals sign records padding; it does not become a third letter of hi or ok.
If you replace every + with a space, stop and identify the surrounding format. That rule belongs to form encoding and is not the standard Base64 rule.
References
- RFC 4648: The Base16, Base32, and Base64 Data Encodings
Sections 3 and 4 define Base64 padding and its standard alphabet.
- RFC 3986: Percent-encoding
Section 2.1 defines % followed by two hex digits for an octet.
- Python 3.12: base64
Documents the standard Base64 encode and decode functions and their alternative-alphabet arguments.
- CyberChef source: From Base64
Names the optional decoding operation. This master-branch source is not a pinned application release.