Open source

Read the code.

Encryption, sync and steganography modules from Bardo and Veil, published in full.


package com.example.notepad.sync.zurich

enum class ZurichLwwWinner { LOCAL, REMOTE }

object ZurichSyncResolver {
    fun chooseLwwWinner(
        localUpdatedAt: Long,
        remoteUpdatedAt: Long,
        localRevision: Long = 0L,
        remoteRevision: Long = 0L
    ): ZurichLwwWinner = when {
        remoteUpdatedAt > localUpdatedAt -> ZurichLwwWinner.REMOTE
        localUpdatedAt > remoteUpdatedAt -> ZurichLwwWinner.LOCAL
        remoteRevision >= localRevision -> ZurichLwwWinner.REMOTE
        else -> ZurichLwwWinner.LOCAL
    }
}

package com.example.notepad.sync.zurich

internal object HChaCha20 {
    private val CONSTANTS = intArrayOf(0x61707865, 0x3320646e, 0x79622d32, 0x6b206574)
    private const val ROUNDS = 20

    fun deriveSubkey(key: ByteArray, nonce16: ByteArray): ByteArray {
        require(key.size == 32) { "HChaCha20 key must be 32 bytes" }
        require(nonce16.size == 16) { "HChaCha20 nonce must be 16 bytes" }

        val state = IntArray(16)
        CONSTANTS.copyInto(state, 0)
        for (i in 0 until 8) state[4 + i] = leWordAt(key, i * 4)
        for (i in 0 until 4) state[12 + i] = leWordAt(nonce16, i * 4)

        var round = 0
        while (round < ROUNDS) {
            quarterRound(state, 0, 4, 8, 12)
            quarterRound(state, 1, 5, 9, 13)
            quarterRound(state, 2, 6, 10, 14)
            quarterRound(state, 3, 7, 11, 15)
            quarterRound(state, 0, 5, 10, 15)
            quarterRound(state, 1, 6, 11, 12)
            quarterRound(state, 2, 7, 8, 13)
            quarterRound(state, 3, 4, 9, 14)
            round += 2
        }

        val output = ByteArray(32)
        for (i in 0 until 4) writeLeWord(output, i * 4, state[i])
        for (i in 0 until 4) writeLeWord(output, 16 + i * 4, state[12 + i])
        return output
    }

    private fun quarterRound(s: IntArray, a: Int, b: Int, c: Int, d: Int) {
        s[a] += s[b]; s[d] = (s[d] xor s[a]).rotateLeft(16)
        s[c] += s[d]; s[b] = (s[b] xor s[c]).rotateLeft(12)
        s[a] += s[b]; s[d] = (s[d] xor s[a]).rotateLeft(8)
        s[c] += s[d]; s[b] = (s[b] xor s[c]).rotateLeft(7)
    }
}

function paddingBucket(length) {
    if (!Number.isSafeInteger(length) || length < HEADER_LENGTH) {
        throw new VeilError("Invalid message length.", "internal_error");
    }

    if (length > MAX_DECODE_ENVELOPE_BUCKET) {
        throw new VeilError("Secret is too large.", "input_too_large");
    }

    for (let index = 0; index < PADDING_BUCKETS.length; index += 1) {
        if (length <= PADDING_BUCKETS[index]) {
            const random = randomBytes(1)[0];

            if (index < PADDING_BUCKETS.length - 1 && random < 32) {
                return PADDING_BUCKETS[index + 1];
            }

            return PADDING_BUCKETS[index];
        }
    }

    const bucket = 2 ** Math.ceil(Math.log2(length));

    if (!isSupportedEnvelopeBucket(bucket)) {
        throw new VeilError("Secret is too large.", "input_too_large");
    }

    return bucket;
}

Projects

01

Aegis 2

OutdatedAndroid · Kotlin

Encrypted container behind protected Bardo Notes exports: authenticated 64 KB chunks, KEK/CEK separation, password re-keying. Code changed in a release (shipped or upcoming). This version is outdated.

XChaCha20-Poly1305 · Argon2idApache 2.0
02

Aegis 2.5 Binary

Android · Kotlin

Binary encryption format for protected Bardo Notes files.

Argon2id · XChaCha20-Poly1305Apache 2.0
03

Bardo Sync

Android · Kotlin

Encrypted push and pull, three-way conflict resolution, and the Zurich Sync client.

E2E · Argon2idApache 2.0
04

Bardo Markdown Engine

OutdatedAndroid · Compose

Real-time markdown parsing and rendering for Jetpack Compose with custom rich-text tags and WYSIWYG editing. Code changed in a release (shipped or upcoming). This version is outdated.

Real-time · WYSIWYG · Custom tagsApache 2.0
05

DarkDrop

Android · Kotlin

Move text between devices with one QR code: deep links, GZIP compression, signature validation.

QR payload · GZIP · SignedApache 2.0
06

Veil

Browser · JavaScript

Hides encrypted messages inside ordinary text. Runs offline, no build step.

Reed–Solomon · AES-256-GCM · Argon2idApache 2.0