最近好忙
好久没有更新了,绝不是因为我被警察叔叔请去喝茶了哟
主要是因为,
还有,
最后是
嘛,手头可以写的素材倒是积了挺多了,有空我会处理掉的
Canned Unicorn Meat
闲逛amazon的时候看到这个神物: http://www.amazon.com/ThinkGeek-Canned-Unicorn-Meat/dp/B004CRYE2C/ref=sr_1_1?ie=UTF8&qid=1349364328&sr=8-1&keywords=canned+unicorn+meat
商品描述:(不翻译了)
No foolin' - Unicorn meat is real! Excellent source of sparkles! Rick Bite Unicorns, as we all know, frolic all over the world, pooping rainbows and marshmallows wherever they go. What you don't know is that when unicorns reach the end of their lifespan, they are drawn to County Meath, Ireland. The Sisters at Radiant Farms have dedicated their lives to nursing these elegant creatures through their final days. Taking a cue from the Kobe beef industry, they massage each unicorn's coat with Guinness daily and fatten them on a diet comprised entirely of candy corn. As the unicorn ages, its meat becomes fatty and marbled and the living bone in the horn loses density in a process much like osteoporosis. The horn's outer layer of keratin begins to develop a flavor very similar to candied almonds. Blending the crushed unicorn horn into the meat adds delightful, crispy flavor notes in each bite. We are confident you will find a world of bewilderment in every mouthful of scrumptious unicorn meat. Tasty Magical Beast Diagram Parts Unfortunately, due to restrictions on the importation of mythical processed meatstuff, we are unable to bring you Canned Unicorn Meat in the way the Sisters of Radiant Farms intended. When you open your can, you will find one tiny unicorn which has been appropriately sliced into its main cuts of meat. Simply use your Growth Ray to re-embiggen the unicorn before skinning it and processing its flesh. Or if you're lazy, just bring it to your local Mad Scientist-Butcher. He'll know what to do.
后面的评论非常欢乐,,节选几条(仍然懒得翻译)
While tasty and full of nutritional value, I found the rainbow sprinkles to get caught in my teeth quite often. Also make sure to brush after eating, as your teeth can become rainbow colored for a couple hours after eating.
I should have listened to Hagrid. I bought this off Amazon and had this, about a hundred years ago. Now I am still alive, always an inch from death, but I have half a life. A cursed one. The only thing that can cure me now is the Philosopher's (Sorcerer's) Stone. But apparently they do not sell that on Amazon.
Chaaaaarliiiieeee! Chaaaarrrrr liiieee! Chaaaaar lieeeee! Chaaaaaaaaaarrliiiieeee! Chaaaar lieee! Chaaaaaaaarlieeee! Chaaaar lieeeee! Chaaaaaaaar liiieeeeee! Chaaaaarlieeeee! Chaaaarliieee! We're in a can, Charlie! (NETA: Charlie the Unicorn, a famous falsh movie)
Don't order this product if you have a conscience. The unicorns in the industrial unicorn farms live in appalling conditions, in many cases worse than those of the pegasus ranches. Don't believe the propaganda of Lisa Frank and the other tycoons of big unicorn; all that awaits these poor creatures is the abattoir and the rainbow factory. Be ethical and buy (kosher) dragon meat instead.
Of course this isn't as good as fresh, but who has time to hunt unicorns these days?
I'm a busy professional so I don't have the luxury of just grabbing my bow and quiver and spending days in the high glens hunting fresh 'corn. This product allows me to come home from a hectic day and enjoy a meal packed with that special nutrition only unicorn can provide. I even keep a few cans at the office for those late nights.
But seriously, this is a great, funny and 'tasteful' gag gift. We received ours from a relative last Christmas and as it was unwrapped everyone burst out in laughter when we saw what it was. The unicorn meat comes in a Spam-shaped can, complete with funny but realistic product information on the side labels.
This gift was enjoyable enough as it was, but then my wife pointed out that the can lid can be pried off to reveal plush unicorn 'parts' inside. Very clever and a great deal of fun for the price. I'm going to be giving a few out to co-workers this Christmas.
One last note: I don't think this gift would be appropriate for small children due to the small stuffed parts as they might be a choking hazard.
之后,我在amazon上搜到了更加稀奇古怪的东西:
Uranium Ore
stackoverflow上热门文章收集
庆祝自己获得了reputation~
我用tree来存贮客户的家庭资料,直到有一个客户啪啪啪了他女儿...
为什么将两个时间"1927-12-31 23:54:08"和"1927-12-31 23:54:07"相减结果是353?
为什么转置一个512x512的矩阵,会比513x513的矩阵慢很多?
谨以此文,纪念刚退休的Professor Sibert以及Professor Goel。你们尽管已年过70,却还仍然坚持在教导学生,实在令人钦佩。我今天所拥有的编程知识,经验,技巧,很大一部分是从你们那儿学来的。谢谢你们。
问题的出处:http://stackoverflow.com/questions/11413855/why-is-transposing-a-matrix-of-512x512-much-slower-than-transposing-a-matrix-of
事情的起因是这样的,先看下面这段代码:
define SAMPLES 1000 #define MATSIZE 512 #include <time.h> #include <iostream> int mat[MATSIZE][MATSIZE]; void transpose() { for ( int i = 0 ; i < MATSIZE ; i++ ) for ( int j = 0 ; j < MATSIZE ; j++ ) { int aux = mat[i][j]; mat[i][j] = mat[j][i]; mat[j][i] = aux; } } int main() { //initialize matrix for ( int i = 0 ; i < MATSIZE ; i++ ) for ( int j = 0 ; j < MATSIZE ; j++ ) mat[i][j] = i+j; int t = clock(); for ( int i = 0 ; i < SAMPLES ; i++ ) transpose(); int elapsed = clock() - t; std::cout << "Average for a matrix of " << MATSIZE << ": " << elapsed / SAMPLES;
很普通的一个求矩阵转置的程序。但是,当MATSIZE取512和513的时候,出现了非常有意思的结果:
512 平均 2.19ms
513 平均 0.57ms
很让人惊讶吧,513竟然比512快。更进一步的研究发现,size=512的时候,运算速度会比同数量级的其它数字慢很多很多。这是怎么一回事呢?
stackoverflow上大牛给的解答非常正确,但是这次,我不想做翻译了。我从Professor Sibert那里,从Professor Goel那里,学到的知识,足够帮我解决这个问题了,我不是一个人。下面是我的解答:
很容易就联想到,造成这个问题的原因是CPU cache,我们有很多种方式来存储cache,具体可以参考这里。
原作者没有给出他的CPU型号,但是如今的pc几乎都是采用的set associative的cache结构,下面我用2-way set associate来做例子,讲解一下cache的工作原理。
(图片取自Professor Sibert的讲义,这可是纯ascii画的哦= =)
一个内存地址,可以划分为block,tag,word,byte 4个部分。10bits的block,对应了1024个cache set,内存地址的block固定了,就必须存储在相应的set里面,这样可以把查询cache的事件从O(n)缩短为O(1)。
举个例子,block是1023(1111111111),你的数据就放在第1023个set里面。可能有人会觉得奇怪,为什么block不是取的最前面的10bits,这当然是有道理的,通常在内存里数据都是连续存放的,就是说,同一段程序用的数据,他们前10位几乎都是一样的,如果用前10位来定位block,那么collision的发生率非常高,cache效率非常低下,所以才选了后面的10位来定位block。
当然,每个set里面有多条记录,2-way是2条,你得遍历这两条记录,比较前面50位的tag,如果tag一样,并且Valid bit(V)=1,那么恭喜你,你的数据在cache里面,接着就可以通过word和byte来取数据了。
如果遍历完这两条记录,还是没有找到tag的话,那么很遗憾,你的数据不在cache里,得从内存里读。从内存里获取相应的数据,然后把它存到对应的cache set里,如果set里有空位的话最好,如果没有的话,用LRU来替换。因为一个set里只有2条数据,所以实现LRU仅仅需要一个额外bit就可以了,非常高效。
好了,背景知识介绍的差不多了,让我们回到这个问题上来。为什么512大小的矩阵,会比其它数字慢那么多?
让我们来计算一下,512x512的int矩阵,在内存里是连续存放的。每个cache line是16bytes,对应4个int,所以一个n阶矩阵的row可以填充n/4个cache set。假设第一个数据a[0][0]正好对应cache set 0,那么其中每一个数据a[i][j]对应的cache set是(512i+j)/4%1024=(128i+j/4)%1024。可以看到,前面的系数正好可以整除。很不巧的是,在进行矩阵转置的运算时,在第2个for循环中,我们需要依次访问每一个row中对应i的值。这样会造成下面的结果:假设i=0,set(a[0][0])=0, set(a[1][0])=128, set(a[2][0])=256...set(a[7][0])=896,set(a[0][0])=0,后面开始重复了,到a[15][0]的时候刚好填完整个cache的所有128整数倍的set,当读取a[16][0]的时候,将会发生replace,把a[0][0]从cache里移除。这样,当源程序的i=1时,将完全重复i=0的计算过程,每次取数据都需要先从memory读到cache中来,cache的作用完全没有体现。
而当size=513的时候,事情就不一样了,mat[i][j]对应的cache set是(513i+j)/4%1024,前面的系数除不尽了,每递增4次结果会比size=512时偏差1。例如:set(a[0][0])=0, set(a[1][0])=128, set(a[2][0])=256,set(a[3][0])=384, set(a[4][0])=513...这样就很微妙的把cache set给错开了。a[16][0]不在第0行而是第4行,不会覆盖之前的数据。即使将全部的a[0-15][i]都读入cache,也不会发生碰撞。之后,由于一个cache有4个word,a[0-15][i+1],a[0-15][i+2],a[0-15][i+3]也同时被读进cache里了,所以计算i+1,i+2,i+3时,仅仅需要读对应行的数据就可以了,同一行的数据都是连续的,所以碰撞率很低。这个计算过程很好的利用了cache,如果不考虑其他因素(实际上,这个已经是影响运行时间的最大因素了),理论上我们可以节省75%的运行时间,可以看到,这个理论预测是和提问者给的数据相符合的。
总之,当你的data size是128的整数倍的时候,得特别小心,搞不好cache collision就把你的程序给拖慢了呢
Update 1: 原代码有逻辑错误,这点大家都不要吐槽了,代码不是我写的= =
Update 2:帅哥问我,为什么可以加速这么多。这个循环包括4次读cache的操作,2次写cache的操作,以及0-2次replace操作。每次replace操作会有一次memory read,有可能会有memory write(假设它是write back)。前面的读写cache时间和读写内存相比,几乎可以忽略,对效率产生显著影响的是后面的内存读写。如果cache的hit率高了,那么内存读写的次数就少了,程序运行时间是会产生很大影响的
Update 3:当然,具体效果还视乎CPU架构而定,我自己试验的只有节省25%左右时间
Update 4: 有人提出了用划分矩阵(把大矩阵分成若干个小矩阵分别计算)的方法来求转置。划分矩阵可以解决类似的问题(譬如说求两个矩阵乘积),但是对解决这个问题没有任何帮助。因为求转置的时候,每个数据只用到了一次,没有重复访问;即便划分成更小的矩阵,在cache里面的位置也没有发生改变。
Update 5: 据说,Professor Goel只是因病休息几个学期,没有退休。。。(原来你还要回来教课!!!)
[翻译]一个app开发者的自白
今天比较忙,随便闲扯一下了。
前段时间,我在reddit上看到一篇一个做app开发的自由职业者的个人经历,并由此展开的一系列讨论。
很遗憾,原文我找不着了,我会尽可能把他们讨论的精华描述出来,如果有记错,还请多多包涵= =
做app能赚钱吗?
很难。假如有两个人用3个月时间全职开发一款app,那他们必须保持他们的app在前200名才可以养家糊口。注意,这里说的是“保持”。即使维持不了很久,至少也要撑到下一款作品问世。
app的定价策略如何?
通常来讲,一款app的定价在1-3美元之间,这是市场价格。也许有人会想“与其用2刀的价格卖1000份,为什么不用20刀的价格卖100份呢?这样用户少了比较容易处理用户反馈”很遗憾,让人操蛋的事实是,如果你卖20刀,可能你连10份都卖不出去。实际上,人们总是希望你的价格可以尽可能的低,有一个评论是这样说的“人们总是希望我可以把自己的app免费发放,可是,那些觉得我的app不值一块钱的家伙,我不想把他们当做用户”
广告收入很多吗?
忽略不计。广告唯一的好处是,可以促使用户去买收费版,毕竟只要一瓶可乐的钱就可以免去这些恼人的广告了。
那么,做app就没有前途了么?
运气好的就可以成功,instagram和sparrow就是很好的例子。但是,人们往往只关注了少数的成功者,而忽略了无数付出不少心血汗水的失败者们。
最后,支持人们全职投入app制作的动力是什么?
自由。没有老板,没有客户,没有需求,你爱怎样就怎样,这是无数人梦寐以求的生活。
[ios]推荐一个好玩的回合制策略游戏&&闲扯
这篇文章跟编程无关啦,只是不偶尔写点类似的东西我都快忘了我是个游戏宅了= =
最近玩到这样一款游戏,hero academy,质量没的说,对得起ign 9.0/10分的评价。
在游戏中,你要带领你的军队,与别的玩家相互对抗,最终目的是摧毁对手的要塞!
游戏是回合制的,每一回合有充足的时间好好思考策略!
不管好友还是陌生人,同时可以和多个对手较量
游戏目前为止一共出了4个种族:
council,攻守平衡的种族(据官方介绍),真相是:近战除了肉盾一点用都没有,但是远程弓箭手有着全游戏最高的远程单体杀伤,终极兵种忍者杀人跟切菜一样,但是被杀也是切菜。。。
Dark Elves:可以吸血(这技能没用,你当对手是电脑啊,人都是盯着一个打的)终极兵种可以通过吃尸体变强(初始能力超弱。。。一般是出来就被秒)战士抗性高,法师施法距离远,这才是这种族的长处
Dwarves 近战全是酱油,远程才是主力,aoe杀伤能力很强(相对的,单体杀伤就有点那个。。。),缺强力魔法攻击,碰到物理抗性高的敌人会很无解
The Tribe 很禽兽的一个种族,几乎没有防御技能,相对的攻击高的不科学,缺点是缺少aoe缺少buff,比较依靠单兵能力。
========================我是分割线===========================
由这个游戏,我不由得想到一个话题,那就是,像这种回合制的策略游戏,要怎么做才能和别的玩家竞争?
一般我们玩星际,fifa,cs,玩家与玩家之间的pk往往是很直接的:
“来,看哥虐你两局”
“滚蛋,我操翻你”
简单明了,高下立现。可是一到策略游戏,就很难很难表现出玩家的水平了:
“玩三国志我可以用公孙康统一全国!”
“so what?”
“...”
于是乎,想当然的,玩家们需要一个能够相互pk战略的平台。在线下,这种东西早已存在,那就是桌游。即便是现在,诸如twilight struggle或者war hammer之类的strategy board game仍然是大热门。有人就想“为什么我们不能把桌游搬到网络上来呢?”他们这样做了,但是立马遇到了一个难题:在桌游中,我们管“一个玩家等待别的玩家行动的时间”称为downtime,一个游戏downtime的长短很大程度影响了桌游的品质。譬如说,像puerto rico, modern art这种游戏,约等于0的downtime,玩家的参与感非常强;而三国杀这种7/8 downtime的游戏,玩起来就非常令人不爽。好吧,扯远了。线上和线下的一个重要区别是:玩家对于downtime的容忍度更低。想想也是,线下的时候,等待对手的时间里可以聊聊天喝喝茶泡泡妞,但是线上除了盯着屏幕发呆就什么也做不了了。一个普遍在用的解决方法是限时,限定你在规定时间之类完成操作,避免对手等待过久。这看起来很美妙,可是,并不是所有游戏都简单的像三国杀一样只要15秒就可以思考完的。很多游戏,我们需要几分钟甚至10多分钟的时间去思考,而玩家也热衷于思考,我们没有办法将时间限制在一个可以接受的范围内。似乎是遇到死胡同了呢,一方面,玩家需要很多时间思考,另一方面,我们要尽量压缩等待时间。这个问题曾经困扰了我很长一段时间,直到我看到了这个网站:http://www.dipbounced.com/。这个网站是桌游diplomacy的线上版,简单介绍一下这个游戏吧,这是一款1959年发明的桌游,7名玩家分别扮演一战期间的英,法,德,俄,意大利,奥匈帝国,土耳其7名列强中的一个,以征服欧洲大陆为目标。地图如下:
在这游戏中,你需要去和别的玩家面对面的“交涉”,签订盟约,互不侵犯,共同进攻,协助防守之类的事情,全部需要你去和别的玩家协商后决定。当然,这个游戏最令人着迷之处在于,你可以不用为你说的任何话负责。为了获取最大利益,你可以假装和人互不侵犯,然后背地里偷偷捅他一刀。战略,交涉,信任,背叛构成了这个游戏的全部。将这个游戏搬到线上来,最大的难题是,交流的时间太久太久了。毕竟线上交流不如当面那么方便,有时候,你需要和别的玩家持续数小时的交流,显然让其他人等你们几个小时是不现实的。解决方法很令人惊讶:既然你们喜欢思考,那给你们足够的时间思考;既然等不了,那就不要等了,该干啥干啥去。即是说,玩家们只需要完成自己的行动即可,不用等待其他玩家,尽管去做别的事情好了,24小时以后统一开始下一轮。这样子,所有问题都解决了。交流不用你和对方同时在线,发mail就好,你甚至不用一次性做决定,反正24小时呢,慢慢来。
不得不说,这种设计,为线上策略游戏开辟了一个新思路。另一个类似的例子就是http://awbw.amarriner.com/。这个网站是任天堂著名游戏advanced wars的线上版,同样是“给够你时间”类型。advanced wars是一个回合制战略游戏,游戏中,双方分别抢占据点,生产军队,攻击敌人。这个游戏原本只是个单机,没法用常规方式搬到网上来,因为游戏里单位数量实在太多了,一个回合里,你需要给你的几十支部队分别下命令,而且,命令的顺序还很有讲究,让对手等着你操作完是不靠谱的。所以,它采用了和diplomacy类似的机制,只是周期更短一些。地图是这样的,注意因为有阴影的概念所以看不到部队,残念。
那么,有没有别的解决方案呢?答案是肯定的,来自于英雄无敌系列的第五作。关于这个游戏,贬褒不一。我个人认为这是一款非常优秀的游戏,很多新机制的引入,无疑为这个古董般的老游戏系列注入了新的活力。其中一个就是同步回合,就是说,系统判断两个玩家相互间的行动不会对对方造成障碍的时候,将会允许两个玩家同行动,一下子把等待时间从a+b缩成了2|a-b|。还有一个机制是幽灵模式,即是说,一个玩家在行动的时候,另一个玩家可以操纵幽灵干扰对手,对手花费的时间越多,幽灵的行动力也越强,这无疑限制了对手无节制的使用时间。遗憾的是,这些机制还存在瑕疵,就结果而言没有能够完全解决问题。随着6代制作组的更换,我们没法看到英雄无敌系列在革新的道路上走更远了,真的非常可惜。
未来,策略游戏将何去何从?没人知道。我唯一能确信的是,只要这世上还有热爱思考,热衷于在虚拟世界里纵横捭阖的玩家在,strategy game将会不断进化,永不消亡。
[翻译]一个中国公司偷了我的游戏
Vim 攻略<5> Registers
一天两更,我还真是勤快~
在vim中,我们每次执行复制,剪切,删除,粘贴操作,其结果都是和寄存器息息相关的,所以,为了更好地使用这些操作,我们有必要了解一下vim的各个寄存器
在之前的文章中我讲过了,寄存器是以"开头,后面跟寄存器的名字,vim中一共有如下几种寄存器:
1. 默认寄存器 ""
2. 10个数字寄存器 "0 到 "9
3. The small delete register(不会翻) "-
4. 26个命名寄存器 "a 到 "z 或者 "A 到 "Z, 不区分大小写
5. 四个只读寄存器 ":, "., "% 和 "#
6. 表达式寄存器 "=
7. 选择和拖拽寄存器 "*, "+ and "~
8. 黑洞寄存器(直译的。。。black hole= =) "_
9. 搜索表达式寄存器 "/
要查看每个寄存器中都存了些什么,只要输入:reg就好了
下面我们来一一介绍下这些寄存器的作用:
1. 默认寄存器 ""
当进行任何删除操作(d,c,s,x),或者复制操作(y)的时候,不管有没有指定寄存器,结果都会被存储在默认寄存器中。任何没有指定寄存器的粘贴(p)操作,会复制默认寄存器中的值
2. 10个数字寄存器 "0 到 "9
这10个寄存器中的值也是自动存储的。
寄存器"0存最近一次复制操作的值,除非那次复制指定了寄存器。
寄存器"1存储了最近一次删除操作的结果,除非那次删除指定了寄存器,或者删除内容少于一行。
寄存器"2存储了倒数第二次删除操作的结果,除非那次删除指定了寄存器,或者删除内容少于一行。
寄存器"3到"9,同理,倒数第三次到第九次删除操作的结果,除非那次删除指定了寄存器,或者删除内容少于一行。
3. small delete register "-
如果某次删除操作删掉了少于一行结果,那那次删除结果会被存在"-中,除非特别指定了寄存器。
4. 命名寄存器"a到"z
不会自动填充,全部交给用户使用。注意:用小写字母表示替换寄存器中的内容,而大写字母表示append!!!
5. 只读寄存器 ":, "., "% 和 "#
这四个寄存器是只读的,用户不可以手动往里面写数据。
". 最近一次插入的文字
"% 当前文件名
"# 其他打开的文件名
": 最近一次执行的指令名
6. 表达式寄存器 "=
用来存表达式的,在表达式那一章我会再提(如果有那一章的话)
7. 选择和拖拽寄存器 "*, "+ and "~
"*, "+ 这俩寄存器就是传说中的剪贴板。其实它们是有略微区别的,不过介于我这篇教程是面向初学者的,我果断决定无视= =
"~ 拖到vim里面的东西,会存在这个寄存器里
8. 黑洞寄存器 "_
顾名思义,往里面填数据的时候,什么都不会发生,从里面读数据的时候,什么都没有......
这个蛋疼东西的作用呢,有些时候,我们删除某样东西的同时却不希望它的值被自动写到寄存器里,这时候就把它往黑洞里扔吧。。。
9. 搜索表达式寄存器 "/
最后一次使用的搜索表达式,在pattern一章我会细说(如果有的话。。。)
最后给大家一个小tip,如果在command mode下想要使用register,只要输入ctrl-r再跟上寄存器名就好啦
Vim 攻略<4> Windows
通过windows,我们可以在同一个vim中打开多个文件。
有人可能会问,为什么不打开几个vim呢?其实,在同一个vim中编辑多个文件有很多好处:
手指不用离开键盘
可以使用通用寄存器(如果跨进程的话就只能用clipboard了)
有command历史记录
可以共用macro
打开文件:
:edit foo.txt
上下切分窗口
:split
关闭当前窗口
:close
关闭除当前窗口外所有窗口
:only
切分窗口并打开另一个文件:
:split two.c
用空白文件切分窗口:
:new
切成n份:
:nsplit text.c
增加当前窗口的大小:
Ctrl-W +
减少当前窗口的大小:
Ctrl-W -
将窗口大小设为一个特定值:
{height}Ctrl-W _
水平划分:
上面所有的split,用vsplit替换就可以了;new用vertical new替换,窗口大小的命令格式完全一样,只是高度变成了宽度
在窗口间移动:
CTRL-W h 移到左边的窗口
CTRL-W j 移到下面的窗口
CTRL-W k 移到上面的窗口
CTRL-W l 移到右边的窗口
CTRL-W t 移到最上面的窗口
CTRL-W b 移到最下面的窗口
这些移动按键和normal mode下的光标移动时一样的,很好记
移动窗口位置:
和上面一样的,只是把小写字母换成了大写
如何正确加密用户密码
vim 系列很可能要坑掉了。。。Orz
很久很久以前,当人们还没有什么安全概念的时候,密码都是不加密存储。这样显然会带来很严重的问题,当你的服务器受到攻击时,用户的密码有非常非常大的概率会泄露出去,这样会给用户带来很严重的问题(参考csdn事件= =)
后来,大家觉得明文存密码太傻X了(工信部的那群**还没有这么觉得= =),于是要把密码加密,最早用的是对称加密法,就是用一个key去加密密码,然后只存储密文,用户验证时候,用同样的key解密密文就可以得到原文了。
不久以后,这个方法还是被大家觉得不太靠谱,毕竟那么多用户,用的都是同一个key,万一key泄露出去了,一样得玩完儿。那么,有没有不用key的加密方式呢?有的,one way hash。简单来讲,就是把用户密码通过不可逆的hash function映射到一个密文上。因为这个hash function的映射区间很大(当前应用比较多的是128或256bit),所以极少会发生两个不同的密码映射到同一个密文的情况。而且,因为这个hash function是不可逆的,即使有人黑掉了数据库,他仍然不知道用户的密码是什么。非要说缺点的话,就是没法帮用户“找回密码”,一般只能重新设一个。因为这个方法极大地提高了密码存储的安全性,所以这点不便就无视吧。(btw,如果哪个网站有找回密码的功能,我强烈建议大家不要再用了。。。)
故事就到这里完了?才不会呢!!!你太小看现在的黑客了!!!虽然上面那个方法看似无懈可击,但是,因为加密算法是固定的(不要试图隐藏你的算法,这是非常不靠谱的),黑客们只要花足够多的时间,就可以列出一张明文-->密文的映射表,再加上类似rainbow-table技术加速查表。一旦有人把表给列出来了,那么不管你的加密算法多么牛X,一样给破解了。不过解决方法也蛮简单的,为每个用户都随机生成一个128位的字符串,叫它salt好了,加密的时候把用户密码和salt一块儿加密,就是说,hash(password+salt)。因为这个salt是随机的,黑客得为每一个salt都写一个rainbow table,这在时间和空间上是不可能做到的,ok,safe!
很遗憾,最近几年,事情又有了变化,由于现在3d游戏市场发展的太快了,intel和nvidia研究出了各种功能强大的gpu。gpu和cpu最大的不同在于,它能够以非常快的速度进行某些算术运算。于是乎,就有人拿gpu来代替cpu来进行暴力破解了。不要觉得这没什么大不了,根据统计数据,现在主流的sha256加密算法(md5 died),原本需要1年时间破解的密码,现在用gpu只需要1个月!破解速度快了10倍多!这下真没辙了,毕竟是用的暴力破解,光增加密文长度没用,又不能强迫用户增加密码长度。。。不过呢,也别觉得压力大,现在已经有不少人着手开发了没法用gpu优化的算法,譬如说这个pbkdf2算法。
如果上面的方法还不够的话,我们还有一些物理手段来加密,譬如说令牌(不是工商银行那种纸牌)。
我最不擅长写总结了,不过还是说一些吧。这世上没有绝对安全的算法,你甚至没法证明它是安全的(证明加密算法安全,实质就是证明NP问题)。只要一个算法还没有被人成功破解,我们就可以继续信任它。只是,我希望大家在build application的时候,能够注意到这一点,毕竟,用户资料的安全,可是很重要的呢~