จากนั้นเราจะให้คำจำกัดความ (อย่างไม่เป็นทางการ) อย่างเป็นทางการมากขึ้น) 2 ส่วนสำคัญของภาษาที่ใช้ใน Tink ได้แก่ แบบพื้นฐาน และอินเทอร์เฟซ
แบบพื้นฐาน
แบบพื้นฐานคือออบเจ็กต์ทางคณิตศาสตร์ที่ตรงกับอัลกอริทึมทั้งหมดซึ่งทำงานบางอย่างอย่างปลอดภัย ตัวอย่างเช่น AEAD แบบพื้นฐานประกอบด้วยอัลกอริทึมการเข้ารหัสทั้งหมดซึ่งตรงตามคุณสมบัติด้านความปลอดภัยที่ Tink กำหนดให้ใช้ Aead
เราเน้นว่าพื้นฐาน เราไม่ได้ยึดติดกับภาษาโปรแกรมหรือวิธีเข้าถึงภาษาเหล่านั้น แต่ควรมองว่าสูตรดั้งเดิมเป็นวัตถุเชิง คณิตศาสตร์ล้วนๆ ตัวอย่างเช่น หากเราพิจารณา AEAD โดยพื้นฐานแล้ว AEAD จะประกอบไปด้วยฟังก์ชัน 1 คู่ คือ 1 คู่ที่จะเข้ารหัส และ อีก 1 ฟังก์ชันจะถอดรหัส
อินเทอร์เฟซ
อินเทอร์เฟซเป็นวิธีหนึ่งที่เราให้สิทธิ์ผู้ใช้เข้าถึงแบบพื้นฐาน
ตัวอย่างเช่น เราคาดว่าในอนาคต Tink จะมีอินเทอร์เฟซ Mac
รวมถึงอินเทอร์เฟซ StreamingMac
ที่ช่วยให้คำนวณ Mac ของข้อมูลที่ไม่ได้โหลดลงในหน่วยความจำโดยตรง
โปรดทราบว่าเราแยกอินเทอร์เฟซและแบบดั้งเดิมอย่างชัดเจน ซึ่งควรระบุให้ชัดเจนว่าอ็อบเจ็กต์ทางคณิตศาสตร์ที่อินเทอร์เฟซ 2 ตัวนี้ให้สิทธิ์เข้าถึงเป็นอันเดียวกัน
คำจำกัดความอย่างเป็นทางการ
สำหรับผู้อ่านส่วนใหญ่ คำอธิบายที่เข้าใจง่ายข้างต้นก็เพียงพอแล้ว อย่างไรก็ตาม เรารู้สึกว่าในบางครั้งการมอบคำอธิบายอย่างเป็นทางการของแนวคิดเหล่านี้ก็เป็นสิ่งสำคัญ
ฟังก์ชันการเข้ารหัส
แนวคิดของฟังก์ชันวิทยาการเข้ารหัสไม่สำคัญเท่ากับแนวคิดของฟังก์ชันพื้นฐาน แต่เราต้องแนะนําฟังก์ชันดังกล่าวเพื่อกำหนดรูปแบบพื้นฐานอย่างเป็นทางการ
- ฟังก์ชันการเข้ารหัสลับ
ฟังก์ชันการเข้ารหัสคือแผนที่
\[ f: {\bf K} \times {\bf R} \times {\bf I} \to {\bf O}\]
จากชุด \({\bf K}\) (พื้นที่ทำงานคีย์) ชุด \({\bf R} = \{0,1\}^{\infty}\) (ความสุ่ม ซึ่งเราถือว่าเป็นชุดบิตสตริงอนันต์) และ ชุด \({\bf I}\) (พื้นที่อินพุต) เป็นชุด \({\bf O}\) (พื้นที่เอาต์พุต)
เหตุผลที่เราเพิ่มพารามิเตอร์การสุ่มที่เฉพาะเจาะจงให้ชัดเจนในภายหลัง
มาดูตัวอย่างกันว่าแนวคิดเหล่านี้จะเชื่อมโยงกับ AES-GCM ได้อย่างไร สำหรับขนาดคีย์ที่ถูกต้องแต่ละขนาด \(s_k\), ขนาดค่าที่ได้จากการสุ่ม \(s_n\)และขนาดแท็ก \(s_t\)นั้น AES-GCM ประกอบด้วยฟังก์ชันการเข้ารหัส 2 ฟังก์ชัน ฟังก์ชันหนึ่งสำหรับการเข้ารหัส และอีกฟังก์ชันหนึ่งสำหรับการถอดรหัส ทั้ง 2 อย่างนี้จะมีพื้นที่ทำงานคีย์เดียวกัน \({\bf K} = \{0,1\}^{s_k}\)
สำหรับฟังก์ชันการเข้ารหัส \(\mathrm{Enc}\)ระบบจะใช้การสุ่ม \(s_n\) บิตแรกเพื่อเลือกค่าที่ได้จากการสุ่ม
ให้ \({\bf B} = \{0,1\}^8\) ระบุไบต์ พื้นที่อินพุตของฟังก์ชันการเข้ารหัสคือคู่ \({\bf I} = {\bf B}^{*} \times {\bf B}^{*}\) ของคู่สตริงไบต์ที่มีความยาวแตกต่างกัน องค์ประกอบแรกของคู่มีไว้สำหรับข้อความ องค์ประกอบที่สองคือข้อมูลที่เกี่ยวข้อง มาตรฐาน AES-GCM มีการจำกัดความยาวของอินพุต แต่เราแนะนำให้เลือกความยาวที่กำหนดเองมากกว่าและเพิ่มสัญลักษณ์ข้อผิดพลาดพิเศษ \(\bot\) ลงในพื้นที่เอาต์พุตแทน จากนั้นพื้นที่เอาต์พุตจะกลายเป็น \({\bf O} = {\bf B}^* \cup \{\bot\}\)ซึ่งเรากำหนดผลของการคำนวณที่สำเร็จตามการต่อเข้าด้วยกัน \((\mathrm{IV} \| \mathrm{ciphertext} \| \mathrm{tag})\) ตามที่กำหนดไว้ในมาตรฐานและเอาต์พุต\(\bot\)ในกรณีที่อินพุตบางรายการยาวเกินไป ดังนั้น สำหรับคีย์คงที่ ฟังก์ชันการเข้ารหัสจะกลายเป็นประเภท \(\mathrm{Enc}_k : {\bf R} \times {\bf B}^* \times {\bf B}^* \rightarrow {\bf B}^* \cup \{\bot\}\)
สำหรับฟังก์ชันการถอดรหัส \(\mathrm{Dec}\) พื้นที่คีย์จะเหมือนกัน พื้นที่อินพุตจะเหมือนกัน: \({\bf I} ={\bf B}^* \times {\bf B}^*\)แต่ตอนนี้องค์ประกอบแรกมีไว้เพื่อเป็นเอาต์พุตของฟังก์ชันการเข้ารหัส ส่วนองค์ประกอบที่ 2 ยังคงเป็นข้อมูลที่เกี่ยวข้อง
พื้นที่เอาต์พุตก็เหมือนกัน \({\bf O} = {\bf B}^* \cup \{\bot\}\) (บังเอิญอีกครั้ง) การตีความจะแตกต่างไปบ้าง เนื่องจาก \(\bot\) มักจะเกิดจากข้อผิดพลาดในการตรวจสอบสิทธิ์ (และจะยังเป็นผลลัพธ์ในกรณีที่อินพุตบางรายการยาวเกินไป)
เราเน้นย้ำว่าการทำให้เป็นทางการข้างต้นไม่ใช่ตัวเลือกเดียวที่จะทำให้มาตรฐานมีความเป็นทางการมากขึ้น เช่น อาจพิจารณาค่าที่ได้จากการสุ่ม (ซึ่งให้ผลวิธีการดั้งเดิมที่ต่างกันมาก) แทนการอ่านค่าที่ได้จากการสุ่ม อีกทางเลือกหนึ่งอาจกำหนดเอาต์พุตเป็น 3 ค่าที่มี nonce, ข้อความเข้ารหัส และแท็ก (แทนการเชื่อม) หรืออาจจำกัดพื้นที่คีย์ (ตามต้องการ) ให้อยู่ที่\({\bf K} = \{0,1\}^{128} \cup \{0,1\}^{256}\)ก็ได้
- อัลกอริทึมการเข้ารหัส:
อัลกอริทึมการเข้ารหัส (แบบสมมาตร) เป็น tuple
\[(f_1, ... f_k)\]
ของฟังก์ชันวิทยาการเข้ารหัสลับ ซึ่งทุกฟังก์ชันมีคีย์พื้นที่เดียวกัน ประเภทของอัลกอริทึมวิทยาการเข้ารหัสคือ Tuple \((({\bf I}_1, {\bf O}_1), \ldots, ({\bf I}_k, {\bf O}_k))\)
เช่น AES-GCM\({}_{s_k, s_n, s_t}\) คืออัลกอริทึมการเข้ารหัสที่มี ทั้ง 2 ฟังก์ชัน \(\mathrm{Enc}\) และ \(\mathrm{Dec}\) ตามที่อธิบายไว้ข้างต้น สำหรับค่า 3 เท่าของคีย์ ค่าที่ได้จากการสุ่ม และขนาดแท็กที่ถูกต้องแต่ละขนาด \((s_k, s_n, s_t)\)
แบบพื้นฐานและอินเทอร์เฟซ
ต่อไปเราจะนิยามของการเข้ารหัสลับพื้นฐาน
- แบบพื้นฐาน
- แบบพื้นฐานคือชุดอัลกอริทึมวิทยาการเข้ารหัสลับที่อัลกอริทึมทั้งหมดมีประเภทเดียวกัน \((({\bf I}_1, {\bf O}_1), \ldots, ({\bf I}_k, {\bf O}_k))\)และพื้นที่สำคัญของอัลกอริทึมไม่มีคู่กัน
ตัวอย่างเช่น \(\mathrm{AEAD}\) ตัวเลือกพื้นฐานใน Tink โดยมีอัลกอริทึมหลายแบบ เช่น AES-GCM สำหรับขนาดคีย์ 128 และ 256 บิต, ขนาด Nonce 96 บิต, AES-EAX ที่มีขนาดคีย์บางขนาด และ XChaCha20Poly1305 โดยแต่ละคีย์จะมีช่องว่างของคีย์ที่ไม่เชื่อมโยงกัน แต่ทุกฟังก์ชันมีฟังก์ชันในการเข้ารหัสเดียวกัน \(\mathrm{Enc}\) และ \(\mathrm{Dec}\)(เราไม่เห็นจุดประสงค์ในการยุบ AES-GCM ขนาดต่างๆ ที่สำคัญในการพูดคุยอย่างเป็นทางการนี้ แต่ก็แน่นอนว่าสามารถทำได้)
การนิยามค่าดั้งเดิม
วิธีคิดแบบพื้นฐานทั่วไปคือให้กำหนดสมบัติของฟังก์ชันวิทยาการเข้ารหัสก่อน จากนั้นจึงพิจารณาข้อมูลพื้นฐานว่าเป็นอัลกอริทึมทั้งหมด
เช่น สำหรับ AEAD เราจะบอกว่า \(\mathrm{Dec}_k(\mathrm{Enc}_k(m, a), a) = m\) พอใจ 'เสมอ' (ยกเว้นเช่น ถ้าข้อความธรรมดา \(m\) ยาวเกินไป) นอกจากนี้ เรายังมีคุณสมบัติด้านความปลอดภัย เช่น สำหรับคีย์แบบสุ่ม การเข้ารหัสจะมีความปลอดภัยในเชิงความหมาย
จากนั้น AEAD แบบพื้นฐานจะเป็นชุดอัลกอริทึมวิทยาการเข้ารหัสลับทั้งหมดที่ตรงตามพร็อพเพอร์ตี้เหล่านี้ กล่าวคือ ในทางปฏิบัติ เมื่อเราให้คำจำกัดความเบื้องต้นที่เฉพาะเจาะจง เราจะนิยามตามคุณสมบัติ เราไม่ได้แสดงรายการอัลกอริทึม ดังที่นิยามไว้
อินเทอร์เฟซ
อินเทอร์เฟซใน Tink ให้สิทธิ์การเข้าถึงแบบพื้นฐาน ทำให้สามารถคำนวณองค์ประกอบของพื้นที่เอาต์พุตจากพื้นที่อินพุตได้ เช่น ลองพิจารณาอินเทอร์เฟซ AEAD ใน Java
public interface Aead {
byte[] encrypt(byte[] plaintext, byte[] associated_data) throws GeneralSecurityException;
byte[] decrypt(byte[] ciphertext, byte[] associated_data) throws GeneralSecurityException;
}
โปรดทราบว่าเราไม่ให้สิทธิ์เข้าถึงการสุ่ม แต่เราอนุญาตให้ผู้ใช้ ใส่องค์ประกอบของพื้นที่อินพุตแทน การไม่อนุญาตสิทธิ์เข้าถึงการสุ่มเป็น การเจตนา1
บางครั้ง Tink อาจมีอินเทอร์เฟซหลายอินเทอร์เฟซสำหรับรูปแบบพื้นฐานรายการเดียว
ซึ่งอาจเป็นประโยชน์อย่างยิ่ง เนื่องจากบางครั้งข้อกำหนดจะแตกต่างกัน ถึงอย่างนั้น วิธีนี้ต้องเสียค่าใช้จ่าย: โดยทั่วไป ยิ่งมีอินเทอร์เฟซมากเท่าไร ความสามารถในการทำงานร่วมกันก็จะยิ่งต่ำลง เช่น สมมติว่ามีคนเขียนไลบรารีตาม Tink ที่กำหนดให้ผู้ใช้ส่งผ่านออบเจ็กต์ Aead
(เพื่อเข้ารหัสบางอย่างเป็นการภายใน) หาก Tink มีอินเทอร์เฟซที่แตกต่างกันมากเกินไปกับ \(\mathrm{AEAD}\) แบบพื้นฐาน มีโอกาสสูงที่ผู้ใช้จะไม่มีอินสแตนซ์พร้อมใช้งานสำหรับคีย์ที่ผู้ใช้เลือกและไลบรารีพร้อมกัน ดังนั้น การเพิ่มอินเทอร์เฟซจึงถือเป็นข้อเสีย
-
การเข้ารหัส AEAD มีคุณสมบัติเพียงพอต่อการป้องกันการโจมตีในรูปแบบการเข้ารหัสข้อความที่เลือกไว้ ซึ่งจะรับประกันได้เฉพาะในกรณีที่ไม่มีการนำค่าตัวเลขนี้ไปใช้ซ้ำ อินเทอร์เฟซ Aead ใน Tink ออกแบบมาเพื่อป้องกันการใช้ Nonce ซ้ำ โดยผู้ใช้จะไม่สามารถระบุ Nonce เป็นอินพุตสำหรับการเข้ารหัสแทน ระบบจะสร้างค่า Nonce ใหม่แบบสุ่มสำหรับการดำเนินการเข้ารหัสแต่ละรายการ↩