Arrays.equals() vs MessageDigest.isEqual()

  Pi Ke        2015-05-14 22:03:29       20,253        0          English  简体中文  ภาษาไทย  Tiếng Việt 

ทั้ง Arrays.equals() และ MessageDigest.isEqual() ใช้สำหรับเปรียบเทียบความเท่ากันของอาร์เรย์สองตัว สามารถใช้แทนกันได้ในหลายกรณี อย่างไรก็ตาม พวกมันมีความแตกต่างบางอย่างที่นำไปสู่การใช้งานที่แตกต่างกันในแอปพลิเคชันจริง

ความแตกต่างอย่างหนึ่งคือ อาร์เรย์ที่ส่งผ่านไปยัง MessageDigest.isEqual() ไม่สามารถเป็น null ได้ ในขณะที่ Arrays.equals() สามารถเป็นได้

ความแตกต่างที่สำคัญอย่างหนึ่งระหว่างเมธอดทั้งสองนี้คือ Arrays.equals() ไม่ใช่ time-constant ในขณะที่ MessageDigest.isEqual() เป็น time-constant นั่นหมายความว่าเมื่อเปรียบเทียบอาร์เรย์สองตัว อาร์เรย์จะถูกเปรียบเทียบทีละไบต์ Arrays.equals() จะส่งคืนทันทีสำหรับไบต์แรกที่ไม่เท่ากัน MessageDigest.isEqual() จะเปรียบเทียบไบต์ทั้งหมดในอาร์เรย์ไม่ว่าไบต์แรกจะไม่เท่ากันที่ตำแหน่งใด

การใช้งานของ Arrays.equals() คือ :

public static boolean equals(byte[] a, byte[] a2) {
    if (a==a2)
        return true;
    if (a==null || a2==null)
        return false;

    int length = a.length;
    if (a2.length != length)
        return false;

    for (int i=0; i<length; i++)
        if (a[i] != a2[i])
            return false;

    return true;
}

จากลูป for Arrays.equals() เป็นเมธอด fail fast ถ้าไบต์แรกไม่เท่ากัน มันจะส่งคืนทันที โดยปกติแล้วหมายถึงประสิทธิภาพสูงแต่ความปลอดภัยน้อยกว่า จริงๆแล้วจากการใช้งาน เมธอดนี้ถูกออกแบบมาเพื่อประสิทธิภาพ พวกมันมีการตรวจสอบไม่กี่อย่างเพื่อตรวจสอบว่าอาร์เรย์สองตัวเท่ากันอย่างรวดเร็วโดยไม่ต้องเปรียบเทียบเนื้อหาของอาร์เรย์จริงๆ

การใช้งานของ MessageDigest.isEqual() คือ :

public static boolean isEqual(byte[] digesta, byte[] digestb) {
    if (digesta.length != digestb.length) {
        return false;
    }

    int result = 0;
    // time-constant comparison
    for (int i = 0; i < digesta.length; i++) {
        result |= digesta[i] ^ digestb[i];
    }
    return result == 0;
}

จากลูป for อาร์เรย์จะถูกเปรียบเทียบอย่างสมบูรณ์ นั่นหมายความว่าความปลอดภัยสูงแต่ประสิทธิภาพต่ำกว่า

ในระบบที่มีความต้องการด้านความปลอดภัยสูง Arrays.equals() อาจมีความเสี่ยงต่อการโจมตีแบบ time constant ตัวอย่างเช่น ถ้ามีการเปรียบเทียบแฮชหรือคีย์โดยใช้ Arrays.equals() การโจมตีสามารถปลอมแฮชหรือคีย์และทำการเปรียบเทียบกับแฮชหรือคีย์จริง พวกเขาสามารถวัดเวลาที่ใช้สำหรับ Arrays.equals() ในการส่งคืนเพื่อทำความเข้าใจว่ามีไบต์ที่ตรงกับแฮชหรือคีย์ปลอมกี่ไบต์ หลังจากลองหลายร้อยหรือหลายพันครั้ง พวกเขาอาจเปิดเผยแฮชและคีย์จริง สำหรับรายละเอียดเกี่ยวกับวิธีการโจมตีนี้ คุณสามารถอ่านเพิ่มเติมได้ที่ A Lesson In Timing Attacks (or, Don’t use MessageDigest.isEquals).

ดังนั้นเมื่อคุณตัดสินใจที่จะใช้เมธอดในการเปรียบเทียบอาร์เรย์สองตัว โปรดพิจารณาอย่างรอบคอบว่าแอปพลิเคชันนั้นเกี่ยวข้องกับความปลอดภัยหรือประสิทธิภาพหรือไม่ ถ้าสิ่งที่คุณต้องการคือประสิทธิภาพ ให้ใช้ Arrays.equals() แต่ถ้าคุณกำลังพัฒนาผลิตภัณฑ์ด้านความปลอดภัย โปรดระมัดระวังและใช้ MessageDigest.isDigest() ต่อไป

จำไว้ว่าแฮกเกอร์เป็นกลุ่มคนที่ "ใช้ทุกวิธีการที่นึกออก; ไม่หยุดยั้ง"

ARRAYS.EQUAL()  MESSAGEDIGEST.ISEQUAL()  JAVA  SECURITY 

       

  RELATED


  0 COMMENT


No comment for this article.



  RANDOM FUN

How Chinese learn to drive

A Chinese lady is learning how to drive secirouly with equipments found in her own house. She is so creative.