Bytes, hex & cryptographic trust

Read binary data and separate hashes, signatures, encryption, and trust.

10 min readChapter 6 of 50Beginner
In this chapter

Android boot and security material names image bytes, offsets, hashes, signatures, keys, and rollback indexes. This lesson supplies the small data-representation model needed to read those claims without treating a hex string as magic. It uses a tiny synthetic file—not a real boot image—and standard-library Python as a provided inspection utility. You do not need to learn Python first.

Before you start#

Read C and C++ for Android source readers. You should be comfortable with a terminal and a text file. The lab uses Python 3, but the program is supplied as a utility; it does not require Python programming knowledge. Do not use real keys, credentials, firmware images, or a personal device for this exercise.

Learning goals#

You should be able to convert small binary/decimal/hex values, distinguish byte offsets from values, calculate a field's value under explicitly stated endianness, inspect a harmless file and its SHA-256 digest, and describe what a hash, signature, encryption, and rollback protection can and cannot establish. This is security literacy, not cryptography implementation.

Bits, bytes, and units

A bit is one binary digit, either 0 or 1. Eight bits make a byte. A byte can represent 256 possible values, from decimal 0 through 255 (0x00 through 0xff). For example, decimal 10 is binary 00001010 and hexadecimal 0x0a. Hexadecimal (base 16) uses digits 0–9 and a–f; 0x is a common notation prefix. Each hex digit represents four bits, so two hex digits describe one byte.

Storage units need context. SI kilobyte is 1,000 bytes; a kibibyte (KiB) is 1,024 bytes (NIST binary prefixes). Software interfaces and human-written documentation sometimes use “KB” loosely, so state the unit when a size matters. This lab's file is 13 bytes, or 13 × 8 = 104 bits.

Offsets and endianness

An offset counts byte positions from a defined start, usually zero at the first byte of a file or buffer. It is not itself a value stored in the file. In a byte display, offset 0x00 labels the first byte, 0x01 the next, and so on. Reading bytes requires a format specification: where fields begin, how long they are, which byte order to use, and whether padding exists.

Suppose two bytes encode decimal 0x1234. Big-endian stores the most significant byte first: 12 34. Little-endian stores the least significant byte first: 34 12. Neither is inherently more secure; the format defines which interpretation is correct. Real Android boot formats and host CPU representation are not interchangeable assumptions. AOSP's boot-image documentation describes structured headers and version-dependent layouts; do not infer a partition format from a filename alone. Android boot image header

Four different trust questions

Four separate trust questions
Hash → byte comparison
Does this content match a trusted expected digest? An untrusted digest does not establish origin.
Signature → key authentication
Does valid signed data match a key and policy the verifier accepts?
Rollback policy → freshness
Is the signed version at least the stored permitted minimum?
Encryption → confidentiality
Can a reader obtain the required decryption key under the relevant policy?
Conceptual model. These are independent properties, not stages or a security ranking. A signature authenticates under a trusted-key policy; it does not hide content or prove code safe.

A checksum such as a CRC is primarily designed to find accidental corruption; it is not an identity/authenticity check against an active attacker. A cryptographic hash maps data to a fixed-length digest. If you compare a file's digest with a trusted expected digest, a mismatch is evidence that the bytes differ. A digest written beside an untrusted download is not proof of who supplied either item: an attacker could replace both. NIST describes security properties such as preimage and collision resistance for approved hash functions; none makes a digest secret or an identity by itself. NIST hash-function glossary

A digital signature uses a private signing key and a corresponding public verification key. Verification can establish that the signed data matches the signature and that it was produced by whoever controls the corresponding private key—assuming the public key is trusted, the scheme and implementation are sound, and policy accepts it. A signature does not hide the content. It does not prove that the signed program is bug-free or harmless. A certificate can bind a public key to an identity under an issuer's rules; trust still depends on verifying the chain and policy.

Encryption transforms data so that a party without the needed key should not be able to read it. Its principal goal is confidentiality; authenticated encryption can also detect tampering under its defined model. Encryption does not prove the sender's identity unless the protocol adds authentication. A trust root is the key or policy at the starting point of a verification chain. Android Verified Boot checks a chain rooted in device trust material and also has rollback protection; a successful signature check alone is not the same as checking that the version is not too old. AOSP Verified Boot overview

Keep these questions separate: Are bytes unchanged relative to a known digest? Were they signed by a key I trust? Are they permitted by version/rollback policy? Are they confidential to unauthorized readers? Each requires different evidence. NIST's digital-signature glossary lists origin authentication, data integrity, and signatory non-repudiation as signature services; confidentiality is not in that list.

Practice#

The 13-byte teaching record

Synthetic teaching data, not a device capture.

Select a field to connect its position, bytes, and meaning.

13 bytes in file order. Offsets start at zero.

Selected: Marker. ASCII LAB1.

Read the byte table
OffsetFieldHex bytesInterpretation
0Marker4c 41 42 31ASCII LAB1
4Little-endian34 120x1234 = 4660
6Big-endian00 050x0005 = 5
8Text68 65 6c 6c 6fASCII hello
Synthetic teaching data. Exact bytes from toy.bin below. Offsets count from zero; field interpretation comes from the declared format, not the printable-character view.

Host-only, source-free, and harmless: in a newly created empty practice directory, create a synthetic record. Do not point the script at an existing file; it deliberately writes toy.bin. If that name already exists, stop and choose a new empty directory rather than overwriting it. From your workstation shell:

sh
mkdir "$HOME/android-bytes-YOURNAME"
cd "$HOME/android-bytes-YOURNAME"

Create the file with the Python 3 standard library. The first four bytes are a teaching marker LAB1; bytes 4–5 hold the number 0x1234 in little-endian order; bytes 6–7 hold the number 5 in big-endian order; the last five bytes spell hello in ASCII. Python's struct module is used with explicit < and > order instead of the host's native layout. Python struct documentation

sh
python3 - <<'PY'
from pathlib import Path
import struct

record = b"LAB1" + struct.pack("<H", 0x1234) + struct.pack(">H", 5) + b"hello"
Path("toy.bin").write_bytes(record)
print("length:", len(record))
print("hex:", record.hex(" "))
for offset in range(0, len(record), 8):
    chunk = record[offset:offset + 8]
    text = "".join(chr(byte) if 32 <= byte <= 126 else "." for byte in chunk)
    print(f"{offset:04x}: {chunk.hex(' '):<23} {text}")
print("field at offset 4, little-endian:", struct.unpack_from("<H", record, 4)[0])
print("field at offset 6, big-endian:", struct.unpack_from(">H", record, 6)[0])
PY

Expected output:

text
length: 13
hex: 4c 41 42 31 34 12 00 05 68 65 6c 6c 6f
0000: 4c 41 42 31 34 12 00 05 LAB14...
0008: 68 65 6c 6c 6f          hello
field at offset 4, little-endian: 4660
field at offset 6, big-endian: 5

At offset 4, bytes 34 12 become 0x1234, decimal 4660, when interpreted little-endian. At offset 6, 00 05 becomes decimal 5 in big-endian. The ASCII column maps printable bytes to characters and uses a dot for non-printable bytes; it is a display, not another copy of the file. If output differs, check the exact code and Python version before changing the expected value.

Notice that the marker is followed by the byte 0x34, which happens to be the printable ASCII character 4; that is why the display reads LAB14..., not simply LAB1..... A hex view is authoritative for the byte values in this exercise; the text view is only a convenience for spotting readable regions. Real binary formats can contain arbitrary bytes, including zero bytes and text that resembles a marker by coincidence.

Now compute a digest, still using Python's standard library:

sh
python3 - <<'PY'
from hashlib import sha256
from pathlib import Path
print(sha256(Path("toy.bin").read_bytes()).hexdigest())
PY

Expected SHA-256 for these exact 13 bytes (FIPS 180-4, Secure Hash Standard):

text
715897a6ec3a078955432a2493214714f70cf7aa9d312c8ee61d5626db70b7eb

This checks your generated artifact against the stated expected bytes. To demonstrate change detection, alter exactly one byte in a copy of the file (not a real image), then compute both digests; they should differ. Never conclude that a download is authentic just because its hash matches a digest obtained from the same untrusted download page. Python documents hashlib.sha256 as a digest interface; it does not establish a trust source for a comparison value. Python hashlib

Transfer to Android: Android Verified Boot's AVB0 magic is the first four bytes of a vbmeta image header, not a signature check by itself. The Android 14 source defines AVB_MAGIC in libavb/avb_vbmeta_image.h; the separate avb_vbmeta_image_verify() path checks header/version and reports unsigned, digest-mismatch, and signature-mismatch cases separately. AOSP 14 AVB_MAGIC · AOSP 14 avb_vbmeta_image_verify() A boot verifier considers structure, signatures, keys, descriptors, device state, and policy. The Android 14 avb_slot_verify.c path compares an image's rollback index with the device-stored value and rejects a lower value (unless the caller allows verification errors to continue), even if the image signature verifies. AOSP 14 rollback-index check Encryption of user files is a separate confidentiality mechanism; it does not authenticate boot code. AOSP documents these boundaries, while exact device layouts and trust anchors vary.

Knowledge check#

Before reading the answers, annotate the 13-byte record with offsets, the two integer fields, and the text bytes. If the bytes at offset 4 were mistakenly parsed big-endian, what number would result? A download and a separately published digest match: what is proven, and what is not, if both came from the same untrusted server? Which property—integrity, authenticity, rollback resistance, or confidentiality—does each of a hash, trusted signature, minimum-version check, and encryption primarily address? Identify one fact a checksum alone cannot prove.

Answers#

Offset 4 contains 34 12; reading big-endian yields 0x3412, decimal 13330, rather than 0x1234. The matching digest proves only that the checked bytes match that digest value; if both came from the same untrusted server, it does not establish an independent trusted origin. A trusted signature can support integrity and authenticity, a rollback minimum addresses stale-version acceptance, and encryption addresses confidentiality; the exact protocol may combine properties. A checksum cannot prove who created the bytes or whether they are safe.

Checkpoint#

Keep toy.bin, the displayed hex/offset annotation, and a short trust table: mechanism, property, assumption, and one thing it does not prove. Ready: you can correctly decode both fields with stated byte order and explain why a same-source hash is not authentication. Revise: if a value is wrong, recalculate the bytes by grouping each pair of hex digits and checking the field's offset/width/order. Not yet evidenced: if Python is unavailable, annotate the displayed expected record by hand; record that the local artifact/hash run was not completed. This is data-reading practice, not cryptographic or AVB implementation expertise.

Sources#

A little further beneath the surface.

Check your understanding with the checkpoint. Marking a chapter as read saves a bookmark, not a proficiency assessment.