星期三, 一月 04, 2012

如何制造一个『实名』

本文是http://code.google.com/p/md5-password-creator/ 的原理说明,利用http://code.google.com/p/md5-password-creator/downloads/list 中列出的程序,每个人都可能制作出自己的『实名』,通过网站的实名验证。继续匿名的使用网络。

『实名制』是邪恶的。『实名制』将可能会产生自我审查,你在发言之前,要考虑到是否有人可能会威胁你自身,或者威胁你的社会关系,于是你的发言就要有所顾忌。在实行实名制之前,你的网络身份仍然可能是暴露的,但是只有少数人通过技术手段才可以获得,但是实行实名制之后,自我审查的压力会大得多。这个大陆旁边正好有两个栗子,一个是西朝鲜,一个是北台湾。

代码本身就是一种力量。在代码的世界里,代码说了算。下面,我会解释如何产生一个『实名』的代码,将代码的力量赋予你。

要产生一个『实名』,要满足两个条件,一个是不重样,一个是不走样。所谓不重样,是指每一个网站可以产生不同的身份,不同的人,可以产生不同的身份。所谓不走样,是指同样的条件产生同样的身份。基于MD5密码生成器的原理,我们也可以用HASH的方法来产生新的不重样不走样的身份。

MD5密码生成器的基本概念是利用HASH函数,子密码=MD5(主密码+网站名),于是对于同一个主密码,只要改变网站名就可以产生无数不重样,不走样的子密码。『实名』生成部分,就是以每一个网站的子密码为种子生成的。

*  生成身份种子:

1. 首先生成子密码=MD5(主密码+网站名+时间代)
2. 将以16进制的子密码转换成10进制的数
3. 为了避免从生成的身份推导出子密码,所以稍微加了一步MD5和撒盐的可能:
var ID_decimal=hex2dec(md5(str_md5+md5("")));
这里的 ID_decimal就是生成的身份种子,这是一个32位的10进制正整数,是由主密码,网站名和时间代唯一决定的。从这个身份种子出发通过同样规则产生的信息也是不重样不走样的。

*  生成姓名:

中国人的姓名包含几个部分:第一个字是姓,考虑到算法的复杂性增加,暂时不加入复姓了,第二个字是辈分,第三个字的偏旁是表示兄弟姊妹的关系,最后半个字是自己的。产生姓名的基本 策略是从可选的字列表中挑选一个字,挑选的方法为了和身份种子产生关系,所以我使用了求余的计算。

var surName=surNameList.substr((ID_decimal.substr(0,10)) % (surNameList.length),1);

这句是说,把身份种子的前10位数字取出来,除以入选的姓氏数量,取得余数,然后从姓氏字列表中挑出余数所代表的那个字。这样的算法保证了一定可以从姓氏列表中挑出一个数字,不会出现选了百家姓中的30个姓,结果算出余数=31。

姓氏的列表是百家姓的前65位,基本可以涵盖大多数人的姓氏了。

名字的中间字和第三个字的算法类似, 如果你想让生成的名字都带有某个偏旁,就可以把同一个偏旁的字放在列表之中,如果自己一时想不出那么多,除了元素周期表,还可以从 http://www.douban.com/note/186053601/ 这里面查查。我暂时比较偏爱斜玉旁的汉字,都是代表了某种玉石,透着非普通青年的范儿。

var middleName=myNameList.substr((ID_decimal.substr(10,15))%(myNameList.length),1);
var myName=myNameList.substr((ID_decimal.substr(10,10))%(myNameList.length),1);

注意从32位身份种子之中挑出来做被除数的数字,每次的起止位置应该不一样,否则姓、名之间的相关性就太高了。能够产生的名字总数就少了。

*  生成性别:

性别的生成不过是从『男女』这个长度=2的列表中挑字而已。

var gender=genderList.substr(ID_decimal.substr(20,10)%(2),1);

*  生成注册名/email ID:

在我刚刚提出用MD5计算密码的时候,果壳网上有位先知非常逆向思维的提出应该将用户名也加密,生成各自不相同的用户名。这实在是一个对抗社会工程学的好方法,使各个网站的身份数据完全隔离开来。

生成注册名的时候我比较懒惰,直接截取了一部分子密码的尾部,有一定潜在的危险。
var mailID=str_base64.toLowerCase().substr(20,8);

*  生成ID号码:

这才是整个程序与身份相关的重点。理论上身份证号和姓名是一一对应的,并且可以到公安部的数据库中可以查到。但毫无疑问,政府是贪婪的,查询一次这样的数据需要人民币5元,也存在有背景的企业能够分一杯羹,到一个叫做『国政通』的企业去查询,一次查询的费用降低到2元。

认证一个身份2元是个什么概念呢?新浪在报告中声称注册用户有2亿,也就是说其中全部通过身份认证下来需要4亿人民币,即使国政通给新浪批发价,打一折,也是4千万之巨。这个行动可以很清楚的从新浪的财报中看出来,如果没有这笔支出,新浪一定没有去国政通认证,同理其他互联网上市公司也不可能去做的。那么国政通甚至公安部是否有可能免费给网站做身份验证呢?这不是降低GDP么,用脚趾头想想也不可能。而且如果免费了,或者超低价认证身份了,马上就有新公司可以打着认证到旗号,把整个数据库给剥出来。

是否有可能由国家财政拨款补贴呢?显然有可能,拿纳税人的钱治纳税人。那补贴可不是仅仅给新浪一家4亿,而是新浪、搜狐、网易、腾讯每家4亿。那样的话,我也去开个小破论坛,生成一堆实名认证要求,去申请补贴。记得有本书叫做《民主的细节》,看来《专制的细节》应该是本更厚的书。

那么现在互联网企业是如何进行『实名』认证的呢?他们其实只做了一步,就是检查身份证号码是否是一个合法的身份证号而已。也就是用身份证校验算法去验证最后一位和前17位之间的关系。

身份证号码的规定在中华人民共和国国家标准GB 11643-1999《公民身份号码》之中进行了详细的规定。在维基百科上也有详细的解释:http://zh.wikipedia.org/wiki/中华人民共和国公民身份号码

下面引自维基百科:

18位数字组合的方式是:

1
1
0
1
0
2
Y
Y
Y
Y
M
M
D
D
8
8
8
X
地址码
出生日期码
顺序码
校验码
  • 地址码指的是公民常住户口所在县(市、旗、区)的行政区划代码,如110102是北京市西城区
  • 出生日期码表示公民出生的公历年(4位)、月(2位)、日(2位)。
  • 顺序码是给同地址码同出生日期码的人编定的顺序号,其中奇数分配给男性,偶数分配给女性。
  • 最后一位是校验码,这里采用的是ISO 7064:1983,MOD 11-2校验码系统。校验码为一位数,但如果最后采用校验码系统计算的校验码是“10”,碍于身份证号码为18位的规定,则以“X”代替校验码“10”。

校验码计算方法

  • 1. 将身份证号码从右至左标记为a1即为校验码;
  • 2. 计算权重系数
i
18
17
16
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
Wi
7
9
10
5
8
4
2
1
6
3
7
9