Project1

标题: 加密素材的简单方法 [打印本页]

作者: guoxiaomi    时间: 2017-10-5 21:39
标题: 加密素材的简单方法
本帖最后由 guoxiaomi 于 2017-10-5 21:46 编辑

之前考虑过单独加密图片素材的方法,于是在论坛上找到了这个:https://rpg.blue/forum.php?mod=viewthread&tid=87968原贴楼主是柳之一,这是08年的陈年老贴。

这个帖子里介绍了 bitmap marshal 的技术,所有的截图存档里也都有类似功能的代码。于是利用一点点小trick就可以用这个来做素材加密。

因为已经决定不加密素材,所以就把这个trick公开了。

修改 RPG::Cache 中的 load_bitmap 方法,在直接调用 Bitmap.new(path) 前,检查一下是否有加密的素材。加密的素材保存在 Resource 文件夹下,并且文件名是 path 的 md5 值,其实我这里也没有算 md5 值,就是拿 crc32 随便糊了个假的。

RUBY 代码复制
  1. module RPG
  2.   module Cache
  3.     def self.load_bitmap(folder_name, filename, hue = 0)
  4.       path = folder_name + filename
  5.       #----------------------------------------------------------------
  6.       # 优先从 resource 里加载
  7.       #----------------------------------------------------------------
  8.       if not @cache.include?(path) or @cache[path].disposed?
  9.         if filename != ""
  10.           resource = 'Resource/' + md5(path)
  11.           if FileTest.exist?(resource)
  12.             @cache[path] = load_data(resource)
  13.           else
  14.             @cache[path] = Bitmap.new(path)
  15.           end
  16.         else
  17.           @cache[path] = Bitmap.new(32, 32)
  18.         end
  19.       end
  20.       if hue == 0
  21.         @cache[path]
  22.       else
  23.         key = [path, hue]
  24.         if not @cache.include?(key) or @cache[key].disposed?
  25.           @cache[key] = @cache[path].clone
  26.           @cache[key].hue_change(hue)
  27.         end
  28.         @cache[key]
  29.       end
  30.     end
  31.  
  32.     def self.md5(string)
  33.       # 这里简单的用 crc32 值取代 md5 值
  34.       sprintf('%08x%08x', Zlib::crc32(string.downcase), Zlib::crc32(string.downcase.reverse))
  35.     end
  36.   end
  37. end


上面说的是解密的方法,关于加密直接看工程吧~范例工程中的 Graphics/Pictures/biaoti.png 可以删掉,但是仍然能正常读取 Resource 文件夹里的内容。
resource.zip (732.09 KB, 下载次数: 171)
只要把输出的内容字符串在写入/读取之前进行加/解密就可以实现加密,毕竟 marshal / zlib.deflate 等于是明文保存。
我写了一个dll用来对每个 byte 进行单字符替换的加密,经测试,这个运算跟 zlib.inflate 的耗时是一样的,30M 的文件大概需要 0.05s。但是用 ruby 直接做字符串的替换就很慢了。

这个trick的一个缺点是,只能针对使用 RPG::Cache 创建的 Bitmap 对象进行加密,如果直接使用 Bitmap.new(path) 方法创建就没办法了。所以需要仔细检查脚本,尽可能用 RPG::Cache 创建 bitmap,或者对特定的素材文件夹不进行加密处理。

作者: 芯☆淡茹水    时间: 2017-10-5 23:44
嘛,以前就试验过,用 get_pixel 把每点颜色记录储存,然后生成空白Bitmap逐点画。
这是个笨办法,但还原得还不错。就是还原的时候有点慢,图大的话要等2,3秒。






作者: war202122    时间: 2020-5-19 02:28
试了一下加密 jpg 图档,发现档案大小增加很多。合计 300M 大小的 jpg 档,在有经过 zlib.deflate 的情况下还是爆增成了 2.5G。
推测是在 marshal dump Bitmap 时,是将每个点的像素信息存下来,因此大小比原本 jpg 格式还要大很多。

不知道有什么可以有效减少容量的方式?
作者: guoxiaomi    时间: 2020-7-1 17:49
本帖最后由 guoxiaomi 于 2020-7-2 18:05 编辑
war202122 发表于 2020-5-19 02:28
试了一下加密 jpg 图档,发现档案大小增加很多。合计 300M 大小的 jpg 档,在有经过 zlib.deflate 的情况下 ...


试试看我这个最新的范例?我把图片压缩成了PNG,然后再保存以减少体积。同时还把png文件的前1024个字节加密以防止直接解析png文件。对这个640x480的范例,读取速度似乎比原生的要慢1倍,完全可以接受。不知道读一些巨大的图片会不会更慢?

按照 SixRC 的建议用 -static 编译,并且使用了memcpy,效率有明显提升(~20%)
resource.zip (1.18 MB, 下载次数: 70)
效率:如果不进行加密直接保存成png文件,读取的时间比原生的多 50%。作为对比,主楼中的方法应该只比原生多10-20%的时间。aes解密的耗时正比于被加密的字节数,个人控制aes解密耗时在原生的50%左右就可以了。
加密:到底需要加密多少字节才比较合适?如果说只是阻止操作系统识别文件,那只要加密前16个字节就够了。密码学上有个说法是不要混用不同破解难度的加密算法,再对其他的地方进行弱加密显得没有必要了。何况密钥写在了脚本里,理论上只能用跟默认加密一样难度的算法,否则就是把房门钥匙放在门框上一样搞笑。总之应对傻瓜解包器肯定是足够了,进一步可以把这段内容base64一下塞到那种很长的脚本里eval,玩一个捉迷藏的游戏……

尝试加密了RTP,从12.3M增加到了27.3M(+122%),我发现RTP里不少文件都是jpg格式,可能无损压缩就是会增加大小吧……不知道咋办了,只能看具体情况再处理了。





欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1