def _nfold(str, nbytes):
# Convert str to a string of length nbytes using the RFC 3961 nfold
# operation.
# Rotate the bytes in str to the right by nbits bits.
def rotate_right(str, nbits):
nbytes, remain = (nbits//8) % len(str), nbits % 8
return ''.join(chr((ord(str[i-nbytes]) >> remain) |
((ord(str[i-nbytes-1]) << (8-remain)) & 0xff))
for i in xrange(len(str)))
# Add equal-length strings together with end-around carry.
def add_ones_complement(str1, str2):
n = len(str1)
v = [ord(a) + ord(b) for a, b in zip(str1, str2)]
# Propagate carry bits to the left until there aren't any left.
while any(x & ~0xff for x in v):
v = [(v[i-n+1]>>8) + (v[i]&0xff) for i in xrange(n)]
return ''.join(chr(x) for x in v)
# Concatenate copies of str to produce the least common multiple
# of len(str) and nbytes, rotating each copy of str to the right
# by 13 bits times its list position. Decompose the concatenation
# into slices of length nbytes, and add them together as
# big-endian ones' complement integers.
slen = len(str)
lcm = nbytes * slen / gcd(nbytes, slen)
bigstr = ''.join((rotate_right(str, 13 * i) for i in xrange(lcm / slen)))
slices = (bigstr[p:p+nbytes] for p in xrange(0, lcm, nbytes))
return reduce(add_ones_complement, slices)
评论列表
文章目录