Base64与非标准
我在尝试为bacula创建一个python客户端,但在认证方面遇到了一些问题。
这个算法是:
import hmac
import base64
import re
...
challenge = re.search("auth cram-md5 ()", data)
#exemple ''
passwd = 'b489c90f3ee5b3ca86365e1bae27186e'
hm = hmac.new(passwd, challenge).digest()
rep = base64.b64encode(hm).strp().rstrip('=')
#result with python : 9zKE3VzYQ1oIDTpBuMMowQ
#result with bacula client : 9z+E3V/YQ1oIDTpBu8MowB'
有没有比直接移植bacula的base 64实现更简单的方法?
int bin_to_base64(char *buf, int buflen, char *bin, int binlen, int compatible) { uint32_t reg, save, mask; int rem, i; int j = 0; reg = 0; rem = 0; buflen--; /* allow for storing EOS */ for (i=0; i >= (rem - 6); if (j
2 个回答
1
我搞定这个问题了。
我遇到了和你一样的问题,花了大约4个小时找出问题所在,并重新实现了一下。
问题在于Bacula的base64编码是有问题的,完全不对!
具体来说,有两个问题:
第一个问题是,传入的字节被当作有符号数处理,而不是无符号数。这意味着,如果一个字节的最高位是1(大于127),那么它就会被当作负数;而当它和之前字节的“剩余”位结合时,所有的剩余位都会被当作1(也就是二进制的1)。
第二个问题是,在b64处理完所有完整的6位输出块后,可能会剩下0、2或4位(这取决于输入块的3的余数)。标准的Base64处理方式是把剩下的位数放在最后一个6位块的最高位进行处理,而Bacula却把它们放在最低位。
需要注意的是,某些版本的Bacula可能同时接受“Bacula有问题的base64编码”和标准编码,用于接收认证;他们似乎在认证时使用的是有问题的编码。
def bacula_broken_base64(binarystring):
b64_chars="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
remaining_bit_count=0
remaining_bits=0
output=""
for inputbyte in binarystring:
inputbyte=ord(inputbyte)
if inputbyte>127:
# REPRODUCING A BUG! set all the "remaining bits" to 1.
remaining_bits=(1 << remaining_bit_count) - 1
remaining_bits=(remaining_bits<<8)+inputbyte
remaining_bit_count+=8
while remaining_bit_count>=6:
# clean up:
remaining_bit_count-=6
new64=(remaining_bits>>remaining_bit_count) & 63 # 6 highest bits
output+=b64_chars[new64]
remaining_bits&=(1 << remaining_bit_count) - 1
if remaining_bit_count>0:
output+=b64_chars[remaining_bits]
return output
我知道你问这个问题已经过去6年了,但也许其他人会觉得这有用。
1
为了验证你的CRAM-MD5实现,最好使用一些简单的测试向量,检查(挑战、密码、用户名)这些输入的组合是否能得到预期的输出。
这里有一个例子(来自 http://blog.susam.in/2009/02/auth-cram-md5.html):
import hmac
username = 'foo@susam.in'
passwd = 'drowssap'
encoded_challenge = 'PDc0NTYuMTIzMzU5ODUzM0BzZGNsaW51eDIucmRzaW5kaWEuY29tPg=='
challenge = encoded_challenge.decode('base64')
digest = hmac.new(passwd, challenge).hexdigest()
response = username + ' ' + digest
encoded_response = response.encode('base64')
print encoded_response
# Zm9vQHN1c2FtLmluIDY2N2U5ZmE0NDcwZGZmM2RhOWQ2MjFmZTQwNjc2NzIy
不过,我确实在网上找到了一些例子,发现上面的代码生成的响应和相关网站上预期的响应不一样,所以我对那些情况仍然不是很清楚。