自从添加了‘循环冗余校验’后,牛郎织女信件内容的准确度极大提高。
但是最近,牛郎突然发现,信件中部分句子,还是有不少7次都没有正确传输的。
“难道是我对传输稳定性的预估有误?”牛郎暗自想,“但是这不可能啊。”
忽然,牛郎灵机一动:“不会是有人像篡改内容,但是尚不知校验规则,正在探索尝试吧?”
“这就危险了,‘循环冗余校验’难度不大,破解只是时间问题。”
“既然如此,还需要一种识别数据篡改的方式。”
接下来的几天,牛郎没有与织女联系。
牛郎心里清楚,每次联系都是给对方试探的机会,自己没有想好新的校验规则之前,需要尽量减少与织女的沟通。
“其实,也不是很难,只要找到一种方式,让全文所有内容参与计算,得出一个校验值就好了。”牛郎自言自语。
“但是,全文内容太多了,如果还是之前的笔画方式的话,恐怕误差会比较大。”
“同时,还要考虑安全性,算法总是会暴露的,如何在王母知道了算法的情况下,也尽量保证数据安全。”
看来,需要考虑的事情不少,牛郎想各个击破。
“首先,是算法上的问题。本质上还是笔画,只是按原来‘循环冗余校验’的方式,王母想要伪造太简单。”
“只要替换一句笔画相同的句子,就可以绕过校验了。这很危险,必须让每个字的笔画都参与运算,都会影响结果。”
“如果两句话字数、每个字的笔画数都一样,但是却要表达不同的意思,这很难。这就是新的校验法的核心思想。”
那么问题来了,具体应该怎么办呢?
牛郎想,不如先从简单地方式来思考,先把每个字的笔画,都写出来。
原本是一封全是文字的信件,每个文字对应的位置替换为笔画数,瞬间变成了一张数字表。
“这个数字表看起来很条理,不如把每一列都加起来试试。只是每一句话有长有短,最后的结果取决于最长的一句,这样不太好。”
牛郎重新思考了一下,信件中,最长的句子是80字,以后可能会有更长的句子,这样会失控的。
牛郎拿起一张新的纸,按照每行32个字的规则,将整篇信件抄写了一遍。
“现在好了,句子再长,由于32个字就会换行,再也不会出现校验值过长的问题了。”
牛郎重新在每个字的位置标好笔画数目,标点符号作为一个字,但笔画记为0画。
如此按照列加起来,牛郎得到了32个非常大的数字。
“从一定程度上讲,这32个数字,确实可以校验一篇内容的完整性。但这样,还是有点冗长了。”
这时候,牛郎又想起了那个魔数7,“不如把每个数字再除以7,取余数,这样就是32个一位数了,应该就方便多了。”
牛郎写下来这32个数字,还是感觉缺少了点什么。总感觉,好像是过于死板了,缺少一种灵动感。
突然,牛郎一拍脑门,“明白了!数字还是看起来太乱了,32位数字更是让人一眼就看晕了。”
“这样的话,我用12的余数,用12地支表示结果,每8个一组,应该会好很多了。”
于是,牛郎重新计算校验值,然后在下方写下了:
“子丑寅卯……”
牛郎看着一列一列计算出来的校验值,如此大量的文字,竟然最后的结果只有这么一串文字。
取个什么名字好呢?将信件分散为笔画,然后按列来计算,不如就叫做“散列算法”吧。
防止篡改的方法确定了,那么,如何避免计算出来的校验值被修改呢?
牛郎想了想,既然如此,就把这个校验值放在信件的第一行吧。
先发出去校验值,即使被拦截,由于对方不知道信件的整体内容,也是无法进行修改的。
牛郎赶紧给织女写了一封信,描述了这个方法,并约定以后的通信,都用这种方式进行校验。
牛郎很开心,自己终于解决了一个大问题。
第二天,牛郎收到了织女的回信,内容很简单:“通篇伪造怎么办?”
牛郎一时语塞,想想也是,自己解决了局部篡改问题,只修改部分内容可以被快速发现。
但是,王母知道了该机制后,确实无法改一部分,但他们直接把一整篇全伪造,我这还真没办法。
甚至,说的极端一点,现在我看到这封信,还真不能肯定,到底是织女写的还是王母写的。
这个问题,确实是有点尴尬的。
“看来,需要混入一些只有我和织女才知道的东西,才能保证对方身份的安全性。”牛郎想。
“比如,将我和织女初次见面的时间算进去?”
接着,牛郎又否定了自己的想法:“现在仅仅基于笔画,方法过于简单,多次通信后,王母可能反推出这个时间。”
“看来,要想办法强化这个算法的不可逆性质了。”
牛郎来到桌前,在纸上写出32位的校验值,然后又按照“年月日”的格式,写出了8位时间。
也就是说,牛郎需要将原始校验值与见面日期结合,生成一个安全的校验值,同时还要保证,见面日期不可被反推出来。
“要保证见面日期的安全性,这还真是有点难度的。”牛郎自言自语道,“因为安全校验值是明文传输的,而原始校验值则可以通过内容计算出来。”
牛郎想着想着,突然手中的笔不小心掉了下来,刚好涂掉了原始校验值的最后两位。
牛郎捡起笔,放到桌上,看着纸上留下的痕迹,灵机一动:
“对了,只要减少见面日期影响的位数,就很难反推了。如果见面日志只影响这最后两位,神仙也不能能基于它推出原来8位的日期。”
牛郎再次拿起笔,在纸上记下了处理思路:“取原始校验值的最后两位,与见面日期拼成10位,与剩余的30位原始校验值计算出2位尾数,拼回去作为安全校验值。”
那么问题来了,具体要怎么算呢?这没什么难点,在没有前人铺垫的情况下,我说啥不就是啥么?
牛郎重新看了一眼信件,将被涂掉的最后两位重新写到纸上。
“午戌。午是第7位,戌是第11位。那第二行,从第5位开始写这10位,第三行,从第11位开始写这10位内容。”
牛郎写好后,将这三列再次按列加起来,得到30位内容。
现在,要想办法将这30位变成2位数,并且要尽量有选择地丢弃一些信息,避免数据被反推。
牛郎很随性地想了一个办法:“第一位,将3的倍数位的内容加起来,取除以7的余数。”
“第二位,将4的倍数位的内容,加起来,也取7的余数。这样,由于筛选,见面日期总是部分参与运算,从而保证安全性。”
牛郎算出了结果,第一位是2,第二位是4,牛郎就在原始校验值的30位后面,补充上了这两位:“2对应‘乙’,4对应‘丁’,这就完整了。”
牛郎再次修书一封,告知织女。
虽然整个算法在书信中是明文,王母也可能看到,但是,王母不知道他们的初次见面日期,只能看,干着急。
不久,牛郎收到了织女的回信,信中高度评价牛郎的算法,同时也提出来一个新的问题:
“目前已知的仙术中,并没有‘统计文字笔画数’这样鸡肋的仙术……每次都手动数,太麻烦了……”
牛郎感叹,“也是,这种毫无攻击力、基本没有利用价值的仙术,谁会去创造呢?看来,是我展现实力的时候了……”
转念一想,“不对呀,我这神仙就学了一个‘HelloWorld’,然后就妄想创造仙术了,也太狂妄了吧……”
牛郎将自己的想法告诉织女,织女安慰了一番,然后在信中补充说道:
“仔细去体会HelloWorld,其实,仙术的本质,是能量的有无变换。”
“说简单点,有能量可以记作1,没有能量可以记作0,如此按一定规律交替,就是仙术。”
“当然,为了便于记忆,描述仙术时,一般8个一组。”
“虽然没有字数仙术,但我之前学过一个翻页法术,或许有参考价值,口诀是:00101100……”
牛郎此时对仙术还是一知半解,既然织女又教了一个,那就想办法用这个仙术解决问题吧。
牛郎翻出一本记录了已知所有文字的手册,就叫它字典吧。
“就到100页吧!”牛郎将100作为参数,代入到口诀中默念起来,手中控制着能量,按口诀中的0和1,规律地波动着。
当最后一位能量归位后,牛郎看到手中的字典亮了起来……
牛郎很高兴,然而,这字典亮了一下,接着有熄灭了。
“字典并没翻开呀,难道是能量不够?”牛郎再次执行口诀,这次控制1的能量比之前大了一倍。
这时,字典再次亮起来,仔细看这亮光之中,竟然显示出了字典的内容。
牛郎赶紧翻开字典,果然与第100页完全一致。
牛郎窃喜:“这比翻页高级多了呀,这是内容提取的仙术!不愧是织女传授的仙术,之后看书方便了,再也不用翻开了,哈哈。”
“但问题也来了,我怎么知道,一个字在哪一页上?要是按拼音来查的话,也就只省去了翻页的功夫,找到一个字还是太慢了。”
“看来,要考虑专门设计一个便于检索的‘笔画字典’了。”
牛郎赶紧来到桌子前,进行设计。
其实思路很简单,看到一个字,只要知道它的页码,就可以用仙术将这一页的内容提取出来了。
但是每页一个字和它的笔画,想法很好,问题出在页码上:如何看到一个字就知道它的页码?
这难不倒牛郎的,瞬间牛郎就想到了“拼音页码映射”思路。
一个字至少有一个读音,而读音除去声调外,最长是6位,每一位只能是单个的声母或韵母,共26种可能。
没有0,按声母bpmf从1开始排序,20个单声母刚好排到20,六个韵母从21开始排序。
如此,可以确定一个字的绝对页码数:比如,“牛”字,二声,niu,即对应页码 n i u 2。
转换为对应的数字,即 7 24 25 2 。
只是,这个四位数,每一位都超过10了呀?牛郎给出了解释:“满26进1而已。”
就这样,牛郎确定了笔画字典的模式:字典页码采用26进制,每个字根据声母、韵母、声调确定唯一页码。
当然,一页上同音字可能有好几个,这个暂时没法用仙术了,人工看下应该也很快了。
确定了字典的理论后,字典的编撰工作又成了难题:总不能一个一个手动抄吧?
无奈之下,牛郎只得继续求助织女。
织女很快给出了回复:“沙玉戒指还有印象吧?戒指内部是个空间,可以储存物品。”
“这世界上还有另一种储物戒,可以储存仙术,称为‘桃源仙戒’。你已经知道了,仙术的本质是0和1,一般可以写在纸上存储。”
“但是每次读取很不方便,所以,桃源仙戒可以绕过纸张记录,直接存储整段的0和1,按段整体读取,速度非常快。”
“你应该已经想到沙玉戒指中的传送仙术了吧?这‘沙玉’戒指,其实也是一个‘桃源仙戒’,你可以用它存储仙术信息。”
“对了,这沙玉也不是很高级的存储器,它对仙术的存储是有限的,大约是1吨信息吧。”
“简单说,大概有1亿块分区,每块分区可以存储长度大约为八千的仙术信息。”
“接下来是书页抽象仙术,配合它,你可以在沙玉中存储世界上所有的书籍……”
废话好像有点多,但是牛郎也算是听明白了,可以直接用仙术生成字典页,然后存储在沙玉中。
接着配合页面提取仙术,就能实现笔画的瞬间查找了。
牛郎赶紧开工,将字典按自己之前的设计,重新提取内容,存入‘沙玉’戒指中……
牛郎将一块分区划分为5块,表示5种声调。这样,每个分区,可以存储一种读音的文字了。
由于最长的读音有6个拼音长度,为了便于寻找页面,一共有26的6次方种组合。
因此,牛郎存储完所有的信息,一共用了3亿多个分区。
看着这坚硬的、圆盘状的戒指,牛郎不禁心生感叹:
“这东西,不如给它起个别名,就叫做‘硬盘’吧。不过,这1吨(T)的硬盘,容量不大呀,还是要省着点用啊。”
不管怎么样,事情反正是办到了。牛郎施展页面提取仙术,果然可以瞬间找到任何一个字的笔画。
牛郎非常开心,赶紧把这个好消息告诉织女,并详细说明了策略,便于织女也如法炮制。
织女回信称赞了牛郎的聪慧,同时也指出了不足:“初学仙术,就有如此设计,极为不易。”
“但是,其实存储是非常宝贵的资源,你仔细想想,有没有办法用1万块分区解决问题呢?”
“仙术,也是需要不断优化的。一本字典用3亿分区,整个戒指也就存不到4本字典。但如果只用1万分区,就能存10万本字典了。”
牛郎一想,还真有道理,自己存储仙术的方式,其中有很多空着的页,白白占用资源。
一块分区只划分为5部分,每一部分也就几个字,空着的太多了。
如何在保证自己查找方便的情况下,压缩仙术的存储空间呢?
现在确实没什么好的思路,看来,以后,有必要找个时间,优化下了自己的字典存储策略了。
网友评论