หลีกเลี่ยงอักขระที่กำกวมทางสายตาใน ID
(gajus.com)- ในกระบวนการที่คนต้องอ่านและส่งต่อ ID เช่น การรายงานบั๊ก การกรอกรหัสส่วนลด หรือการติดตามการจัดส่ง ความกำกวมทางสายตา อย่าง
O/0,I/l/1/7สามารถนำไปสู่ข้อผิดพลาดในการป้อนได้ง่าย - ความสับสนจะยิ่งมากขึ้นตามแบบอักษรและลายมือ และมี คู่ที่แยกความต่างได้ไม่ชัด ปรากฏซ้ำ ๆ เช่น
5/S,2/Z,8/B,6/G,9/q/g - สำหรับ ID ที่มนุษย์ต้องจัดการโดยตรง เช่น ฝ่ายบริการลูกค้า, error ID, product ID การเลือก ชุดอักขระที่อ่านง่าย สำคัญต่อคุณภาพการใช้งานจริงมากกว่าการใช้ชุดอักขระขนาดใหญ่แบบไม่คิด
- หากแยกตัวพิมพ์เล็ก-ใหญ่ได้ ID ยาว 5 ตัวอักษรจะสร้างชุดค่าผสมได้
418,195,493แบบ แต่ถ้าไม่แยกจะลดเหลือ5,153,632แบบ จึงต้องมี การแลกเปลี่ยนระหว่างความยาวกับความปลอดภัย - ID ที่แยกตัวพิมพ์เล็ก-ใหญ่เหมาะกับการทำให้สั้นลง แต่ระบบหรือโปรโตคอลของบุคคลที่สามบางส่วนอาจทำงานแบบ ไม่แยกตัวพิมพ์เล็ก-ใหญ่ ซึ่งอาจก่อปัญหาในขั้นตอนการเชื่อมต่อรวมระบบ
ความสับสนของอักขระใน ID ที่มนุษย์ต้องอ่าน
- เมื่อมีการเขียนหรือส่งต่อ ID ในการโต้ตอบกับระบบ เช่น รายงานบั๊ก การกรอกรหัสส่วนลด หรือการติดตามการจัดส่ง ความสับสนของอักขระที่หลีกเลี่ยงได้สามารถทำลายประสบการณ์ผู้ใช้ได้
- ตัวอย่างคู่ อักขระกำกวมทางสายตา ที่พบบ่อยมีดังนี้
O/0: ในเลข 0 ที่ไม่มีขีดเฉียงหรือจุด ตัวอักษรOกับเลข0อาจดูคล้ายกันI/l/1/7: ตัวพิมพ์ใหญ่I, ตัวพิมพ์เล็กl, เลข1, เลข7แยกได้ยากในสิ่งพิมพ์และลายมือหลายแบบ5/S,2/Z,8/B,6/G,9/q/g: อาจสับสนกันได้ในบางฟอนต์ ฟอนต์แบบตกแต่ง หรือลายมือ
- สตริงตัวอย่าง
9qg6G8B2Z5SIl170Oถูกใช้เป็นตัวเปรียบเทียบในฟอนต์ระบบหลายแบบ เช่น Arial, Helvetica, Courier, Times, Verdana, Georgia, Tahoma, Impact, Comic Sans - บางคู่ เช่น
Iกับlอาจยังดูคลุมเครือในหลายฟอนต์อย่างต่อเนื่อง และบางชุดอย่าง9qgก็อาจยิ่งสับสนเมื่อเขียนด้วยมือ -
-
ประเภทของ ID ที่ปัญหานี้รุนแรงเป็นพิเศษ
- รหัสส่วนลดที่ส่งไปมาระหว่างลูกค้ากับฝ่ายบริการ
- รหัสติดตามที่ใช้ในการจัดส่งหรือโลจิสติกส์
- error ID ที่จำเป็นต่อการทำซ้ำปัญหาและการตอบคำถาม
- product ID ที่ใช้ระบุสินค้า
-
การแลกเปลี่ยนระหว่างการแยกตัวพิมพ์เล็ก-ใหญ่กับชุดอักขระ
- ควรตัดสินใจไปพร้อมกันตั้งแต่กำหนดกฎการสร้างว่า ID จะมอง
abcกับABCเป็นค่าเดียวกันหรือไม่ - หากแยกตัวพิมพ์เล็ก-ใหญ่และตัดอักขระที่กำกวมทางสายตาออก จะเหลืออักขระที่เลือกใช้ได้ 53 ตัว
- หากไม่แยกตัวพิมพ์เล็ก-ใหญ่ อักขระที่เลือกใช้ได้จะลดลงเหลือ 22 ตัว
- จำนวนชุดค่าผสมที่เป็นไปได้ตามความยาวของ ID มีดังนี้
- 5 ตัวอักษร, แยกตัวพิมพ์เล็ก-ใหญ่:
53^5 = 418,195,493 - 5 ตัวอักษร, ไม่แยกตัวพิมพ์เล็ก-ใหญ่:
22^5 = 5,153,632 - 8 ตัวอักษร, แยกตัวพิมพ์เล็ก-ใหญ่:
53^8 = 62,259,690,411,361 - 8 ตัวอักษร, ไม่แยกตัวพิมพ์เล็ก-ใหญ่:
22^8 = 54,875,873,536
- 5 ตัวอักษร, แยกตัวพิมพ์เล็ก-ใหญ่:
- สุดท้ายแล้ว ตัวเลือกคือการหาสมดุลระหว่าง ID ที่สั้นแต่มีโอกาสสับสนสูง กับ ID ที่ยาวกว่าแต่อ่านง่ายกว่า
- หากใช้ทั้งตัวพิมพ์เล็กและใหญ่ วันหนึ่งอาจเจอพฤติกรรมไม่คาดคิดจากระบบหรือโปรโตคอลของบุคคลที่สามที่ ไม่แยกตัวพิมพ์เล็ก-ใหญ่
- มีระบบเชิงพาณิชย์ระบบหนึ่งที่อนุญาตให้ผู้ใช้เลือก
iDและidเป็นคนละ ID ได้ แต่เมื่อค้นหา ID ที่ไม่มีอยู่ กลับทำการจับคู่แบบไม่แยกตัวพิมพ์เล็ก-ใหญ่และคืนข้อมูลที่ผิด - คำตอบที่ได้รับต่อบั๊กนั้นคือเป็นพฤติกรรมเพื่อ “ความสะดวก”
- มีระบบเชิงพาณิชย์ระบบหนึ่งที่อนุญาตให้ผู้ใช้เลือก
อาจต้องหลีกเลี่ยงไม่ใช่แค่อักขระเดี่ยว แต่รวมถึงชุดอักขระ
- มีกรณีที่ชุดอักขระทั้งชุดดูเหมือนอักขระอื่นได้ด้วย
rnอาจดูเหมือนmvvอาจดูเหมือนw
- หากตัดอักขระจำนวนมากออกเพียงเพราะเหตุนี้ ชุดอักขระที่ใช้ได้อาจเล็กเกินไป ดังนั้นแนวทางที่สมจริงกว่าอาจเป็นการหลีกเลี่ยงเฉพาะบางชุดในขั้นตอนการสร้าง
- ในสถานการณ์ที่ต้องส่งต่อด้วยคำพูด ก็อาจพิจารณา ความคล้ายทางเสียง ร่วมด้วย
- ตัวอย่างเช่น
bกับpอาจฟังคล้ายกันเมื่อพูดออกเสียง
- ตัวอย่างเช่น
แนวทางที่มีอยู่แล้วและน่าอ้างอิง
- Crockford's Base32 ถอดรหัสอักขระกำกวมให้เป็นค่าเดียวกัน และยังคำนึงถึงปัญหาการเกิดคำหยาบโดยไม่ตั้งใจ
- Open Location Code ใช้ชุดอักขระ
23456789CFGHJMPQRVWX- ชุดอักขระนี้ถูกเลือกเพื่อหลีกเลี่ยงอักขระที่กำกวมทางสายตา และหลีกเลี่ยงการสะกดเป็นคำในภาษาทั่วไปด้วย
- อย่างไรก็ตาม ยังรวมทั้ง
6กับG,9กับQไว้ด้วย
3 ความคิดเห็น
อันนี้ก็ดูน่าสนใจเหมือนกันครับ : https://stackoverflow.com/a/58098360/8556340
น่าทึ่งจริง ๆ ที่คำนึงถึงแม้กระทั่งการออกเสียง
ความคิดเห็นจาก Hacker News
ที่ทำงานเคยจัดส่งอุปกรณ์หลายล้านเครื่องโดยติด หมายเลขซีเรียล ไว้ แต่ไม่ได้ตัดตัวอักษรหรือตัวเลขที่ชวนสับสนออกเลย ทำให้ลูกค้าลำบากมากในการอ่านให้ถูกต้อง
ต้องเขียนสคริปต์ regex ที่สร้างชุดความเป็นไปได้ของการพิมพ์ผิดทั้งหมดจากค่าที่ลูกค้าบอก แล้วแสดงเฉพาะรายการที่ตรงกับฐานข้อมูลโรงงาน จากนั้นจึงเทียบกับข้อมูลอื่น ๆ อย่างวันที่เพื่อคาดเดาหมายเลขซีเรียลจริง
ที่ย้อนแย้งยิ่งกว่าคือ ตัวเลขบางตำแหน่งไม่มีวันเปลี่ยนเลย และบางตำแหน่งใช้แค่ 0, 1, 2 เพื่อแยกโรงงานก็พอ ดังนั้นตั้งแต่แรกก็ไม่จำเป็นต้องใช้ชุดอักขระทั้งหมด เหมือนกับว่าเชื่อกันว่าจะผลิตถึง 8,000 ล้านล้านเครื่อง
เช่น ถ้าติดหมายเลขสินค้าเรียงลำดับ 1, 2, 3 ก็สามารถประเมินยอดขายรวมได้ค่อนข้างง่ายจากตัวอย่างเพียงเล็กน้อย บางครั้งการทำให้เดาหมายเลขซีเรียลที่ถูกต้องได้ยากยังช่วยป้องกันการฉวยโอกาสอย่างการขอคืนเงินโดยมิชอบได้ด้วย
แน่นอนว่าแม้จะมีข้อกังวลเหล่านี้ ก็ยังสามารถหลีกเลี่ยงอักขระที่อ่านยากควบคู่กันไปได้ และถ้านั่นหมายความว่ามีใครสักคนกำลังคิดเรื่องว่าจะใช้ระบบหมายเลขแบบไหน ก็ควรจะตระหนักถึงปัญหาแบบนี้ได้ดีกว่านี้ด้วยซ้ำ แต่ในความเป็นจริง ดูเป็นไปได้สูงว่ามีใครสักคนคิดอยู่ราว 30 วินาทีแล้วบอกว่า “ใช้จำนวนหลักเท่านี้ก็ไม่มีทางหมดแน่ จบ”
ดูเหมือนหมายเลขซีเรียลของอุปกรณ์จะใช้เฉพาะพยัญชนะกับตัวเลข
การเข้ารหัสควรขึ้นอยู่กับ ผู้ใช้ Base32 โดยเฉพาะ Crockford และ RFC 4648 เหมาะกับการเขียนให้สั้น และมีชุดตัวอักษรที่ไม่กำกวมพร้อมเหตุผลรองรับอย่างดี
แต่ถ้าผู้ใช้ต้องพูดออกเสียง การแทนด้วย รายการคำ อย่าง “TIDE ITCH SLOW REIN RULE MOT” ตาม s/key RFC 1751 อาจดีกว่า
ไม่ควรสร้างรายการคำเอง เพราะมีกับดักซ่อนอยู่ไม่รู้จบ ทั้งสำนวน คำพ้องเสียง ภาษาถิ่น ฯลฯ อย่าเผลอสร้างหายนะครั้งใหญ่แบบ “wet clam butterfly” ขึ้นมาโดยไม่ตั้งใจ
RFC 1751 [0] ที่ยกตัวอย่างนี้ไม่ได้ตั้งใจให้เป็นการเข้ารหัสสำหรับถ่ายทอดด้วยวาจา แต่มีเป้าหมายเพื่อให้ผู้ใช้ “อ่าน จำ และป้อน” ได้ง่ายขึ้น
ถ้าผู้เชี่ยวชาญสื่อสารกันด้วยวาจา การเลือกใช้แค่อักษรตัวพิมพ์ใหญ่ 26 ตัวแล้วพึ่งพาอักษรสะกดคำแบบ NATO ก็สมเหตุสมผล แต่ปัญหาการรับรหัสจากผู้ใช้ที่ไม่ได้ผ่านการฝึก ในสภาพแวดล้อมการพูดที่มีเสียงรบกวนมาก ยังคงเป็นปัญหาที่ยังไม่ถูกแก้
[0] https://datatracker.ietf.org/doc/html/rfc1751
แค่ตรงที่ว่า “ต้องใช้อัลกอริทึม message digest แบบมีคีย์ MD5 และมันแข็งแรงเพียงพอ” ก็ขำแล้ว
ตอนที่บอกว่า “คนส่วนใหญ่จะอ่าน จำ และป้อนได้ยาก” ยังดีอยู่ แต่แล้วก็ไปต่อว่า “คำภาษาอังกฤษนั้นผู้คนจำและป้อนได้ง่ายกว่ามาก” ทั้งที่มีปัญหาว่าคนส่วนใหญ่ไม่รู้ภาษาอังกฤษ พอนึกว่าจะเปลี่ยนรายการคำก็ได้ กลับบอกว่า “ไม่พึงประสงค์ที่จะมีพจนานุกรมแยกตามภาษา เพราะเหตุผลด้านการทำงานร่วมกัน”
สุดท้ายกลายเป็นทำนองว่า ทั้งโลกเรียนตัวอักษรอังกฤษ 26 ตัวกันมาแล้ว เพิ่มคำอีกไม่กี่คำก็คงไม่เป็นไร แต่ใน
char Wp[2048][4] = […]ไม่ได้มีคำพื้นฐานที่พบบ่อยและเหมาะกับผู้เริ่มต้น หากเต็มไปด้วยคำอย่าง “WAD, BESS, MERT…” แถมยังมี “ORR? AGEE EGAN HAAS!!”, “GAUL FLAM! DRAB!” อีกด้วยเรื่องนี้ทำให้นึกถึงเรื่องเก่า ๆ วันหนึ่งตอนป่วย ผมสร้างโมดูลของเล่นสำหรับทำ เลขคณิตฐานใดก็ได้ เพื่อเบี่ยงเบนความสนใจจากอาการป่วย และเพราะมันง่ายเลยเอาขึ้น CPAN
โมดูลนั้นคือ https://metacpan.org/pod/Math::Fleximal
ในบรรดาของเล็ก ๆ น้อย ๆ ที่ผมทำ ผมคิดว่าสิ่งนี้คงไม่มีวันมีใครมาขอซัพพอร์ตแน่ ๆ แต่จริง ๆ แล้วมี เพราะผมใส่ตัวอย่างการแปลงเลขฐาน 16 เป็นโค้ดแบบตัวอักษรและตัวเลขไว้ แล้วมีใครบางคนเกิดไอเดียเจ๋ง ๆ ว่าจะเอาไปใช้ตรง ๆ เพื่อแปลงตัวเลขยาว ๆ ให้เป็นโค้ดที่อ่านง่าย
โมดูลทำงานได้ดี แต่ความจริงที่ว่าสิ่งนี้เข้าไปอยู่ใน โปรดักชัน ที่ไหนสักแห่งนั้นค่อนข้างชวนอึ้ง
บทความเน้นให้หลีกเลี่ยงอักขระที่แม้เขียนด้วยลายมือก็แยกยาก แต่ในตารางตัวอย่างกลับมีเลข 7 อยู่ ผมเจอกรณีที่แยก 7 ของบางคนกับ 1 ได้ยากมานับครั้งไม่ถ้วน
การขีดเส้นกลางเลข 7 ช่วยได้ แต่หลายคนไม่ได้เขียนแบบนั้น จึงมีบางครั้งที่ไม่แน่ใจว่าเป็น 7 หรือเป็น 1 ที่มี serif
บางครั้งสองตัวนี้แทบแยกไม่ออก อาจใช้อักษรมาตรฐาน NATO/การบิน (Alpha, Bravo, Charlie, Delta...) ได้ แต่ถ้ากลุ่มลูกค้าไม่ได้ถูกจำกัดไว้อย่างเข้มงวดมาก ก็ไม่ได้ช่วยมากนัก ชุดแบบนี้ก็ควรหลีกเลี่ยงเช่นกัน
แม้สตริง ID จะยาวขึ้นเล็กน้อย การเพิ่มความสามารถในการอ่าน พูด และฟังตัวอักษรให้สูงสุดย่อมดีกว่ามาก และช่วยประหยัดเวลาและความหงุดหงิดได้มากกว่าเยอะ
อยากรู้เหมือนกันว่าลายมือแบบไหนที่ทำให้ 1 คล้ายกับ 7 แค่ขีดแนวนอนด้านบนของ 7 ก็น่าจะพอแยกได้แล้ว
ถ้าใช้ทั้งตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก สักวันหนึ่งมีโอกาสสูงที่จะโดนระบบหรือโปรโตคอลของบุคคลที่สามที่ ไม่แยกแยะตัวพิมพ์เล็ก-ใหญ่ เล่นงาน
ผมเคยเห็นระบบเชิงพาณิชย์ที่อนุญาตให้ผู้ใช้เลือก ID ที่แยกตัวพิมพ์เล็ก-ใหญ่ได้ โดยยอมให้
iDกับidเป็นคนละค่า แต่เมื่อค้นหา ID ที่ไม่มีอยู่จริง กลับทำการจับคู่แบบไม่สนตัวพิมพ์เล็ก-ใหญ่ แล้วส่งคืนข้อมูลผิด ๆพอรายงานบั๊กนี้ไป ก็ได้รับคำตอบว่าเป็น “ฟีเจอร์เพื่อความสะดวก”
ตอนป้อนหมายเลขซีเรียลของ DLC บน Nintendo Switch ปุ่มอักขระที่คลุมเครือถูกปิดใช้งาน บนคีย์บอร์ดหน้าจอ ซึ่งรู้สึกว่าเป็นประสบการณ์ผู้ใช้ที่ค่อนข้างดี
นั่นหมายความว่าหมายเลขซีเรียลถูกสร้างขึ้นมาโดยไม่มีอักขระที่คลุมเครือตั้งแต่แรกแล้ว ผมไม่ค่อยแน่ใจว่า UX นี้ฝังอยู่ในระบบปฏิบัติการ หรือมีเฉพาะในเกมที่เล่นอยู่คือ Mario + Rabbids Sparks of Hope
ตัวจัดการรหัสผ่านโอเพนซอร์ส KeepassXC ใช้สีเพื่อทำให้รหัสผ่านอ่านง่ายขึ้น เป็นวิธีที่ใช้อีกสีหนึ่งกับอักขระแต่ละประเภท เช่น ตัวพิมพ์ใหญ่ ตัวพิมพ์เล็ก ตัวเลข และสัญลักษณ์
เป็นไอเดียที่เรียบง่ายมาก แต่โดยเฉพาะกับรหัสผ่านแบบสุ่ม มันช่วยได้มากแม้จะใช้ฟอนต์ที่อ่านง่ายอยู่แล้วก็ตาม
ผมเข้าใจยากว่าซอฟต์แวร์ที่เน้นรหัสผ่านจะยอมให้แสดงอักขระด้วยฟอนต์ที่คลุมเครือโดยไม่มีการแบ่งสีใด ๆ ได้อย่างไร
เวลาต้องป้อนรหัสผ่านยาว ๆ ผ่านอินเทอร์เฟซอย่างรีโมตทีวี แล้วมารู้ตัวว่าสับสนระหว่าง
l1|Iมันน่าหงุดหงิดมาก ผมเลยใส่ไว้ในรายการยกเว้นเองเป็นบทความที่อ่านดี เพราะพูดถึงปัญหาที่เจอบ่อยในชีวิตประจำวัน
ทุกครั้งที่จด โค้ดสำรองสำหรับการยืนยันตัวตนสองขั้นตอน ลงกระดาษ พอเจออักขระอย่าง
o/0,v/u,5/Sก็รู้สึกไม่สบายใจ เลยตั้งใจเขียนอักขระพวกนี้ให้ดูต่างกันเล็กน้อยพอเห็นส่วน “ความคล้ายกันทางเสียง” ก็ทำให้นึกถึงตอนเลือกรหัสผ่าน Wi‑Fi ผมอยากได้คำธรรมดาที่แชร์เป็นประโยคเดียวก็ไม่คลุมเครือ เด็กประถม 3 ก็สะกดได้ และมีพยัญชนะหลายตัว สุดท้ายเลยเลือก “vacation”
5/S,0/O,8/Bได้ คู่ที่เป็นปัญหาจริง ๆ จะแตกต่างกันไปตามลายมือของแต่ละคนถ้าไม่มั่นใจจริง ๆ ก็เติม NATO/ตัวอักษรการบิน [1] เข้าไปด้วย เช่น ถ้ามี
Uก็เริ่มจากUแล้วเขียนUniformเฉียงออกไปแค่ต้องมีวินัยนิดหน่อย ผมทำแบบนี้มานานกว่า 10 ปี และไม่เคยทำโค้ด 2FA หายเลยสักครั้ง
[1] การจับผิดเรื่องความแตกต่างจริง ๆ ระหว่าง NATO กับรหัสการบิน ส่งไปที่
/dev/nullได้อย่างปลอดภัยหัวกลายเป็นคอขวด
ผมชอบบทสนทนาแบบนี้ อาจไม่ใช่หัวข้อที่ล้ำสมัยหรือน่าตื่นเต้น แต่มีความหมายและพลังไม่น้อยในการทำให้ชีวิตของทั้งคนและเครื่องจักรง่ายขึ้น
เรื่องพวกนี้ยังอยู่ในขอบเขตของ แนวทางปฏิบัติที่ดี ซึ่งเมื่อทำได้ดี กลับไม่มีใครสังเกตเห็น เป็นความจริงที่น่าเสียดายที่ความใส่ใจและความจริงจังในรายละเอียดถูกเหมารวมว่าเป็น “สิ่งที่ควรเป็นอยู่แล้ว” จึงแทบไม่ได้รับคำชมเป็นพิเศษ
ถ้าจะชี้ข้อผิดพลาดในบทความ ใน
9qg6G8B2Z5SIl170O (ariel)ชื่อฟอนต์ไม่ใช่ Ariel แต่เป็น Arial ต่างหาก เงือกน้อยไม่ได้อยู่ตรงนี้บน Linux บรรทัดส่วนใหญ่ดูเหมือนกันหมด
https://github.com/gajus/gajus-com/blob/main/src/blogPosts/2...
ผมแก้คำผิดไว้แล้ว