我们常常在电视上看到这样的一幕:一位老太太兴冲冲地走上台去,翻过三个商标牌,发现上面尽是5块钱、10块钱的小奖,垂头丧气地回到观众席;然后马脸李咏会跑出来,边翻着另外几个牌子边说,1000块的大奖在这个后面,800块的在这里,之类的。或许有人会纳闷了,为什么主持人要演出“事后揭大奖”这一幕呢?道理很简单,节目组想通过这一个“验证过程”告诉观众,这个环节不是骗人的,大奖真的就在这后面,只是刚才那家伙运气背了没摸到而已。摸奖前宣称有大奖,摸完奖之后还能证实大奖真的存在,这就是带有防欺骗的承诺。
但是,同样的事情在网络上似乎是办不到的。一个典型的例子就是QQ原来弄的那个恶心的砸金蛋砸银蛋。屏幕左边那个是银蛋,屏幕右边那个是金蛋,你鼠标选一个敲下去,看能否砸出QQ宠物来。大量测试表明砸出宠物的概率远远低于50%,让人质疑游戏的真实性。鬼知道它那个程序是不是真的预先指定了一个有宠物的蛋蛋,很可能不管你点了哪个蛋蛋结果都一样,系统按照概率直接显示出抽奖结果来。当然,怀疑游戏的公平性也没办法,要想在网络上实现带防欺骗的承诺是比较困难的,毕竟让你看一段从另一个蛋蛋里跳出一个宠物的Flash动画不能让你相信刚才你是真的“选错”了吧。
我们的问题就是:如何设计一个协议,用以保证一个二选一的网络互动抽奖游戏的真实性?换句话说,假如你选择了金蛋,结果没有中奖,那么系统如何能够令你相信奖品刚才真的在银蛋里?
md5一类的单向散列函数提供了一个不错的方案。系统首先随机选择一个蛋(比如银蛋),在蛋里面藏好奖品,然后把单词“silver”连同一个随机字符串(比如“jq548s”)进行md5。在你抽奖之前,把这个md5值先告诉你。然后你砸蛋,发现金蛋里没有奖品。此时,系统宣布字符串“silverjq548s”,你计算它的md5值,发现和之前系统告诉你的一模一样。此时,你便相信系统刚才是真的把奖品藏在银蛋里了。若你刚才真的砸了银蛋,那系统就没办法抵赖了,因为md5函数是一个单向的、不可逆的、不可预测的函数,想要构造一个“golden某某某”形式的,且md5值和刚才一样的字符串,那比登天还难。另外,注意到在单词后面添加随机字符串这一步骤是必须的,否则你可以尝试计算“silver”和“golden”各自的md5值,从而获知哪个蛋里面有奖品。
不过,现在看来,这个协议也不可靠了。系统有一个办法可以耍赖:字符串“jq548s”有可能根本不是随机生成的,而是经过一系列精心构造的。我们不能排除这样一种情况,即我们可以通过某种算法构造出一对字符串xxx和yyy,使得“silverxxx”和“goldenyyy”的md5值是一样的。md5被破解后,造成这种“碰撞”更是轻松,并且同一对碰撞还可以反复用于欺骗不同的用户。其中一个解决办法是,你可以在协议最初时生成一个自己的随机字符串发给系统,并要求系统传回 “silver/golden” + 系统生成的随机串 + 你自己传过去的随机串 三者并在一起后的md5值。用户一旦参与了字符串的构造,系统作弊就变得真正棘手了。
还有没有什么其它办法呢?我在《应用密码学》里看到了一个颇有意思的协议,它用伪随机序列来代替单向散列函数。不妨把银蛋标为数字“0”,金蛋标为“1”。在砸蛋之前,你给系统发一个足够长(比方说100位吧)的随机01串A。然后,系统把奖品藏在标号为X的蛋里。下面,系统选择一个随机种子,通过伪随机数列发生器生成100个随机数,并全部模2得到一个100位的随机01串B。然后系统计算01串C,其中
C[i] = B[i] 当A[i]为0
C[i] = B[i] xor X 当A[i]为1
系统把C传给你,并宣布准备完毕,开始抽奖。事后,系统公开自己选取的随机种子的值,你便能还原序列B,验证序列C是否和系统之前所给的一样。
如果系统想作弊的话,这要求系统能寻找两个不同的随机种子s1和s2,使得在由它们生成的随机01串(的前100位)中,A中等于“0”的位置上它们的值全部相等,A中等于“1”的位置上它们的值正好相反。但伪随机数列发生器的行为是不可预测,找到这样的s1和s2相当困难,目前看来该协议仍然是安全的。即使找出了这样的碰撞,这样的努力也是一次性的,因为当别的人来抽奖时,随机串A又不一样了,刚才的碰撞就完全没用了。
沙发一个~
板凳……好文章
good
我觉得在第二个方法里面
谁能确定系统的随机种子真正的是随机的而不是每个数都随机+筛选(来满足“两个不同的随机种子s1和s2,使得在由它们生成的随机01串(的前100位)中,A中等于“0”的位置上它们的值全部相等,A中等于“1”的位置上它们的值正好相反。”)而刻意构造的呢?
的确可以筛选。但是s1和s2与A有关,A是用户提交的,对任意的A找到一组满足条件的s1和s2相当困难。
当然,从理论上说这个协议也不能100%的OK。
最近也在读 应用密码学
@wzc
明白了,谢谢
今天冬令营上GYH留了一道题,说第一个人先掷一个硬币(只有他自己看得见),可以押一元或两元钱,然后第二个人猜正反面,第三个人决定是否加倍。我说:这是个密码学问题,在伪随机数列发生器存在的情况下,存在一个策略,使得没有有效的算法能使第二个人每次游戏亏钱显著少于0.75元……
没有用的……
关键是构建这个网站的人他愿意写的代码;
或者说就是搞这个活动的人他的意愿;
我觉得如果他真不想给奖肯定会做手脚的;
淘宝就是个垃圾!
这个用WINRAR压缩有结果的txt 密码随机生成 10位数字+字母
应该是比较实用的~
现在的社会啊,哎~~~~
没有承诺的承诺
你可能没看过王晓云关于MD5碰撞的文章,其实SHA算法比MD5安全一些……
最近也在看 应用密码学
A=rndbit(100)
X=rndbit(1)*(1<<100-1)
B=rndybit(100)
C=B^(X&A)
tell C
…
这不科学。。。万一可以找到发生在中间的碰撞呢。