อัตชีวประวัติของ LSB

กาลครั้งหนึ่งฉันเขียนของฉัน โพสต์แรกบนฮับ. และโพสต์นั้นเน้นไปที่ปัญหาที่น่าสนใจมาก นั่นคือการลักลอบค้าสัตว์ แน่นอนว่า แนวทางแก้ไขที่เสนอในหัวข้อเก่านั้นไม่สามารถเรียกว่าการซุบซิบในความหมายที่แท้จริงของคำนี้ได้ มันเป็นเพียงเกมที่มีรูปแบบไฟล์ แต่ก็เป็นเกมที่น่าสนใจทีเดียว

วันนี้เราจะพยายามเจาะลึกลงไปอีกเล็กน้อยแล้วดูอัลกอริธึม LSB สนใจเชิญใต้แมวได้เลยครับ (ภายใต้การตัดคือปริมาณการรับส่งข้อมูล: ประมาณเมกะไบต์)

ก่อนอื่นต้องแนะนำตัวสั้นๆ ก่อน ทุกคนรู้ดีว่าจุดประสงค์ของการเข้ารหัสคือการทำให้ไม่สามารถอ่านข้อมูลลับได้ แน่นอนว่าการเข้ารหัสนั้นมีการใช้งาน แต่ก็มีวิธีอื่นในการปกป้องข้อมูล เราไม่จำเป็นต้องเข้ารหัสข้อมูล แต่แสร้งทำเป็นว่าเราไม่มีข้อมูลนั้น นี่คือสาเหตุที่แน่ชัดว่าเหตุใดจึงมีการคิดค้นสุริยคติขึ้นมา วิกิพีเดียให้คำรับรองแก่เราว่า “การอำพรางข้อมูล (จากภาษากรีก στεγανοσ - ซ่อนเร้น และภาษากรีก γραφω - ฉันเขียนตามตัวอักษรว่า “การเขียนลับ”) เป็นศาสตร์แห่งการถ่ายทอดข้อมูลที่ซ่อนเร้นโดยการรักษาข้อเท็จจริงของการถ่ายทอดไว้เป็นความลับ

แน่นอนว่าไม่มีใครห้ามไม่ให้รวมวิธีการเข้ารหัสและ Steganographic เข้าด้วยกัน ยิ่งไปกว่านั้น ในทางปฏิบัติพวกเขาทำเช่นนี้ แต่งานของเราคือการเข้าใจพื้นฐาน หากคุณศึกษาบทความ Wikipedia อย่างถี่ถ้วน คุณจะพบว่าอัลกอริธึมการอำพรางข้อมูลรวมถึงสิ่งที่เรียกว่า คอนเทนเนอร์และข้อความ คอนเทนเนอร์คือข้อมูลใดๆ ที่ช่วยซ่อนข้อความลับของเรา

ในกรณีของเรา คอนเทนเนอร์จะเป็นรูปภาพในรูปแบบ BMP ก่อนอื่น มาดูโครงสร้างของไฟล์นี้กันก่อน ไฟล์สามารถแบ่งออกเป็น 4 ส่วน: ส่วนหัวของไฟล์, ส่วนหัวของรูปภาพ, จานสี และตัวรูปภาพเอง เพื่อจุดประสงค์ของเรา เราเพียงแต่ต้องรู้ว่ามีอะไรเขียนอยู่ในส่วนหัวเท่านั้น

สองไบต์แรกของส่วนหัวคือลายเซ็น BM จากนั้นขนาดไฟล์เป็นไบต์จะถูกเขียนด้วยคำคู่ ส่วน 4 ไบต์ถัดไปจะถูกสงวนไว้และต้องมีเลขศูนย์ และสุดท้ายคำคู่อีกคำหนึ่งมีการชดเชยจากจุดเริ่มต้นของ ไฟล์เป็นไบต์ที่แท้จริงของภาพ ในไฟล์ bmp 24 บิต แต่ละพิกเซลจะถูกเข้ารหัสด้วยไบต์ BGR สามไบต์

ตอนนี้เรารู้วิธีเข้าถึงภาพแล้ว สิ่งที่เหลืออยู่คือต้องเข้าใจว่าเราจะเขียนข้อมูลที่เราต้องการลงในนั้นได้อย่างไร สำหรับสิ่งนี้ เราจำเป็นต้องใช้วิธี LSB สาระสำคัญของวิธีการมีดังนี้: เราแทนที่บิตที่มีนัยสำคัญน้อยที่สุดในไบต์ที่รับผิดชอบในการเข้ารหัสสี สมมติว่าไบต์ถัดไปของข้อความลับของเราคือ 11001011 และไบต์ในภาพคือ...11101100 01001110 01111100 0101100111... การเข้ารหัสจะมีลักษณะดังนี้ เราจะแบ่งไบต์ข้อความลับออกเป็น 4 ส่วนสองบิต: 11, 00, 10, 11 และแทนที่บิตลำดับต่ำของรูปภาพด้วยแฟรกเมนต์ผลลัพธ์: ...11101111 01001100 01111110 0101100111…. การแทนที่ดังกล่าวโดยทั่วไปไม่สามารถมองเห็นได้ด้วยตามนุษย์ ยิ่งไปกว่านั้น อุปกรณ์เอาท์พุตรุ่นเก่าๆ จำนวนมากจะไม่สามารถแสดงการเปลี่ยนแปลงเล็กๆ น้อยๆ ดังกล่าวได้ด้วยซ้ำ

เป็นที่ชัดเจนว่าคุณสามารถเปลี่ยนได้ไม่เพียงแต่ 2 บิตที่มีนัยสำคัญน้อยที่สุด แต่ยังสามารถเปลี่ยนจำนวนเท่าใดก็ได้ มีรูปแบบดังต่อไปนี้: ยิ่งเราเปลี่ยนแปลงบิตมากเท่าใด เราก็สามารถซ่อนข้อมูลได้มากขึ้นเท่านั้น และการรบกวนนี้จะทำให้เกิดการรบกวนในภาพต้นฉบับมากขึ้นเท่านั้น ตัวอย่างเช่น นี่คือรูปภาพสองรูป:

อัตชีวประวัติของ LSB
อัตชีวประวัติของ LSB

แม้ว่าฉันจะพยายามอย่างเต็มที่ แต่ฉันไม่เห็นความแตกต่างระหว่างพวกเขา แต่อย่างไรก็ตามในภาพที่สองโดยใช้วิธีการที่อธิบายไว้ บทกวีของ Lewis Carroll เรื่อง "The Hunting of the Snark" ก็ถูกซ่อนอยู่ หากคุณได้อ่านมาไกลขนาดนี้แล้ว คุณคงสนใจที่จะเรียนรู้เกี่ยวกับการนำไปปฏิบัติ มันค่อนข้างง่าย แต่ฉันจะเตือนคุณทันทีว่าทุกอย่างเสร็จสิ้นใน Delphi มีสองเหตุผลสำหรับเรื่องนี้: 1. ฉันคิดว่า Delphi เป็นภาษาที่ดี; 2. โปรแกรมนี้เกิดขึ้นในกระบวนการเตรียมหลักสูตรเกี่ยวกับพื้นฐานของการมองเห็นคอมพิวเตอร์และคนที่ฉันกำลังสอนหลักสูตรนี้ยังไม่รู้อะไรเลยนอกจาก Delphi สำหรับผู้ที่ไม่คุ้นเคยกับไวยากรณ์ สิ่งหนึ่งที่ต้องอธิบาย: shl x เป็นการเลื่อนระดับบิตไปทางซ้ายด้วย x, shr x เป็นการเลื่อนระดับบิตไปทางขวาด้วย x

เราถือว่าเรากำลังเขียนข้อความที่เก็บไว้ในสตริงลงในคอนเทนเนอร์และแทนที่สองไบต์ล่าง:
รหัสการบันทึก:

สำหรับ i:=1 ถึง length(str) do
    เริ่ม
      l1:=ไบต์(str[i]) shr 6;
      l2:=byte(str[i]) shl 2; l2:=l2 shr 6;
      l3:=byte(str[i]) shl 4; l3:=l3 shr 6;
      l4:=byte(str[i]) shl 6; l4:=l4 shr 6;
 
      ฉReadBuffer(tmp,1);
      ฉ.ตำแหน่ง:=ฉ.ตำแหน่ง-1;
      tmp:=((tmp shr 2) shl 2)+l1;
      ฉWriteBuffer(tmp,1);
 
      ฉReadBuffer(tmp,1);
      ฉ.ตำแหน่ง:=ฉ.ตำแหน่ง-1;
      tmp:=((tmp shr 2) shl 2)+l2;
      ฉWriteBuffer(tmp,1);
 
      ฉReadBuffer(tmp,1);
      ฉ.ตำแหน่ง:=ฉ.ตำแหน่ง-1;
      tmp:=((tmp shr 2) shl 2)+l3;
      ฉWriteBuffer(tmp,1);
 
      ฉReadBuffer(tmp,1);
      ฉ.ตำแหน่ง:=ฉ.ตำแหน่ง-1;
      tmp:=((tmp shr 2) shl 2)+l4;
      ฉWriteBuffer(tmp,1);
 
    จบ;

รหัสที่จะอ่าน:

สำหรับ i:=1 ถึง MsgSize ทำ
    เริ่ม
      ฉReadBuffer(tmp,1);
      l1:=tmp shl 6;
      ฉReadBuffer(tmp,1);
      l2:=tmp shl 6; l2:=l2 shr 2;
      ฉReadBuffer(tmp,1);
      l3:=tmp shl 6; l3:=l3 shr 4;
      ฉReadBuffer(tmp,1);
      l4:=tmp shl 6; l4:=l4 shr 6;
      STR:=str+ถ่าน(l1+l2+l3+l4);
    จบ;

สำหรับคนขี้เกียจจริงๆ - ลิงก์ไปยังโปรแกรมและซอร์สโค้ด.

ขอบคุณ

ที่มา: will.com

เพิ่มความคิดเห็น