Şifre Kasam
Flutter ile çok kullanıcılı yerel şifre yöneticisi. Kayıtlar cihazda AES-256-GCM ile şifreli; anahtar ana paroladan Argon2id ile türetiliyor.
Şifre yöneticilerinin çoğu bulut tabanlı. Tek cihazda kalan, internet bağlantısı gerektirmeyen ve aynı telefonu paylaşan birden fazla kişiyi destekleyen bir kasa yazmak istedim.
- Kasa anahtarı ana paroladan Argon2id ile türetiliyor (19 MiB, 2 tur). Her kullanıcının kendi rastgele tuzu var, yani aynı parolayı kullanan iki kişi aynı anahtarı üretmiyor.
- Kayıtlar AES-256-GCM ile şifreleniyor. Her yazmada yeni nonce üretiliyor, böylece iki hesabın şifresinin aynı olduğu bilgisi bile sızmıyor.
- Parola hiç saklanmıyor, hash’i de saklanmıyor: doğrulama, anahtarla şifrelenmiş sabit bir işaretin çözülüp çözülemediğine bakılarak yapılıyor.
- Düz metin saklayan eski sürümden gelen kayıtlar için tek transaction içinde çalışan bir göç yazdım — veri kaybı olmadan şifreleniyor.
Bireysel proje, tamamı bana ait.
Kasa artık şifreli. Şifreleme katmanı testli: şifrele-çöz turu, nonce rastgeleliği, yanlış parola reddi, kurcalama tespiti ve anahtar türetme maliyetinin ölçümü. Uygulama tamamen çevrimdışı.
Şifreleme eklendi ama güvenlik yüzeyi bundan ibaret değil. Kasa anahtarı işletim sisteminin güvenli deposunda (Keystore / Keychain) değil, yalnızca süreç belleğinde tutuluyor. Kopyalanan şifre panoda süresiz kalıyor, ekran görüntüsü engellenmiyor ve uygulama arka plana alınınca kasa kendiliğinden kilitlenmiyor. Hepsi README’de madde madde yazılı.
Şifrelemeyi eklerken asıl dersi beklemediğim yerde aldım: uygulamada 4 haneli PIN vardı ve anahtarı ondan türetmek şifrelemeyi göstermelik yapacaktı. Kendi cihazımda ölçtüm — Argon2id tek türetmede ~220 ms sürüyor, yani 10.000 olasılığın tamamı 37 dakikada taranıyor. Anahtarın gücü KDF’ten değil parolanın entropisinden geliyormuş; KDF yalnızca çarpanı sağlıyor. PIN’i kaldırıp ana parolaya geçtim ve bu ölçümü kıran bir test bıraktım.
Flutter · Dart · SQLite · sqflite · Argon2id · AES-256-GCM