简述有意思程序员

怎让设置一个14位自然数密码,尽可能不被无意中猜中?

2015-11-15  本文已影响3251人  李欣宜

原问题地址:http://www.zhihu.com/question/36989779

问题描述

下了个APP,表面是个普通计算器,输入特定数字后,会显示自己保存的秘密图片和文件。怎么尽量避免熊孩子使用这个计算器时刚按到这个数字或答案是这个数字?
注:小于15位,且不得以0开头的自然数。不含字母、符号、小数点。

我的回答

根据题主的需求描述,这是一个口令的生成和管理问题。那么我们就需要遵循以下原则:

综上所述,有一个可行的思路就是生成伪随机数作为口令。

方案一

取一个能记住的字符串或者数字,用散列函数计算hash值,取前14位作为输出

比如这个就可以取60354186872526

再比如这个可以取32993841519355

觉得生成的数字太凑巧的话也可以换个熟悉的单词短语再算一遍,直到生产满意的为止。

方案二

找一张图片,比如你喜欢的CP的同人图,用MD2编码生成数字指纹作为随机种子,用这个种子生成一个14位的随机数作为口令。
如果需要得到这个口令,再用原来的图像按这个流程走一遍就行。

我们可以事先定义一个函数:

ApplyForPassword[x_] := {
SeedRandom[Hash[Import[x], "MD2"]];
  RandomInteger[{10^14, 10^15 - 1}]
  }

这样需要口令的时候调用ApplyForPassword["path"]就可以得到这个14位伪随机口令(其中path为图片路径字符串)

方案三

随机生成一个14位自然数作为密码,使用隐写术(Steganography)将密码伪装成看上去非常普通的图片,需要再取用这个密码的时候恢复其中的信息。比如这里有个已经完成的隐写术代码方案可以参考一下:

伪装过程:

恢复过程:

这些关于隐写术的操作也可以被封装为两个函数。
伪装函数(第一个参数为载体图片,第二个是密文):

StegCover[Carrier_Image, text_] := 
 Block[{CarrierData, TruncatedCarrier, pixelChannels, SecretBits, 
   LifeLength, SecretData},
  CarrierData = ImageData[Carrier, "Byte"]; 
  TruncatedCarrier = BitAnd[CarrierData, 2^^11111110];
  pixelChannels = Apply[Times, Dimensions[CarrierData]]; 
  SecretBits = 
   Flatten[IntegerDigits[
     ToCharacterCode[
      ToString[text, InputForm, CharacterEncoding -> "ASCII"]], 2, 
     8]]; LifeLength = IntegerDigits[Length[SecretBits], 2, 48];
  SecretData = 
   Fold[Partition, 
    PadRight[Join[LifeLength, SecretBits], pixelChannels], 
    Reverse@Rest[Dimensions[CarrierData]]];
  Image[TruncatedCarrier + SecretData, "Byte"]]

恢复函数(参数为伪装图片):

StegUncover[CoverImage_Image] := 
 Block[{SecretData, LifeLength, secretBytes}, 
 SecretData = Flatten[BitAnd[ImageData[CoverImage, "Byte"], 1]]; 
 LifeLength = FromDigits[Take[SecretData, 48], 2]; 
 secretBytes = Partition[Take[Drop[SecretData, 48], LifeLength], 8]; 
 ToExpression[
  FromCharacterCode[FromDigits[#, 2] & /@ Take[secretBytes]]]
 ]

这样需要使用的时候就可以直接调用StegCoverStegUncover了,就可以把任意文本(甚至其他形式的内容)隐藏在任意图片中了。

当然这个方案也有很大缺陷,就是降低了资源的利用率。比如苏教版语文第七册一篇课文的彩色插图,508*715像素,有RGB三个色彩通道,以我们的方法完全可以存储508*715*3/8=136207个字符,而这里如果仅仅用来存储14位密码(+字符串终止标识‘\0’,一共15个char空间的密文)是严重浪费的。中华人民共和国香港特别行政区基本法 (豆瓣)全书一共55983字,即时假设全部为2个char长度的中文字符(ASCII编码),那么也只需要111966个字符的空间,再用于存储长度的6个字节,还剩24235字节是空余的,我们的方案这时就显得有些杀鸡用宰牛刀了。
那不妨偏个题,这样有个好处就是这样的方案可以隐藏非常大的信息量,一篇GettysburgAddress放进图片里简直毫无感觉。生成的伪装图片也可以通过存储为png或其他无损格式的图片在网络或者别的平台交换信息。

彩蛋,猜猜这张图里藏了什么?

(未完待续)

上一篇下一篇

猜你喜欢

热点阅读