How Boho authentication and encryption work
This guide describes Boho JS 2.2.0 and Boho Arduino 0.8.0, used alongside the IOSignal JS 7.2.0 documentation baseline. Boho's version numbering is independent. It combines shared-key authentication with a SHA-256-derived XOR stream and integrity checks. Understanding that construction does not make it equivalent to TLS or a standardized AEAD cipher.
XOR, hashes, and one-time pads
For plaintext P and stream S, ciphertext is C = P XOR S; applying the same stream again restores P. A true one-time pad requires an unpredictable secret stream as long as the message, used only once. Reusing it exposes C1 XOR C2 = P1 XOR P2.
SHA-256 outputs 32 bytes. It is a hash, not encryption. Hashing a public nonce alone does not make a secret stream, and hashing a weak password does not create password entropy. Boho's virtual OTP is a deterministic pseudorandom construction, not an information-theoretically secure one-time pad. ChaCha also expands secret material into a stream, but its construction and analysis differ.
Stream generation
The implementation derives:
K = SHA256(input key)
B = SHA256(K || salt12)
S_i = SHA256(B || LE32(i)), i = 1, 2, ...
salt12 consists of seconds (4 bytes), milliseconds (2), a counter (2), and a nonce (4). The index is encoded little-endian. A 70-byte plaintext consumes 32 + 32 + 6 stream bytes. resetOTP, getIndexOTP / generateIndexOTP, and xotp manage block generation and XOR. Arduino can generate one 32-byte block at a time, but packet and application buffers still consume memory.
Repeating the same key and salt repeats the stream. Uniqueness must hold across devices, directions, restarts, and counter reuse—not merely within one message loop.
Integrity and authentication
The packet integrity value is the first eight bytes of:
SHA256(K || salt12 || plaintext)
The receiver decrypts and checks the value before accepting the message. Some implementation names use HMAC, but this formula is not the standard inner/outer-pad HMAC construction. Do not transfer standard HMAC guarantees to it by name alone.
The authentication exchange uses SERVER_TIME_NONCE (server clock/challenge), AUTH_REQ (ID, client nonce, authentication value), and AUTH_RES (server authentication value). Authentication uses 32-byte values rather than the packet's truncated eight-byte integrity value. The key is not sent, and peers demonstrate knowledge of configured key material. This is neither a public-CA identity check nor a fresh public-key key exchange.
Packet formats
| Operation | Overhead and context |
|---|---|
encryptPack / decryptPack | 25 bytes |
encrypt_488 / decrypt_488 | 21 bytes; the authentication nonce is already known, so time/counter contribute 8 transmitted bytes |
End-to-end encrypted ENC_PACK | Internal encrypted packet overhead of 25 bytes, plus outer routing/transport framing |
These sizes describe packet fields, not total Ethernet/TCP/WebSocket overhead or a performance benchmark.
Relationship to TLS and end-to-end encryption
TLS handles transport authentication/key establishment and symmetric record protection. Certificate-based TLS is common; TLS also has PSK modes, including PSK with ephemeral key exchange. Neither TLS nor Boho provides network anonymity. CPU, memory, and bandwidth costs depend on hardware and configuration.
Boho's configured shared key requires a provisioning and rotation strategy. IOSignal AUTO mode can select Boho protection when TLS is absent and authentication succeeds; it does not make every anonymous connection encrypted. Check the actual negotiated connection and encryption mode.
For end-to-end encryption, final endpoints must share a separate key that the relay does not possess. Routing metadata remains visible. Securely delivering browser code still matters: HTTPS protects the code that handles the key.
Limits to account for
- Use strong key material.
set_keyapplies a single SHA-256 operation, not a slow password-based KDF. - JS uses
crypto.getRandomValues; the Arduino nonce path usesmicros, which is not a cryptographically secure random generator. Assess nonce/salt reuse across boots and devices. - Boho alone does not enforce challenge freshness or maintain a complete replay cache. IOSignal/server/application checks must enforce the relevant clock, lifetime, and replay rules.
- This construction does not provide forward secrecy by itself and should not be described as having standardized AEAD guarantees.
- Key exposure affects traffic protected with that key. Separate transport and end-to-end keys and define replacement procedures.
For implementation review, use the Boho JS source and Arduino source at the stated versions. Related specifications include SHA-256, FIPS 180-4, ChaCha20/Poly1305, RFC 8439, HMAC, RFC 2104, and TLS 1.3, RFC 8446. These references describe the standards; they do not certify Boho as an implementation of those constructions.