What Encryption Protocol Is Used for End-to-End Encryption in the BLE Mesh Transport?
The BLE mesh transport in bitchat implements end-to-end encryption using the Noise Protocol framework (specifically the Noise_XX handshake pattern) combined with XChaCha20-Poly1305 authenticated encryption.
The permissionlesstech/bitchat repository provides a peer-to-peer messaging system that utilizes Bluetooth Low Energy (BLE) mesh networking for decentralized communication. Understanding what encryption protocol is used for end-to-end encryption in the BLE mesh transport reveals a sophisticated cryptographic architecture designed to ensure both confidentiality and authentication while maintaining forward secrecy.
Noise Protocol Framework with XChaCha20-Poly1305
The bitchat implementation relies on the Noise Protocol framework rather than traditional TLS or custom cryptographic implementations. This choice provides formal security guarantees and resistance to common cryptographic pitfalls.
According to the source code in bitchat/BLENoisePayloadFactory.swift and the architectural documentation in docs/BLE-ARCHITECTURE-V3.md, the system employs a layered approach:
- Noise_XX handshake pattern for Initial key exchange and session establishment
- X25519 (Curve25519) elliptic curve keys for ephemeral and static key exchange
- XChaCha20-Poly1305 as the AEAD (Authenticated Encryption with Associated Data) construction for payload encryption
The Noise_XX Handshake Pattern
The Noise_XX pattern is a specific handshake sequence within the Noise Protocol framework that provides strong identity hiding and forward secrecy. In bitchat/BLEService+LinkLayerCentralRole.swift, each peer generates an X25519 key pair during session initialization.
The handshake process establishes a shared secret between communicating devices without transmitting the actual keys over the air. This ensures that even if session keys are compromised in the future, past communications remain secure—a property known as forward secrecy.
Payload Encryption with XChaCha20-Poly1305
Once the Noise_XX handshake completes, the derived shared secret feeds into the XChaCha20-Poly1305 AEAD construction. This modern cryptographic primitive provides both confidentiality (encryption) and integrity (authentication) in a single operation.
The encrypted payloads are then wrapped in outer packets signed with the peer's Ed25519 identity key. This dual-layer approach ensures that while the Ed25519 signature provides sender authentication and non-repudiation, the Noise-derived encryption guarantees that the payload content remains confidential even if the signature keys are later compromised.
Implementation in the Bitchat Codebase
The encryption logic is distributed across several key files in the repository, demonstrating a clean separation between the cryptographic primitives and the BLE transport layer.
Key Exchange and Session Establishment
In bitchat/BLEService+LinkLayerCentralRole.swift, the BLE transport layer integrates with the BLENoisePayloadFactory to handle the cryptographic handshake. When establishing a connection, the service initializes the Noise_XX handshake state and manages the transition from plaintext to encrypted communication.
The test suite in bitchatTests/Services/NoiseEncryptionServiceTests.swift validates the correctness of this implementation, ensuring that payloads encrypted by one peer can be successfully decrypted by the intended recipient using the shared secrets derived during the Noise handshake.
Packet Signing and Identity Verification
While the Noise protocol handles session encryption, bitchat adds an additional layer of security using Ed25519 signatures. Each outer packet carries a self-signature from the sender's identity key, binding the Noise payload to the correct sender.
This architecture means that the BLE transport itself cannot inspect the interior payload—it merely routes the encrypted blob. Only the intended recipient possessing the correct session keys can decrypt the content using the BLENoisePayloadFactory decryption methods.
Practical Usage Example
The following Swift code demonstrates how the bitchat SDK handles encrypted file transfers over the BLE mesh transport:
// Create a Noise payload for a private file (used by the BLE mesh)
let fileData = try Data(contentsOf: fileURL)
let encryptedPayload = try BLENoisePayloadFactory.privateFile(fileData)
// Send the encrypted payload through the BLE service
bleService.send(payload: encryptedPayload, to: destinationPeer)
// On the receiving side the payload is decrypted automatically
let receivedPayload = try bleService.receive()
let plainFile = try BLENoisePayloadFactory.decrypt(receivedPayload)
The BLENoisePayloadFactory.privateFile(_:) method constructs a payload using the Noise_XX handshake parameters and encrypts the content with XChaCha20-Poly1305. The bleService.send(payload:to:) method then passes this encrypted blob to the BLE transport layer without exposing the plaintext content to the mesh intermediaries.
Upon receipt, BLENoisePayloadFactory.decrypt(_:) reverses the Noise handshake process to derive the same shared secret and decrypt the payload, returning the original file data only to the authorized recipient.
Summary
- bitchat uses the Noise Protocol framework with the Noise_XX handshake pattern for BLE mesh encryption.
- X25519 (Curve25519) provides the underlying elliptic curve cryptography for key exchange.
- XChaCha20-Poly1305 handles authenticated encryption of message payloads.
- The implementation spans
bitchat/BLENoicePayloadFactory.swift,bitchat/BLEService+LinkLayerCentralRole.swift, and related test files. - Ed25519 signatures provide outer packet authentication while Noise provides end-to-end confidentiality.
- This architecture ensures forward secrecy and prevents the BLE transport layer from accessing message contents.
Frequently Asked Questions
What specific Noise handshake pattern does bitchat use for BLE mesh?
The implementation uses the Noise_XX handshake pattern, as documented in docs/BLE-ARCHITECTURE-V3.md and implemented in the BLENoisePayloadFactory. This pattern provides mutual authentication and strong forward secrecy while allowing both parties to transmit static public keys in encrypted form, protecting against passive surveillance of the BLE mesh network.
How does bitchat achieve forward secrecy in BLE communications?
Forward secrecy is achieved through the X25519 ephemeral key exchange during the Noise_XX handshake. Each session generates new ephemeral keys that are not stored after the session ends. Even if an attacker compromises the long-term Ed25519 identity keys at a later date, they cannot decrypt past communications because the session keys were ephemeral and the shared secrets were never transmitted over the network.
What is the difference between the Ed25519 signing and the Noise encryption?
The Ed25519 signature provides cryptographic proof of sender identity and ensures message integrity at the packet level, functioning as an outer wrapper. The Noise Protocol encryption provides the inner end-to-end confidentiality, ensuring that only the intended recipient can read the payload contents. This separation allows the BLE mesh to verify packet authenticity without accessing the encrypted message content, creating a zero-trust transport layer.
Where is the encryption logic implemented in the bitchat source code?
The core encryption logic resides in bitchat/BLENoisePayloadFactory.swift, while the BLE transport integration appears in bitchat/BLEService+LinkLayerCentralRole.swift. The architectural rationale is documented in docs/BLE-ARCHITECTURE-V3.md, and comprehensive test coverage exists in bitchatTests/Services/NoiseEncryptionServiceTests.swift.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →