LDAP的MD5算法

和php、MySQL的 md5() 函数不一样,LDAP里用户认证时候的md5算法有点不一样,留个记录。来源:OpenLDAP邮件列表

首先说说php和MySQL的md5函数,例如:
md5("testing") = "ae2b1fca515949e5d54fb22b8ed95575";
这个和Python的 hexdigest() 函数结果是一样的
>>> md5(”testing”).hexdigest()
‘ae2b1fca515949e5d54fb22b8ed95575′

在LDAP里怎么表示的呢?

dn: cn=md5user,dc=my,dc=example,dc=com
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: md5user
description: MD5USER
userPassword: {MD5}CgIBDAUFBA4NBAsCCA0FBw==
]

怎么得到的呢?

我们研究 字符串 testing 的 MD5 字串:ae 2b 1f ca 51 59 49 e5 d5 4f b2 2b 8e d9 55 75
首先隔一个字符提取一个字符,得到一个新的字符串,例如:
a21c554ed4b28d575
得到:
a  2  1  c  5  5  4  e  d  4  b  2  8  d  5  7
那么把每一位看成十六进制,转换成对应的ASCII字符,例如第一位的 a,十六进制是 \x0A,也就是个回车:\n,把转换后的ASCII字符连起来,那么我们可以得到一串字符,不可显示的:'\n\x02\x01\x0c\x05\x05\x04\x0e\r\x04\x0b\x02\x08\r\x05\x07'

最后把这串不可打印的字符用base64编码之后,就可以得到LDAP标准的MD5字串,例如我们在Python里:

>>> '\n\x02\x01\x0c\x05\x05\x04\x0e\r\x04\x0b\x02\x08\r\x05\x07'.encode('base64'
).strip()
'CgIBDAUFBA4NBAsCCA0FBw=='

strip()是去掉一个没有用的回车符号。

最后我们用Python实现这一算法:

ActivePython 2.5.1.1 (ActiveState Software Inc.) based on
Python 2.5.1 (r251:54863, May 1 2007, 17:47:05) [MSC v.1310 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from md5 import md5
>>>
>>> mysql_md5 = md5("testing").hexdigest()
>>> mysql_md5
‘ae2b1fca515949e5d54fb22b8ed95575′
>>> binary_md5 = ”.join([ chr(int(mysql_md5[i:i+1],16)) for i in range(0,len(mysql_md5),2)])
>>> binary_md5
‘\n\x02\x01\x0c\x05\x05\x04\x0e\r\x04\x0b\x02\x08\r\x05\x07′
>>> ldap_md5 = binary_md5.encode(”base64″).strip()
>>> ldap_md5
‘CgIBDAUFBA4NBAsCCA0FBw==’
>>>

顺便说下,一个 single sign-on 的系统设计还真麻烦。要实现一个password同步、LDAP认证,AuthSub,等等,ho~~~累!

Comments