AES-GCM-HKDF Akış AEAD

Bu belgede, proto biçiminde type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey olarak kodlanmış AES-GCM-HKDF akış anahtarlarıyla temsil edilen matematiksel işlev resmi olarak tanımlanmaktadır.

Bu şifreleme, HRRV15'e1 dayanır. Güvenlik analizi için HS202'yi kullanırız.

Anahtar ve parametreler

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

  • \(\mathrm{KeyValue}\), bayt dizesi.
  • \(\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\) (Daha sonra açıklanacağı gibi bu, \(\mathrm{len}(\mathrm{Header}) + 16\) değerine eşittir).

Bu özelliklerin hiçbirini karşılamayan anahtarlar, anahtar ayrıştırıldığında veya ilgili ilkel oluşturulduğunda Tink tarafından reddedilir.

Şifreleme işlevi

Bir mesajı \(\mathrm{Msg}\) ilişkili verilerle\(\mathrm{AssociatedData}\)şifrelemek için bir başlık oluşturur, mesajı segmentlere böler, her segmenti şifreler ve şifrelenmiş segmentleri birleştiririz.

Üstbilgi oluşturma

\(\mathrm{DerivedKeySize}\) uzunluğunda \(\mathrm{Salt}\) tekdüze bir rastgele dize ve 7 uzunluğunda \(\mathrm{NoncePrefix}\)tekdüze bir rastgele dize seçeriz.

Ardından, başlığın uzunluğunun tek bir bayt olarak kodlandığı \(\mathrm{Header} := \mathrm{len}(\mathrm{Header}) \| \mathrm{Salt} \| \mathrm{NoncePrefix}\)değerini belirleriz. \(\mathrm{len}(\mathrm{Header}) \in \{24, 40\}\)

Ardından, \(\mathrm{HkdfHashType}\)tarafından sağlanan karma işleviyle HKDF3'ü ve \(\mathrm{ikm} := \mathrm{KeyValue}\), \(\mathrm{salt} := \mathrm{Salt}\)ve \(\mathrm{info} := \mathrm{AssociatedData}\)girişlerini, \(\mathrm{DerivedKeySize}\)çıkış uzunluğuyla kullanırız. Sonuç, \(\mathrm{DerivedKey}\)olarak adlandırılır.

İletiyi bölme

Ardından mesaj \(\mathrm{Msg}\) aşağıdaki bölümlere ayrılır: \(\mathrm{Msg} = M_0 \| M_1 \| \cdots \| M_{n-1}\).

Uzunlukları şu koşulları 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 uzunlukta olmalıdır.

\(n\) en fazla \(2^{32}\)karakter olabilir. Aksi takdirde şifreleme başarısız olur.

Blokları şifreleme

\(M_i\)segmentini şifrelemek için \(\mathrm{IV}_i := \mathrm{NoncePrefix} \| \mathrm{i} \| b\)değerini hesaplarız. Burada \(\mathrm{i}\) , büyük endian kodlamasında 4 bayttır ve $b$ baytı, $i < n-1$ ise 0x00, aksi takdirde 0x01 olur.

Ardından,\(\mathrm{DerivedKey}\)anahtarının, \(\mathrm{IV}_i\)başlatma vektörünün ve boş dizenin ilişkili olduğu veriler olduğu AES-GCM4 kullanılarak \(M_i\) şifrelenir. \(C_i\) , bu şifrelemenin sonucudur (yani, bağlantı verilen AES-GCM referansının 5.2.1.2 numaralı bölümündeki \(C\) ve \(T\) dizelerinin birleştirilmesi).

Şifrelenmiş segmentleri birbirine bağlama

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

Şifre çözme

Şifre çözme işlemi, şifrelemeyi tersine çevirir.\(\mathrm{NoncePrefix}\)değerini almak için başlığı kullanır ve şifrelenmiş metnin her segmentinin şifresini tek tek çözeriz.

API'ler rastgele erişime veya dosyanın sonunu incelemeden dosyanın başına erişime izin verebilir (ve genellikle verir). Önceki ve kalan tüm şifrelenmiş metin bloklarının şifresini çözmeden \(M_i\) \(C_i\)'den şifresini çözmek mümkün olduğundan bu durum bilinçli olarak tasarlanmıştır.

Ancak API'ler, kullanıcıların dosya sonu ve şifre çözme hatalarını karıştırmasına izin vermemelidir: Her iki durumda da API'nin bir hata döndürmesi muhtemeldir ve bu farkın göz ardı edilmesi, saldırganların dosyaları etkili bir şekilde kısaltmasına neden olabilir.

Anahtarları serileştirme ve ayrıştırma

Bir anahtarı "Tink Proto" biçiminde serileştirmek için önce parametreleri aes_gcm_hkdf_streaming.proto adresinde verilen proto ile açık bir şekilde eşleriz. version alanının 0 olarak ayarlanması gerekir. Ardından, normal proto serileştirmesini kullanarak bunu serileştiririz ve elde edilen dizeyi bir KeyData protosunun value alanına yerleştiririz. type_url alanını type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey olarak ayarladık. Ardından key_material_type değerini SYMMETRIC olarak ayarlayıp bunu bir anahtar grubuna yerleştiririz. Genellikle output_prefix_type değerini RAW olarak belirleriz. Bunun istisnası, anahtar output_prefix_type için farklı bir değer ayarlanarak ayrıştırılmışsa 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 kullanılan normal şekilde). key_material_type alanı yoksayılır. output_prefix_type değeri yoksayılabilir veya RAW ile farklı output_prefix_type değerlerine sahip anahtarlar reddedilebilir. version değeri 0'dan farklı olan anahtarlar reddedilmelidir.

Bilinen sorunlar

Yukarıdaki şifreleme işlevinin uygulamalarının çatallamaya karşı güvenli olması beklenmez. Fork Safety başlıklı makaleyi inceleyin.

Referanslar


  1. Hoang, Reyhanitabar, Rogaway, Vizar, 2015. Online kimlik doğrulaması yapılmış şifreleme ve tek seferlik rastgele sayı yeniden kullanımıyla ilgili kötüye kullanıma karşı direnç. CRYPTO 2015. https://eprint.iacr.org/2015/189 

  2. Hoang, Shen, 2020. Google'ın Tink Kitaplığında Akış Şifreleme'nin Güvenliği. https://eprint.iacr.org/2020/1019 

  3. RFC 5869. HMAC tabanlı Anahtar Çıkarma ve Genişletme İşlevi (HKDF). https://www.rfc-editor.org/rfc/rfc5869 

  4. NIST SP 800-38D. Blok Şifre Çalışma Modları için Öneri: Galois/Karşı Mod (GCM) ve GMAC. https://csrc.nist.gov/pubs/sp/800/38/d/final