สตรีมมิง AEAD สำหรับ HMAC ของ AES-CTR

เอกสารนี้กำหนดฟังก์ชันทางคณิตศาสตร์อย่างเป็นทางการซึ่งแสดงโดยคีย์สตรีมมิง AES-CTR HMAC (เข้ารหัสในรูปแบบโปรโตเป็น type.googleapis.com/google.crypto.tink.AesCtrHmacStreamingKey)

การเข้ารหัสนี้อิงตาม [HRRV15]1 อย่างคร่าวๆ สําหรับการวิเคราะห์ความปลอดภัย โปรดดูที่ [HS20]2 โปรดทราบว่าการทดสอบข้ามภาษาของ Tink ยังมีไฟล์ทดสอบ aes_ctr_hmac_streaming_key_test.py ซึ่งมี test_manually_created_test_vector พร้อมคำแนะนำแบบสมบูรณ์เกี่ยวกับวิธีรับข้อความที่เข้ารหัส

คีย์และพารามิเตอร์

คีย์จะอธิบายด้วยส่วนต่อไปนี้ (ขนาดทั้งหมดในเอกสารนี้เป็นหน่วยไบต์)

  • \(\mathrm{InitialKeyMaterial}\)ซึ่งเป็นสตริงไบต์: ข้อมูลคีย์เริ่มต้น
  • \(\mathrm{CiphertextSegmentSize} \in \{1, 2, \ldots, 2^{31}-1\}\)
  • \(\mathrm{DerivedKeySize} \in \{16, 32\}\)
  • \(\mathrm{HkdfHashType} \in \{\mathrm{SHA1}, \mathrm{SHA256}, \mathrm{SHA512}\}\)
  • \(\mathrm{HmacHashType} \in \{\mathrm{SHA1}, \mathrm{SHA256}, \mathrm{SHA512}\}\)
  • \(\mathrm{HmacTagSize} \in \mathbb{N}\)

คีย์ที่ถูกต้องจะต้องมีคุณสมบัติตรงตามพร็อพเพอร์ตี้ต่อไปนี้ด้วย

  • \(\mathrm{len}(\mathrm{InitialKeyMaterial}) \geq \mathrm{DerivedKeySize}\)
  • ถ้า \(\mathrm{HmacHashType} = \mathrm{SHA1}\) แล้ว \(\mathrm{HmacTagSize} \in \{10, \ldots, 20\}\)
  • ถ้า \(\mathrm{HmacHashType} = \mathrm{SHA256}\) แล้ว \(\mathrm{HmacTagSize} \in \{10, \ldots, 32\}\)
  • ถ้า \(\mathrm{HmacHashType} = \mathrm{SHA512}\) แล้ว \(\mathrm{HmacTagSize} \in \{10, \ldots, 64\}\)
  • \(\mathrm{CiphertextSegmentSize} > \mathrm{DerivedKeySize} + \mathrm{HmacTagSize} + 8\) (ค่านี้เท่ากับ \(\mathrm{len}(\mathrm{Header}) + \mathrm{HmacTagSize}\) ตามที่อธิบายไว้ภายหลัง)

Tink จะปฏิเสธคีย์ที่ไม่เป็นไปตามคุณสมบัติเหล่านี้ (เมื่อมีการแยกวิเคราะห์คีย์หรือเมื่อสร้างพรอมิตที่เกี่ยวข้อง)

ฟังก์ชันการเข้ารหัส

หากต้องการเข้ารหัสข้อความ \(\mathrm{Msg}\) ที่มีข้อมูลที่เกี่ยวข้อง \(\mathrm{AssociatedData}\)เราจะสร้างส่วนหัว แบ่งข้อความออกเป็นส่วนๆ เข้ารหัสแต่ละส่วน และต่อเชื่อมส่วนต่างๆ เราอธิบายขั้นตอนเหล่านี้ดังต่อไปนี้

การสร้างส่วนหัว

ในการสร้างส่วนหัว ก่อนอื่นเราจะเลือกสตริงแบบสุ่มแบบสม่ำเสมอ \(\mathrm{Salt}\)ที่มีความยาว \(\mathrm{DerivedKeySize}\)ถัดไปเราจะเลือกสตริงแบบสุ่มแบบสม่ำเสมอที่มีความยาว 7\(\mathrm{NoncePrefix}\)

จากนั้นเราตั้งค่า\(\mathrm{Header} := \mathrm{len}(\mathrm{Header}) \| \mathrm{Salt} \| \mathrm{NoncePrefix}\)โดยความยาวของส่วนหัวจะเข้ารหัสเป็นไบต์เดี่ยว เราพบว่า \(\mathrm{len}(\mathrm{Header}) \in \{24, 40\}\)

ถัดไป เราใช้ HKDF3 กับฟังก์ชันแฮช \(\mathrm{HkdfHashType}\)เพื่อคํานวณข้อมูลคีย์ที่มีความยาว \(\mathrm{DerivedKeySize} + 32\) สําหรับข้อความนี้ \(k := \mathrm{HKDF}(\mathrm{InitialKeyMaterial}, \mathrm{Salt}, \mathrm{AssociatedData})\) ระบบจะใช้อินพุตในอินพุตที่เกี่ยวข้องของ \(\mathrm{HKDF}\)โดย \(\mathrm{InitialKeyMaterial}\) คือ \(\mathrm{ikm}\) \(\mathrm{Salt}\) คือเกลือ และ \(\mathrm{AssociatedData}\) จะใช้เป็น \(\mathrm{info}\)

จากนั้น \(k\) สตริงจะแบ่งออกเป็น 2 ส่วน \(k_1 \| k_2 := k\)ดังนี้ \(\mathrm{len}(k_1) = \mathrm{DerivedKeySize}\) และ \(\mathrm{len}(k_2) = 32\)

การแยกข้อความ

ข้อความ \(M\) จะแบ่งออกเป็นส่วนๆ ดังนี้ \(M = M_0 \| M_1 \| \cdots \| M_{n-1}\)

ความยาวของวิดีโอจะเลือกให้เป็นไปตามข้อกำหนดต่อไปนี้

  • \(\mathrm{len}(M_0) \in \{0,\ldots, \mathrm{CiphertextSegmentSize} - \mathrm{len}(\mathrm{Header}) - \mathrm{HmacTagSize}\}\)
  • ถ้า \(n > 1\)ให้ \(\mathrm{len}(M_1), \ldots, \mathrm{len}(M_{n-1}) \in \{1,\ldots, \mathrm{CiphertextSegmentSize} - \mathrm{HmacTagSize}\}\)
  • หาก \(n > 1\)\(M_{0}, \ldots, M_{n-2}\) ต้องมีความยาวสูงสุดตามข้อจำกัดข้างต้น

ในการแยกนี้ \(n\) ต้องมีความยาวไม่เกิน \(2^{32}\)มิฉะนั้นการเข้ารหัสจะไม่สำเร็จ

การเข้ารหัสบล็อก

หากต้องการเข้ารหัสกลุ่ม \(M_i\)ก่อนอื่นเราจะคํานวณ \(\mathrm{IV}_i := \mathrm{NoncePrefix} \| \mathrm{i} \| b \| 0x00000000\) โดยเข้ารหัส \(\mathrm{i}\) เป็น 4 ไบต์โดยใช้การเข้ารหัส Big-Endian และตั้งค่าไบต์ $b$ เป็น 0x00 หาก $i < n-1$ และ 0x01 ในกรณีอื่น

จากนั้นเราจะเข้ารหัส \(M_i\) โดยใช้คีย์ AES CTR \(k_1\)และเวกเตอร์การเริ่มต้น \(\mathrm{IV}_i\)กล่าวคือ อินพุตสําหรับการเรียกใช้ AES คือ \(\mathrm{IV}_i, \mathrm{IV}_i + 1, \mathrm{IV}_i + 2, \ldots\) โดยที่ \(\mathrm{IV}_i\) จะตีความเป็นจํานวนเต็มแบบ Big-endian ซึ่งจะให้ผลลัพธ์เป็น \(C'_i\)

เราคํานวณแท็กโดยใช้ HMAC ด้วยฟังก์ชันแฮชที่ระบุโดย \(\mathrm{HmacHashType}\) และคีย์ \(k_2\) ในการเชื่อมต่อ\(\mathrm{IV}_i \| C'_i\)

จากนั้นเราจะต่อข้อความที่เข้ารหัสตามด้วยแท็กเพื่อรับ \(C_i\)

ต่อกลุ่ม

สุดท้าย ระบบจะต่อกลุ่มทั้งหมดเป็น\(\mathrm{Header} \| C_0 \| \cdots \| C_{n-1}\)ซึ่งเป็นข้อความที่เข้ารหัสขั้นสุดท้าย

ฟังก์ชันการถอดรหัส

การถอดรหัสคือการถอดรหัสการเข้ารหัส เราใช้ส่วนหัวเพื่อรับ Nonce และถอดรหัสข้อความที่เข้ารหัสแต่ละส่วนแยกกัน

API อาจ (และมักจะ) อนุญาตการเข้าถึงแบบสุ่มหรือการเข้าถึงส่วนต้นของไฟล์โดยไม่ตรวจสอบส่วนท้ายของไฟล์ ซึ่งเราตั้งใจให้เป็นแบบนั้น เนื่องจากสามารถถอดรหัส \(M_i\) จาก \(C_i\)ได้โดยไม่ต้องถอดรหัสบล็อกข้อความที่เข้ารหัสก่อนหน้าและที่เหลือทั้งหมด

อย่างไรก็ตาม API ควรระมัดระวังไม่ให้ผู้ใช้สับสนระหว่างข้อผิดพลาดเกี่ยวกับไฟล์สิ้นสุดและข้อผิดพลาดในการถอดรหัส เนื่องจากทั้ง 2 กรณี API อาจต้องแสดงข้อผิดพลาด และ การละเว้นความแตกต่างอาจทําให้คู่แข่งตัดไฟล์ได้อย่างมีประสิทธิภาพ

การจัดรูปแบบและการแยกวิเคราะห์คีย์

หากต้องการจัดรูปแบบคีย์เป็นรูปแบบ "Tink Proto" ก่อนอื่นเราจะแมปพารามิเตอร์ในลักษณะที่ชัดเจนไปยังโปรโตที่ระบุไว้ที่ aes_ctr_hmac_streaming.proto ต้องตั้งค่าช่อง version เป็น 0 จากนั้นเราจะจัดรูปแบบโดยใช้การแปลงเป็นอนุกรมโปรโตปกติ และฝังสตริงที่ได้ไว้ในค่าของช่องโปรโต KeyData เราตั้งค่าช่อง type_url เป็น type.googleapis.com/google.crypto.tink.AesCtrHmacStreamingKey จากนั้นตั้งค่า key_material_type เป็น SYMMETRIC และฝังลงในชุดคีย์ เรามักจะตั้งค่า output_prefix_type เป็น RAW ข้อยกเว้นคือหากมีการแยกวิเคราะห์คีย์ด้วยการตั้งค่าค่าอื่นสําหรับ output_prefix_type ไว้ Tink อาจเขียน RAW หรือค่าก่อนหน้า

หากต้องการแยกวิเคราะห์คีย์ เราจะย้อนกระบวนการข้างต้น (ตามปกติเมื่อแยกวิเคราะห์ Proto) ระบบจะละเว้นช่อง key_material_type ระบบอาจละเว้นค่าของ output_prefix_type หรือปฏิเสธคีย์ที่มี output_prefix_type แตกต่างจาก RAW ระบบจะปฏิเสธคีย์ที่มี version ต่างจาก 0

ข้อมูลอ้างอิง


  1. [HRRV15] Hoang, Reyhanitabar, Rogaway, Vizar. การเข้ารหัสที่ตรวจสอบสิทธิ์ทางออนไลน์และการป้องกันการละเมิดการใช้ Nonce ซ้ำ CRYPTO 2015 https://eprint.iacr.org/2015/189 

  2. [HS20] ความปลอดภัยของการเข้ารหัสสตรีมมิงในไลบรารี Tink ของ Google Hoang, Shen, 2020. https://eprint.iacr.org/2020/1019 

  3. [HKDF] ฟังก์ชันการสร้างคีย์แบบแยกและขยาย (HKDF) ที่ใช้ HMAC RFC 5869 https://www.rfc-editor.org/rfc/rfc5869