XOR
(chiark.greenend.org.uk)- XOR คือการดำเนินการที่ให้ค่าเป็น 1 เมื่อบิตสองบิตแตกต่างกัน และสามารถทำความเข้าใจได้ว่าเชื่อมโยงแนวคิดของ OR แบบเอกสิทธิ์, การไม่เท่ากัน, การกลับค่าตามเงื่อนไข, และการบวก/ลบ mod 2 ไว้ในการทำงานเดียว
- XOR แบบระดับบิตสำหรับจำนวนเต็มจะประมวลผลแต่ละหลักอย่างอิสระ ทำให้เห็น ความแตกต่างในแต่ละบิต และทำงานคล้ายการบวกเลขฐานสองแบบไม่มีการทด พร้อมคงสมบัติการสลับที่, การเปลี่ยนหมู่, เอกลักษณ์ 0, และอินเวอร์สของตัวเองไว้
- ในงานเข้ารหัส มันถูกใช้เพื่อผสานข้อความปกติกับ keystream และในกราฟิกพิกเซลยุคก่อน ก็ใช้วิธีวาดภาพเดิมซ้ำเพื่อให้ลบออกได้ ช่วยลดภาระด้านหน่วยความจำและ CPU
- สมบัติของ XOR ถูกนำไปใช้โดยตรงในงานคำนวณที่ สร้างความต่างแล้วหักล้างกลับได้ เช่น อัตลักษณ์ของ half adder, การสลับบิต, XOR swap สามครั้ง, และเงื่อนไขชนะของเกม Nim
- มันเชื่อมโยงต่อไปถึง symmetric difference ของเซต, กลุ่มที่มีเลขชี้กำลัง 2, nim-sum, พีชคณิตเชิงเส้นและพหุนามบน GF(2) รวมถึงเทคนิคตรวจจับ/แก้ไขข้อผิดพลาดและการเข้ารหัสอย่าง Hamming code, CRC, AES, GCM และ Classic McEliece
ความหมายพื้นฐานของ XOR
- XOR เป็น การดำเนินการแบบบูลีน ที่มีบิตอินพุตสองบิตและบิตเอาต์พุตหนึ่งบิต โดยตารางค่าความจริงคือ
00→0,01→1,10→1,11→0 - เมื่อมองเป็น “exclusive OR” มันจะให้ค่า 1 เมื่อมีเพียงอินพุตตัวใดตัวหนึ่งเท่านั้นที่เป็นจริง และถ้าทั้งคู่เป็นจริงจะได้ 0
- เมื่อมองเป็น “not equals” จะได้ว่า
a XOR bเท่ากับa ≠ bจึงให้ค่า 1 เมื่อค่าบูลีนสองค่าต่างกัน - เมื่อมองเป็น การกลับค่าตามเงื่อนไข ถ้า
a=0จะคงbไว้ตามเดิม และถ้าa=1จะกลับค่าของb- ด้วยเหตุผลเดียวกัน ยังตีความได้โดยให้
bเป็นอินพุตควบคุมและกลับค่าของa
- ด้วยเหตุผลเดียวกัน ยังตีความได้โดยให้
- ในมุมมองของ parity มันบอกได้ว่าจำนวน 1 ในอินพุตเป็นจำนวนคี่หรือไม่
- สำหรับสองบิต มันเท่ากับ
a+b mod 2 - และยังเท่ากับ
a-b mod 2 - เมื่อนำหลายค่ามา XOR กัน ก็จะบอกได้ว่าจำนวน 1 ในอินพุตทั้งหมดเป็นจำนวนคี่หรือคู่
- สำหรับสองบิต มันเท่ากับ
สมบัติเชิงพีชคณิตของ XOR
- XOR เป็นไปตาม กฎการสลับที่ และ กฎการเปลี่ยนหมู่
a XOR b = b XOR a(a XOR b) XOR c = a XOR (b XOR c)- ในรายการ XOR ที่ยาว ลำดับและวิธีจัดกลุ่มไม่มีผลต่อผลลัพธ์
- 0 เป็น เอกลักษณ์ ของ XOR
a XOR 0 = 0 XOR a = a- ในรายการ XOR ที่ยาว สามารถตัด 0 ออกได้
- ทุกค่าคือ อินเวอร์สของตัวเอง
a XOR a = 0- ถ้าตัวแปรเดียวกันปรากฏสองครั้ง ก็สามารถตัดสองพจน์นั้นออกพร้อมกันได้
- เช่นใน
(a XOR b) XOR b = aเราสามารถ XOR พจน์ที่รู้ค่าอีกครั้งเพื่อกำจัดมันออกจากค่าที่ผสมอยู่แล้วได้
XOR แบบระดับบิตสำหรับจำนวนเต็ม
- XOR แบบระดับบิตของจำนวนเต็มคือการนำจำนวนเต็มสองค่ามาเขียนเป็นเลขฐานสอง แล้ว XOR บิตแต่ละหลักอย่างอิสระ
- สมบัติของ XOR สำหรับบิตเดี่ยวใช้กับจำนวนเต็มได้เช่นเดิม
a XOR b = b XOR a(a XOR b) XOR c = a XOR (b XOR c)a XOR 0 = aa XOR a = 0
- XOR แบบระดับบิตบอก ความแตกต่างของแต่ละบิต ระหว่างจำนวนเต็มสองค่า
- ถ้า
a=bจะได้a XOR b = 0 - ถ้า
a≠bจะมีอย่างน้อยหนึ่งบิตที่ต่างกัน จึงได้a XOR b ≠ 0 - บิต 1 ในผลลัพธ์แสดงตำแหน่งที่อินพุตสองค่าต่างกัน
- ถ้า
- XOR แบบระดับบิตยังมองได้ว่าเป็น ตัวกลับค่าบิตตามเงื่อนไข
- มันจะกลับบิตข้อมูลเฉพาะในตำแหน่งที่ค่าควบคุมมีบิตเป็น 1
- ใน ASCII และ encoding ที่สืบทอดบางแบบ ตัวอักษรละตินพิมพ์ใหญ่กับพิมพ์เล็กต่างกันเพียงหนึ่งบิต จึงสามารถ XOR ค่าอักขระด้วย 32 เพื่อสลับตัวพิมพ์ได้
- กฎนี้ใช้ไม่ได้กับอักขระ Unicode ทั้งหมด และมีอักขระจำนวนมากที่ไม่มีแนวคิดเรื่องตัวพิมพ์หรือไม่เป็นไปตามกฎนี้
- XOR แบบระดับบิตเทียบได้กับ การบวกเลขฐานสองแบบไม่มีการทด
- มันทำเพียงการบวก mod 2 ในแต่ละหลัก และไม่ส่งการทดไปยังหลักถัดไป
XOR ในงานเข้ารหัส
- ในงานเข้ารหัส มักสร้าง keystream ที่มีความยาวเท่ากับข้อความปกติ แล้วนำไบต์หรือเวิร์ดของข้อความปกติมาผสานกับ keystream เพื่อสร้างข้อความเข้ารหัส
- โดยทั่วไปขั้นตอนการผสานนี้ใช้ XOR
- ฝั่งรับสามารถ XOR ด้วย keystream เดิมอีกครั้งเพื่อกู้คืนข้อความปกติเดิม
- การที่ผู้ส่งและผู้รับใช้การดำเนินการเดียวกันก็สะดวกขึ้นเล็กน้อยด้วย
- วิธีสร้าง keystream เองอาจซับซ้อนกว่านั้น
- one-time pad ใช้ข้อมูลสุ่มจริงยาวเท่าข้อความทั้งหมดและไม่สามารถถอดรหัสได้ แต่แทบไม่สะดวกต่อการใช้งานส่วนใหญ่
- โดยทั่วไปจะใช้ stream cipher หรือ block cipher ที่ทำงานใน counter mode เพื่อสร้าง keystream ตามความยาวที่ต้องการจากกุญแจขนาดเล็ก
- วิธีนี้อาจให้ ความลับของข้อมูล ได้ถ้า keystream ดีพอ แต่ไม่ได้ให้ ความถูกต้องสมบูรณ์ของข้อมูล สำหรับตรวจจับการดัดแปลงข้อความ
- การปกป้องความถูกต้องสมบูรณ์เป็นปัญหาอีกส่วนหนึ่ง
- การละเลยเรื่องความถูกต้องสมบูรณ์เป็นความผิดพลาดที่พบบ่อยในการออกแบบระบบเข้ารหัสสำหรับผู้เริ่มต้น และยังทำให้เกิดผลลัพธ์ผิดพลาดในระบบเข้ารหัสที่ซับซ้อนกว่านั้นได้
- ในฮาร์ดแวร์ XOR เรียบง่ายกว่าการบวก
- การบวกต้องมีการแพร่การทดระหว่างบิต จึงใช้พื้นที่บนชิปและเวลามากกว่า
- XOR ไม่มีการทด จึงมีต้นทุนต่ำกว่าในวงจรเฉพาะทาง
การวาดแบบ XOR และกราฟิกพิกเซล
- คอมพิวเตอร์ตามบ้านในยุค 1980 มีจำนวนบิตต่อพิกเซลและ RAM จำกัด ทำให้เก็บภาพทั้งหน้าจอสองชุดได้ยาก
- หากวาดวัตถุที่เคลื่อนที่ด้วย XOR ก็สามารถ กู้คืนหน้าจอเดิม ได้เพียงวาดวัตถุเดิมซ้ำอีกครั้ง
- นำค่าพิกเซล
Sของหน้าจอกับพิกเซลMของวัตถุที่เคลื่อนที่มา XOR กันเพื่อสร้างCและภายหลังก็นำMเดิมมา XOR ซ้ำเพื่อกู้Sกลับคืน
- นำค่าพิกเซล
- ในหน้าจอที่พิกเซลหลายตัวถูก packed อยู่ในหนึ่งไบต์ หรือใช้โครงสร้างแบบ bit plane การผสมภาพด้วยการบวกทำได้ยาก
- การบวกทั่วไปอาจทำให้การทดของพิกเซลหนึ่งล้นไปยังพิกเซลถัดไป
- XOR ไม่มีการทดเลย จึงไม่เกิดปัญหานี้
- ถ้าวาดเส้นด้วย XOR พิกเซลที่เส้นสองเส้นตัดกันจะถูกกลับค่าสองครั้งและกลับไปเป็นสีพื้นหลัง ทำให้ดูเหมือนมีตำหนิเล็ก ๆ
- ตำหนินี้ถูกยอมรับว่าเป็นข้อแลกเปลี่ยนเพื่อให้ลบเส้นหนึ่งได้โดยไม่ทำลายอีกเส้น
- การวาดแบบ XOR ยังเหมาะกับแอนิเมชันแบบง่าย
- เพียงวาดเส้นใหม่หนึ่งเส้น และวาดเส้นเก่าซ้ำอีกหนึ่งเส้นเพื่อลบ ก็ได้เฟรมถัดไป
- ไม่จำเป็นต้องวาดพิกเซลทั้งหมดบนหน้าจอหรือเส้นทั้งหมดใหม่ จึงใช้หน่วยความจำและ CPU น้อย
- วิธีนี้ถูกใช้กับเส้นเคลื่อนที่ในเกม Qix ปี 1981 และเส้นขอบหน้าต่างขณะย้ายตำแหน่งใน GUI ยุคแรก ๆ
อัตลักษณ์ของ half adder
- ในการบวกหนึ่งบิต บิตต่ำของ
a+bคือa XOR bและบิตสูงคือa AND b - ความสัมพันธ์เดียวกันนี้ใช้ได้กับการดำเนินการระดับบิตของจำนวนเต็มเช่นกัน
a + b = (a XOR b) + 2 × (a AND b)a XOR bคือค่าที่ได้จากการบวกแบบไม่มีการทด และa AND bเก็บบิตการทดที่ควรเกิดขึ้นในแต่ละหลัก
- ความสัมพันธ์นี้มองได้ว่าเป็น อัตลักษณ์ของ half adder
- half adder ในฮาร์ดแวร์ใช้เกต AND และ XOR เพื่อสร้างบิตการทดและบิตต่ำของการบวกสองบิต
- มันไม่ได้สร้างการบวกจำนวนเต็มทั้งหมดด้วยการดำเนินการง่าย ๆ เพียงอย่างเดียว เพราะ
+ในสมการด้านขวายังต้องทำหน้าที่จัดการการแพร่การทดให้เสร็จ
- อัตลักษณ์นี้ใช้คำนวณค่าเฉลี่ยของจำนวนเต็มสองค่าโดยไม่เกิด overflow ได้
- ถ้าแค่ทำ
a+bแล้วเลื่อนขวา อาจสูญเสียบิตสูงสุดของผลรวมแบบ 33 บิต - บน CPU ที่ไม่มี carry flag หรือมีคำสั่งอย่าง RRX/RCR ที่ไม่มีหรือใช้งานไม่สะดวก รูปแบบ
(a XOR b) >> 1 + (a AND b)เป็นทางเลือกได้ - ตัวอย่างเช่น MIPS, RISC-V และ DEC Alpha ไม่มี carry flag ส่วน Arm Thumb รุ่นแรกไม่มี RRX
- ถ้าแค่ทำ
- บน CPU ที่ไม่มีคำสั่ง XOR ก็สามารถกลับอัตลักษณ์นี้เพื่อสร้าง XOR ได้
a XOR b = (a + b) − 2 × (a AND b)- CPU ของ Data General ในยุค 1970 มี AND แต่ไม่มี bitwise XOR
การสลับบิตและค่า
- ปัญหาการสลับบิตสองบิตลดรูปได้ว่า ถ้าบิตสองตัวเท่ากันก็ไม่ต้องทำอะไร และถ้าต่างกันก็แค่กลับค่าทั้งสองบิต
- ด้วย XOR และ shift เราสามารถหาว่าบิตสองตำแหน่งต่างกันหรือไม่ และหากจำเป็นก็กลับค่าทั้งสองตำแหน่งพร้อมกันได้
diff_all = input XOR (input >> distance)ใช้คำนวณความต่างของคู่บิตที่ห่างกันตามระยะที่กำหนด- ใช้
ANDเพื่อคัดเลือกเฉพาะตำแหน่งที่สนใจ - จากนั้นคัดลอกความต่างที่เลือกไปยังอีกตำแหน่ง แล้ว XOR กลับเข้าอินพุตเพื่อกลับค่าทั้งสองบิตเฉพาะเมื่อจำเป็น
- วิธีเดียวกันนี้ยังใช้สลับคู่บิตหลายคู่ที่ห่างเท่ากันได้พร้อมกัน
- ใช้ mask ที่มีหลายบิตแทน mask บิตเดียว
- Beneš network สามารถแทนการเรียงสับเปลี่ยนแบบใดก็ได้ด้วยการสลับหลายคู่ที่มีระยะเท่ากันในหลายขั้นตอน
- ยังสามารถสลับ ค่าทั้งหมดสองค่า ด้วย XOR swap สามครั้ง ได้
a = a XOR bb = b XOR aa = a XOR b- แม้ไม่มีตัวแปรชั่วคราว ค่าสองค่าก็จะถูกสลับกัน
- XOR swap สามครั้งมีปัญหาเรื่อง aliasing
- มันทำงานได้เมื่อสลับตัวแปรคนละตัว
- แต่ถ้าชื่อสองชื่อชี้ไปยังตำแหน่งเก็บข้อมูลเดียวกัน เช่น การสลับสมาชิกตัวเดียวกันของอาร์เรย์กับตัวมันเอง ค่าอาจกลายเป็น 0 ได้
เกม Nim และ XOR
- Nim เป็นเกมที่มีหลายกอง ผู้เล่นผลัดกันเลือกหนึ่งกองแล้วนำหมากออกได้ตั้งแต่ 1 ชิ้นขึ้นไปตามต้องการ และผู้ที่เดินต่อไม่ได้เป็นฝ่ายแพ้
- ใน Nim แบบพื้นฐาน ตำแหน่งแพ้ คือตำแหน่งที่ XOR แบบระดับบิตของขนาดกองทั้งหมดเป็น 0
- ในตำแหน่งที่ XOR เป็น 0 ถ้าเปลี่ยนขนาดกองหนึ่งจาก
aเป็นค่าอื่นbค่า XOR รวมจะเปลี่ยนไปเป็นa XOR bและเพราะa≠bจึงไม่เป็น 0 - ในตำแหน่งที่ XOR ไม่เป็น 0 ให้ดูบิต 1 ที่สูงที่สุดของค่า XOR รวม
xแล้วเลือกกองที่มีบิตนั้นเป็น 1 จากนั้นลดขนาดเป็นpile XOR xก็จะทำให้ XOR รวมกลายเป็น 0 - ตัวอย่างเช่น ขนาดกอง 12, 10, 3 อยู่ในเลขฐานสองเป็น
1100,1010,0011และ XOR กันได้0101- มีเพียงกองใหญ่สุด 12 ที่เมื่อ XOR กับ
0101แล้วลดลงเป็น 9 - ดังนั้นตาชนะคือเอาออก 3 ชิ้นจาก 12 ให้เหลือ 9
- มีเพียงกองใหญ่สุด 12 ที่เมื่อ XOR กับ
โครงสร้างทางคณิตศาสตร์ที่คล้าย XOR
- ในทฤษฎีเซต symmetric difference
X∆Yเป็นการดำเนินการที่รวมสมาชิกซึ่งอยู่ในสองเซตนั้นเพียงเซตเดียวเท่านั้น- ถ้ามองการเป็นสมาชิกของเซตเป็นค่าบูลีน symmetric difference ก็เท่ากับ XOR
- ดังนั้นจึงมีสมบัติแบบเดียวกับ XOR เช่น กฎการสลับที่และกฎการเปลี่ยนหมู่
- ในทฤษฎีกลุ่ม กลุ่มที่มีเลขชี้กำลัง 2 คือกลุ่มที่สมาชิกทุกตัวเป็นอินเวอร์สของตัวเอง
- การดำเนินการของกลุ่มแบบนี้เป็นไปตามกฎการเปลี่ยนหมู่ และตามแบบฝึกหัดมาตรฐานยังตามด้วยกฎการสลับที่
- การที่สมาชิกตัวเดิมสองตัวหักล้างกันได้ทำให้มันดูคล้าย XOR
- กลุ่มที่มีเลขชี้กำลัง 2 ทุกกลุ่มสามารถทำความเข้าใจได้ว่าเป็น XOR แบบระดับบิตของฟังก์ชันที่ให้ค่า
{0,1}บางชุด
- ในการวิเคราะห์แบบ Sprague-Grundy ตำแหน่งของ impartial game จำนวนมากจะถูกกำหนด Grundy number
- Grundy number ของเกมประกอบที่รวมหลายเกมย่อยเข้าด้วยกันคำนวณได้จากการทำ bitwise XOR ของ Grundy number ของแต่ละเกมองค์ประกอบ
- ใน game theory บางครั้ง bitwise XOR ของจำนวนเต็มไม่ติดลบจะถูกเรียกว่า nim-sum
- ฟิลด์
GF(2)เป็นฟิลด์จำกัดที่มีสมาชิกเพียง 0 และ 1- การบวกและการลบทำงานเหมือน XOR
- การคูณทำงานเหมือน AND
- ดังนั้น
a AND (b XOR c) = (a AND b) XOR (a AND c)จึงเป็นจริง
พีชคณิตเชิงเส้นบน GF(2) และการแก้ไขข้อผิดพลาด
- เวกเตอร์และเมทริกซ์บน
GF(2)เป็นโครงสร้างที่แต่ละองค์ประกอบมีค่า 0 หรือ 1 และการบวกเวกเตอร์หรือเมทริกซ์คือ XOR รายองค์ประกอบ - การคูณเมทริกซ์
Mกับเวกเตอร์vเทียบได้กับการนำคอลัมน์ของMที่ถูกเลือกโดยองค์ประกอบ 1 ในvมา XOR รวมกัน - รหัสแก้ไขข้อผิดพลาด จะขยายข้อความ
mบิตให้เป็น codewordnบิตที่ยาวกว่า เพื่อให้สามารถตรวจจับหรือแก้ไขข้อผิดพลาดของบางบิตได้- ถ้า codeword ที่ถูกต้องต่างกันหลายบิต ข้อผิดพลาดเพียงไม่กี่บิตก็จะไม่เปลี่ยนมันให้กลายเป็น codeword ที่ถูกต้องอีกชุดหนึ่ง
- ถ้า codeword ที่ถูกต้องสองชุดต่างกันอย่างน้อย
kบิต ข้อผิดพลาดน้อยกว่าkบิตจะตรวจจับได้ และน้อยกว่าk/2บิตจะสามารถแก้ไขได้โดยหา codeword ที่ใกล้ที่สุด
- linear code ใช้ generator matrix และ check matrix บน
GF(2)- ผู้ส่งใช้ generator matrix เพื่อขยายข้อความ
mบิตให้เป็น codewordnบิต - ผู้รับใช้ check matrix เพื่อตรวจว่าข้อความที่รับมาเป็น codeword ที่ถูกต้องหรือไม่ และถ้ามีข้อผิดพลาดก็จะได้ syndrome
- รูปแบบข้อผิดพลาดเดียวกันจะสร้าง syndrome เดียวกันโดยไม่ขึ้นกับข้อความเดิม
- ผู้ส่งใช้ generator matrix เพื่อขยายข้อความ
- Hamming code เป็นตัวอย่างเมื่อความยาวโค้ด
nมีค่าเป็น2^d−1- เมื่อ
n=15จะกำหนดหมายเลขตำแหน่งบิต 15 ตำแหน่งด้วยเลขไบนารี 4 บิตที่ไม่เป็นศูนย์ตั้งแต่ 0001 ถึง 1111 - ผู้รับจะ XOR ดัชนีของบิตทั้งหมดที่มีค่า 1 และถ้าผลลัพธ์เป็น 0 ก็เป็น codeword ที่ถูกต้อง
- ถ้ามีบิตหนึ่งบิตถูกกลับค่า ผล XOR จะกลายเป็นดัชนีของบิตที่ผิดนั้นโดยตรง ทำให้แก้ข้อผิดพลาด 1 บิตได้โดยไม่ต้องมี lookup table
- Hamming code ขนาด 15 บิตบรรจุข้อมูลได้ 11 บิต และใช้ 4 บิตสำหรับการแก้ไขข้อผิดพลาด
- เมื่อ
พหุนามบน GF(2), CRC และฟิลด์จำกัดที่ใหญ่กว่า
- พหุนามบน
GF(2)คือพหุนามเชิงรูปแบบที่สัมประสิทธิ์เป็น 0 หรือ 1 และการบวกเทียบได้กับการ XOR สัมประสิทธิ์ที่มีดีกรีเดียวกัน - การคูณพหุนามทำโดยสร้าง partial product แบบพหุนามทั่วไป แล้วลดสัมประสิทธิ์ด้วย mod 2
- ถ้ามองรูปแบบนี้เป็นบิตสตริง มันคล้ายการคูณจำนวนเต็ม แต่ตอนรวม partial product จะใช้ XOR แบบไม่มีการทดแทนการบวกทั่วไป
- x86 มีคำสั่งคูณแบบไม่มีการทดรวมถึง
CLMULและ Arm มีชุดคำสั่งสำหรับ polynomial multiplication
- CRC คือวิธีใช้เศษจากการหารพหุนามบน
GF(2)เป็น checksum- มองบิตสตริงของข้อความที่ส่งเป็นพหุนามขนาดใหญ่
Mแล้วเก็บเศษM mod Pจากการหารด้วยพหุนามที่ตกลงกันไว้P - มันถูกใช้ในการตรวจสอบแพ็กเก็ตเครือข่ายอย่าง Ethernet และเครือข่ายที่คล้ายกัน
- CRC ไม่ได้แก้ไขข้อผิดพลาด แต่มีไว้เพื่อตรวจจับเท่านั้น และเหมาะกับสถานการณ์ที่การส่งส่วนใหญ่ถูกต้องตามปกติและมีการกลับบิตหรือสัญญาณรบกวนเกิดขึ้นไม่บ่อย
- มองบิตสตริงของข้อความที่ส่งเป็นพหุนามขนาดใหญ่
- ฟิลด์จำกัดที่ใหญ่กว่าสามารถสร้างได้จากโครงสร้างเศษเหลือของพหุนามบน
GF(p)เมื่อหารด้วย irreducible polynomialQ- ถ้าดีกรีของ
Qเท่ากับdฟิลด์จำกัดใหม่จะมีสมาชิกp^dตัว - ในกรณี
p=2irreducible polynomial สามารถเขียนเป็นรูปแบบบิตเหมือนจำนวนเต็มได้ และลำดับดังกล่าวถูกบันทึกไว้ใน OEIS A014580
- ถ้าดีกรีของ
- ฟิลด์จำกัดที่มีขนาดเป็นกำลังของ 2 ปรากฏในเทคนิคการเข้ารหัสหลายแบบ
- ฟิลด์จำกัดขนาด
2^8เป็นองค์ประกอบหลักของ AES และ Twofish - ฟิลด์จำกัดขนาด
2^128ถูกใช้ใน GCM ซึ่งรวมการเข้ารหัสข้อมูลจำนวนมากกับการปกป้องความถูกต้องสมบูรณ์ของข้อมูล - ฟิลด์จำกัดขนาดเป็นกำลังของ 2 ยังปรากฏใน elliptic-curve cryptography บางแบบ และในอัลกอริทึมถอดรหัสของ Classic McEliece ซึ่งเป็นวิธีแบบ post-quantum
- ฟิลด์จำกัดขนาด
1 ความคิดเห็น
ความคิดเห็นบน Hacker News
เทคนิค XOR ต้องสาปที่ผมชอบคือ XOR doubly linked list: https://en.m.wikipedia.org/wiki/XOR_linked_list
แทนที่แต่ละโหนดจะเก็บพอยน์เตอร์ถัดไป/ก่อนหน้าแยกกัน มันเก็บค่าเดียวที่ได้จากการ XOR ทั้งสองค่าเข้าด้วยกัน แน่นอนว่ามันไม่ใช่พอยน์เตอร์ที่ถูกต้อง แต่ตอนวนลูป ถ้าเอาพอยน์เตอร์ของโหนดก่อนหน้ามา XOR กับพอยน์เตอร์รวม ก็จะได้พอยน์เตอร์ของโหนดถัดไปออกมา และยังวนได้สองทิศทางด้วย รู้สึกเหมือนอะไรที่ผิดกฎหมาย
ข้อเสียที่เป็นสาระรองลงมาคือ การเขียน XOR linked list ใน C ที่เคร่งตามมาตรฐานนั้นยุ่งยากมาก มาตรฐานไม่ได้รับประกันว่าเมื่อ cast พอยน์เตอร์ตัวเดียวกันเป็นจำนวนเต็มแล้วจะได้จำนวนเต็มค่าเดียวกัน ดังนั้นในทางปฏิบัติจึงต้องทำทุกอย่างเป็น
uintptr_tเพื่อคงเวอร์ชัน cast เป็นจำนวนเต็มที่ canonicalized ไว้ไกลกว่านั้น อาจใช้พอยน์เตอร์แบบ near/relative 16 บิตก็ได้ อาจเข้ากับ data-oriented design ได้ดี เช่นมีบล็อก 64K elements แล้วให้องค์ประกอบภายในชี้กันด้วย index แบบ
uint16มีอย่างหนึ่งที่ตกหล่นไป XOR ยังเป็น ฟังก์ชันแฮชเชิงเส้นแบบ 3-wise independent ด้วย จึงใช้สำหรับการสุ่มตัวอย่างคำตอบของฟังก์ชันบูลีนแบบเกือบสม่ำเสมอเชิงความน่าจะเป็น และการนับจำนวนคำตอบได้ มันมีประโยชน์จริง ๆ และถูกใช้สร้างตัวนับที่ให้จำนวนแบบพิสูจน์ได้แม้จะเป็นเชิงความน่าจะเป็น ผมเขียนคำอธิบายที่เข้าใจง่ายกว่าไว้ที่นี่ https://www.msoos.org/2018/12/how-approximate-model-counting...
โดยพื้นฐานแล้ว ทุกครั้งมันจะลดปริภูมิคำตอบลงเกือบพอดีครึ่งหนึ่ง ดังนั้นก็เพิ่มเงื่อนไข XOR ต่อไปเรื่อย ๆ จนเช่นเหลือคำตอบ 10 รายการ แล้วถ้าจำนวน XOR ที่เพิ่มเข้าไปคือ k ก็เอา 10 คูณ 2^k ได้เลย เพราะแต่ละครั้งลดครึ่งหนึ่ง จึงไปถึงระดับ 10 รายการได้เร็วและสเกลได้ดี
งานวิจัยที่เกี่ยวข้องอยู่ที่ https://arxiv.org/abs/1306.5726 และ https://www.cs.toronto.edu/~meel/Papers/cav20-sgm.pdf ส่วนเครื่องมืออยู่ที่ https://github.com/meelgroup/approxmc และ https://github.com/meelgroup/unigen ในการแข่งขัน model counting ครั้งที่ผ่านมา เมื่อจับคู่กับตัวนับแบบ exact แล้ว มันเหนือกว่าคู่แข่งรายอื่นอย่างท่วมท้น สไลด์อยู่ที่ https://mccompetition.org/assets/files/2024/MC2024_awards.pd...
เกร็ดเรื่อง XOR ที่ผมชอบเรื่องหนึ่งคือเรื่องที่ Bryan Cantrill จาก Oxide, Joyent, Sun เล่าไว้ในพรีเซนเทชันนี้ https://speakerdeck.com/bcantrill/oral-tradition-in-software... และวิดีโอนี้ https://www.youtube.com/watch?v=4PaWFYm0kEw
สรุปแบบไม่ต้องกดลิงก์คือ ตอนอยู่ที่ Sun เขาคุยกับเพื่อนร่วมงาน Roger Faulkner ว่าทำไม C ถึงไม่มี logical XOR แล้ว Faulkner บอกว่าเพราะมันทำ short-circuit evaluation ไม่ได้ Brian คิดว่ามันแปลก Roger เลยส่งอีเมลไปถาม Dennis Ritchie และ Ritchie ก็ยืนยันว่า Faulkner พูดถูก วิธีเล่าของ Cantrill ก็ตลกดี แต่ที่น่าทึ่งคือการที่เขาสามารถถามเจ้าตัวได้โดยตรง
dmr@research.att.comเพื่อถามว่ามีข้อมูลสถาปัตยกรรมเพิ่มเติมไหมตอนนั้นยังไม่มี Google และห้องสมุดมหาวิทยาลัยก็ไม่มีเอกสาร ไม่กี่วันต่อมาเขาถามที่อยู่จริง แล้วอีกไม่กี่สัปดาห์ถัดมา สำเนา คู่มือสรุปชุดคำสั่ง ก็มาถึงตู้ไปรษณีย์ มันให้ความรู้สึกเหมือนตระกูล IBM 360 และผมยังเก็บไว้จนถึงทุกวันนี้
!=นั่นเอง ต่างจาก logical operator อื่น ๆ ตรงที่ต้อง normalize อาร์กิวเมนต์ให้เป็นค่าความจริงเดี่ยว และเข้ากันได้ดีกับสำนวนการแปลงเป็นบูลีนของ C คือ!!^มานานกว่า 40 ปีแล้ว: https://www.geeksforgeeks.org/bitwise-operators-in-c-cpp/วันนี้เพิ่งรู้ว่า ถ้านำอีโมจิรถยนต์ไป XOR กับ
0x20หรือพูดอีกอย่างคือทำให้เป็น “ตัวพิมพ์เล็ก” มันจะกลายเป็น อีโมจิห้ามคนเดินเท้า ดูบังเอิญแบบพอดีเกินไป เลยสงสัยว่ามีใครรู้ไหมว่ามันตั้งใจทำหรือเปล่าถ้าคิดเลยเถิดไปอีก ก็อาจได้ไอเดียประหลาดว่าอักษรตัวพิมพ์เล็กของอีโมจิรถยนต์คือป้าย “ห้ามคนเดินเท้า”
>>> from unicodedata import lookup, name>>> name(chr(ord(lookup('AUTOMOBILE')) ^ 0x20))'NO PEDESTRIANS':tada:→:tophat:,:rocket:→:mountain_cableway:ก็ทำได้เช่นกันอุปมาในโลกจริงที่ใช้説明 XOR ได้ดีคือ สวิตช์ไฟ บนบันไดในบ้าน มีสวิตช์ตัวหนึ่งอยู่ด้านล่าง อีกตัวอยู่ด้านบน และทั้งคู่ควบคุมไฟดวงเดียวกัน
ตอนแรกทั้งคู่ อยู่ในตำแหน่งปิด พอเปิดสวิตช์ด้านล่าง ไฟก็ติด พอเดินขึ้นบันไดไปเปิดสวิตช์ด้านบน แม้สวิตช์ทั้งสองจะอยู่ในตำแหน่ง “เปิด” แต่ไฟกลับดับ ไฟจะติดก็ต่อเมื่อมีสวิตช์เพียงตัวเดียวที่ “เปิด” และอีกตัว “ปิด” เท่านั้น นอกนั้นไฟจะดับ
ผมไม่ชอบเลยที่ฟังก์ชันตรรกะนี้มักถูกเรียกว่า XOR หรือ “exclusive OR” เพราะแทบทุกครั้งความหมายจริง ๆ คือ “ผลบวกโมดูโล 2” หรือ พาริตี ไม่ใช่ exclusive OR
“ผลบวกโมดูโล 2”/พาริตี กับ “exclusive OR” เป็นฟังก์ชันตรรกะคนละตัวกัน และบังเอิญตรงกันเฉพาะตอนมีโอเปอแรนด์อินพุต 2 ตัวเท่านั้น เพราะมีจำนวนคี่ที่ไม่เกิน 2 อยู่แค่ค่าเดียว
เมื่อมีอินพุต 3 ตัวขึ้นไป สิ่งที่คนส่วนใหญ่เรียกว่า XOR แท้จริงแล้วคือพาริตี ซึ่งให้ค่า 1 เมื่อมีอินพุตจำนวนคี่ตัวเป็น 1 ในทางตรงกันข้าม exclusive OR เมื่อมีอินพุต 3 ตัวขึ้นไป จะเป็นฟังก์ชันที่ให้ค่า 1 ก็ต่อเมื่อมีอินพุตเพียงตัวเดียวเท่านั้นที่เป็น 1 และที่เหลือทั้งหมดเป็น 0
ในฮาร์ดแวร์คอมพิวเตอร์ พาริตีสำคัญกว่า exclusive OR มาก เหตุผลหลักคือการบวกโมดูโล 2 ถูกใช้เป็นองค์ประกอบสำหรับสร้างการบวกจำนวนที่ใหญ่กว่า ในทางกลับกัน ในคณิตศาสตร์ exclusive OR สำคัญกว่าพาริตีมาก
เช่น ตัวบ่งปริมาณที่ใช้แสดงว่าภาคแสดงหนึ่งเป็นจริงสำหรับสมาชิกบางตัว สมาชิกทุกตัว หรือสมาชิกตัวเดียวเท่านั้นของเซต จะอิงกับ OR, AND และ exclusive OR ตามลำดับ “or” ในภาษาธรรมชาติมักหมายถึง inclusive OR หรือ exclusive OR เสมอ ไม่ได้หมายถึงพาริตีที่โปรแกรมเมอร์จำนวนมากเรียกว่า XOR
ในการเขียนโปรแกรม โอกาสที่จะต้องคำนวณฟังก์ชันตรรกะ exclusive OR มีน้อย แต่ใช้บ่อยในการอธิบายพฤติกรรมของโปรแกรม เช่น เมื่อบอกว่าในคำสั่งผสม select/case/switch จะมีคำสั่งที่หนึ่ง หรือคำสั่งที่สอง หรือคำสั่งที่สามเพียงคำสั่งหนึ่งถูกเรียกใช้ หรือเมื่ออธิบายชนิดที่ค่าปัจจุบันของตัวแปรแบบ union/sum type อาจมีได้
=1และ parity gate เป็น2k + 1แต่เวลาใช้ซอฟต์แวร์ออกแบบวงจรสำหรับ PCB หรือ FPGA ก็ยังอาจโดนหลอกได้ เพราะได้สิ่งที่ต่างจากที่คาดไว้∃!ยังมี Kademlia distributed hash table ด้วย: kademlia distributed hash table ไอเดียใหญ่คือแต่ละโหนดได้รับบิตแบบสุ่มในช่วง
[0, 2^m)และนิยามระยะทางด้วย XOR เป้าหมายคือหาอัลกอริทึมแบบกระจายศูนย์ที่ส่งข้อมูลจาก X ไปยัง Y ได้อย่างรวดเร็วโดยไม่ต้องรู้จักทั้งเครือข่ายแค่มองคณิตศาสตร์ก็พิสูจน์ได้ว่ามันทำงาน แต่สัญชาตญาณเชิงภาพที่ผมชอบคือแบบนี้ สมมติว่าโหนดเริ่มต้น X ต้องการหาโหนด k นิยาม “ต้นไม้ระยะทางจาก X” เป็นต้นไม้ไบนารีที่ดัชนีใบคือ 0, 1, 2... โดยติดป้ายแต่ละใบเป็น
X^leaf_indexเพื่อแทนระยะทางจาก X ตัวอย่างเช่นdist(x, x) = x^x = 0ดังนั้นป้ายของโหนดเดิม X จะอยู่ที่ใบซ้ายสุด 0ช่วง
[2^i, 2^(i+1))คือซับทรีบางต้นในต้นไม้ระยะทางจาก X ถ้ารู้ว่าระยะของ k อยู่ในช่วงนั้น ก็จะสอบถามโหนด Y บางตัวในช่วงนั้นในฐานะเพื่อนบ้านโดยประมาณไม่ว่าจะเลือก Y ตัวไหน ในต้นไม้ระยะทางจาก Y ผลลัพธ์ส่วน prefix จะเป็นเพียงการเรียงสับเปลี่ยนบางแบบของซับทรี
[2^i, 2^(i+1))ที่เลือกไว้ในต้นไม้ระยะทางจาก X เสมอ พูดให้แม่นขึ้นคือมองได้ว่าlabels_of_leaves_of_X([2^i, 2^(i+1))) == labels_of_leaves_of_Y([0, 2^i))ดัชนีอิงตามระยะทาง แต่ป้ายอาจต่างกันได้สำหรับการเปรียบเทียบกับ distributed hash table แบบอื่นอย่าง Chord มีข้อมูลที่เข้มงวดกว่ามากทั้งเชิงคณิตศาสตร์และเชิงประสบการณ์ แต่สัญชาตญาณเชิงภาพนี้ทำให้เห็นว่า “สมมาตร” ของ Kademlia คืออะไร และให้ความรู้สึกว่าทุกคนมีเพื่อนบ้านในพื้นที่กับซับทรีของตัวเอง
ในทางกลับกัน Chord แม้จะทำแบบสองทิศทาง หน่วยความจำก็เพิ่มเป็น 2 เท่า และการใช้งานก็ดูเสี่ยงกว่า อีกทั้งยากจะได้ “ความโดดเดี่ยว” ระดับนี้ หน้าต่างเลื่อนของเพื่อนบ้านขนาด S จะเคลื่อนตลอดเวลา และมีเพื่อนบ้านที่ต่างกัน
2^mตัวต่อบิต แม้เพื่อนบ้านส่วนใหญ่จะดูคล้ายกัน แต่ก็ไม่เรียบร้อยนักKademlia มีเพื่อนบ้าน
1 + 2 + 4 ... + 2^m-1ตัว และทั้งระบบถูกจัดวางอย่างเป็นระเบียบเสริมเผื่อใครสงสัย คนนี้คือ Simon Tatham คนเดียวกับใน Simon Tatham's Portable Puzzle Collection ถ้ายังไม่รู้จัก ก็เหมาะไว้เล่นตอนเบื่อ ๆ แบบออฟไลน์
สมัยมัธยมผมเสียเวลาไปกับของพวกนี้เยอะมาก: https://www.chiark.greenend.org.uk/~sgtatham/puzzles/
ทุกวันนี้ตัวแก้ปัญหาแบบปรับแต่งเฉพาะทางจำนวนมาก เช่น Ising Machine ใช้ปัญหา XOR เป็นเบนช์มาร์ก ในทางปฏิบัติ การแก้อนุประโยค XOR หลาย ๆ อันสามารถทำได้ในเวลาพหุนามด้วยวิธีกำจัดแบบเกาส์ จึงมีประโยชน์ลดลงอยู่บ้าง แต่เนื่องจากตัวแก้ปัญหาทั้งหมดแสดงการขยายตัวแบบเอ็กซ์โปเนนเชียล มันจึงยังเป็นวิธีที่ดีในการประเมินประสิทธิภาพ
การนำไปใช้อีกแบบที่น่าสนใจแบบที่สองเกี่ยวข้องกับ ระบบเข้ารหัส McEliece ซึ่งเป็นการเข้ารหัสกุญแจสาธารณะจากยุค 70 และช่วงนี้กลับมาได้รับความสนใจอีกครั้งเพราะทนทานต่อควอนตัม การโจมตีเพื่อถอดรหัสคือปัญหาการหาคำตอบของชุดสมการ XOR ซึ่งก็เป็นเวลาแบบพหุนามเช่นกัน แต่มีเงื่อนไขเพิ่มเติมว่าระยะทางแฮมมิงต้องเท่ากับค่าบางอย่างที่รวมอยู่ในกุญแจสาธารณะ
ตอนเรียน Z80 Assembly เพื่อเขียนโปรแกรมบน TI-83 ทุกไบต์ของภาษาเครื่องล้วนสำคัญ เพราะพื้นที่เก็บข้อมูลทั้งหมดของเครื่องคิดเลขมีเพียง 24KB
หากต้องการเริ่มต้นรีจิสเตอร์ตัวสะสมหลัก
aให้เป็น 0 จะใช้XOR aแทนLD a, 0ในคำสั่งทางคณิตศาสตร์aเป็นตัวถูกดำเนินการโดยอัตโนมัติ ดังนั้นXOR aจึง XORaกับตัวมันเอง และคำสั่งทั้งหมดมีขนาดเพียง 1 ไบต์ ในทางกลับกัน หากจะโหลดค่า 0 เข้าไปในaอย่างชัดเจน ค่า literal 0 ต้องอยู่ใน opcode ทำให้LD a, 0เป็นคำสั่งขนาด 2 ไบต์