在Cat中隐藏信息


24

您是试图与祖国沟通的秘密特工。当然,信息需要隐藏,因此没人会掉落您的信息。有什么比猫更合适的呢?每个人都喜欢猫的有趣图片[需要引用],因此他们不会怀疑其中隐藏着秘密信息!


受到摩纳哥用来保存共享关卡的关卡信息的算法的启发,编写一个程序将信息编码为图像颜色的最低有效位是您的任务。

编码格式:

  • 前24位确定剩余编码字节串的长度(以位为单位)
  • 从左到右和从上到下读取图像,显然从左上像素开始
  • 从红色到绿色到蓝色读取通道
  • 读取每个通道的最低有效位
  • 位按大端顺序保存

规则:

  • 您的程序需要对单个字节字符串进行编码,并对基本映像使用单个映像文件名
  • 生成的图像必须作为真彩色PNG文件输出
  • 您可以使用任意形式的I / O(ARGV,STDIN,STDOUT,从文件写入/读取),只要您声明如何使用程序即可
  • 您必须随机选择一个有趣的猫咪图片并将其编码到其中,以表明您的程序可以正常工作
  • 您可以假设只提供了有效的输入,如果位数不足,图像不是真彩色格式,图像不存在或类似的问题,您可以做自己想做的事情
  • 您可以假定所提供的图像不包含任何Alpha通道
  • 长度以不带BOM的UTF-8字节计数

您可以使用此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 2014年

4
ME helpimtrappedinacatfactory OW
TheDoctor 2014年

另外,不用于编码的位是否需要保持原样?还是可以将它们设置为所需的值(因为这不会真正影响图像质量并且对解码无关紧要)?
Martin Ender 2014年

1
我可以使用非内置库来加载和保存png文件,例如Python中的PIL吗?
Claudiu 2014年

1
@TimWolla来自猫吗?将其放在室内并监控垃圾桶。从照片?如果您拍摄了足够高的分辨率的X射线照片,则可以查看闪存芯片中各个晶体管的状态。我敢肯定,尽管这只猫可能还有其他想法,但这肯定是传递秘密信息最有效的方法。
Sonic Atom

Answers:


3

Perl的&ImageMagick的(Linux)的,198 190

编辑:偶然地,我较早在装有Q8(8位深度)版本的ImageMagick的计算机上进行了测试。“标准” 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读取,第一行的图像文件名,后跟“ secret”消息,以终止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

数学,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的解码器运行它。;)

顺便说一句,我可以让它仅用7个字节处理UTF-8机密(更改 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 2014年

1
@TessellatingHeckler,没错。尝试使用等宽字体,并注意其中包含UNIX样式的新行(例如,尝试使用宽度至少为180个字符的终端或PowerShell,或者如果您将其作为Web脚本在浏览器中运行,然后查看源代码);)
马丁·恩德

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

取消示例代码中隐藏了代码。经过OP的解码器测试。对不起,不好笑的猫图片。


1
请在您的答案中添加非公开代码。
AL

1
您可以缩短0xff255
TimWolla 2014年

如果您假设使用短标签:,则可以节省4个字节<?function
nyuszika7h 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.