安全--区块链资产朴素安全课



  • 原创: 汤强 汤强
    链接:https://mp.weixin.qq.com/s/I1peVTOTsQvrayNEvwkmKA

    阿土仔走进房间,锁门关窗,变出一个私钥。他很得意,因为这个房间密不透风,之后一个月他陆续把18.5个比特币放进对应的地址。

    两天后,这些币不翼而飞。

    阿土仔一屁股坐在地上,欲哭无泪,保密工作严丝合缝,不会是被人猜到了私钥吧?

    这是个坊间传闻,让人不寒而栗。我们先绕开这个故事的真实性,从概率角度帮阿土仔算算私钥被人猜到的可能性,并且吹散一朵悬在你心头已久的疑云:

    为什么私钥不可能被猜到?

    一、私钥是一个随机数

    如果你有过比特币,那你眼中的私钥应该长这样:
    KxqVS5Bs1T1MoNA5HG9kgFyF5wtNeWMRFUf55Bq2XAqjshWNw85d

    但在计算机内部,私钥是一个256位的随机数,表现为256个0或1。我们借Excel用8✕32的表格展现。注意,实际上并不是八行,而是一行:

    0_1540373668289_571daa78-5f8d-4f4f-b32d-da3a85af7200-image.png
    图1 比特币私钥是个256位随机数

    每一位只有0或1两种可能,但256位的长度,使得这个随机数的可能数量达到2的256次方。如果你用计算器算,就会发现结果是1.16×10的77次方。

    我们都知道这是个很大的数,但到底能有多大,并不是每个人都清楚。

    假如你从3岁起数星星,每秒数1只,不吃不喝不睡,节假日双不休,数到303岁,那么你能数完100亿颗星星。而这个数字,是10的10次方。

    你可能会想,如果开个挂,300年的星星在1秒内数完,是不是能快点?那么恭喜你,用同样的勤勉数上300年,能数完的星星数量是10的20次方。好吧,你累了,兄弟我来陪你一起数,而且继续开挂:把10的20次方个星星打包成1颗星,1秒数完,那么到我们150岁生日那天,能数完的星星数量是10的30次方。

    太好了,我们并肩数完了全宇宙的星星,可是私钥还有很多呀。我们把三生三世数过的十里星光换算成私钥的数量,并且操起量子计算机的锅铲,再炒三世轮回,那我们能遍历多少私钥呢?答案是10的60次方。

    那现在我们距离私钥世界的尽头10的77次方还要走几里路呢?

    数学说:很好,你俩已完成了全部工作量的0.0000000000000000001%

    心好累。

    量子助场,几世开挂,本想死磕自己,却没想到磕死了兄弟我,还没磕出根毛。

    其实也不奇怪,因为私钥个数在数量级上接近一个数字:宇宙中全部原子的个数——10的80次方。

    我们花几辈子去数全宇宙的原子,数不完也不冤。所以可想而知,作为一个随机数,被人撞出来得有多憋屈?

    不过确实有一种可能,使得私钥被撞不是神话,因为一些工具生成的私钥是伪随机数。

    二、什么是伪随机数?

    伪随机数由确定性算法产生,乍看很难找出规律,但只要重复足够多次,周期特征就会浮出屏幕。

    为什么会这样?

    因为伪随机数的生成原理:种子驱动。

    每个伪随机数都由上一个数和种子决定。种子来自其他随机算法,是随机数的随机数,最常见的种子是时间,如2018年3月10日18:30。

    任何人只要知道随机算法和种子,就能根据前一数掐算出后一数。也就是说,如果算法和种子被人猜到,随机数就是明文。

    我们平时可以用伪随机数在单位年会上抽个奖,但在雕刻私钥的场合,还是应该谨慎些,因为伪随机数的可测性使得它在密码学上并不安全。

    比如,本来应该遍历我们七生七世数过的星星数,但一次不经意的循环就能指数级地剥落遍历范围,使得最终能遍历到的随机数数量,仅限于我们第一世数过的星星:100亿个。

    所以,即使恶意者不知道你的种子,但只要他们搬出一台小小的量子计算机,就能一炮轰开你的财富大门,因为你算法能遍历的空间就这么一点。如果换作普通计算机,一年半载也能攻破。

    可事实却是:

    绝大多数人在制作私钥时,并不会在意是否使用了伪随机数生成器,也不会在意使用的种子是什么货色,更不会在意暴力遍历全局所需的时间

    伪随机数像一个头箍一样,套在我们看不见的旷野上,把原本庞大的可能性越箍越细,极速收敛,收敛到只剩一点,甚至是点中的点。

    但是,如果你从没在意过这些也不必焦虑。还记得么?我们几世轮回开挂数过的星星数目,最终也不过是根毛。所以,如果一个伪随机数生成器能遍历到我们那样的范围,同时很难找到规律,那也算个英雄。

    很多研究称程序算法生成的都是伪随机数,这是有充分根据的。可如果遍历范围足够大、不可测性足够高、破解时间需要成万上亿年,那么在数学意义上它也足够安全。

    你可能已经发现,每枚硬币都是一个伪随机数生成器,只是遍历范围小,而且规律明显:出现频率各为50%的0和1。但256枚硬币拼出的伪随机数矩阵,就接近一个真随机数生成器。

    三、真随机数不在灯火阑珊处

    真随机数指依赖硬件参数变化产生的随机数,能遍历所有数字空间——维基百科

    我们可以用物理方法产生真随机数:抛硬币、掷筛子、使用电子元件的噪音信号。基于真随机数产生的私钥范围充斥1到2的256次方之间,而且完全摸不到规律。

    说到真随机数,有个无法绕过的概念——熵池

    熵池是贮藏随机性的思维工具,用熵池值度量。你可以把熵池值理解为捣糨糊的程度:浆糊捣得越浓厚,熵池值就越高,能提供的随机性也越大,在此基础上烤出来的随机数就越香。

    基于图1的私钥原理,我们可以土法炼钢,烧制出自己的真随机数私钥。方法是抛硬币,逐一记下结果,断网后用数学工具将结果转成私钥格式。

    但是你把一个硬币连抛256次,熵池值就不如你分别抛256个硬币来得高;一口气抛256个硬币,熵池值就不如每天吸一口气、分十口气抛完来得高。

    熵池的概念同样适用于伪随机数,如果你钟情高熵池,可以先打开钱包,再打开我们公众号抚摸两篇文章,再生成私钥,就能获得更多的随机性。

    熵池解决的是随机性问题,让人找不到下一个数出现的规律。这是真伪随机数共享的概念,而区别于伪随机数最重要的点在于:真随机数范围极大。

    你一定听过国王在棋盘上奖励别人大米的故事:64个格子,第1个格子奖1粒米,之后每格奖的米粒比前一格多一倍,到第64个格子,需要奖出的米是全球800年大米产量之和。

    在任何不起眼的小点上翻一倍,持续翻,用不了多久就会出现一个令人乍舌的数字。

    把国王的故事反过来看:对着任何好运拦腰连砍256刀,就能切碎所有偶然。所以,真随机数虽然存在,但并不在灯火阑珊处,并非闲杂人士用千百次回首就能找到。

    于是我们能推测,用量子计算机去刺探真随机数私钥,有生之年是刺不过来的。

    量子计算机看起身强力壮,但在遍历真随机数私钥上是肌无力的,它咬紧牙关也只能往前爬10-20个数量级,而真随机数私钥有77个数量级,有种手握圆珠笔头、心想戳穿地球的感觉。

    而且,假设未来出现超越量子计算机的技术,能追上真随机数的数量,但只要轻轻拉长私钥长度,哪怕只长出一位,就能让这种尖端技术的锋芒像棉花一样噗嗤软下来。

    下面我们从视觉角度,对比真伪随机数的生成,白线和蓝线代表两种随机数游走的结果:

    0_1540374771004_6e3b7110-5587-43f4-b467-86a49af1cb03-image.png

    刚开始,我们并不能断言谁真谁伪:

    0_1540374782135_285309cc-ed7b-45a5-a793-fe2c20dd9da2-image.png

    还是看不出规律?此时,如果让蓝线继续游走,周期特征立即了然:

    0_1540374791380_3cd28905-8427-468c-b4d4-036349a17ddf-image.png

    经过足够多次的重复游走,真伪随机数的面目已然清晰:

    0_1540374814491_f56d3a5a-8ccb-4d27-996c-6d17ab1d093d-image.png

    我们并不能因此断言白色就是真随机数,因为如果把上图向四周扩展到足球场那么大,可能会出现另一种规律。但相对蓝数,白数伪得不是很厉害。

    有研究称,严格意义上的真随机数只存在于量子力学中。到底有没有真随机数?我们无力遍历,也无法证伪,所以这种讨论会飘成一个哲学问题。

    但有一点可以明确,如果两次产生了相同的私钥,那一定是程序问题,历史上几次因随机数导致的丢币,都是因为写错程序,比如blockchain.info上两三次随机数事件。

    回忆一下我们曾面对的星空,对于2的256次方来说,碰撞绝无可能,这是整个密码学的根基。

    具体体现在:如果你确实知道,那你当场就能拿出私钥。可如果不知道,那你盼穿双眼、望尽飞鸿,飞鸿也不会理你。

    真随机相对伪随机不仅遍历范围大,而且没规律。如果伪随机数是地球上的石头,那真随机数就是宇宙里的沙子。

    同时,任何一颗沙子往下个数量级一滚,就会泼出一片宇宙,我们抬眼望到的宇宙星空全景,不过是一颗微尘表面无法被人感知的突起。

    所以,如果有人问你为什么真随机数私钥无法被人猜中,那古倩敏写的一句歌词就是对他最好的回答:

    山河大地本是微尘,更何况是尘中的尘。

    结语

    阿土仔并非虚构,而是确有其人:Turkeyslam。他曾用一个月陆续存入10笔比特币,两天后被人转走,他跑去Reddit上求助,还贴出自己地址的交易记录。

    但这于事无补,因为那个世界没有法院,只认私钥。

    这是密码学的底层哲学——用数学燃尽心怀恶意者的好运,以此保护你的财产神圣不可侵犯。可人们常常未曾在意过数学端来的这份好意,这和我们生活的场景有很大关系。

    比如,日常生活中得知同事工资比自己多10%时,很多人会心生杂念,但直面大数时,人类往往束脑无策,因为它极少出现在生活场景中。很多人对超大数的感知和婴儿对手枪的陌生是一样的。

    在超大数层面,几倍的不同都可以认为完全相等,数量级外的差距才值得关注。

    这是我们基因中缺失的一缕DNA。

    人类祖先刚把大脑从史前空运而来,这让我们对超大超小数的概念停留在结绳计数时代——所有的数不过是十根手指嘛。科技爆炸短短百年,我们还不习惯脱离本能思考,所以总在看不见的数量级上一脸茫然。

    唯一的应对方式是凝视自己的直觉,不断启用大脑皮层的逻辑思考区域,而真随机数的概念是对这种认知模式的小小历练。

    我们从真随机数的星空回到日常生活,凡事都有利弊,但不是所有弊端都值得计较。很多时候经你权衡,很容易算出优劣,并且常常是数量级的差距。

    很多牛人忽略小事不是大老粗的个性,而是因为细算过的理性。

    谁都曾用扔掉西瓜的代价去捡过芝麻,所以我们需要明辨的除了轻重缓急,还有轻重的数量级,然后把精力和资源倾注到那些最重要的事情上,这是数学曾在我们耳边私语过的悄悄话。

    0_1540375057623_0e7c201d-a2b9-4236-9acd-edb0d1fed11a-image.png



  • 在超大数层面,几倍的不同都可以认为完全相等,数量级外的差距才值得关注。

    这句话让我想到三体里说的:在高级文明面前,钻木取火和核电是一样。