AES-GCM-HKDF Akış AEAD

Bu belgede, AES-GCM-HKDF Akış anahtarları (type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey olarak proto biçiminde kodlanmıştır) tarafından temsil edilen matematik işlevi açıklanmaktadır.

Bu şifreleme genel olarak [HRRV15]1'e dayalıdır. Güvenlik analizi için [HS20]2 adresini ziyaret edebilirsiniz.

Anahtar ve parametreler

Anahtarlar aşağıdaki bölümlerde açıklanmıştır (bu belgedeki tüm boyutlar bayt cinsindendir):

  • \(\mathrm{KeyValue}\), bir baytlık dizedir.
  • \(\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 karşılar:

  • \(\mathrm{len}(\mathrm{KeyValue}) \geq \mathrm{DerivedKeySize}\).
  • \(\mathrm{CiphertextSegmentSize} > \mathrm{DerivedKeySize} + 24\) (Bu, daha sonra açıklandığı gibi \(\mathrm{len}(\mathrm{Header}) + 16\) eşittir).

Bu özelliklerden herhangi birine uymayan anahtarlar Tink tarafından reddedilir (anahtar ayrıştırıldığında veya karşılık gelen temel öğe oluşturulduğunda).

Şifreleme işlevi

Bir iletiyi \(\mathrm{Msg}\) ilişkili verilerle\(\mathrm{AssociatedData}\)şifrelemek için bir başlık oluşturur, iletiyi segmentlere ayırır, her bir segmenti şifreler ve segmentleri birleştiririz. Bu adımlar aşağıda açıklanmıştır.

Başlık oluşturma

Üstbilgiyi oluşturmak için önce \(\mathrm{Salt}\) uzunluğunda \(\mathrm{DerivedKeySize}\)tek tip bir rastgele dize seçeriz. Sonra, 7 uzunluğunda tek tip bir rastgele \(\mathrm{NoncePrefix}\) dize seçeriz.

Daha sonra, başlığın uzunluğu tek bayt olarak kodlanan\(\mathrm{Header} := \mathrm{len}(\mathrm{Header}) \| \mathrm{Salt} \| \mathrm{NoncePrefix}\)öğesini ayarlarız. Not: \(\mathrm{len}(\mathrm{Header}) \in \{24, 40\}\).

Ardından, \(\mathrm{HkdfHashType}\)ve girişlerin \(\mathrm{ikm} := \mathrm{KeyValue}\),\(\mathrm{salt} := \mathrm{Salt}\)ve\(\mathrm{info} := \mathrm{AssociatedData}\)girişlerinin yanı sıra çıkış uzunluğu \(\mathrm{DerivedKeySize}\)ile HKDF3'ü kullanıyoruz. Bu sonuca \(k\)diyoruz.

İletiyi bölme

Mesaj \(\mathrm{Msg}\) daha sonra bölümlere ayrılır: \(\mathrm{Msg} = M_0 \| M_1 \| \cdots \| M_{n-1}\).

Uzunlukları aşağıdaki gereksinimleri karşılayacak şekilde 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.

Bu bölmede, \(n\) en fazla \(2^{32}\)olabilir. Aksi takdirde, şifreleme başarısız olur.

Blokları şifreleme

Segmenti \(M_i\)şifrelemek için ilk olarak\(\mathrm{IV}_i := \mathrm{NoncePrefix} \| \mathrm{i} \| b\)işlemini hesaplarız. Bu hesaplamada,\(\mathrm{i}\) büyük uçlu kodlama kullanarak\(\mathrm{i}\) 4 baytı kodlar, $i <n-1$ olması halinde $b$ baytını 0x00, aksi takdirde 0x01 olarak ayarlarız.

Daha sonra \(M_i\) AES GCM kullanarak4 şifrelemeleri yaparız. Burada anahtar \(\mathrm{DerivedKey}\), başlatma vektörü \(\mathrm{IV}_i\) ve ilişkili veriler \(A\) boş dizedir. \(C_i\) öğesini bu şifrelemenin sonucu olacak şekilde ayarladık (yani, \(C\) ve \(T\) yukarıdaki referansta birleştirilmesi).

Segmentleri birleştirin

Son olarak, tüm segmentler nihai şifrelenmiş metin olan\(\mathrm{Header} \| C_0 \| \cdots \| C_{n-1}\)olarak birleştirilir.

Şifre çözme

Şifre çözme, şifrelemeyi tersine çevirir. Tek seferlik rastgele metni elde etmek ve her bir şifreli metnin şifresini çözmek için başlığı kullanırız.

API'ler, rastgele erişime veya dosyanın sonunu incelemeden dosyanın başlangıcına erişime izin verebilir (ve tipik olarak bunu yapar). Önceki ve kalan tüm şifrelenmiş metin bloklarının şifresini çözmeden \(M_i\) \(C_i\)ürününün şifresini çözmek mümkün olduğundan bu yöntem kasıtlıdır.

Ancak API'ler, kullanıcıların dosya sonu ve şifre çözme hatalarını karıştırmasına izin vermemeye dikkat etmelidir: Her iki durumda da API'nin bir hata döndürmesi gerekir ve fark göz ardı edildiğinde kötü niyetli kişi dosyaları etkili bir şekilde kırpabilir.

Anahtarların serileştirilmesi ve ayrıştırılması

Bir anahtarı "Tink Proto" biçiminde serileştirmek için önce parametreleri açık bir şekilde aes_gcm_hkdf_streaming.proto adresinde verilen protoda eşliyoruz. version alanı 0 olarak ayarlanmalıdır. Daha sonra, bunu normal proto serileştirmeyi kullanarak serileştiririz ve elde edilen dizeyi, bir KeyData protosunun alan değerine yerleştiririz. type_url alanını type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey olarak ayarlıyoruz. Ardından key_material_type öğesini SYMMETRIC olarak ayarlayıp bir anahtar kümesine yerleştiriyoruz. output_prefix_type genellikle RAW olarak ayarlanır. İstisna olarak, anahtar output_prefix_type için farklı bir değerle ayrıştırılırsa Tink, RAW değerini veya önceki değeri yazabilir.

Bir anahtarı ayrıştırmak için yukarıdaki işlemi geri alırız (proto'ları ayrıştırırken normal şekilde). key_material_type alanı yoksayılır. output_prefix_type değeri yoksayılabilir veya output_prefix_type değeri RAW değerinden farklı olan anahtarlar reddedilebilir. version değeri 0'dan farklı olan anahtarlar reddedilmelidir.

Bilinen sorunlar

Yukarıdaki şifreleme işlevinin uygulamalarının, çatallama açısından güvenli olması beklenmez. Çatal Güvenliği bölümüne bakın.

Referanslar


  1. [HRRV15] Hoang, Reyhanitabar, Rogaway, Vizar. Online kimliği doğrulanmış şifreleme ve tek seferlik tekrar olmayan hatalı kullanım direnci. KRİPTO 2015. https://eprint.iacr.org/2015/189 

  2. [HS20] Google'ın Tink Library'de Akış Şifreleme Güvenliği. Hoang, Shen, 2020. https://eprint.iacr.org/2020/1019 

  3. [HKDF] HMAC Tabanlı Ayıklama ve Genişletme Anahtar Türetme İşlevi (HKDF), RFC 5869. https://www.rfc-editor.org/rfc/rfc5869 

  4. NIST SP 800-38D, Blok Şifre Çalışma Modları için Öneri: Galois/Sayaç Modu (GCM) ve GMAC.