啊我死了 發表於 2019-7-9 10:16:00

Javascript实现的图片隐写术

<h1 class="postTitle">javascript图片隐写术,感觉可以用它来干点有想法的事情</h1>
<div class="clear">&nbsp;</div>
<div class="postBody">
<div id="cnblogs_post_body" class="blogpost-body">
<h2>1、什么是图片隐写术?</h2>
<p>权威的wiki说法是“<strong>隐写术</strong>是一门关于信息隐藏的技巧与科学,所谓信息隐藏指的是不让除预期的接收者之外的任何人知晓信息的传递事件或者信息的内容。”,图片隐写术简而言之就是利用图片来隐藏某些数据,让人一眼看去以为是很普通很正常的图片,但其实里面隐藏着某些“机密”数据。</p>
<p>据传911事件里,KB份子就是通过黄色图片来传递信息而躲过了FBI的监控。还有大众点评也是通过图片隐写术来保护自身合法权益。所以图片隐写术是一个双刃剑,就看你用它做什么了。</p>
<p>比如下面这张图片:</p>
<p><img src="https://images2017.cnblogs.com/blog/25430/201712/25430-20171201151310992-247518948.png" alt=""></p>
<p>看起来是一张很漂亮的风景照片,但其实它里面却藏着一张美女图(注:美女图片来源于淘宝某店),如下:</p>
<p><img src="https://images2017.cnblogs.com/blog/25430/201712/25430-20171201151405898-1394445312.jpg" alt=""></p>
<p>是不是很惊艳?看得你热血沸腾鼻血都往外冲呢?这就是图片隐写术的历害之处,“机密”隐藏于无形之中!</p>
<h2>2、图片隐写术是怎么做到的?</h2>
<p>  &nbsp;图片隐写有多种方式,我这里介绍的是采用图片的最低有效位(LSB)进行隐写。其原理就是图片的像素点都是由三原色(RGB)构成(如下图),由这三原色可以组成各种颜色,如CSS里的颜色定义#FFFFFF,即是三原色的16进制值写法,每个颜色各占用8bit。而LSB隐写就是修改像素中每个颜色值的最低位值,而这些修改,人眼一般是分辨不出来的,从而达到数据隐藏的目的。</p>
<p><img src="https://images2017.cnblogs.com/blog/25430/201712/25430-20171201152935430-1596403381.jpg" alt=""></p>
<p>  譬如我们想把’A’隐藏进来的话,如下图,就可以把A转成16进制的0x61再转成二进制的01100001,再修改为红色通道的最低位为这些二进制串。</p>
<p><img src="https://images2017.cnblogs.com/blog/25430/201712/25430-20171201153039305-2068174246.jpg" alt=""></p>
<p>&nbsp;</p>
<p>(注:以上图片和示例来源于Wooyun)</p>
<p>&nbsp;</p>
<h2>3、Javascript实现的图片隐写术</h2>
<p>  代码项目见GitHub:&nbsp;https://github.com/kingthy/imagemask</p>
<ul>
<li>
<p>在线演示&nbsp;https://ipfs.io/ipfs/QmUG1TKotQYsp6bSw6pX4crFWfhJRNTnJre7buEaYYBV72</p>
</li>
<li>
<p>使用示例</p>
</li>
</ul>
<div class="highlight highlight-text-html-basic">
<div class="cnblogs_Highlighter sh-gutter">
<div>
<div id="highlighter_74598" class="syntaxhighlighterhtml">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
<div class="line number6 index5 alt1">6</div>
<div class="line number7 index6 alt2">7</div>
<div class="line number8 index7 alt1">8</div>
<div class="line number9 index8 alt2">9</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="html plain">&lt;</code><code class="html keyword">script</code>&nbsp;<code class="html plain">type="text/javascript" src="imagemask.js"&gt;&lt;/</code><code class="html keyword">script</code><code class="html plain">&gt;</code></div>
<div class="line number2 index1 alt1"><code class="html plain">&lt;</code><code class="html keyword">script</code>&nbsp;<code class="html plain">type="text/javascript"&gt;</code></div>
<div class="line number3 index2 alt2"><code class="html plain">var mask = new ImageMask({</code></div>
<div class="line number4 index3 alt1"><code class="html spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="html plain">debug: false,&nbsp;&nbsp; //是否开启调试模式</code></div>
<div class="line number5 index4 alt2"><code class="html spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="html plain">charSize: 16,&nbsp;&nbsp; //字符的字节位数,默认为16,即字符最大值为0xFFFF</code></div>
<div class="line number6 index5 alt1"><code class="html spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="html plain">mixCount: 2,&nbsp;&nbsp;&nbsp; //隐写数据要混合到图片颜色值里的最低位数,值范围在1-5,默认为2,如果大于3,则图片会失真很严重</code></div>
<div class="line number7 index6 alt2"><code class="html spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="html plain">lengthSize: 24&nbsp; //数据长度值的占用字节位数,默认为24,也即数据长度最大值为16777215</code></div>
<div class="line number8 index7 alt1"><code class="html plain">});</code></div>
<div class="line number9 index8 alt2"><code class="html plain">&lt;/</code><code class="html keyword">script</code><code class="html plain">&gt;</code></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<p>  </p>
</div>
<ul>
<li>隐写文本</li>
</ul>
<div class="highlight highlight-source-js">
<div class="cnblogs_Highlighter sh-gutter">
<div>
<div id="highlighter_913208" class="syntaxhighlighterhtml">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="html plain">//脚本里传入页面的canvas对象和要隐写的文本</code></div>
<div class="line number2 index1 alt1"><code class="html plain">var output = document.getElementById('output');</code></div>
<div class="line number3 index2 alt2"><code class="html plain">var canvas = document.getElementById('canvas');</code></div>
<div class="line number4 index3 alt1"><code class="html plain">mask.hideText(canvas, '要隐写的文本');</code></div>
<div class="line number5 index4 alt2"><code class="html plain">output.src = canvas.toDataURL();</code></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<p>  </p>
</div>
<ul>
<li>隐写文件</li>
</ul>
<div class="highlight highlight-source-js">
<div class="cnblogs_Highlighter sh-gutter">
<div>
<div id="highlighter_481860" class="syntaxhighlighterjavascript">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
<div class="line number6 index5 alt1">6</div>
<div class="line number7 index6 alt2">7</div>
<div class="line number8 index7 alt1">8</div>
<div class="line number9 index8 alt2">9</div>
<div class="line number10 index9 alt1">10</div>
<div class="line number11 index10 alt2">11</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="javascript comments">//脚本里传入页面的canvas对象和要隐写的文件</code></div>
<div class="line number2 index1 alt1"><code class="javascript keyword">var</code>&nbsp;<code class="javascript plain">output = document.getElementById(</code><code class="javascript string">'output'</code><code class="javascript plain">);</code></div>
<div class="line number3 index2 alt2"><code class="javascript keyword">var</code>&nbsp;<code class="javascript plain">canvas = document.getElementById(</code><code class="javascript string">'canvas'</code><code class="javascript plain">);</code></div>
<div class="line number4 index3 alt1"><code class="javascript keyword">var</code>&nbsp;<code class="javascript plain">file = document.getElementById(</code><code class="javascript string">'file'</code><code class="javascript plain">);</code></div>
<div class="line number5 index4 alt2"><code class="javascript plain">mask.hideFile(canvas, file.files, ,&nbsp;</code><code class="javascript keyword">function</code><code class="javascript plain">(result){</code></div>
<div class="line number6 index5 alt1"><code class="javascript spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="javascript keyword">if</code><code class="javascript plain">(result.success){</code></div>
<div class="line number7 index6 alt2"><code class="javascript spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="javascript plain">output.src = canvas.toDataURL();</code></div>
<div class="line number8 index7 alt1"><code class="javascript spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="javascript plain">}</code><code class="javascript keyword">else</code><code class="javascript plain">{</code></div>
<div class="line number9 index8 alt2"><code class="javascript spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="javascript plain">alert(result.message);</code></div>
<div class="line number10 index9 alt1"><code class="javascript spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="javascript plain">}</code></div>
<div class="line number11 index10 alt2"><code class="javascript plain">});</code></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<p>  </p>
</div>
<ul>
<li>读出图片里隐写的文本</li>
</ul>
<div class="highlight highlight-source-js">
<div class="cnblogs_Highlighter sh-gutter">
<div>
<div id="highlighter_180585" class="syntaxhighlighterjavascript">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="javascript keyword">var</code>&nbsp;<code class="javascript plain">canvas = document.getElementById(</code><code class="javascript string">'canvas'</code><code class="javascript plain">);</code></div>
<div class="line number2 index1 alt1"><code class="javascript keyword">var</code>&nbsp;<code class="javascript plain">message = mask.revealText(canvas);</code></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<p>  </p>
</div>
<ul>
<li>读出图片里隐写的文件</li>
</ul>
<div class="highlight highlight-source-js">
<div class="cnblogs_Highlighter sh-gutter">
<div>
<div id="highlighter_804659" class="syntaxhighlighterjavascript">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="javascript keyword">var</code>&nbsp;<code class="javascript plain">canvas = document.getElementById(</code><code class="javascript string">'canvas'</code><code class="javascript plain">);</code></div>
<div class="line number2 index1 alt1"><code class="javascript keyword">var</code>&nbsp;<code class="javascript plain">file = mask.revealFile(canvas);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="javascript comments">//file.name = 文件名称, file.data = 文件数据</code></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<p>  </p>
</div>
<h2>4、示例图片</h2>
<ul>
<li>原图<br><img src="https://images2017.cnblogs.com/blog/25430/201712/25430-20171201154457711-816456262.jpg" alt="" width="500"><br><br></li>
<li>&nbsp; 隐写一章3千多字的小说内容后的图片效果</li>
<li><em id="__mceDel"><img src="https://images2017.cnblogs.com/blog/25430/201712/25430-20171201154710133-1346353429.png" alt="" width="500"><br>(隐写什么小说内容,各位有兴趣的将图片保存下来,然后在演示页面里读出来即可知道。)</em></li>

</ul>
<p>以上两张(包括上面有美女的那张)图片效果几乎是一样的,人眼是看不出来有任何变化。</p>
<p>&nbsp;</p>
<h2>5、附加说明</h2>
<p>  1)、LSB方式的隐写图片只能存储为PNG或者BMP图片格式,并且不允许再采用有损压缩(比如JPEG),否则会丢失隐写的数据!</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp;2)、图片里可以隐写任何数据,并且可以存储的数据多少由图片的大小(长宽)来决定。也许一张图片就能存储下一部圣经的所有文字。</p>
<p>&nbsp;</p>
<h2>6、脑洞时间</h2>
<p>  工具是有了,我们可以用来做些什么呢?发挥你的想象吧:)</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; 1)、防采集:将文本内容隐写到图片里,这样就能防直接的采集(比如小说网站、内容原创网站)&nbsp; ,当然了,只能防君子了。</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; 2)、版权水印:将版权水印(文字或者图片)或者其它身份识别标记(如公司里防泄密)隐写到图片里,如果对方直接盗用,则可以起到鉴别作用(如大众点评网案例)。当然了,如要防“攻击”(压缩,变形,涂改等)则需要更高深的隐写方式。有兴趣的可阅读啊里月饼事件引发的知乎讨论贴里的牛人回复。</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;传递门:https://www.zhihu.com/question/50735753/answer/122717091</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; 3)、防监控:将文本或图片隐写到图片里,可以防机器(某墙?)监控(比如整网站都是好孩子图片或风景图,但其实都是坏孩子图片或者XX小说、XX内容)</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; 4)、文件下载:&nbsp;直接将文件存于图片里,绕过文件格式限制问题。比如很多图床只能传图片,但经过隐写后就可以图片里藏任意文件了,比如大家都喜欢的种子,当然了,要求图床不会再进行图片再次压缩。</p>

</div>

</div>
<div class="postBody">&nbsp;</div>
<div class="postBody">&nbsp;</div>
<div class="postBody">此文来源于 :https://www.cnblogs.com/kingthy/p/imagemask.html#3855945</div>
<div class="postBody">&nbsp;</div>

</div>
<div id="MySignature" role="contentinfo">
    <div>作 者:一支会记忆的笔</div>
<div>出 处:https://www.cnblogs.com/JonaLin/
</div>

<p>---------------------</p>

<p>个性 签名:真正的学习不是记住知识,而是学会如何提出问题,研究问题,解决问题。</p>
<p>如果觉得这篇文章对你有小小的帮助的话,记得在下方<span>“关注”</span>哦,博主在此感谢!
</p>
<p>
</p>
<p></p><br><br>
来源:https://www.cnblogs.com/JonaLin/p/11155690.html
頁: [1]
查看完整版本: Javascript实现的图片隐写术