Bu belge, proto biçiminde type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey
olarak kodlanan, AES-GCM-HKDF Akış anahtarlarıyla temsil edilen matematiksel işlevi resmi olarak tanımlar.
Bu şifreleme genel olarak HRRV151'e dayanır. Güvenlik analizi için HS202'yi kullanırız.
Anahtar ve parametreler
Anahtarlar aşağıdaki bölümlerde açıklanmıştır (bu belgedeki tüm boyutlar bayt cinsindendir):
- \(\mathrm{KeyValue}\), bir bayt dizesidir.
- \(\mathrm{CiphertextSegmentSize} \in \{1, 2, \ldots, 2^{31}-1\}\).
- \(\mathrm{DerivedKeySize} \in \{16, 32\}\).
- \(\mathrm{HkdfHashType} \in \{\mathrm{SHA1}, \mathrm{SHA256}, \mathrm{SHA512}\}\).
Geçerli anahtarlar ayrıca aşağıdaki özellikleri de karşılar:
- \(\mathrm{len}(\mathrm{KeyValue}) \geq \mathrm{DerivedKeySize}\).
- \(\mathrm{CiphertextSegmentSize} > \mathrm{DerivedKeySize} + 24\) (Bu, daha sonra \(\mathrm{len}(\mathrm{Header}) + 16\) açıklandığı gibidir).
Bu özelliklerin hiçbirini karşılamayan anahtarlar, anahtar ayrıştırıldığında veya karşılık gelen temel öğe oluşturulduğunda Tink tarafından reddedilir.
Şifreleme işlevi
Bir mesajı \(\mathrm{Msg}\) ilişkilendirilmiş verilerle\(\mathrm{AssociatedData}\)şifrelemek için üst bilgi oluşturur, mesajı segmentlere ayırır, her segmenti şifreler ve şifrelenmiş segmentleri birleştiririz.
Üstbilgiyi oluşturma
Uzunluğu 7 olan \(\mathrm{Salt}\) tek tip bir dize\(\mathrm{DerivedKeySize}\) ve 7 karakter uzunluğunda rastgele bir dize \(\mathrm{NoncePrefix}\)seçiyoruz.
Daha sonra, başlığın uzunluğunun tek bir bayt olarak kodlandığı \(\mathrm{Header} := \mathrm{len}(\mathrm{Header}) \| \mathrm{Salt} \| \mathrm{NoncePrefix}\)değerini ayarlarız. Unutmayın: \(\mathrm{len}(\mathrm{Header}) \in \{24, 40\}\).
Ardından, HKDF3'ü \(\mathrm{HkdfHashType}\)ve girişler \(\mathrm{ikm} := \mathrm{KeyValue}\), \(\mathrm{salt} := \mathrm{Salt}\)ve \(\mathrm{info} := \mathrm{AssociatedData}\)çıkış uzunluğu \(\mathrm{DerivedKeySize}\)ile belirtilen karma işleviyle birlikte kullanırız. Sonuca \(\mathrm{DerivedKey}\)adını veriyoruz.
Mesajı böl
Ardından, \(\mathrm{Msg}\) mesaj parçalara ayrılır: \(\mathrm{Msg} = M_0 \| M_1 \| \cdots \| M_{n-1}\).
Videoların uzunlukları şu koşullara göre seçilir:
- \(\mathrm{len}(M_0) \in \{0,\ldots, \mathrm{CiphertextSegmentSize} - \mathrm{len}(\mathrm{Header}) - \mathrm{16}\}\).
- \(n>1\)ise \(\mathrm{len}(M_1), \ldots, \mathrm{len}(M_{n-1}) \in \{1,\ldots, \mathrm{CiphertextSegmentSize} - \mathrm{16}\}\).
- \(n>1\)ise \(\mathrm{len}(M_{0}), \ldots, \mathrm{len}(M_{n-2})\) yukarıdaki kısıtlamalara göre maksimum uzunluğa sahip olmalıdır.
\(n\) en fazla olabilir \(2^{32}\). Aksi takdirde şifreleme başarısız olur.
Blokları şifrele
Segmenti şifrelemek için \(M_i\), \(\mathrm{IV}_i := \mathrm{NoncePrefix}
\| \mathrm{i} \| b\)hesaplama yaparız. Burada \(\mathrm{i}\) büyük-endian kodlamasında 4 bayt, $i < n-1$ ise 0x01
ise $b$ değeri 0x00
olur.
Daha sonra, AES-GCM4 kullanılarak şifreleme yaparız. Burada anahtar\(\mathrm{DerivedKey}\), başlatma vektörü \(\mathrm{IV}_i\)ve ilişkili veriler boş dizedir. \(C_i\) Bu şifreleme, \(C_i\) bağlantılı AES-GCM referansının 5.2.1.2 bölümünde \(C\) birleştirilmesiyle elde edilir. \(M_i\) \(T\)
Şifrelenmiş segmentleri birleştirme
Son olarak, tüm segmentler son şifrelenmiş metin olan \(\mathrm{Header} \| C_0 \| \cdots \| C_{n-1}\)olarak birleştirilir.
Şifre çözme
Şifre çözme işlemi, şifrelemeyi ters çevirir. \mathrm{NoncePrefix}$$ öğesini elde etmek ve her bir şifrelenmiş metin segmentinin şifresini ayrı ayrı çözmek için başlığı kullanırız.
API'ler rastgele erişime veya dosyanın sonunu denetlemeden dosyanın başlangıcına erişim izni verebilir (ve genellikle izin verir). Önceki ve kalan tüm şifrelenmiş metin bloklarının şifresini çözmeden \(M_i\) şifreyi \(C_i\)çözmek mümkün olduğu için bu kasıtlı olarak yapılır.
Bununla birlikte, API'ler kullanıcıların dosya sonu ve şifre çözme hatalarını karıştırmalarına izin vermemeye dikkat etmelidir: Her iki durumda da API'nin muhtemelen bir hata döndürmesi gerekir ve aradaki farkı göz ardı etmek, zararlı bir kişinin dosyaları etkili bir şekilde kesebilmesine neden olabilir.
Anahtarların serileştirilmesi ve ayrıştırılması
Bir anahtarı "Tink Proto" biçiminde seri hale getirmek için parametreleri ilk olarak aes_gcm_hkdf_streaming.proto adresinde verilen protokole açık bir şekilde eşleriz. version
alanının 0 olarak
ayarlanması gerekir. Daha sonra, bunu normal proto serileştirmesi kullanarak serileştirir ve elde edilen dizeyi KeyData protokolü alanının değerine yerleştiririz. type_url
alanını type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey
olarak ayarladık. Daha sonra, key_material_type
öğesini SYMMETRIC
olarak ayarladık ve bunu bir anahtar kümesine yerleştirdik. Genellikle output_prefix_type
özelliğini RAW
olarak ayarlarız. Bunun istisnası, anahtarın output_prefix_type
için farklı bir değerle ayrıştırılması durumunda Tink'in RAW
veya önceki değeri yazabilmesidir.
Bir anahtarı ayrıştırmak için yukarıdaki işlemi tersine çeviririz (protoları ayrıştırırken normal şekilde). key_material_type
alanı yoksayılır. output_prefix_type
değeri yoksayılabilir veya RAW
değerinden farklı output_prefix_type
değerine sahip anahtarlar reddedilebilir. version
değeri 0'dan farklı olan anahtarlar reddedilmelidir.
Bilinen sorunlar
Yukarıdaki şifreleme işlevinin uygulamalarının çatallanmaya uygun olması beklenmez. Çatal Güvenliği başlıklı makaleyi inceleyin.
Referanslar
-
Hoang, Reyhanitabar, Rogaway, Vizar, 2015. Online kimliği doğrulanmış şifreleme ve bunun tekrar tekrar olmayan hatalı kullanım direnci. CRYPTO 2015. https://eprint.iacr.org/2015/189 ↩
-
Hoang, Shen, 2020. Google'ın Tenk Kitaplığı'nda Akış Şifrelemesinin Güvenliği. https://eprint.iacr.org/2020/1019 ↩
-
RFC 5869. HMAC tabanlı Ayıklama ve Genişlet Anahtar Türetme İşlevi (HKDF). https://www.rfc-editor.org/rfc/rfc5869 ↩
-
NIST SP 800-38D. Şifreleme Çalışma Modlarını Engelleme Önerisi: Galois/Counter Mode (GCM) ve GMAC. https://csrc.nist.gov/pubs/sp/800/38/d/final ↩