callwhite, mesaj yolunda sunucu bulunmayan bir messenger. Mesajlar, yalnız iki tarafın paylaştığı anahtar malzemesinden türetilen adreslere yazılıp oradan okunuyor; relay ise türetemediği, göndericiye ya da okuyucuya bağlayamadığı adreslerde sabit boyutlu opak bloblar tutuyor. Birebir ve grup sohbetleri, medya dahil.
Bunun kaldırdığı şey, şifrelemenin geride bıraktığı yarı: kim kiminle temas etti, ne zaman, ne sıklıkla, ne kadar. Ölçeklenen yarı da bu — bir kişinin mesajlarını okumak mahkeme kararı ve bir analist ister, herkesin iletişim grafiğini okumak bir veritabanı sorgusu.
ELİNE NE GEÇİYOR
Protokol makalesi değil. İki platforma kurduğun, ikisinin de altında aynı Rust çekirdeği derlenmiş bir uygulama.
- Eşleşme
- Davet bağlantısı ya da yüz yüze okutulan QR. İki taraf birbirinden bağımsız olarak aynı on beş gruplu doğrulama dizesini türetiyor. Diziler tutmuyorsa karşındaki sandığın kişi değildir — ve arayüz sana baktırıyor.
- Sohbet
- Birebir ve grup. Gruplar her epoch'ta anahtar yeniliyor; birini çıkarmak bir sonraki yazımda geçerli oluyor, "zamanla" değil. Relay üye listesini hiç görmüyor.
- Medya
- Bir seferde birden çok fotoğraf ve uygulama içinde kaydedilen sesli notlar. İkisi de çıkış yolunda diske yazılmıyor.
- Kılıf
- On üç çalışan kılıf uygulaması — hesap makinesi, not defteri, saat, alarm, kronometre, çevirici, renk kartelası, beş oynanabilir oyun. Başlatıcıda seçtiğin kılıf, kendi adı ve simgesiyle duruyor.
- Kasa
- Üç şifre. Biri gerçek hesabı, biri kendi depolama alanı olan ayırt edilemez bir yem hesabı, biri de her şeyi yok ediyor. Yem şifresi doğru sayılıyor ve yanlış deneme sayacını sıfırlıyor.
- Vekil
- Yalnız yüz yüze, taranan kodla atanan bir kişi; hesabını şifreli kanal üzerinden uzaktan yok edebiliyor — cihaz hâlâ ulaşılabilirken.
- Cihaz kontrolü
- Uygulama kendi ortamını denetleyip rapor veriyor: ekran yakalama reddediliyor mu, ekranı okuyabilecek bir erişilebilirlik servisi var mı, bağlantı gitmesi gereken yere mi gidiyor.
- Platformlar
- Android tarafında Kotlin ve Jetpack Compose. Masaüstünde Tauri. İkisinin altında tek bir Rust çekirdeği — telefonda UniFFI ile, masaüstünde yerel derlemeyle.
MEKANİZMA
BİR GÖZLEMCİ NE GÖRÜR
TELEFON ELE GEÇTİĞİNDE
Yukarıdakilerin tamamı tel hakkında. Cihaz bir başkasının elinde kilidi açık duruyorsa hiçbiri işe yaramaz; o yüzden bu durum ayrıca tasarlandı — telefonu elinde tutanın bir şifreyi zorla aldırabileceği varsayımıyla.
Kurulu olan şey bir messenger'a benzemiyor. Kendini on üç sıradan uygulamadan biri olarak tanıtıyor — hesap makinesi, not defteri, saat, alarm listesi, kronometre, birim çevirici, renk kartelası ya da beş oynanabilir oyundan biri. Hangisi olacağı kullanıcının seçimi, çünkü tek ve sabit bir kılıf kendisi parmak izine dönüşürdü. Her biri gerçekten çalışan bir uygulama: hesap makinesi hesaplıyor, oyunlar oynanıyor, kronometre zaman tutuyor. Hepsi dolu başlıyor, çünkü boş bir not defteri en kolay ele veren şeydir. Gerçek uygulamaya geçiş yolu her kılıfta farklı ve her seferinde o uygulamada zaten yapacağınız bir eylem — jest gibi duran bir jest değil.
Bunların hiçbiri sır muamelesi görmüyor ve arayüz bunu bu kelimelerle söylüyor. Bu yazılımı bilen biri telefonda bir hesap makinesi görürse onu nasıl açacağını da bilir. Kılıf, gelişigüzel bir bakışa karşı doğallık kazandırır; gizlilik kazandırmaz, ve aksini iddia eden bir tasarım kullanıcıya masal satıyor olurdu.
Asıl savunma, kasanın üç şifresi olması. Biri gerçek hesabı açıyor. Biri bir yem hesabı açıyor — ayırt edilemez tipte, kendi depolama alanı olan, eksiksiz ve masum bir hesap; gerçek hesap ise gizli kalıyor ve varlığına dair hiçbir işaret verilmiyor. Biri de yem hesabın kendi alanı dahil her şeyi yok ediyor. Yem şifresi doğru şifre sayılıyor ve yanlış deneme sayacını sıfırlıyor; yani baskı altında onu vermek kaçamak gibi görünmüyor.
Ayrıca bir kişi vekil atanabiliyor — yalnız yüz yüze, taranan kodla — ve hesabı şifreli kanal üzerinden uzaktan yok edebiliyor. Arayüz sınırı gizlemek yerine yazıyor: bu yolun çalışması için cihazın ulaşılabilir olması gerekir, yani çevrimdışı tutulan ele geçmiş bir telefon komutu hiç almaz.
EKRAN GÖRÜNTÜSÜ YOK — TASARIM GEREĞİ
Bu sayfada uygulamanın hiçbir resmi yok, olamaz da. Android istemcisindeki her pencere
FLAG_SECURE ile işaretli: işletim sistemi ekran görüntüsü almayı ve ekran
kaydını reddediyor, uygulama son-uygulamalar önizlemesine de çizilmiyor. Bu kural, yazan
kişi için de herkes için olduğu kadar geçerli.
Kısıtın bir bedeli var ve asıl mesele o bedel. Eşleşme kodu gözle doğrulanamıyor, çünkü cihazdaki hiçbir araç onu yakalayamıyor — bu yüzden kodu üretip yeniden çözen bir gidiş-dönüş testiyle doğrulanıyor. Kimsenin fotoğraflayamadığı bir ekran, saldırganın da fotoğraflayamadığı ekrandır; bunun dayattığı şey pazarlamada değil test takımında görünür.
NELER YAPMIYOR
İki şey aynı anda doğru olamaz; aksini iddia eden bir proje ya kafası karışıktır ya da bir şey satıyordur.
Varsayılan derleme sunucusuzdur ve küresel pasif gözlemciye direnmez. Ağdaki her bağlantıyı aynı anda izleyebilen biri, giren ve çıkan trafiği yine ilişkilendirebilir. Sabit hızlı örtü trafiği bu maliyeti ciddi biçimde yükseltir; sıfıra indirmez. Yerel bir gözlemciye, internet sağlayıcısına, relay işletenine ya da cihazı elinden alan birine karşı tasarım tutar. Ağın tamamını gören bir düşmana karşı tutmaz.
O düşmana direnecek olan mixnet katmanı ise sunucusuz değildir. Bir karıştırma ağına ve bir sağlayıcıya yaslanır; yani işletmediğin altyapıya güvenmek demektir. Bilinçli bir seçenektir, varsayılan değildir, ve takas gizlenmek yerine yazılır: mükemmel izlenemezlik ile tam sunucusuzluk aynı anda elde edilemez.
Relay keşfi yok ve istemci tek bir relay'e bağlanıyor. Replikasyon tasarımı yazılı — buluşma özetlemesiyle seçilen beş replika, iki okuma eşiği, üç ölü ya da düşman düğüme dayanıklılık — ve seçim kodu yazılmış, testleri de var. Uygulamaya bağlanmadı. Bugün relay adresi kullanıcıya elden veriliyor ve kasada tek bir dize olarak duruyor; yani ortadan kalkan bir relay, yenisi verilene kadar teslim yolunu da beraberinde götürüyor. Federasyon bir tasarım ve bir spike'tır, dağıtılan bir özellik değil; başka türlü anlatmak, bu sayfanın var olma sebebi olan hatanın ta kendisi olurdu.
Daha küçük sınırlar da var ve onlar burada bir dipnotta değil, kullanıcının karşılaştığı yerde — arayüzün içinde. Uzaktan imha, cihazın ulaşılabilir olmasını gerektirir. Kılıf gelişigüzel bir bakışa dayanır, aramaya değil. Unutulan bir giriş jesti geri getirilemez, çünkü istismar edilecek bir kurtarma yolu yoktur.
ÖLÇÜLDÜ, İDDİA EDİLMEDİ
- 4096bayt, her zaman Teldeki her blob aynı boyutta. Boşa çıkan bir sorgu 4096 baytlık yem döndürüyor; yani doluluk da bir bilgi kaynağı değil.
- 3.9MB / saat, sabit Örtü trafiği, konuşuyor ol ya da olma, sabit hızda akıyor. Boşta ve etkin durum dışarıdan birebir aynı görünüyor.
- 98ms iş kanıtı Her yazımda ödenen, 64 MiB'lık bellek-sert Argon2id. Böylece bir relay'i boğmanın bedeli savunanın bant genişliği değil saldırganın işlemcisi oluyor.
-
466otomatik test
Rust çekirdeği, masaüstü istemcisi ve Android istemcisi boyunca. Clippy
-D warningsile temiz. - 6kırmızı-takım turu Bu kod tabanı üzerinde altı yapılandırılmış kırmızı-takım turu. Bir bulgu sayılabilmek için önce çürütülme denemesinden sağ çıkmak zorunda — beşinci tur 53 adayın 10'unu, altıncı tur 123'ün 23'ünü eledi. Kapanan her bulgu, adını taşıyan bir regresyon testi taşıyor.
- 0bilen sunucu Mesaj yolundaki hiçbir bileşen yönlendirme durumu tutmuyor. El konulacak, mahkemeyle istenecek, sızdırılacak ya da satılacak bir sohbet grafiği yok.
SÜRÜLDÜ, BENZETİLMEDİ
Aşağıdakilerin her biri gerçek Tor ve gerçek bir onion relay üzerinde sürüldü — taklit taşıma katmanı değil, geri-döngü düzeneği değil.
- Android'den masaüstüne, uçtan uca. Telefon, Tor üzerinden canlı bir relay'e davet bıraktı. Masaüstü daveti çekti, kabul etti ve iki taraf birbirinden bağımsız olarak aynı on beş gruplu doğrulama dizesini türetti. Masaüstünün şifreli mesajı telefonda çözüldü. İki farklı Tor uygulaması, tek tel formatı.
- Çapraz-makine birebir mesajlaşma, relay üzerinden; ve masaüstü arayüzünden sürülen eşleşme — doğrulama dizesi iki uçta da birebir tuttu.
- Üç relay'li federasyon — buluşma özetlemesiyle yerleştirme, N/M yazım, çoğunlukla okuma ve düğüm kaybına dayanıklılık. Bu bir spike ikilisiyle koştu. Dağıtılan istemci bunu kullanmıyor: hâlâ elle girilen tek bir relay adresine bakıyor.
- Yeniden başlatmada kalıcılık — işletim sistemince mühürlenmiş ana anahtarın altında Argon2id anahtar deposu. Yeniden başlatma kilit ekranına düşüyor; kilit açılınca kişi listesi geri geliyor.
- Sohbet ortasında kontrol noktası ve geri yükleme, canlı olarak; oturum sonrasında kaldığı yerden devam etti.
Üç hata ancak gerçek cihazda ortaya çıktı ve üçü de hiçbir birim testinin ulaşamayacağı cinsten: hiç kurulmamış bir kriptografi sağlayıcısı yüzünden Tor açılışında sürecin çökmesi; ağ çağrısı boyunca tutulan ve yeniden-girişli olmadığı için eşleşmeyi dakikalarca kilitleyen bir mutex; ve host derleme betiklerini sessizce bozan global bir derleyici bayrağı. Üçü de kapandı, ikincisine sebep olan kilitleme deseni artık geçerli olduğu her yerde kullanılıyor.
NASIL İNŞA EDİLDİ
İki istemcinin altında yedi Rust crate'i, tek bir tel protokolü ve tekrar üretip manifestoyla karşılaştırabileceğin bir derleme.
- Çekirdek — Rust, yedi crate: kriptografi, protokol, taşıma, relay, Tor tümleşimi, FFI, düğüm.
- Android — Jetpack Compose ile Kotlin, Rust çekirdeğine UniFFI üzerinden köprülenmiş.
- Masaüstü — Tauri, aynı çekirdek yerel olarak derlenmiş.
- Relay — tel protokolünü konuşan ve okuyabildiği hiçbir şeyi saklamayan küçük, statik bir ikili. Tümüyle statik bir Linux hedefine çapraz derlendi.
- Derleme — tekrarlanabilir; kaynak ağacının SHA-256 manifestosu, 617 bileşeni kapsayan CycloneDX SBOM'u ve CI'da bağımlılık ile lisans kapıları.
HATALAR NASIL BULUNDU
Yazmaya değer hatalar hiçbir zaman çökme olmadı. Doğru görünen ama olmayan şeylerdi — her biri tam olarak bunu aramak için kurulmuş bir denetim süreciyle bulundu ve her biri artık adını taşıyan bir regresyon testi taşıyor:
Yanlış sebeple geçen bir test
Bir depolama düzenini tarif eden sabit, üç ayrı test dosyasına kopyalanmıştı. Biçim bir alan kazanınca üçü birden aynı anda — ve aynı yönde — yanlışa düştü. Testler yine geçiyordu. Kodun hiç görmeyeceği bir yükü sınıyorlardı ve korumaları gereken yükseltme yolu aslında hiç test edilmemişti. Yineleme, koca bir hata sınıfını görünmez kılmıştı.
Kırık olduğu için "temiz" diyen bir güvenlik kapısı
Bir derleme adımı, ikililerde asla dağıtılmaması gereken dizeleri tarıyordu. Uzun süre "temiz" dedi. Meğer alttaki araç o platformda çöküp hiçbir şey basmıyormuş ve boş çıktı, "hiçbir şey bulamadım" yerine "hiçbir şey yok" diye okunuyormuş. Kapı artık bir kanarya taşıyor: kesinlikle bulunması gereken bir dize. Tarama kanaryayı bulamıyorsa tarama bozuktur ve derleme geçmek yerine durur.
Nonce tekrarı üreten bir tazeleme mekanizması
Grup durumunu daha erişilebilir kılmayı amaçlayan bir kural, her katılımcıya hem yürürlükteki hem sonraki pencereye yazdırıyordu. Mühürleme anahtarı ile nonce aynı girdilerden belirlenimci biçimde türetildiği için ikinci yazım bir anahtar akışını tekrar kullanıyordu. Pratikte hiç istismar edilebilir bir hataya dönüşmemesinin sebebi, relay'deki alakasız bir savunmanın ikinci yazımı reddetmesiydi. Bunu oraya kimse bu amaçla koymamıştı; tam da bu yüzden öyle bırakılmadı: adres türetmesi artık epoch'u içeriyor, yani çakışma kazara engellenmiş değil yapısal olarak imkânsız.
Tetikleyicisi yok diye elenen bir bulgu
Bir kırmızı-takım turunda, bir veri yoluna dair iki bulgu "hiçbir arayüz o koda ulaşamıyor" gerekçesiyle çürütüldü. O çürütme yanlıştı ve sebebi adını koymaya değer: var olmayan bir giriş noktası savunma değil, ayrı bir kusurdur — kimsenin kullanamayacağı bir işlevin dağıtılmış olması. Hem asıl bulgular hem eksik giriş noktaları artık düzeltildi ve ders denetim sürecine yazıldı.
Yakalayamayacak şekilde kurulmuş bir test takımı
Grup mesajlaşmasının bir ön koşulu, tam olarak hiçbir testin göremeyeceği yerde duruyordu. Birebir uçtan uca test, taklit bir taşıma katmanı — bir hash tablosu — üzerinde koşuyordu; orada grup halkası, iş kanıtı, adreslerin yazma-yetkisine bağlanması ve yem dolgusu yok, dolayısıyla grup akışı o katmanda ifade bile edilemiyordu. Altındaki birim testleri iki tarafı da doğru kuruyor ama üyeye yöneticinin grup anahtarını doğrudan veriyordu; üretimde ise üye onu eşleşmiş kanaldan türetir. İki katman da geçiyordu. İkisi de çalışması gereken şeyi sınamıyordu.
Düzeltme bir yama değildi. Grubun tamamını gerçek sertleştirilmiş depo ve gerçek tel üzerinde süren bir testti: eşleşme gerçek davet akışıyla, kontrol kaydı gerçek adresine yazılıp oradan okunarak, mesaj ve medya doğrudan halka opcode'larıyla. Test anında, iki yerden birden düştü ve ikisi de dağıtıma girmiş kusurdu. Kriptografi baştan beri doğruymuş. Bozuk olan kablolamaydı — düzeneğin bakmayacak şekilde kurulduğu tek yerde.
Hepsi kayıtta — depoda, commit mesajlarında ve denetim belgelerinde; daha önceki bir sonucun geri alınmak zorunda kaldığı turlar dahil. Yalnız başarıları kaydeden bir dokümantasyon pazarlama ürünüdür ve bu işi sıradaki kim sürdürecekse onun için değersizdir.
İLETİŞİM
Rust, uygulamalı kriptografi ve mahremiyeti koruyan sistem mühendisliği alanlarında uzaktan sözleşmeli ve tam zamanlı iş.