# Bitchat Android Binary Protocol Packet Header: Key Fields and Structure

> Explore the Bitchat Android binary protocol packet header. Learn about key fields like Version, Type, TTL, Timestamp, Flags, and PayloadLength in this essential guide.

- Repository: [permissionlesstech/bitchat-android](https://github.com/permissionlesstech/bitchat-android)
- Tags: deep-dive
- Published: 2026-07-28

---

**The Bitchat Android binary protocol packet header is a fixed big-endian structure of either 14 bytes (v1) or 16 bytes (v2) that contains the Version, Type, TTL, Timestamp, Flags, and PayloadLength fields, after which variable sections such as sender ID, recipient ID, route, payload, and signature may follow depending on flag bits.**

The `permissionlesstech/bitchat-android` repository implements a peer-to-peer messaging protocol that remains fully compatible with its iOS counterpart. The Bitchat Android binary protocol packet header sits at the start of every transmitted packet and dictates how the rest of the byte stream is parsed. Its layout, constants, and encode-decode logic are defined in [`app/src/main/java/com/bitchat/android/protocol/BinaryProtocol.kt`](https://github.com/permissionlesstech/bitchat-android/blob/main/app/src/main/java/com/bitchat/android/protocol/BinaryProtocol.kt) (lines 39–46).

## Fixed Header Layout

The fixed header uses big-endian byte order and occupies either **14 bytes** for version 1 or **16 bytes** for version 2.

| Offset | Size | Field | Description |
|--------|------|-------|-------------|
| 0 | 1 | **Version** | Protocol version (`1u` or `2u`). Determines header size and PayloadLength width. |
| 1 | 1 | **Type** | Message type such as `MessageType.MESSAGE` or `MessageType.FRAGMENT`. |
| 2 | 1 | **TTL** | Time-to-live hop count. |
| 3 | 8 | **Timestamp** | Unix epoch milliseconds as an unsigned 64-bit integer (`ULong`). |
| 11 | 1 | **Flags** | Bit-field controlling optional sections (see below). |
| 12 | 2 (v1) / 4 (v2) | **PayloadLength** | Length of the payload, including compression overhead. |

### Version

The first byte specifies the protocol version. A value of `1u` produces a 14-byte header, while `2u` produces a 16-byte header and widens the PayloadLength field to four bytes.

### Type

The second byte stores the message type identifier. This field uses the same enumeration values as the iOS implementation so that cross-platform peers can interpret packets consistently.

### TTL

The third byte holds the time-to-live counter. Each forwarding node decrements this hop count until the packet expires.

### Timestamp

Bytes 3 through 10 encode an unsigned 64-bit Unix timestamp in milliseconds. This `ULong` value lets peers evaluate message age and order.

### Flags

Byte 11 is a bit-field defined in [`BinaryProtocol.kt`](https://github.com/permissionlesstech/bitchat-android/blob/main/BinaryProtocol.kt) that signals which variable sections follow the header:

- **Bit 0** — `HAS_RECIPIENT` (recipient ID present)
- **Bit 1** — `HAS_SIGNATURE` (signature present)
- **Bit 2** — `IS_COMPRESSED` (payload is compressed)
- **Bit 3** — `HAS_ROUTE` (source-route present; v2 only)

### PayloadLength

Starting at byte 12, this field is two bytes wide in v1 and four bytes wide in v2. It stores the length of the payload that follows the header, including any extra bytes prepended when compression is active.

## Variable Sections

After the fixed header, the parser reads optional blocks in a deterministic order. Their presence is determined by the flags byte. As implemented in `permissionlesstech/bitchat-android`, these sections are:

- **Sender ID**
- **Recipient ID** (if `HAS_RECIPIENT` is set)
- **Route** (if `HAS_ROUTE` is set; v2+)
- **Payload**
- **Signature** (if `HAS_SIGNATURE` is set)

## Encoding and Decoding Examples

### Encoding a v1 Packet

```kotlin
import com.bitchat.android.protocol.*

val packet = BitchatPacket(
    type = MessageType.MESSAGE.value,
    senderID = hexStringToByteArray("a1b2c3d4e5f60708"),
    timestamp = System.currentTimeMillis().toULong(),
    payload = "Hello, world!".toByteArray(),
    ttl = 5u,                     // 5 hops
    version = 1u                 // v1 → 14‑byte header
)

val binary = packet.toBinaryData()   // uses BinaryProtocol.encode
// `binary` now contains the 14‑byte header followed by sender ID, payload, etc.

```

### Decoding Received Data

```kotlin
val received: ByteArray = ... // from BLE or Tor transport
val decoded = BitchatPacket.fromBinaryData(received)

if (decoded != null) {
    println("Version: ${decoded.version}")
    println("Type: ${decoded.type}")
    println("TTL: ${decoded.ttl}")
    println("Payload (${decoded.payload.size} bytes): ${String(decoded.payload)}")
}

```

### Inspecting Header Bytes Manually

```kotlin
val header = binary.copyOfRange(0, if (binary[0] == 1.toByte()) 14 else 16)

val version = header[0].toUByte()
val type = header[1].toUByte()
val ttl = header[2].toUByte()
val timestamp = ByteBuffer.wrap(header, 3, 8).order(ByteOrder.BIG_ENDIAN).long.toULong()
val flags = header[11].toUByte()
val payloadLen = if (version == 1u.toUByte()) {
    ByteBuffer.wrap(header, 12, 2).order(ByteOrder.BIG_ENDIAN).short.toInt()
} else {
    ByteBuffer.wrap(header, 12, 4).order(ByteOrder.BIG_ENDIAN).int
}

```

## Key Source Files

- **[`app/src/main/java/com/bitchat/android/protocol/BinaryProtocol.kt`](https://github.com/permissionlesstech/bitchat-android/blob/main/app/src/main/java/com/bitchat/android/protocol/BinaryProtocol.kt)** (lines 39–46) — Defines the header layout, flag constants, and size logic; also hosts the `BitchatPacket` data class (lines 54–64).
- **[`app/src/main/java/com/bitchat/android/model/FragmentPayload.kt`](https://github.com/permissionlesstech/bitchat-android/blob/main/app/src/main/java/com/bitchat/android/model/FragmentPayload.kt)** — Contains the 13-byte fragment-payload header used when large packets are split.
- **[`app/src/main/java/com/bitchat/android/protocol/MessagePadding.kt`](https://github.com/permissionlesstech/bitchat-android/blob/main/app/src/main/java/com/bitchat/android/protocol/MessagePadding.kt)** — Implements iOS-compatible padding after the header, interacting with header size calculations.

## Summary

- The **Bitchat Android binary protocol packet header** is a fixed big-endian structure of **14 bytes (v1)** or **16 bytes (v2)**.
- It contains six sequential fields: **Version**, **Type**, **TTL**, **Timestamp**, **Flags**, and **PayloadLength**.
- The **Flags** byte at offset 11 determines which optional sections—recipient ID, route, payload, or signature—appear after the header.
- **[`BinaryProtocol.kt`](https://github.com/permissionlesstech/bitchat-android/blob/main/BinaryProtocol.kt)** in `permissionlesstech/bitchat-android` is the authoritative source for layout constants and encode/decode routines.

## Frequently Asked Questions

### What is the total size of the Bitchat Android binary protocol packet header?

The fixed header is **14 bytes** for version 1 and **16 bytes** for version 2. The size difference comes from the PayloadLength field, which expands from 2 bytes to 4 bytes in v2.

### How does the Flags field affect packet parsing?

Byte 11 is a bit-field that tells the parser which optional blocks follow the fixed header. For example, if bit 0 (`HAS_RECIPIENT`) is set, the parser expects a recipient ID immediately after the sender ID. If bit 3 (`HAS_ROUTE`) is set and the version is 2 or higher, a source-route block is present before the payload.

### What is the difference between v1 and v2 packet headers?

Version 2 extends the PayloadLength field from 2 bytes to 4 bytes and introduces the `HAS_ROUTE` flag in bit 3. Otherwise, the field order and semantics remain identical to maintain backward compatibility.

### Where is the packet header defined in the source code?

The layout, constants, and encode/decode logic are defined in [`app/src/main/java/com/bitchat/android/protocol/BinaryProtocol.kt`](https://github.com/permissionlesstech/bitchat-android/blob/main/app/src/main/java/com/bitchat/android/protocol/BinaryProtocol.kt) in the `permissionlesstech/bitchat-android` repository. The `BitchatPacket` data class declared inside that file (around lines 54–64) holds the header values and payload.