มองแนวคิด security-by-construction ของ Daniel J. Bernstein ในเชิงปฏิบัติ—จาก qmail ถึง Curve25519—และความหมายของ “คริปโตเรียบง่ายที่ยืนยันได้” ในการใช้งานจริง

Security-by-construction คือการสร้างระบบให้ความผิดพลาดทั่วไปทำได้ยากขึ้น—และเมื่อเกิดข้อผิดพลาดที่หลีกเลี่ยงไม่ได้ ผลกระทบจะถูกจำกัดไว้ แทนที่จะพึ่งพาเช็คลิสต์ยาว ๆ ("อย่าลืมตรวจ X, ทำความสะอาด Y, ตั้งค่า Z...") คุณออกแบบซอฟต์แวร์ให้เส้นทางที่ปลอดภัยที่สุดเป็นเส้นทางที่ง่ายที่สุด
คิดแบบบรรจุภัณฑ์กันเด็ก: มันไม่สมมติว่าทุกคนจะระมัดระวังอย่างสมบูรณ์ แต่สมมติว่ามนุษย์เหนื่อย งานยุ่ง และบางครั้งก็ทำผิด การออกแบบที่ดีลดปริมาณพฤติกรรมที่ต้องการจากนักพัฒนา ผู้ดูแล และผู้ใช้
ปัญหาด้านความปลอดภัยมักซ่อนตัวในความซับซ้อน: ฟีเจอร์มากเกินไป ตัวเลือกมากเกินไป ปฏิสัมพันธ์ระหว่างคอมโพเนนต์มากเกินไป ปุ่มปรับแต่ละอันสามารถสร้างโหมดความล้มเหลวใหม่—วิธีที่ไม่คาดคิดที่ระบบจะพังหรือถูกใช้งานผิด
ความเรียบง่ายช่วยในสองทางที่เป็นรูปธรรม:
นี่ไม่ใช่เรื่องมินิมอลเพื่อความชอบส่วนตัว แต่มันคือการทำให้ชุดพฤติกรรมเล็กพอที่คุณจะเข้าใจ ทดสอบ และคิดได้ว่ามันจะเกิดอะไรขึ้นเมื่อมีบางอย่างผิดพลาด
บทความนี้ใช้ผลงานของ Daniel J. Bernstein เป็นตัวอย่างเชิงปฏิบัติของ security-by-construction: qmail มุ่งลดโหมดความล้มเหลวอย่างไร, ความคิดแบบ constant-time ป้องกันการรั่วที่มองไม่เห็นอย่างไร, และ Curve25519/X25519 กับ NaCl ผลักดันไปสู่คริปโตที่ยากต่อการใช้งานผิดได้อย่างไร
สิ่งที่จะไม่ทำ: ให้ประวัติศาสตร์เต็มรูปแบบของคริปโต พิสูจน์ว่าอัลกอริทึมปลอดภัย หรืออ้างว่าไลบรารีตัวเดียว "ดีที่สุด" สำหรับทุกผลิตภัณฑ์ และจะไม่ทำเหมือนอ็ปริมิติฟดี ๆ แก้ปัญหาทุกอย่าง—ระบบจริงยังล้มเหลวเพราะการจัดการคีย์ การรวมระบบผิดพลาด และช่องว่างด้านปฏิบัติการ
เป้าหมายง่าย ๆ: แสดงรูปแบบการออกแบบที่ทำให้ผลลัพธ์ที่ปลอดภัยมีแนวโน้มเกิดขึ้นมากขึ้น แม้ว่าคุณจะไม่ใช่ผู้เชี่ยวชาญด้านคริปโตก็ตาม
Daniel J. Bernstein (มักเรียกย่อว่า “DJB”) เป็นนักคณิตศาสตร์และวิทยาการคอมพิวเตอร์ ผลงานของเขาปรากฏบ่อยในวิศวกรรมความปลอดภัยเชิงปฏิบัติ: ระบบอีเมล (qmail), อ็อพทิมิทีฟและโปรโตคอลคริปโต (โดยเฉพาะ Curve25519/X25519), และไลบรารีที่ห่อคริปโตให้ใช้งานจริงได้ (NaCl)
ผู้คนอ้างถึง DJB ไม่ใช่เพราะเขาเป็นผู้เดียวที่ "ถูกต้อง" แต่เพราะโปรเจกต์ของเขามีสัญชาตญาณด้านวิศวกรรมที่สอดคล้องกันซึ่งลดจำนวนวิธีที่ระบบจะผิดพลาดได้
ธีมที่เกิดซ้ำคือ อินเทอร์เฟซที่เล็กและเข้มงวด หากระบบเปิดจุดเข้าออกและตัวเลือกการตั้งค่าน้อยลง การตรวจสอบและทดสอบจะง่ายขึ้นและการใช้งานผิดพลาดโดยไม่ได้ตั้งใจก็ยากขึ้น
อีกธีมคือ สมมติฐานที่ชัดเจน ความล้มเหลวมักเกิดจากความคาดหวังที่ไม่ได้พูด—เกี่ยวกับความสุ่ม พฤติกรรมเวลา การจัดการข้อผิดพลาด หรือวิธีเก็บคีย์ งานเขียนและการใช้งานของ DJB มักทำให้โมเดลภัยคุกคามชัดเจน: ปกป้องอะไร จากใคร และภายใต้เงื่อนไขใด
สุดท้ายมีแนวโน้มสู่ ค่าเริ่มต้นที่ปลอดภัย และ ความถูกต้องที่น่าเบื่อ การออกแบบหลายอย่างในประเพณีนี้พยายามขจัดขอบคมที่นำไปสู่บั๊กละเอียดอ่อน: พารามิเตอร์กำกวม โหมดที่เป็นทางเลือก และทางลัดเชิงประสิทธิภาพที่รั่วข้อมูล
บทความนี้ไม่ใช่เรื่องชีวิตหรือถกเถียงเรื่องบุคลิกภาพ แต่เป็นการอ่านเชิงวิศวกรรม: รูปแบบที่สังเกตได้ใน qmail, แนวคิด constant-time, Curve25519/X25519, และ NaCl และวิธีที่รูปแบบเหล่านั้นแมปไปสู่การสร้างระบบที่ง่ายต่อการยืนยันและทนทานขึ้นในสภาพการใช้งานจริง
qmail ถูกสร้างมาแก้ปัญหาไม่หรูหรา: ส่งอีเมลอย่างเชื่อถือได้ ในขณะที่ถือว่าเซิร์ฟเวอร์เมลเป็นเป้าหมายที่มีมูลค่าสูง ระบบเมลอยู่บนอินเทอร์เน็ต รับข้อมูลเป็นศัตรูตลอดวัน และจัดการข้อมูลอ่อนไหว (ข้อความ ข้อมูลประจำตัว กฎการส่งต่อ) ในอดีต บั๊กหนึ่งจุดในเดมอนเมลมอนอลิธิกอาจหมายถึงการถูกเจาะทั้งระบบ—หรือการสูญหายของข้อความโดยไม่มีใครสังเกตจนสายเกินไป
แนวคิดที่เด่นใน qmail คือแยก "การส่งเมล" ออกเป็นโปรแกรมเล็ก ๆ แต่ละตัวทำงานเดียว: รับ คิว ส่งท้องถิ่น ส่งระยะไกล ฯลฯ แต่ละส่วนมีอินเทอร์เฟซแคบและความรับผิดชอบจำกัด
การแยกนี้สำคัญเพราะความล้มเหลวจะเป็นท้องถิ่น:
นี่คือ security-by-construction ในรูปแบบปฏิบัติ: ออกแบบระบบให้ "ความผิดพลาดหนึ่งครั้ง" มีโอกาสน้อยที่จะกลายเป็น "ความล้มเหลวทั้งหมด"
qmail ยังเป็นแบบอย่างของนิสัยที่ใช้ได้เกินวงการอีเมล:
ข้อสรุปไม่ใช่ "ใช้ qmail" แต่คือคุณมักได้กำไรด้านความปลอดภัยมากโดยการออกแบบใหม่เพื่อลดโหมดความล้มเหลวก่อนเขียนโค้ดเพิ่มหรือเพิ่มปุ่มปรับ
"พื้นผิวการโจมตี" คือผลรวมของทุกที่ที่ระบบของคุณถูกแตะ ถูกกระตุ้น หรือถูกหลอกให้ทำสิ่งผิด ทางหนึ่งที่ช่วยได้คือการลดจำนวนจุดเข้าออก อุปมาเหมือนบ้าน: ประตู หน้าต่าง ที่เปิดโรงรถ กุญแจสำรอง ช่องส่งของ ทุกอย่างคือทางเข้า คุณอาจติดตั้งล็อกที่ดีกว่า แต่ปลอดภัยขึ้นด้วยการมีทางเข้าน้อยลงตั้งแต่แรก
ซอฟต์แวร์ก็เหมือนกัน พอร์ตที่เปิด รูปแบบไฟล์ที่ยอมรับ จุดแอดมินที่เปิด เฟล็กการตั้งค่า และฮุกปลั๊กอิน ทุกอย่างเพิ่มวิธีที่ระบบอาจพัง
"อินเทอร์เฟซที่แคบ" คือ API ที่ทำงานน้อยลง ยอมรับความหลากหลายน้อยลง และปฏิเสธอินพุตที่กำกวม แม้มันจะรู้สึกจำกัด แต่มันง่ายขึ้นที่จะป้องกันเพราะมีเส้นทางโค้ดน้อยลงให้ตรวจสอบและปฏิสัมพันธ์ที่น่าประหลาดใจน้อยลง
ลองพิจารณาการออกแบบสองแบบ:
การออกแบบที่สองลดสิ่งที่ผู้โจมตีปรับแต่งได้ และลดสิ่งที่ทีมของคุณอาจตั้งค่าผิด
ตัวเลือกทวีความยุ่งยากในการทดสอบ ถ้าคุณสนับสนุนท็อกเกิล 10 ตัว คุณไม่ได้มีพฤติกรรมแค่ 10 แบบ—คุณมีการรวมกันหลายแบบ บั๊กความปลอดภัยมักเกิดในรอยต่อเหล่านั้น: "สวิตช์นี้ปิดการตรวจ" "โหมดนี้ข้ามการตรวจสอบ" "การตั้งค่าเก่าข้ามการจำกัดอัตรา" อินเทอร์เฟซที่แคบเปลี่ยน "เลือกการผจญภัยความปลอดภัย" ให้เป็นเส้นทางเดียวที่สว่างชัด
ใช้รายการนี้เพื่อหาพื้นผิวโจมตีที่เติบโตโดยเงียบ ๆ:
เมื่อไม่สามารถย่ออินเทอร์เฟซได้ ให้ทำให้เข้มงวด: ตรวจตั้งแต่ต้น ปฏิเสธฟิลด์ไม่รู้จัก และเก็บฟีเจอร์พลังสูงไว้หลังเอนด์พอยต์ที่จำกัดขอบเขต
พฤติกรรม "constant-time" หมายถึงการคำนวณใช้เวลาที่ (โดยประมาณ) เท่าเดิมไม่ว่าค่าลับจะเป็นอะไร เป้าหมายไม่ใช่ทำให้เร็ว แต่ทำให้ "น่าเบื่อ": ถ้าผู้โจมตีไม่สามารถจับคู่เวลารันกับค่าลับ พวกเขาจะยากขึ้นมากที่จะดึงค่าลับโดยการสังเกต
การรั่วไหลจากเวลาเป็นเรื่องสำคัญเพราะผู้โจมตีไม่จำเป็นต้องถอดรหัสทางคณิตศาสตร์ ถ้าพวกเขารันการดำเนินการซ้ำ ๆ (หรือดูมันบนฮาร์ดแวร์ที่ใช้ร่วมกัน) ความแตกต่างเล็ก ๆ — ไมโครวินาที นาโนวินาที หรือผลกระทบจากแคช — อาจเผยแพทเทิร์นที่สะสมจนสามารถกู้คีย์ได้
โค้ดปกติ ๆ ก็อาจทำงานต่างกันตามข้อมูล:
if (secret_bit) { ... } เปลี่ยนการไหลของการควบคุมและมักเปลี่ยนเวลาคุณไม่จำเป็นต้องอ่านแอสเซมบลีเพื่อให้ได้ค่าจากการตรวจสอบ:
การคิดแบบ constant-time น้อยกว่าจะเป็นการกระทำฮีโร่ แต่เป็นวินัย: ออกแบบโค้ดให้ความลับไม่สามารถชี้ทิศทางเวลาการทำงานได้ตั้งแต่ต้น
การแลกเปลี่ยนคีย์แบบ elliptic-curve เป็นวิธีให้สองฝ่ายสร้าง shared secret เดียวกัน แม้ว่าพวกเขาจะส่งข้อความ "สาธารณะ" ข้ามเครือข่ายเท่านั้น ฝ่ายแต่ละฝ่ายสร้างค่าลับส่วนตัวและค่าพับลิคที่สอดคล้อง หลังจากแลกค่าพับลิค ทั้งสองรวมคีย์ส่วนตัวของตนกับคีย์สาธารณะของอีกฝ่ายเพื่อให้ได้ shared secret เดียว ผู้ดักฟังเห็นแต่ค่าพับลิคแต่ไม่สามารถกู้ shared secret ได้อย่างมีเหตุผล ฝ่ายทั้งสองจึงสามารถสกัดกุญแจเข้ารหัสสมมาตรและสื่อสารเป็นส่วนตัวได้
Curve25519 เป็นเคิร์ฟพื้นฐาน; X25519 เป็นฟังก์ชันแลกเปลี่ยนคีย์ที่เป็นมาตรฐานซึ่งระบุ "ทำสิ่งนี้เฉพาะ" ขึ้นบนมัน ความน่าสนใจมาจาก security-by-construction: ลด foot-gun พารามิเตอร์น้อยลง ตัวเลือกน้อยลง และโอกาสน้อยที่จะเลือกการตั้งค่าที่ไม่ปลอดภัยโดยไม่ตั้งใจ
มันยังเร็วบนฮาร์ดแวร์หลากหลาย ซึ่งสำคัญสำหรับเซิร์ฟเวอร์ที่รับการเชื่อมต่อจำนวนมากและโทรศัพท์ที่ต้องประหยัดแบตเตอรี การออกแบบยังส่งเสริมการนำไปใช้งานที่ง่ายต่อการรักษาให้เป็น constant-time (ช่วยต้านการโจมตีแบบเวลาที่รั่ว) ซึ่งลดความเสี่ยงที่ผู้โจมตีจะดึงคีย์ด้วยการวัดความต่างเล็ก ๆ ในประสิทธิภาพ
X25519 ให้คุณ ตกลงคีย์: ช่วยสองฝ่ายสกัด shared secret สำหรับการเข้ารหัสสมมาตร
มัน ไม่ ให้การยืนยันตัวตนด้วยตัวมันเอง หากคุณรัน X25519 โดยไม่ยืนยันว่ากำลังคุยกับใคร (เช่น ด้วยใบรับรอง ลายเซ็น หรืิอคีย์ที่แชร์ล่วงหน้า) คุณยังอาจถูกหลอกให้คุยกับฝ่ายที่ผิด กล่าวคือ: X25519 ป้องกันการดักฟัง แต่ไม่ป้องกันการแอบอ้างเพียงลำพัง
NaCl (Networking and Cryptography library) ถูกสร้างด้วยเป้าหมายง่าย ๆ: ทำให้ยากสำหรับนักพัฒนาแอปที่จะประกอบคริปโตผิดพลาด แทนที่จะยื่นบุฟเฟต์อัลกอริทึม โหมด กฎการเติม และตัวปรับแต่ง ไว้ข้างหน้า NaCl ผลักคุณไปยังชุดการดำเนินการระดับสูงเล็ก ๆ ที่ต่อกันอย่างปลอดภัยแล้ว
box และ secretbox เป็นบล็อกที่ปลอดภัยกว่าAPI ของ NaCl ตั้งชื่อตามสิ่งที่คุณต้องการทำ ไม่ใช่ตามอัลกอริทึมที่คุณจะเอามาประกอบ
crypto_box (box): การเข้ารหัสสาธารณะ-คีย์ที่มีการยืนยันผู้ส่ง คุณให้คีย์ส่วนตัวของคุณ คีย์สาธารณะของผู้รับ nonce และข้อความ แล้วได้ ciphertext ที่ (ก) ซ่อนข้อความ และ (ข) ยืนยันมาจากคนที่ถือคีย์ที่ถูกต้องcrypto_secretbox (secretbox): การเข้ารหัสแบบคีย์ร่วมที่มีการยืนยัน แนวคิดเดียวกันแต่ใช้คีย์ร่วมเดียวประโยชน์หลักคือคุณไม่ต้องแยกเลือก "โหมดการเข้ารหัส" และ "อัลกอริทึม MAC" แล้วหวังว่าคุณจะประกอบถูกต้อง ค่าเริ่มต้นของ NaCl บังคับให้การประกอบเป็นวิธีที่ทันสมัยและต้านการใช้งานผิด (encrypt-then-authenticate) จึงลดโหมดความล้มเหลวทั่วไปเช่น การลืมตรวจความสมบูรณ์
ความเข้มงวดของ NaCl อาจรู้สึกจำกัดถ้าคุณต้องการความเข้ากันแบบเก่า รูปแบบเฉพาะ หรืออัลกอริทึมที่กฎหมายกำหนด คุณแลก "ตั้งพารามิเตอร์ทุกตัวได้" กับ "สามารถส่งของที่ปลอดภัยได้โดยไม่ต้องเป็นผู้เชี่ยวชาญคริปโต" สำหรับผลิตภัณฑ์หลายอย่าง นี่แหละคือจุดประสงค์: จำกัดพื้นที่ออกแบบเพื่อให้บั๊กน้อยลง ถ้าจำเป็นต้องปรับแต่งจริง ๆ คุณสามารถลงไปใช้พรินมิติฟระดับต่ำกว่าได้—แต่คุณกำลังยอมรับขอบคมอีกครั้ง
"ปลอดภัยตามค่าเริ่มต้น" หมายถึงตัวเลือกที่ปลอดภัยที่สุดและสมเหตุสมผลที่สุดคือสิ่งที่คุณได้เมื่อไม่ทำอะไร หากนักพัฒนาติดตั้งไลบรารี คัดลอกตัวอย่างด่วน หรือใช้ค่าเริ่มต้นของเฟรมเวิร์ก ผลลัพธ์ควรยากต่อการใช้งานผิดและยากต่อการอ่อนแอโดยไม่ได้ตั้งใจ
ค่าเริ่มต้นสำคัญเพราะระบบจริงมักรันด้วยค่าเหล่านั้น ทีมเคลื่อนไหวเร็ว เอกสารถูกอ่านแบบผิวเผิน และการตั้งค่าขยายตัวตามธรรมชาติ ถ้าค่าเริ่มต้นเป็น "ยืดหยุ่น" มักแปลว่า "ง่ายจะตั้งค่าผิด"
ความล้มเหลวของคริปโตไม่ใช่แค่เพราะ "คณิตศาสตร์ผิด" มักเกิดจากการเลือกการตั้งค่าที่อันตรายเพราะมันพร้อมใช้งาน คุ้นเคย หรือสะดวก ตัวอย่างกับดักค่าเริ่มต้น:
เลือกสแตกที่ทำให้เส้นทางปลอดภัยเป็นเส้นทางที่ง่ายที่สุด: พรินมิติฟที่ผ่านการตรวจสอบ พารามิเตอร์ที่อนุรักษ์นิยม และ API ที่ไม่ถามให้คุณตัดสินใจเสี่ยง หากไลบรารีบังคับให้เลือกอัลกอริทึมสิบตัว โหมดห้าแบบ และการเข้ารหัสหลายรูปแบบ คุณกำลังทำวิศวกรรมความปลอดภัยด้วยการตั้งค่า
เมื่อเป็นไปได้ ให้เลือกไลบรารีและออกแบบที่:
security-by-construction เป็นส่วนหนึ่งของการปฏิเสธที่จะเปลี่ยนการตัดสินใจทุกอย่างเป็นเมนูดรอปดาวน์
"ยืนยันได้" ในทีมผลิตภัณฑ์ส่วนใหญ่ไม่ได้หมายถึง "พิสูจน์เชิงรูปแบบ" แต่มันคือความสามารถสร้างความมั่นใจได้เร็ว ทำซ้ำได้ และมีโอกาสน้อยที่คนจะเข้าใจผิดว่าโค้ดทำอะไร
โค้ดเป็นไปได้ว่าจะยืนยันได้มากขึ้นเมื่อ:
ทุกสาขา โหมด และฟีเจอร์พิเศษ เพิ่มสถานะที่ผู้ตรวจสอบต้องคิดถึง อินเทอร์เฟซที่เรียบง่ายจำกัดชุดสถานะที่เป็นไปได้ ซึ่งช่วยปรับปรุงคุณภาพการตรวจสอบในสองทาง:
ทำให้มันน่าเบื่อและทำซ้ำได้:
ชุดนี้จะไม่ทดแทนการตรวจสอบจากผู้เชี่ยวชาญ แต่จะยกระดับพื้นฐาน: มีความประหลาดใจน้อยลง ตรวจจับเร็วขึ้น และโค้ดที่คุณพอจะคิดตามได้จริง
แม้ว่าคุณจะเลือกพรินมิติฟที่ได้รับการยอมรับเช่น X25519 หรือ API แบบ NaCl รูปแบบระบบยังล้มเหลวที่ส่วนที่ยุ่งเหยิง: การรวม การเข้ารหัสรูปแบบ (encoding) และการปฏิบัติการ เหตุการณ์ในโลกจริงส่วนใหญ่ไม่ใช่ "คณิตศาสตร์ผิด" แต่เป็น "คณิตศาสตร์ถูกใช้ผิด"
ความผิดพลาดในการจัดการคีย์ พบบ่อย: ใช้คีย์ระยะยาวที่ควรเป็นคีย์ชั่วคราว เก็บคีย์ใน source control หรือสับสนระหว่าง "public key" กับ "secret key" เพราะทั้งคู่เป็นแค่ไบต์อาเรย์
การใช้ nonce ผิดวิธี เป็นผู้กระทำผิดซ้ำ หลายสคีมต้องการ nonce เฉพาะต่อคีย์ หากใช้ nonce ซ้ำ (มักเกิดจากการรีเซ็ตเคาน์เตอร์ แข่งกันระหว่างหลายกระบวนการ หรือสมมติว่า "สุ่มพอแล้ว") คุณอาจเสียความลับหรือความสมบูรณ์
ปัญหาการเข้ารหัสและการแยกวิเคราะห์ ทำให้เกิดความล้มเหลวเงียบ: base64 กับ hex ผิดพลาด ตัดศูนย์นำหน้าทิ้ง ความต่าง endianness หรือยอมรับการเข้ารหัสหลายแบบที่เปรียบเทียบต่างกัน ข้อบกพร่องเหล่านี้อาจเปลี่ยน "ลายเซ็นยืนยันแล้ว" เป็น "ยืนยันบางอย่างอื่น"
การจัดการข้อผิดพลาด อันตรายทั้งสองทาง: คืนค่าข้อความผิดพลาดละเอียดที่ช่วยผู้โจมตี หรืิอเพิกเฉยต่อความล้มเหลวการยืนยันแล้วดำเนินการต่อ
ความลับรั่วผ่าน ล็อก รายงานการแครช การวิเคราะห์ และจุดดีบัก คีย์ยังลงท้ายใน แบ็กอัพ อิมเมจ VM และ ตัวแปรสภาพแวดล้อม ที่แชร์กว้างเกินไป ในขณะเดียวกัน การอัปเดต dependency (หรือการไม่อัปเดต) อาจทำให้คุณติดกับการใช้งานที่มีช่องโหว่แม้ว่าการออกแบบจะดี
Security-by-construction คือการออกแบบซอฟต์แวร์ให้เส้นทางที่ปลอดภัยที่สุดเป็นเส้นทางที่ง่ายที่สุด แทนที่จะพึ่งพาคนให้จำรายการตรวจสอบยาว ๆ คุณจำกัดระบบไว้เพื่อให้ข้อผิดพลาดทั่วไปเป็นสิ่งที่ทำได้ยาก และเมื่อมีข้อผิดพลาดที่หลีกเลี่ยงไม่ได้ ผลกระทบจะถูกจำกัดไว้ (ลด “blast radius”).
ความซับซ้อนสร้างปัญหาด้านความปลอดภัยเพราะมีปฏิสัมพันธ์และสถานะขอบที่ซ่อนอยู่ซึ่งยากต่อการทดสอบและง่ายต่อการตั้งค่าผิด
ตัวอย่างประโยชน์จากความเรียบง่าย:
อินเทอร์เฟซที่แคบ (tight interface) ทำงานน้อยลงและยอมรับความแปรผันน้อยลง มันหลีกเลี่ยงอินพุตที่กำกวมและลดโหมดตัวเลือกที่สร้าง “security by configuration”.
แนวทางปฏิบัติที่เป็นรูปธรรม:
qmail แยกการจัดการอีเมลเป็นโปรแกรมเล็ก ๆ (รับ คิว ส่งท้องถิ่น ส่งระยะไกล ฯลฯ) ที่มีความรับผิดชอบจำกัด ซึ่งลดรูปแบบความล้มเหลวเพราะ:
พฤติกรรมแบบ "เวลาเท่ากัน" (constant-time) พยายามทำให้เวลาการคำนวณ (และบ่อยครั้งรูปแบบการเข้าถึงหน่วยความจำ) ไม่ขึ้นกับค่าลับ เช่น คีย์ส่วนตัว หรือ nonce นั่นสำคัญเพราะผู้โจมตีอาจอนุมานค่าลับได้โดยวัดเวลา ผลต่างแม้เพียงจุลวินาทีก็อาจสะสมและเปิดเผยข้อมูล
เป้าหมายคือป้องกันการรั่วไหลที่มองไม่เห็น ไม่ใช่แค่เลือกอัลกอริทึมที่แข็งแรง
เริ่มจากระบุว่าตัวแปรไหนเป็นความลับ (คีย์ส่วนตัว คีย์ร่วม แท็ก MAC ฯลฯ) แล้วมองหาจุดที่ความลับมีอิทธิพลต่อการไหลของโปรแกรม
สัญญาณเตือน:
if ที่ขึ้นกับข้อมูลลับนอกจากนี้ ให้ยืนยันว่าขึ้นอยู่กับไลบรารีคริปโตที่อ้างว่ามีพฤติกรรม constant-time สำหรับการดำเนินการที่คุณพึ่งพา
X25519 เป็นฟังก์ชันแลกเปลี่ยนคีย์เฉพาะที่สร้างบน Curve25519 ความนิยมมาจากการลด "foot-guns": มีพารามิเตอร์ให้เลือกน้อย ความเร็วดีบนฮาร์ดแวร์หลากหลาย และการออกแบบที่สนับสนุนการทำให้เป็น constant-time ได้ง่ายขึ้น
ควรคิดว่าเป็นทางเลือกเริ่มต้นที่ปลอดภัยสำหรับการแลกเปลี่ยนคีย์—แต่คุณยังต้องจัดการการยืนยันตัวตนและการจัดการคีย์ให้ถูกต้อง
ไม่ใช่ X25519 ให้การตกลงคีย์ (shared secret) แต่ไม่ยืนยันตัวตนของอีกฝั่งด้วยตัวมันเอง
เพื่อป้องกันการแอบอ้าง ให้จับคู่กับการยืนยันตัวตน เช่น:
หากไม่มีการยืนยันตัวตน คุณอาจ "สื่อสารอย่างปลอดภัย" กับฝ่ายที่ผิดได้
แนวคิดใหญ่ของ NaCl คือการลดทางเลือกลงเพื่อให้ยากต่อการประกอบคริปโตที่ไม่ปลอดภัย ด้วยการเสนอชุดการทำงานระดับสูงที่ประกอบเข้ากันอย่างปลอดภัยแทนที่จะให้เลือกอัลกอริทึม โหมด และการปนกันเองมากมาย
สองบล็อกสำคัญ:
crypto_box: การเข้ารหัสแบบ public-key ที่มีการยืนยันผู้ส่งcrypto_secretbox: การเข้ารหัสแบบ shared-key ที่มีการยืนยันประโยชน์เชิงปฏิบัติคือคุณจะไม่ต้องประกอบการเข้ารหัสและการตรวจสอบความสมบูรณ์ให้ถูกเอง ซึ่งมักเป็นแหล่งความผิดพลาด
แม้อัลกอริทึมดี ๆ แต่การใช้งานผิดยังคงทำให้ระบบล้มเหลว จุดบกพร่องทั่วไปรวมถึง:
การบรรเทา: