นากมิ้นต์ต้นฉบับเทียบลูกปัดไบต์สองแถว โดยลูกปัดสีอำพันค่าช่วงสูงถูกมองเป็นบวก

Java Arrays.compareUnsigned: เรียง byte array แบบข้อมูลไบนารี ไม่ใช่เลขติดลบ

พี่โชว์Engineering

Java เก็บ byte เป็น signed ช่วงลบถึงบวก แต่ข้อมูล network, digest และ binary key มักตีความแต่ละ byte เป็น 0–255 ครับ Arrays.compareUnsigned เปรียบเทียบแบบ lexicographic โดยใช้ค่าที่ไม่ติดลบ

WHY: byte เดียวกันมีสองความหมาย

บิตทุกบิตเหมือนเดิม แต่ (byte) 0xFF มีค่า -1 ใน Java หากเปรียบเทียบ signed มันจะน้อยกว่า 0x01 ทั้งที่ protocol มองเป็น 255 ซึ่งมากกว่า 1 เหมือนป้ายราคาที่เครื่องหนึ่งอ่านเป็นหนี้ อีกเครื่องอ่านเป็นมูลค่าสูงสุด ต้องตกลง semantics ก่อนเรียง

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        byte[] high = {(byte) 0xFF};
        byte[] low = {0x01};

        assert Arrays.compare(high, low) < 0;
        assert Arrays.compareUnsigned(high, low) > 0;
        assert Arrays.compareUnsigned(
            new byte[] {0x01, 0x02},
            new byte[] {0x01, 0x03}
        ) < 0;
        assert Arrays.compareUnsigned(
            new byte[] {0x01},
            new byte[] {0x01, 0x00}
        ) < 0;
        System.out.println("unsigned comparison checks passed");
    }
}

เมธอดหยุดที่ byte แรกที่ต่าง ถ้า prefix เท่ากัน array ที่สั้นกว่าจะมาก่อน นี่เหมาะกับ binary identifiers ที่กำหนด order แบบ unsigned แต่ไม่ควรใช้แทน constant-time comparison สำหรับ secret เพราะเวลาทำงานอาจเผยตำแหน่งแรกที่ต่าง

Recap

  • เลือก signed หรือ unsigned ตาม protocol ไม่ใช่ตามความเคยชิน
  • compareUnsigned เรียงแบบ lexicographic
  • prefix เท่ากัน array สั้นมาก่อน
  • secret ใช้ primitive ที่ออกแบบเพื่อลด timing side-channel