Files
md6/md6.py
T
2014-10-14 13:34:18 +09:00

235 lines
4.6 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# md6hash for Python 2, 3
#
# Usage:
# md6 = md6hash();
# data = "md6 FTW";
# result = md6.hex(data);
# print(result)
#
import binascii
class md6hash():
def __to_word(self, i_byte):
length = len(i_byte)
o_word = []
for i in range(0, length, 8):
o_word.append(
((i_byte[i + 0] & 0xff) << 56) |
((i_byte[i + 1] & 0xff) << 48) |
((i_byte[i + 2] & 0xff) << 40) |
((i_byte[i + 3] & 0xff) << 32) |
((i_byte[i + 4] & 0xff) << 24) |
((i_byte[i + 5] & 0xff) << 16) |
((i_byte[i + 6] & 0xff) << 8) |
((i_byte[i + 7] & 0xff) << 0)
)
return o_word
def __from_word(self, i_word):
length = len(i_word)
o_byte = []
for i in range(length):
o_byte.append((i_word[i] >> 56) & 0xff)
o_byte.append((i_word[i] >> 48) & 0xff)
o_byte.append((i_word[i] >> 40) & 0xff)
o_byte.append((i_word[i] >> 32) & 0xff)
o_byte.append((i_word[i] >> 24) & 0xff)
o_byte.append((i_word[i] >> 16) & 0xff)
o_byte.append((i_word[i] >> 8) & 0xff)
o_byte.append((i_word[i] >> 0) & 0xff)
return o_byte
def __crop(self, size, data, right):
length = int((size + 7) / 8)
remain = size % 8
if right:
data = data[len(data) - length:]
else:
data = data[:length]
if remain > 0:
data[length - 1] &= (0xff << (8 - remain)) & 0xff
return data
def __hash(self, size, data, key, levels):
b = 512
c = 128
n = 89
d = size
M = data
K = key[:64]
k = len(K)
while len(K) < 64:
K.append(0x00)
K = self.__to_word(K)
r = max(80 if k else 0, 40 + int(d / 4))
L = levels
ell = 0
S0 = 0x0123456789abcdef
Sm = 0x7311c2812425cfa0
Q = [
0x7311c2812425cfa0, 0x6432286434aac8e7, 0xb60450e9ef68b7c1,
0xe8fb23908d9f06f1, 0xdd2e76cba691e5bf, 0x0cd0d63b2c30bc41,
0x1f8ccf6823058f8a, 0x54e5ed5b88e3775d, 0x4ad12aae0a6d6031,
0x3e7f16bb88222e0d, 0x8af8671d3fb50c2c, 0x995ad1178bd25c31,
0xc878c1dd04c4b633, 0x3b72066c7a1552ac, 0x0d6f3522631effcb
];
t = [17, 18, 21, 31, 67, 89]
rs = [10, 5, 13, 10, 11, 12, 2, 7, 14, 15, 7, 13, 11, 7, 6, 12]
ls = [11, 24, 9, 16, 15, 9, 27, 15, 6, 2, 29, 8, 15, 5, 31, 9]
def f(N):
S = S0
A = list(N)
j = 0
i = n
while j < r:
for s in range(16):
x = S
x ^= A[i + s - t[5]]
x ^= A[i + s - t[0]]
x ^= A[i + s - t[1]] & A[i + s - t[2]]
x ^= A[i + s - t[3]] & A[i + s - t[4]]
x ^= x >> rs[s]
if len(A) <= i + s:
while len(A) <= i + s:
A.append(0x00)
A[i + s] = x ^ ((x << ls[s]) & 0xffffffffffffffff)
S = (((S << 1) & 0xffffffffffffffff) ^ (S >> 63)) ^ (S & Sm)
j += 1
i += 16
return A[(len(A) - 16):]
def mid(B, C, i, p, z):
U = ((ell & 0xff) << 56) | i & 0xffffffffffffff
V = ((r & 0xfff) << 48) | ((L & 0xff) << 40) | ((z & 0xf) << 36) | ((p & 0xffff) << 20) | ((k & 0xff) << 12) | (d & 0xfff)
return f(Q + K + [U, V] + C + B)
def par(M):
P = 0
B = []
C = []
z = 0 if len(M) > b else 1
while len(M) < 1 or (len(M) % b) > 0:
M.append(0x00)
P += 8
M = self.__to_word(M)
while len(M) > 0:
B.append(M[:int(b / 8)])
M = M[int(b / 8):]
i = 0
p = 0
l = len(B)
while i < l:
p = P if i == (len(B) - 1) else 0
C += mid(B[i], [], i, p, z)
i += 1
p = 0
return self.__from_word(C)
def seq(M):
P = 0
B = []
C = [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
while len(M) < 1 or (len(M) % (b - c)) > 0:
M.append(0x00)
P += 8
M = self.__to_word(M)
while len(M) > 0:
B.append(M[:int((b - c) / 8)])
M = M[int((b - c) / 8):]
i = 0
p = 0
l = len(B)
while i < l:
p = P if i == (len(B) - 1) else 0
z = 1 if i == (len(B) - 1) else 0
C = mid(B[i], C, i, p, z)
i += 1
p = 0
return self.__from_word(C)
while True:
ell += 1
M = seq(M) if ell > L else par(M)
if len(M) == c:
break
return self.__crop(d, M, True)
def __bytes(self, i_str):
i_str = binascii.hexlify(i_str.encode("ascii"))
o_byte = [int(i_str[i:i+2], 16) for i in range(0, len(i_str), 2)]
return o_byte
def __prehash(self, data, size, key, levels):
data = self.__bytes(data)
key = self.__bytes(key)
if size <= 0:
size = 1
elif size > 512:
size = 512
return self.__hash(size, data, key, levels)
def hex(self, data="", size=256, key="", levels=64):
byte = self.__prehash(data, size, key, levels)
hexstr = ""
for i in byte:
hexstr += "%02x" % i
return hexstr
def raw(self, data="", size=256, key="", levels=64):
byte = self.__prehash(data, size, key, levels)
rawstr = ""
for i in byte:
rawstr += chr(i)
return rawstr