การซ่อนข้อมูลใน Cats


24

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


แรงบันดาลใจจากอัลกอริธึมที่เกมโมนาโกใช้ในการบันทึกข้อมูลระดับของระดับที่ใช้ร่วมกันมันเป็นหน้าที่ของคุณในการเขียนโปรแกรมที่เข้ารหัสข้อมูลลงในสีที่มีนัยสำคัญน้อยที่สุดของภาพ

รูปแบบการเข้ารหัส:

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

กฎ:

  • โปรแกรมของคุณใช้การเข้ารหัสไบต์เดียวและชื่อไฟล์ภาพเดียวสำหรับภาพพื้นฐาน
  • ภาพที่ได้จะต้องออกมาเป็นไฟล์ PNG สีจริง
  • คุณสามารถใช้ I / O ในรูปแบบใดก็ได้ที่คุณต้องการ (ARGV, STDIN, STDOUT, การเขียน / อ่านจากไฟล์) ตราบใดที่คุณระบุวิธีการใช้โปรแกรมของคุณ
  • คุณต้องเลือกภาพแมวตลกแบบสุ่มและเข้ารหัสโปรแกรมของคุณเพื่อแสดงว่าโปรแกรมของคุณทำงานได้
  • คุณอาจสมมติว่าคุณได้รับอินพุตที่ถูกต้องเท่านั้นหากจำนวนบิตไม่เพียงพอภาพไม่ได้อยู่ในรูปแบบสีจริงภาพไม่มีอยู่หรือมีปัญหาคล้ายกันคุณอาจทำสิ่งที่คุณต้องการ
  • คุณอาจสันนิษฐานว่าภาพที่ให้ไม่มีช่องอัลฟา
  • ความยาวนับเป็น UTF-8 ไบต์โดยไม่มี BOM

คุณสามารถใช้สคริปต์ PHP นี้เพื่อทดสอบวิธีแก้ปัญหาของคุณระบุชื่อไฟล์ PNG เป็นอาร์กิวเมนต์บรรทัดคำสั่งแรก:

<?php
if ($argc === 1) die('Provide the filename of the PNG to read from');
$imageSize = @getimagesize($argv[1]);

if ($imageSize === false) die('Not a PNG file');
list($width, $height) = $imageSize;

$image = imagecreatefrompng($argv[1]);
$read = 0;
$bits = '';
for ($y = 0; $y < $height; $y++) {
    for ($x = 0; $x < $width; $x++) {
        $colorAt = imagecolorat($image, $x, $y);
        $red = ($colorAt >> 16) & 0xFF;
        $green = ($colorAt >> 8) & 0xFF;
        $blue = ($colorAt >> 0) & 0xFF;

        $bits .= ($red & 1).($green & 1).($blue & 1);
        $read += 3;
        if ($read == 24) {
            $length = (int) bindec($bits);
            $bits = '';
        }
        else if ($read > 24 && ($read - 24) > $length) {
            $bits = substr($bits, 0, $length);
            break 2;
        }
    }
}
if (strlen($bits) !== $length) die('Not enough bits read to fulfill the length');
$parts = str_split($bits, 8);
foreach ($parts as $part) {
    echo chr(bindec($part));
}

ข้อมูลจำเพาะของคุณระบุว่า "โปรแกรมของคุณใช้ภาพเดียวเป็นฐาน ใน Mathematica ภาพเป็นเพียงแค่การแสดงออกเหมือนทุกสิ่งทุกอย่างดังนั้นข้อมูลจำเพาะทางเทคนิคนี้จะอนุญาตให้ฉันทำการโหลดไฟล์นอกโค้ดที่ทำการคำนวณ (โดยพารามิเตอร์อินพุตเป็นรูปภาพจริงแทนที่จะเป็นชื่อไฟล์ของรูปภาพ) . หากคุณไม่ต้องการสิ่งเช่นนั้นคุณอาจต้องการระบุว่าโปรแกรมจำเป็นต้องใช้ชื่อไฟล์ของรูปภาพเป็นอินพุต
Martin Ender

4
ME helpimtrappedinacatfactory OW
TheDoctor

นอกจากนี้บิตที่ไม่ได้ใช้สำหรับการเข้ารหัสจะต้องไม่มีการเปลี่ยนแปลงหรือไม่ หรือเราสามารถตั้งค่าให้เป็นสิ่งที่เราต้องการ (เพราะมันจะไม่ส่งผลกระทบต่อคุณภาพของภาพและไม่สำคัญสำหรับการถอดรหัส)
Martin Ender

1
ฉันสามารถใช้ไลบรารี่ที่ไม่ใช่บิวด์อินเพื่อโหลดและบันทึกไฟล์ png เช่น PIL ใน Python ได้หรือไม่?
Claudiu

1
@ TimWolla จากแมว? เก็บไว้ในอาคารและตรวจสอบถาดทิ้งขยะ จากรูปถ่าย? หากคุณถ่ายภาพเอ็กซ์เรย์ความละเอียดสูงพอคุณอาจเห็นสถานะของทรานซิสเตอร์แต่ละตัวในชิปแฟลช ฉันแน่ใจว่านี่จะเป็นวิธีที่มีประสิทธิภาพมากที่สุดในการส่งต่อข้อมูลลับที่เคยคิดแม้ว่าแมวอาจมีความคิดอื่น
Sonic Atom

คำตอบ:


3

Perl & ImageMagick (Linux), 198 190

แก้ไข:โดยบังเอิญบางครั้งก่อนหน้านี้ฉันทดสอบบนคอมพิวเตอร์ที่ติดตั้ง ImageMagick รุ่น Q8 (ความลึก 8 บิต) 'มาตรฐาน' รุ่น Q16 ต้องระบุอย่างชัดเจน-depth 8ในบรรทัดคำสั่ง บน Linux identifyผลลัพธ์ต้องมีการขึ้นบรรทัดใหม่ด้วย ปัจจัยทั้งสองนำไปสู่การเพิ่มขนาดรหัสดังนั้นฉันโพสต์รุ่น Linux (อาจ Mac เกินไป) เป็นคำตอบด้วยการแก้ไขที่ใช้และยังมีบางสิ่งที่ Windows เท่านั้นเอาออก (การแปลง CR-lf, ไบนารีเทียบกับข้อความ ฯลฯ ) รุ่นพกพา (อีกเล็กน้อย) จะโพสต์ใกล้จะจบ

ด้วยการขึ้นบรรทัดใหม่เพื่อให้อ่านง่าย:

$/=$1;
<>=~/\n/;
$_=`identify -format %wx%h $\``;
chop;
open O,"|convert -size $_ -depth 8 rgb: $`.png";
$_=`convert $\` rgb:`;
print O$_&y//\376/cr|unpack('B*',pack(NX,2048*length$').$')&y//\1/cr

วิ่ง:

perl cat.pl

มันอ่านจาก STDIN ชื่อไฟล์ภาพในบรรทัดแรก 'ความลับ' ctrl-Dข้อความดังต่อไปนี้สิ้นสุดลงด้วย ชื่อไฟล์ที่ส่งออกเป็นต้นฉบับที่มีการ.pngผนวก - ไม่ดีมากมันทำเพื่อความกะทัดรัดเท่านั้น

นี่คือภาพที่มีข้อมูลลับบางอย่างซ่อนอยู่ภายใน:

ป้อนคำอธิบายรูปภาพที่นี่

และด้วยความคิดเห็นบางส่วน:

# Undef input record separator, because we'll slurp input.

$/=$1;

# Read from STDIN, separate first line. 
# $` (prematch) contains image file name,
# $' (postmatch) - text to encode.

<>=~/\n/;

# Get IM's 'identify' output, width and height of the image. 
# Note: we don't have to separate them, \d+x\d+ string will 
# do just fine.

$_=`identify -format %wx%h $\``;
chop;

# Open output pipe - IM's 'convert' command that takes raw RGB data from 
# STDIN and writes output to PNG file. Interpolated into this command
# line is previous IM's 'identify' result. Convert wants '-size' command
# option in case of raw RGB input - for obvious reason.

open O,"|convert -size $_ -depth 8 rgb: $`.png";

# Get raw RGB data into $_.

$_=`convert $\` rgb:`;

# Last line does all the job. 

# y//\376/cr --- create string same length as $_, fill with 0xFE
# $_&y//\376/cr --- zero least significant bit for all image bytes (1).
# pack(NX,2048*length$') --- multiply by 8 (bytes to bits count) and 
#         shift left by 8 (because we'll pack long integer into 3 bytes) -
#         i.e. multiply by 2048.
# unpack('B*',pack(NX,2048*length$').$') ---- append 'secret text' to 
#       its encoded length and convert to 'binary' (consisting of 1 and 
#       0 characters) string.
# ... &y//\1/cr --- equivalent of tr/01/\0\1/. We don't have to worry 
#       that raw RGB length is larger than encoded text length, because
#       '&' truncates longer string argument (2).
# Then bitwise-'or' (1) and (2) strings.

print O$_&y//\376/cr|unpack('B*',pack(NX,2048*length$').$')&y//\1/cr

ถัดไปเป็นรุ่นพกพาทำงานบน Windows (ใช้ctrl-Zเพื่อยุติอินพุต) และ Linux จำนวนไบต์คือ 244

$_=do{local$/;<>};
/\n/;
$_=`identify -format %wx%h $\``;
chomp;
open I,'-|:raw',"convert $` rgb:";
open O,'|-:raw',"convert -size $_ -depth 8 rgb: $`.png";
$_=do{local$/;<I>};
print O$_&y//\376/cr|unpack('B*',pack(NX,2048*length$').$')&y//\1/cr

10

Mathematica, 255 234 206 ไบต์

ฉันเห็นหลาย ๆ ตัว255ในขณะที่ทดสอบสิ่งนี้ฉันมีความสุขอย่างไม่มีเหตุผลเกี่ยวกับขนาดของรหัส :)จากนั้นความใฝ่ฝันของฉันในการตีกอล์ฟให้ดียิ่งขึ้นไปคือสิ่งที่ดีที่สุดสำหรับฉัน ...

f=(j=ImageData[Import@#2,t="Byte"];k=(d=IntegerDigits)[j,2,8]~Flatten~2;n=1;(k[[n++,-1]]=#)&/@d[Length@#,2,24]~Join~#&[Join@@d[ToCharacterCode@#,2,8]];ArrayReshape[#~FromDigits~2&/@k,Dimensions@j]~Image~t)&

มันเป็นฟังก์ชั่นทางเทคนิคไม่ใช่ "โปรแกรม" แต่แล้วอีกครั้งนี่เป็นวิธีที่คุณเขียนคำว่า "โปรแกรม" ใน Mathematica ถ้าแนวคิดนั้นใช้ได้จริง เรียกว่าชอบ

f["my secret", "fully/qualified/cat.png"]

มันจะคืนค่าการแสดงออกของภาพที่แท้จริง (เพราะเป็นวิธีที่ง่ายที่สุดในการส่งคืนรูปภาพใน Mathematica) ดังนั้นหากคุณต้องการไฟล์คุณต้องส่งออก:

Export["output-cat.png", f["my secret", "input-cat.png"]]

นี่คือตัวอย่างที่ต้องการ:

ป้อนคำอธิบายรูปภาพที่นี่

ฉันชอบที่จะแสดงข้อความถอดรหัสที่นี่ แต่มันไม่พอดี ... ดังนั้นให้เรียกใช้ผ่านตัวถอดรหัสของ OP ;)

Btw ฉันสามารถทำให้มันทำงานกับความลับ UTF-8 ได้เพียง 7 ไบต์ (เปลี่ยนToCharacterCode@#เป็น#~ToCharacterCode~"utf8")

รหัสไม่ได้รับการตอบกลับ:

f[secret_, filename_] := (
  bits = Join @@ IntegerDigits[ToCharacterCode[secret], 2, 8];
  bits = Join[d[Length @ bits, 2, 24], bits];
  data = ImageData[Import@#2, "Byte"];
  dims = Dimensions@data;
  data = Flatten[IntegerDigits[data, 2, 8], 2];
  m = n = 1;
  While[m <= Length @ bits,
    data[[n++, -1]] = bits[[m++]]
  ];
  Image[ArrayReshape[FromDigits[#, 2] & /@ data, dims], "Byte"]
)

"ฉันชอบที่จะแสดงข้อความถอดรหัสที่นี่ แต่มันไม่พอดี ... ดังนั้นให้เรียกใช้ผ่านตัวถอดรหัสของ OP;)" - ฉันทำและให้ฉัน "????????? ??? ?? +++++++ ++++++++++++++++++++ ================= ~ === ~ ============ ~ :::: ~~~~~ = [... สำหรับ 9773 ตัวอักษร] "
TessellatingHeckler

1
@TessellatingHeckler นั่นถูกต้อง ลองใช้แบบอักษร monospaced และระวังว่ามีบรรทัดใหม่ของ UNIX ในลักษณะนั้น (เช่นลองใช้เทอร์มินัลหรือ PowerShell ที่มีความกว้างอย่างน้อย 180 ตัวอักษรหรือหากคุณใช้งานเป็นสคริปต์เว็บในเบราว์เซอร์ของคุณ จากนั้นดูที่มา);)
Martin Ender

2
ฉันเห็น! เมตามาก ช่วยให้ฉันอยู่ใน PuTTY รุ่น KiTTY ด้วย😸
TessellatingHeckler

5

PHP, 530 ไบต์

<?php function p($i,$j){return str_pad(decbin($i),$j,0,0);}extract(getopt("i:o:t:"));$t=file_get_contents($t);$_=imagecreatefrompng($i);list($w,$h)=getimagesize($i);$b="";for($i=0;$i<strlen($t);)$b.=p(ord($t[$i++]),8);$l=strlen($b);$b=p($l,24).$b;$l+=24;for($i=$x=$y=0;$y<$h;$y++){for(;$x<$w;){$C=imagecolorat($_,$x,$y);$R=($C>>16)&0xff;$G=($C>>8)&0xff;$B=$C&0xff;$i<$l&&$R=$b[$i++]|$R&~1;$i<$l&&$G=$b[$i++]|$G&~1;$i<$l&&$B=$b[$i++]|$B&~1;imagesetpixel($_,$x++,$y,imagecolorallocate($_,$R,$G,$B));if($i>$l){imagepng($_,$o);die;}}}

php 25443.php -i<input image> -o<output image> -t<file to hide>ทำงานเหมือน

และนี่คือภาพตัวอย่าง

http://i.imgur.com/hevnrbm.png

รหัส Ungolfed ถูกซ่อนอยู่ในภาพตัวอย่าง ทดสอบกับตัวถอดรหัสของ OP ขออภัยสำหรับรูปแมวที่ไม่ตลก


1
กรุณาเพิ่มรหัส ungolfed ในคำตอบของคุณ
อัล

1
คุณสามารถร่นไป0xff 255
TimWolla

คุณสามารถบันทึก 4 <?functionไบต์ถ้าคุณถือว่าแท็กสั้น:
nyuszika7h
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.