Bir sunucu, sırlarımızı okumak için anahtarları tutmadan nasıl saklayabilir ve senkronize edebilir? Confidex'ın anahtarlarını nasıl oluşturduğunu, onları bir kilitte nasıl koruduğunu ve bunları verileri şifrelemek ve değişiklikleri doğrulamak için nasıl kullandığını takip edeceğiz.
Kilit
Kapıyı yalnızca Seçilmiş Kişi açabilir
Matrix Yeniden Yüklendi
Gizli verileri depolamak için sanal bir vault oluşturduğumuzu hayal edin. Uygulama kapandıktan sonra bu verileri bir dizüstü bilgisayarda tutmalı ve başka bir cihazda açmamıza izin vermelidir. Kasanın kendi anahtarlarına ihtiyacı olacak. Dosyaların kopyalanmasının dışarıdan birinin içeriklerini okumasına veya değiştirmesine olanak vermemesi için bunları saklamalıyız.
Bir lock anahtarları korur: küçük, şifrelenmiş bir dosya. Bunu açmak için bir ana şifre ve bir gizli kod gerekir: secret_key; dosyanın kendisinde de yok. Kilidin tamamını sabah gazetesinde basabiliriz. Okuyucular bir kopyaya sahip olacak, ancak bunu yayınlamak özel anahtarları açığa çıkarmayacak.
Dışarıdan birinin bu dosyayı aldığını ve hatta ana şifreyi öğrendiğini varsayalım. Artık yalnızca şifre gerektiren her hesaplamayı tekrarlayabilirler, ancak bu hesaplamalar kilidi açan anahtarı üretmeyecektir: secret_key aynı zamanda bir girdidir. Dosya tek başına şifrenin ayrı bir kontrolünü içermez. Açmak için hala bilinmeyen gizli kod gerekiyor.
Bu kod kriptografik olarak rastgele verilerden geliyor; onu bir kişi icat etmez. secret_key bilinmediği sürece, doğru tahmin edilen bir ana şifre bile kilidi açmaz: Saldırganın hâlâ rastgele bir sırrı yoktur. Bu nedenle zayıf bir parola tek başına sunucu kopyasını pratik bir sözlük saldırısına dönüştürmez.
Saldırgan ayrıca secret_key elde ederse ana şifre tahminlerini çevrimdışı olarak test edebilir. Bu maliyetlidir, ancak nihai zorluk şifrenin gücüne bağlıdır.
Anahtarlar
Beyler, anahtarlar ne işe yarar? Anahtarlar... bazı şeylerin kilidi açılsın mı?
Karayip Korsanları – Ölü Adamın Sandığı
Uygulama, işletim sisteminin şifreleme oluşturucusundan rastgele 32 bayt alır ve bunları anahtar olarak kullanıma hazırlar. Hazırlanan bu baytlar, master_key özel ana anahtarıdır.
Uygulama her zaman aynı anahtarları master_key'dan türetir: aynı hesaplamaların aynı baytlarda tekrarlanması aynı sonucu verir. Bu nedenle bir dizüstü bilgisayar ve bir telefon aynı anahtarları kurtarabilir. Yeni bir cihazda master_key elde etmek için uygulamanın önce ana şifre ve secret_key ile kilidi açması gerekir.
İlk çift: şifreleme
Ben Anahtar Yöneticisiyim.
Hayalet Avcıları
Uygulama, şifrelenmiş verileri depolamak için master_key: secret_key'dan bir genel anahtar hesaplar. Kasa için verileri şifreleyebilir, şifre çözme işlemi ise master_key gerektirir.
"Herkese açık", bu anahtarın algoritmadaki rolünü tanımlar, onu herkese verme zorunluluğunu değil. Confidex'da kullanıcıda kalır. Aynı zamanda kilidi açmak için gereken ikinci sırdır, dolayısıyla yerel kalır ve ağ üzerinden gönderilmez. Tek başına secret_key, birisinin kasa için verileri şifrelemesine izin verir, ancak bu verilerin şifresini çözemez veya değişiklikleri onun adına imzalayamaz.
X25519 master_key değerini alıp secret_key değerini hesaplayan algoritmadır. master_key değerini yalnızca secret_key kullanarak geri elde etmek pratikte mümkün değildir. Saniyede 10^18 eğri işlemi yapan hayali bir süper bilgisayarda bile klasik bir saldırı ortalama yaklaşık 2,3 trilyon yıl sürer (SafeCurves tahmini).
İkinci çift: imzalar
Orijinal olan tek şey imzadır
Yapabilirsen Beni Yakala
İlk çift içeriğin gizlenmesine yardımcı olur. Artık kasa sahibinin bir değişikliğe izin verdiğini doğrulamanın bir yoluna ihtiyacımız var. Sunucunun da imzaları kontrol edebilmesi gerekir, bu nedenle ona genel bir doğrulama anahtarı göndermemiz gerekir. İlk çiftin genel kısmı secret_key olup sunucunun almaması gerekir. Bu nedenle imzalar için ikinci, kalıcı bir anahtar çifti oluşturuyoruz.
Başka bir bağımsız sırrı saklamak yerine, master_key'dan özel bir imzalama anahtarı türetiyoruz ve buna signing_key adını veriyoruz. Uygulama bunu verileri ve kilidi imzalamak için kullanır. Diğer cihazlar ve sunucu, içeriği okumadan imzaları kontrol etmek için genel kısmını kullanır.
Bu çifti aynı master_key'dan kurtarabiliriz. Uygulama bundan bir başlangıç değeri alır: İmza anahtarını benzersiz şekilde belirleyen 32 bayt.
Farklı işler için farklı anahtarlar türetmek amacıyla hesaplamaya sabit bir etiket ekleriz: burada confidex/vault/ed25519/v1. Aynı master_key ve aynı etiket her zaman aynı anahtarı üretir.
Ana şifre bu hesaplamalara girmedi. Her iki çift de bir kişi tarafından icat edilen bir dizgeye değil, master_key'ın rastgele baytlarına bağlıdır. Bu ayrım daha sonra önemli olacaktır: Parola, halihazırda var olan anahtarlara erişimi koruyacaktır, böylece anahtarları değiştirmeden parolayı değiştirebiliriz.
Türetme, karma tabanlı bir anahtar türetme işlevini kullanır: HKDF, HMAC-based Extract-and-Expand Key Derivation Function. Confidex bunu SHA-256 ile kullanır, dolayısıyla adı HKDF-SHA256'dır. Ortaya çıkan 32 bayt, Ed25519 çifti için seed'dir. signing_key'ın herkese açık kısmı secret_key'ı açığa çıkarmaz, dolayısıyla onu imza doğrulaması için sunucuya gönderebiliriz.
Kilit dosyası nedir ve ne işe yarar?
Bölme bölmesinin kapılarını aç HAL.
Bir Uzay Macerası
Üzgünüm Dave. Korkarım bunu yapamam.
Kilit şifrelenmiş bir master_key saklar. Açmak için ana şifre ve secret_key gerekir. Genel başlık, format sürümünü, kasa tanımlayıcısını, signing_key'nin genel kısmını, bir tuzu ve şifre işleme parametrelerini içerir. Dahili biçim sürümü master_key ile birlikte şifrelenir.
Kilidi oluştururken, uygulama zaten master_key'a sahiptir, dolayısıyla şifrelemeden önce secret_key'yi hesaplar. Kullanıcı onu açarken ayrı olarak secret_key sağlar: kilidin genel kopyasında yoktur.
Şifre çözüldükten sonra uygulama, master_key'ın genel kısmını X25519 kullanarak hesaplar ve bunun secret_key ile eşleşmesini gerektirir. Daha sonra signing_key'ı kurtarır ve genel kısmını başlıktaki anahtarla karşılaştırır. Bu sayede kilit kendi kendini kontrol eder.
Ana parola tahminini yavaşlatmak için her denemenin zaman ve belleğe mal olması gerekir. Confidex, 64 MiB bellek ve üç geçişle Argon2id kullanır. Şifre işlemede ayrıca rastgele bir tuz kullanılır. Tuz bir sır değil: aynı şifrenin farklı kilitlerde farklı sonuçlar üretmesini sağlar.
secret_key zaten biliniyorsa şifre uzunluğu, saldırının ölçeğini önemli ölçüde değiştirir. Rastgele 5 küçük Latin harfinin yaklaşık 12 milyon kombinasyonu, 7'nin yaklaşık 8 milyarı ve 12'nin yaklaşık 95 katrilyon kombinasyonu vardır. 7'den 12 harfe geçmek, arama alanını neredeyse 12 milyon kat artırır. Belirli bir makinede 7 harfin aranması ortalama bir gün sürüyorsa, 5 harfin aranması yaklaşık iki dakika, 12 harfin aranması ise yaklaşık 33.000 yıl sürecektir.
Argon2id sonucundan ve secret_key'den bir anahtar elde etmek için, daha önce tanıtılan confidex/lock/wrap/v1 etiketiyle HKDF-SHA256 işlevini kullanırız. Sonuç, kilidi şifreleyen anahtar olan wrapping_key'tır.
master_key'ı saklamalı ve kurcalanmaya karşı korumalıyız. XChaCha20-Poly1305 bunu wrapping_key ile şifreler ve bir kimlik doğrulama etiketi ekler. Etiket, şifreli metni genel başlığa bağlar: yanlış bir şifre veya korunan baytlarda yapılan bir değişiklik, açmanın başarısız olmasına neden olur. Etiket ve rastgele tek kullanımlık değer olan nonce, şifreli metinle birlikte saklanır.
Kilit her oluşturulduğunda veya yeniden şifrelendiğinde, uygulama yeni bir tuz ve nonce alır. Şifrelenmiş içerikler bir sürüm baytını ve master_key'ın 32 baytını içerir; yanlarında 24 baytlık bir nonce ve 16 baytlık bir etiket depolanır. Algoritmanın belgeleri yapıyı açıklar.
Kurtarılan anahtarlar arasındaki uyumsuzluk, kasıtlı olarak hatalı biçimlendirilmiş bir kilitten veya onu oluşturan programdaki bir hatadan kaynaklanabilir. Rastgele bayt bozulması genellikle daha önce etiket kontrol edildiğinde algılanır.
Sunucu, bu etiketi doğrulamak için gereken sırlara sahip değildir. Bu yüzden uygulama, kilidi aktarırken signing_key ile oluşturulan bir imza ekler. İmza, açık başlık ve şifrelenmiş içerik dahil tamamlanmış dosyanın tümünü kapsar. Sunucu imzayı doğrular ve ilk yüklemede signing_key anahtarının açık kısmının tamamını ve kasanın dahili tanımlayıcısını sabitler. Sonraki değişiklikleri de bu anahtarla doğrular. Kilit ve şifrelenmiş veriler aynı signing_key ile imzalanır. Bu anahtar master_key kullanılarak yeniden elde edilir.
Kasa
Artık kilidi yayınlayabiliriz. Yalnızca secret_key ve master password'ı bilen biri master_key okuyabilirken, herkes kilit dosyasından genel imzalama anahtarını alabilir ve kilidin veya verilerin içeriğini görmeden imzalanmış verileri kontrol edebilir.
Bir şifre düşünün, SuperPa55worD. Şimdilik sadece onu kaydetmek istiyoruz: uygulamayı kapattıktan sonra, kilit dosyasını ve şifrelenmiş şifreyi kimse SuperPa55worD görmeden herhangi bir yere gönderebilmeli ve aynı zamanda yazarlığımızı doğrulamalarına izin verebilmeliyiz. secret_key ve master password'a sahip olduğumuzda şifrelemenin geri döndürülebilir olması gerekir. Simetrik bir şifre aynı anahtarla şifreleyebilir ve şifresini çözebilir. Bu anahtarı saklamadığımız için kilidi kullanarak onu kurtarabilmemiz gerekir. Buna message_key adını vereceğiz.
Her yeni şifreleme için ayrı bir message_key elde edeceğiz. Hala kurtarılmasını ayarlamamız gerekiyor: Anahtarı şifreli metnin yanında açık bırakmak, kopyaya sahip olan herkesin her şeyi okumasına olanak tanır.
Uygulama, yeni rastgele baytlardan yalnızca bu şifreleme için geçici bir X25519 çifti oluşturur: record_key. Daha sonra record_key'nin özel kısmını ve kasanın kalıcı genel anahtarı olan secret_key'ı alır ve paylaşılan bir sırrı hesaplar. Bu sırdan ayrı bir işlev message_key türetir; bu anahtar şifremizi şifreler.
Uygulama okurken başka bir yol izliyor. master_key ve record_key'ın genel kısmını kullanır. Bu iki anahtar aynı paylaşılan sırrı üretir. Matematiksel olarak, her iki rota da eğri üzerindeki aynı başlangıç noktasını iki özel sayıyla farklı bir sırayla çarpar. Sıralama sonucu değiştirmez. Bu nedenle, record_key'nin özel kısmını saklamadan şifre çözme anahtarını kurtarabiliriz.
Bu sırrı iki genel anahtardan elde etmek neredeyse imkansızdır: her iki rotanın da karşılık gelen özel anahtara ihtiyacı vardır. Kamu noktaları, onları üreten özel numaraları etkili bir şekilde kurtarmamıza izin vermiyor. Bu matematiksel hile kasanın güvenliğinin temelini oluşturuyor. Ancak bu, birisinin bize kilidimiz takılı farklı bir kasa vermesini engellemez.
Artık şifreli metni record_key'ın genel kısmının yanında saklayabiliriz. record_key'ın özel kısmına ve kullanılan message_key'ye artık gelecekteki okumalar için gerek yok. Daha sonra uygulama, şifre çözme anahtarını master_key'tan ve record_key'ın depolanan genel kısmından kurtarır. Böylece kalıcı bir kasa sırrı, her biri gerektiğinde kurtarılan kendi message_key değerine sahip, ayrı ayrı şifrelenmiş birçok değerin şifresini çözebilir.
Metni gizlemek yeterli değildir; metni okurken kurcalamayı da tespit etmemiz gerekir. Bu nedenle şifreleme, şifrelenmiş verilerle birlikte kontrol edilen kısa bir değer olan bir kimlik doğrulama etiketi ekler. Kontrol başarısız olursa uygulama sonucu reddeder. Başarılı bir şekilde şifresi çözülmüş bir şifre olarak rastgele veya değiştirilmiş metin görüntülememelidir.
Asimetrik bir çiftin paylaşılan bir sır oluşturmaya yardımcı olduğu, message_key'ın ise içerikleri şifrelediği bir yapıyı tanımladık. Buna Hybrid Public Key Encryption veya HPKE adı verilir ve RFC 9180 içinde belirtilir. Confidex, sır üzerinde anlaşmak için X25519'yi, anahtarları türetmek için HKDF-SHA256'ı ve bütünlük kontrolü ile şifreleme için ChaCha20-Poly1305'ı kullanır. Burada, HKDF, record_key ve master_key çifti kullanılarak kararlaştırılan paylaşılan sırrı alır; bu, Ed25519 seed'ın türetilmesinden ayrı bir iştir. RFC 5869, HKDF'ı açıklar.
Bir sonraki şifreleme için uygulama yeni bir record_key ve yeni bir HPKE bağlamı oluşturur. message_key ve nonce kombinasyonunun yeniden kullanılması şifrenin korumasını bozar. Confidex'ta anahtar ve nonce, HPKE içerisinden türetilir, bir mesaj için kullanılır ve ardından bağlam atılır.
ChaCha20'nin kendisi 256 bitlik bir message_key kullanır. Doğrudan bir saldırı hakkında fikir sahibi olmak için, kurgusal bir süper bilgisayarın saniyede bir milyar milyar adayı test ettiğini hayal edin. 2²⁵⁶ olası anahtarları aramak yaklaşık 1,8 × 10⁵¹ yıl sürer. RFC 8439 algoritmayı ve analizini açıklar.
Bir kayıt
Mutlu muyuz?
Ucuz Roman
Şifreyi kaydettik, ancak bir web sitesine giriş yapmak için genellikle bir kullanıcı adı ve adres de gerekir. Bazen yanlarında bir nota ihtiyaç duyarız. Bu değerleri ayrı ayrı saklarsak uygulamanın bir şekilde bunların birbirine ait olduğunu hatırlaması gerekir. Bu “kağıtları” bir zarfa koyalım. Alanları tek bir koleksiyonda birleştiriyoruz ve buna record adını veriyoruz.
Bir kayıt herhangi bir alan kombinasyonunu içerebilir. Uygulama bunları tek bir pakette topluyor, sıkıştırıyor ve az önce anlattığımız yapıyı kullanarak bütünü şifreliyor. Alan değerleri, adlar, türler ve etiketlerin tümü korunur. Aynı şifreyi korurken bile web sitesi adresini değiştirmek, tüm kaydın yeni bir record_key ile şifrelenmiş yeni bir sürümünü oluşturur.
Hash zinciri
PROJENİZ BİR BLOK ZİNCİRİ KULLANMALI MI? → HAYIR
XKCD2267
secret_key'ı bilen biri kasamız için şifrelenmiş bir kayıt hazırlayabilir. Bunu bizimki olarak kabul etmekten kaçınmak için uygulama her kayıt sürümünü signing_key ile imzalar. Bu anahtar olmadan dışarıdan biri, sunucunun ve diğer cihazların kabul edeceği imzaya sahip bir sürüm oluşturamaz.
Şifrelenmiş sürüm bazı eşlik eden bilgilere ihtiyaç duyar: hangi kasaya ve kayda ait olduğu, ne zaman değiştiği ve hangi sürümlerin ondan önce geldiği. Bu genel başlığı oluşturur. Parolayı içermiyor ama yine de korumaya ihtiyacı var: Aksi halde birisi şifreli metne dokunmadan nesnelerin sahipliğini ve ilişkilerini değiştirebilir. Uygulama, şifreli metinle birlikte tam başlık baytlarını imzalar. İmzalı verinin değiştirilmesi imzayı geçersiz kılar.
Sunucu, mühürlü paketlerden oluşan bir depoya benzer. Başlığı, şifreli içeriği ve imzayı görüyor ancak içindeki şifreyi göremiyor ve alıcının şehirde bulunduğunu biliyor. İmzayı signing_key'ın sabitlenmiş genel kısmına göre kontrol eder ve yeni sürümün kabul edilip edilmeyeceğine karar verir. Ne ana şifreye, ne secret_key ne de herhangi bir özel anahtara ihtiyaç duyar. İstemci okurken aynı imzayı kontrol eder, ardından şifre çözme sırasında HPKE kimlik doğrulama etiketini kullanarak içerik ile başlık arasındaki bağlantıyı tekrar kontrol eder.
İmza aynı zamanda sürümler arasındaki bağlantıları da korur. Tam üstbilgi ve şifreli metin baytlarının SHA-256 karması, sürümün tanımlayıcısı olur. Sonraki sürümün başlığı önceki sürümün tanımlayıcısını içerir. Bir web sitesinin şifresini değiştirdiğimizde uygulama bu bağlantıyla yeni bir nesne oluşturup imzalıyor. Eski nesne ve imzası değişmeden kalır. Bu nedenle, yeni sürümün imzasını korurken önceki sürümü değiştirmek başarısız olacaktır. İki cihaz bağımsız değişiklik yaparsa her iki dal da hayatta kalır; birleştirilmiş bir versiyon her ikisine de atıfta bulunabilir.
Blockchain'i hatırladın mı? İşte burada :-).
Genel başlık, şifreyi çözmeden bağlantıları kontrol etmemizi sağlar, ancak bazı bilgiler görünür kalır. Sunucu, tanımlayıcıları, sürüm bağlantılarını, istemci tarafından sağlanan değişiklik zamanını, alan sayısını ve her alan değerinin kodlanmış boyutunu bilir. Şifreleme, bu yapısal bilgiyi değil, kaydın içeriğini gizler.
Eşitleme
"Veri sızıntısı değil, ücretsiz dağıtılmış yedekleme."
İnternet meme'i.
Birden fazla cihaz üzerinde çalışmak için kilidi ve kayıt geçmişini bunlar arasında aktarmamız gerekir. Nesne formatı değişmez: Yerel olarak depolanan aynı şifrelenmiş baytları ve imzaları aktarırız.
Manuel aktarım için uygulama, kilidi, yerel olarak depolanan tüm şifrelenmiş kayıt sürümlerini ve imzalı bir dosya listesini içeren bir ZIP arşivi oluşturur. Ne şifre ne de secret_key dahil değildir. Başka bir cihazda, uygulama önce kilidi açar, ardından imzaları kontrol eder, kayıtların şifresini çözer ve yerel kasa kopyasını geri yükler. İçe aktarma, bu kasanın henüz mevcut olmadığı bir cihaza yöneliktir; geçmişi mevcut bir kopyayla birleştirmez.
Bir senkronizasyon sunucusu, çalışan kopyalar arasında değişiklik alışverişi yapar. İlk yüklemede imzalı kilidi alır, imzayı kontrol eder ve signing_key'ın genel kısmından genel kasa adresini hesaplar. Daha sonra bu anahtarı ve başlıktaki kasa tanımlayıcıyı hatırlar: bu, kasayı sunucuya kaydeder. Sonraki değişiklikler bu tanımlayıcıyla eşleşmeli ve aynı anahtardan bir imza taşımalıdır.
Yeni bir cihazın kasa adresine ve secret_key'a ihtiyacı vardır, dolayısıyla uygulama bunları sağlama toplamı içeren bir aktarım kodunda birleştirir. Kullanıcı bu kodu cihaza aktarır ve ana şifreyi ayrı ayrı girer; sunucuya yalnızca genel adres gönderilir.
İndirilen kilidi açtıktan sonra uygulama, kurtarılan anahtarların genel bölümlerini secret_key ve başlıkla karşılaştırır ve hesaplanan adresi aktarım koduyla karşılaştırır. Daha sonra kayıtları kontrol etmek için signing_key'ın doğrulanmış genel kısmını kaydeder.
Senkronizasyon sırasında uygulama eksik sürümleri getirir ve değişikliklerini yükler. Sunucu imzaları ve önceki sürümlere olan bağlantıları kontrol eder, kabul edilen nesneleri saklar ve bunları diğer cihazlara aktarır. Alınan verilerin kontrol edilmesi, şifresinin çözülmesi ve çakışmaların çözülmesi işlemlerinin tümü kullanıcının cihazlarında gerçekleşir.
Kayıt sırasında isim, e-posta adresi veya ayrı bir şifre sorulmaz. Sunucu genel adresi, imza doğrulama anahtarını, genel başlıkları, nesne boyutlarını ve sürüm bağlantılarını görür. Ayrıca IP adreslerini ve istek zamanlarını da görür. Ana şifre, secret_key, özel anahtarlar ve düz metin kayıt içerikleri kullanıcının cihazlarında kalır. Genel adresi bilen herkes şifrelenmiş nesneleri indirebilir ancak bunları okumak kullanıcının sırlarını gerektirir.
Bu kontroller sahte nesneleri tespit eder ancak sunucunun tüm geçmişi ve en son durumunu gösterdiğini kanıtlamaz. Müşterinin hiç görmediği bir dalı gizleyebilir veya tutarlı, eski bir veri kümesi döndürebilir. İmza, sunucunun yanıtının eksiksizliğini değil, tek bir nesnenin gerçekliğini doğrular. Kullanıcı başka bir cihazda eksik değişikliklerin olduğunu fark edebilir ancak tutarlı bir eski geçmiş, hash-chain doğrulamasını geçecektir.
Ana şifreyi değiştirme
Peki efendimiz onun şifresini değiştirmek ister mi?
Hackerlar (1995)
Ana parolanın değiştirilmesi yalnızca kilidi yeniden şifreler; İçerideki master_key aynı kalıyor. Kayıtlar, imzaları, secret_key ve kasa adresi bu nedenle değişmeden kalır. Yeni kilit aynı signing_key ile imzalanmış.
Eski bir kilit kopyası hâlâ eski şifreyle ve aynı secret_key ile açılıyor; parolayı değiştirmek, halihazırda açığa çıkmış olan anahtarları iptal etmez.
Tam resim
Kilit, master_key'ı korur, message_key kayıtları şifreler ve signing_key imzalar oluşturur. ZIP arşivleri ve sunucu, imzalı şifrelenmiş nesneleri alır.