/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Hash/python_RadioGatun.py |
---|
0,0 → 1,53 |
from pyradiogatun import RadioGatunType |
__all__ = ['new'] |
def new(data=None,wl=64): |
"""Create a new pure python RadioGatun hash object |
wl = wordlength (in bits) of the RadioGatun hash method |
between 1 and 64 (default = 64) |
data = if present, the method call update(arg) is made |
EXAMPLES: (testvectors from: http://radiogatun.noekeon.org/) |
========== |
>>> import python_RadioGatun |
radiogatun[64] |
--------------- |
>>> hasher = python_RadioGatun.new() |
>>> hasher.update('1234567890123456') |
>>> hasher.hexdigest() |
'caaec14b5b4a7960d6854709770e3071d635d60224f58aa385867e549ef4cc42' |
>>> hasher = python_RadioGatun.new() |
>>> hasher.update('Santa Barbara, California') |
>>> hasher.hexdigest() |
'0d08daf2354fa95aaa5b6a50f514384ecdd35940252e0631002e600e13cd285f' |
radiogatun[32] |
--------------- |
>>> hasher = python_RadioGatun.new(wl=32) |
>>> hasher.update('1234567890123456') |
>>> hasher.hexdigest() |
'59612324f3f42d3096e69125d2733b86143ae668ae9ed561ad785e0eac8dba25' |
>>> hasher = python_RadioGatun.new(wl=32) |
>>> hasher.update('Santa Barbara, California') |
>>> hasher.hexdigest() |
'041666388ef9655d48996a66dada1193d6646012a7b25a24fb10e6075cf0fc54' |
""" |
crypto = RadioGatunType(wl) |
if data: |
crypto.update(data) |
return crypto |
def _test(): |
import doctest |
doctest.testmod() |
if __name__ == "__main__": |
print "DOCTEST running... no messages = all good" |
_test() |
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Hash/pymd5.py |
---|
0,0 → 1,395 |
#!/usr/bin/env python |
# -*- coding: iso-8859-1 -*- |
# Note that PyPy contains also a built-in module 'md5' which will hide |
# this one if compiled in. |
"""A sample implementation of MD5 in pure Python. |
This is an implementation of the MD5 hash function, as specified by |
RFC 1321, in pure Python. It was implemented using Bruce Schneier's |
excellent book "Applied Cryptography", 2nd ed., 1996. |
Surely this is not meant to compete with the existing implementation |
of the Python standard library (written in C). Rather, it should be |
seen as a Python complement that is more readable than C and can be |
used more conveniently for learning and experimenting purposes in |
the field of cryptography. |
This module tries very hard to follow the API of the existing Python |
standard library's "md5" module, but although it seems to work fine, |
it has not been extensively tested! (But note that there is a test |
module, test_md5py.py, that compares this Python implementation with |
the C one of the Python standard library. |
BEWARE: this comes with no guarantee whatsoever about fitness and/or |
other properties! Specifically, do not use this in any production |
code! License is Python License! |
Special thanks to Aurelian Coman who fixed some nasty bugs! |
Dinu C. Gherman |
""" |
__date__ = '2004-11-17' |
__version__ = 0.91 # Modernised by J. Hallén and L. Creighton for Pypy |
__metaclass__ = type # or genrpy won't work |
import struct, copy |
# ====================================================================== |
# Bit-Manipulation helpers |
# ====================================================================== |
def _bytelist2long(list): |
"Transform a list of characters into a list of longs." |
imax = len(list)/4 |
hl = [0L] * imax |
j = 0 |
i = 0 |
while i < imax: |
b0 = long(ord(list[j])) |
b1 = (long(ord(list[j+1]))) << 8 |
b2 = (long(ord(list[j+2]))) << 16 |
b3 = (long(ord(list[j+3]))) << 24 |
hl[i] = b0 | b1 |b2 | b3 |
i = i+1 |
j = j+4 |
return hl |
def _rotateLeft(x, n): |
"Rotate x (32 bit) left n bits circularly." |
return (x << n) | (x >> (32-n)) |
# ====================================================================== |
# The real MD5 meat... |
# |
# Implemented after "Applied Cryptography", 2nd ed., 1996, |
# pp. 436-441 by Bruce Schneier. |
# ====================================================================== |
# F, G, H and I are basic MD5 functions. |
def F(x, y, z): |
return (x & y) | ((~x) & z) |
def G(x, y, z): |
return (x & z) | (y & (~z)) |
def H(x, y, z): |
return x ^ y ^ z |
def I(x, y, z): |
return y ^ (x | (~z)) |
def XX(func, a, b, c, d, x, s, ac): |
"""Wrapper for call distribution to functions F, G, H and I. |
This replaces functions FF, GG, HH and II from "Appl. Crypto." |
Rotation is separate from addition to prevent recomputation |
(now summed-up in one function). |
""" |
res = 0L |
res = res + a + func(b, c, d) |
res = res + x |
res = res + ac |
res = res & 0xffffffffL |
res = _rotateLeft(res, s) |
res = res & 0xffffffffL |
res = res + b |
return res & 0xffffffffL |
class MD5Type: |
"An implementation of the MD5 hash function in pure Python." |
def __init__(self): |
"Initialisation." |
# Initial message length in bits(!). |
self.length = 0L |
self.count = [0, 0] |
# Initial empty message as a sequence of bytes (8 bit characters). |
self.input = [] |
# Call a separate init function, that can be used repeatedly |
# to start from scratch on the same object. |
self.init() |
def init(self): |
"Initialize the message-digest and set all fields to zero." |
self.length = 0L |
self.count = [0, 0] |
self.input = [] |
# Load magic initialization constants. |
self.A = 0x67452301L |
self.B = 0xefcdab89L |
self.C = 0x98badcfeL |
self.D = 0x10325476L |
def _transform(self, inp): |
"""Basic MD5 step transforming the digest based on the input. |
Note that if the Mysterious Constants are arranged backwards |
in little-endian order and decrypted with the DES they produce |
OCCULT MESSAGES! |
""" |
a, b, c, d = A, B, C, D = self.A, self.B, self.C, self.D |
# Round 1. |
S11, S12, S13, S14 = 7, 12, 17, 22 |
a = XX(F, a, b, c, d, inp[ 0], S11, 0xD76AA478L) # 1 |
d = XX(F, d, a, b, c, inp[ 1], S12, 0xE8C7B756L) # 2 |
c = XX(F, c, d, a, b, inp[ 2], S13, 0x242070DBL) # 3 |
b = XX(F, b, c, d, a, inp[ 3], S14, 0xC1BDCEEEL) # 4 |
a = XX(F, a, b, c, d, inp[ 4], S11, 0xF57C0FAFL) # 5 |
d = XX(F, d, a, b, c, inp[ 5], S12, 0x4787C62AL) # 6 |
c = XX(F, c, d, a, b, inp[ 6], S13, 0xA8304613L) # 7 |
b = XX(F, b, c, d, a, inp[ 7], S14, 0xFD469501L) # 8 |
a = XX(F, a, b, c, d, inp[ 8], S11, 0x698098D8L) # 9 |
d = XX(F, d, a, b, c, inp[ 9], S12, 0x8B44F7AFL) # 10 |
c = XX(F, c, d, a, b, inp[10], S13, 0xFFFF5BB1L) # 11 |
b = XX(F, b, c, d, a, inp[11], S14, 0x895CD7BEL) # 12 |
a = XX(F, a, b, c, d, inp[12], S11, 0x6B901122L) # 13 |
d = XX(F, d, a, b, c, inp[13], S12, 0xFD987193L) # 14 |
c = XX(F, c, d, a, b, inp[14], S13, 0xA679438EL) # 15 |
b = XX(F, b, c, d, a, inp[15], S14, 0x49B40821L) # 16 |
# Round 2. |
S21, S22, S23, S24 = 5, 9, 14, 20 |
a = XX(G, a, b, c, d, inp[ 1], S21, 0xF61E2562L) # 17 |
d = XX(G, d, a, b, c, inp[ 6], S22, 0xC040B340L) # 18 |
c = XX(G, c, d, a, b, inp[11], S23, 0x265E5A51L) # 19 |
b = XX(G, b, c, d, a, inp[ 0], S24, 0xE9B6C7AAL) # 20 |
a = XX(G, a, b, c, d, inp[ 5], S21, 0xD62F105DL) # 21 |
d = XX(G, d, a, b, c, inp[10], S22, 0x02441453L) # 22 |
c = XX(G, c, d, a, b, inp[15], S23, 0xD8A1E681L) # 23 |
b = XX(G, b, c, d, a, inp[ 4], S24, 0xE7D3FBC8L) # 24 |
a = XX(G, a, b, c, d, inp[ 9], S21, 0x21E1CDE6L) # 25 |
d = XX(G, d, a, b, c, inp[14], S22, 0xC33707D6L) # 26 |
c = XX(G, c, d, a, b, inp[ 3], S23, 0xF4D50D87L) # 27 |
b = XX(G, b, c, d, a, inp[ 8], S24, 0x455A14EDL) # 28 |
a = XX(G, a, b, c, d, inp[13], S21, 0xA9E3E905L) # 29 |
d = XX(G, d, a, b, c, inp[ 2], S22, 0xFCEFA3F8L) # 30 |
c = XX(G, c, d, a, b, inp[ 7], S23, 0x676F02D9L) # 31 |
b = XX(G, b, c, d, a, inp[12], S24, 0x8D2A4C8AL) # 32 |
# Round 3. |
S31, S32, S33, S34 = 4, 11, 16, 23 |
a = XX(H, a, b, c, d, inp[ 5], S31, 0xFFFA3942L) # 33 |
d = XX(H, d, a, b, c, inp[ 8], S32, 0x8771F681L) # 34 |
c = XX(H, c, d, a, b, inp[11], S33, 0x6D9D6122L) # 35 |
b = XX(H, b, c, d, a, inp[14], S34, 0xFDE5380CL) # 36 |
a = XX(H, a, b, c, d, inp[ 1], S31, 0xA4BEEA44L) # 37 |
d = XX(H, d, a, b, c, inp[ 4], S32, 0x4BDECFA9L) # 38 |
c = XX(H, c, d, a, b, inp[ 7], S33, 0xF6BB4B60L) # 39 |
b = XX(H, b, c, d, a, inp[10], S34, 0xBEBFBC70L) # 40 |
a = XX(H, a, b, c, d, inp[13], S31, 0x289B7EC6L) # 41 |
d = XX(H, d, a, b, c, inp[ 0], S32, 0xEAA127FAL) # 42 |
c = XX(H, c, d, a, b, inp[ 3], S33, 0xD4EF3085L) # 43 |
b = XX(H, b, c, d, a, inp[ 6], S34, 0x04881D05L) # 44 |
a = XX(H, a, b, c, d, inp[ 9], S31, 0xD9D4D039L) # 45 |
d = XX(H, d, a, b, c, inp[12], S32, 0xE6DB99E5L) # 46 |
c = XX(H, c, d, a, b, inp[15], S33, 0x1FA27CF8L) # 47 |
b = XX(H, b, c, d, a, inp[ 2], S34, 0xC4AC5665L) # 48 |
# Round 4. |
S41, S42, S43, S44 = 6, 10, 15, 21 |
a = XX(I, a, b, c, d, inp[ 0], S41, 0xF4292244L) # 49 |
d = XX(I, d, a, b, c, inp[ 7], S42, 0x432AFF97L) # 50 |
c = XX(I, c, d, a, b, inp[14], S43, 0xAB9423A7L) # 51 |
b = XX(I, b, c, d, a, inp[ 5], S44, 0xFC93A039L) # 52 |
a = XX(I, a, b, c, d, inp[12], S41, 0x655B59C3L) # 53 |
d = XX(I, d, a, b, c, inp[ 3], S42, 0x8F0CCC92L) # 54 |
c = XX(I, c, d, a, b, inp[10], S43, 0xFFEFF47DL) # 55 |
b = XX(I, b, c, d, a, inp[ 1], S44, 0x85845DD1L) # 56 |
a = XX(I, a, b, c, d, inp[ 8], S41, 0x6FA87E4FL) # 57 |
d = XX(I, d, a, b, c, inp[15], S42, 0xFE2CE6E0L) # 58 |
c = XX(I, c, d, a, b, inp[ 6], S43, 0xA3014314L) # 59 |
b = XX(I, b, c, d, a, inp[13], S44, 0x4E0811A1L) # 60 |
a = XX(I, a, b, c, d, inp[ 4], S41, 0xF7537E82L) # 61 |
d = XX(I, d, a, b, c, inp[11], S42, 0xBD3AF235L) # 62 |
c = XX(I, c, d, a, b, inp[ 2], S43, 0x2AD7D2BBL) # 63 |
b = XX(I, b, c, d, a, inp[ 9], S44, 0xEB86D391L) # 64 |
A = (A + a) & 0xffffffffL |
B = (B + b) & 0xffffffffL |
C = (C + c) & 0xffffffffL |
D = (D + d) & 0xffffffffL |
self.A, self.B, self.C, self.D = A, B, C, D |
# Down from here all methods follow the Python Standard Library |
# API of the md5 module. |
def update(self, inBuf): |
"""Add to the current message. |
Update the md5 object with the string arg. Repeated calls |
are equivalent to a single call with the concatenation of all |
the arguments, i.e. m.update(a); m.update(b) is equivalent |
to m.update(a+b). |
The hash is immediately calculated for all full blocks. The final |
calculation is made in digest(). This allows us to keep an |
intermediate value for the hash, so that we only need to make |
minimal recalculation if we call update() to add moredata to |
the hashed string. |
""" |
leninBuf = long(len(inBuf)) |
# Compute number of bytes mod 64. |
index = (self.count[0] >> 3) & 0x3FL |
# Update number of bits. |
self.count[0] = self.count[0] + (leninBuf << 3) |
if self.count[0] < (leninBuf << 3): |
self.count[1] = self.count[1] + 1 |
self.count[1] = self.count[1] + (leninBuf >> 29) |
partLen = 64 - index |
if leninBuf >= partLen: |
self.input[index:] = list(inBuf[:partLen]) |
self._transform(_bytelist2long(self.input)) |
i = partLen |
while i + 63 < leninBuf: |
self._transform(_bytelist2long(list(inBuf[i:i+64]))) |
i = i + 64 |
else: |
self.input = list(inBuf[i:leninBuf]) |
else: |
i = 0 |
self.input = self.input + list(inBuf) |
def digest(self): |
"""Terminate the message-digest computation and return digest. |
Return the digest of the strings passed to the update() |
method so far. This is a 16-byte string which may contain |
non-ASCII characters, including null bytes. |
""" |
A = self.A |
B = self.B |
C = self.C |
D = self.D |
input = [] + self.input |
count = [] + self.count |
index = (self.count[0] >> 3) & 0x3fL |
if index < 56: |
padLen = 56 - index |
else: |
padLen = 120 - index |
padding = ['\200'] + ['\000'] * 63 |
self.update(padding[:padLen]) |
# Append length (before padding). |
bits = _bytelist2long(self.input[:56]) + count |
self._transform(bits) |
# Store state in digest. |
digest = struct.pack("<IIII", self.A, self.B, self.C, self.D) |
self.A = A |
self.B = B |
self.C = C |
self.D = D |
self.input = input |
self.count = count |
return digest |
def hexdigest(self): |
"""Terminate and return digest in HEX form. |
Like digest() except the digest is returned as a string of |
length 32, containing only hexadecimal digits. This may be |
used to exchange the value safely in email or other non- |
binary environments. |
""" |
return ''.join(['%02x' % ord(c) for c in self.digest()]) |
def copy(self): |
"""Return a clone object. |
Return a copy ('clone') of the md5 object. This can be used |
to efficiently compute the digests of strings that share |
a common initial substring. |
""" |
if 0: # set this to 1 to make the flow space crash |
return copy.deepcopy(self) |
clone = self.__class__() |
clone.length = self.length |
clone.count = [] + self.count[:] |
clone.input = [] + self.input |
clone.A = self.A |
clone.B = self.B |
clone.C = self.C |
clone.D = self.D |
return clone |
# ====================================================================== |
# Mimic Python top-level functions from standard library API |
# for consistency with the md5 module of the standard library. |
# ====================================================================== |
digest_size = 16 |
def new(arg=None): |
"""Return a new md5 crypto object. |
If arg is present, the method call update(arg) is made. |
""" |
crypto = MD5Type() |
if arg: |
crypto.update(arg) |
return crypto |
def md5(arg=None): |
"""Same as new(). |
For backward compatibility reasons, this is an alternative |
name for the new() function. |
""" |
return new(arg) |
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Hash/__init__.py |
---|
0,0 → 1,7 |
# hash functions of pycrypto can be just imported |
# wrapping might be a better idea if docstrings need to be expanded |
# wrapping in Cipher was needed to make the new chaining modes available |
from Crypto.Hash import SHA, SHA256, MD5, MD2, MD4, HMAC |
__all__ = ["SHA","SHA256","MD5","MD2","MD4","HMAC","RIPEMD"] |
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Hash/python_SHA512.py |
---|
0,0 → 1,30 |
from pysha512 import sha512 |
__all__ = ['new','digest_size'] |
def new(data=None): |
"""Create a new pure python SHA-512 hash object |
data = initial input (raw string) to the hashing object |
if present, the method call update(arg) is made |
EXAMPLE: FIPS 180-2 |
========= |
>>> from CryptoPlus.Hash import python_SHA512 |
>>> message = "abc" |
>>> hasher = python_SHA512.new() |
>>> hasher.update(message) |
>>> hasher.hexdigest() |
'ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f' |
>>> message = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" |
>>> hasher = python_SHA512.new() |
>>> hasher.update(message) |
>>> hasher.hexdigest() |
'8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909' |
""" |
return sha512(data) |
digest_size = sha512.digest_size |
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Hash/python_SHA224.py |
---|
0,0 → 1,30 |
from pysha224 import sha224 |
__all__ = ['new','digest_size'] |
def new(data=None): |
"""Create a new pure python SHA-224 hash object |
data = initial input (raw string) to the hashing object |
if present, the method call update(arg) is made |
EXAMPLE: FIPS 180-2 |
========= |
>>> from CryptoPlus.Hash import python_SHA224 |
>>> message = "abc" |
>>> hasher = python_SHA224.new() |
>>> hasher.update(message) |
>>> hasher.hexdigest() |
'23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7' |
>>> message = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" |
>>> hasher = python_SHA224.new() |
>>> hasher.update(message) |
>>> hasher.hexdigest() |
'75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525' |
""" |
return sha224(data) |
digest_size = sha224.digest_size |
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Hash/pyradiogatun.py |
---|
0,0 → 1,379 |
# ============================================================================= |
# Copyright (c) 2008 |
# Christophe Oosterlynck (christophe.oosterlynck_AT_gmail.com) |
# Philippe Teuwen (philippe.teuwen_AT_nxp.com) |
# |
# Permission is hereby granted, free of charge, to any person obtaining a copy |
# of this software and associated documentation files (the "Software"), to deal |
# in the Software without restriction, including without limitation the rights |
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
# copies of the Software, and to permit persons to whom the Software is |
# furnished to do so, subject to the following conditions: |
# |
# The above copyright notice and this permission notice shall be included in |
# all copies or substantial portions of the Software. |
# |
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
# THE SOFTWARE. |
# ============================================================================= |
"""RadioGatun pure python implementation |
Code based on the standard found here: http://radiogatun.noekeon.org/ |
Api and code interface is based on the MD5 implementation of pypy |
http://codespeak.net/pypy/dist/pypy/doc/home.html |
""" |
BELT_WIDTH = 3 |
BELT_LENGTH = 13 |
MILL_SIZE = 2*BELT_WIDTH + BELT_LENGTH |
NUMBER_OF_BLANK_ITERATIONS = 16 |
def state_init(): |
"""construct an empty state variable |
""" |
return {"A":[0]*MILL_SIZE, "B":[[0]*BELT_WIDTH for x in range(BELT_LENGTH)]} |
def XOR_F_i(state, inp, wl): |
"""Input mapping |
mapping input blocks to a state variable + XOR step of the alternating- |
input construction |
input = 1 blocklength string |
wl = wordlength of the RadioGatun hash object |
""" |
for i in xrange(BELT_WIDTH): |
# reverse endianness of byte ordering and convert the input |
# block to integer |
p_i = string2number(inp[i*wl:(i+1)*wl][::-1]) |
state["B"][0][i] ^= p_i |
state["A"][i+MILL_SIZE-BELT_WIDTH] ^= p_i |
return state |
def R(state, wl): |
"""Round function R |
state = the RadioGatun status |
wl = wordlength of the RadioGatun hash object |
""" |
out = state_init() |
# Belt function: simple rotation |
out["B"] = state["B"][-1:]+state["B"][:-1] |
# Mill to belt feedforward |
for i in xrange(BELT_LENGTH - 1): |
out["B"][i+1][i%BELT_WIDTH] ^= state["A"][i+1] |
# Run the mill |
out["A"] = Mill(state["A"], wl) |
# Belt to mill feedforward |
for i in xrange(BELT_WIDTH): |
out["A"][i+BELT_LENGTH] ^= state["B"][-1][i] |
return out |
def Mill(a, wl): |
"""The Mill function |
a = Mill variable of the RadioGatun status |
wl = wordlength of the RadioGatun hash object |
""" |
A = [0]*MILL_SIZE |
# Gamma: Non-linearity |
for i in xrange(MILL_SIZE): |
A[i] = a[i] ^ ~((~a[(i+1)%MILL_SIZE]) & (a[(i+2)%MILL_SIZE]) ) |
# Pi: Intra-word and inter-word dispersion |
for i in xrange(MILL_SIZE): |
a[i] = rotateRight(A[(7*i)%MILL_SIZE], i*(i+1)/2, wl*8) |
# Theta: Diffusion |
for i in xrange(MILL_SIZE): |
A[i] = a[i] ^ a[(i+1)%MILL_SIZE] ^ a[(i+4)%MILL_SIZE] |
# Iota: Asymmetry |
A[0] = A[0] ^ 1 |
return A |
class RadioGatunType: |
"An implementation of the RadioGatun hash function in pure Python." |
def __init__(self, wl): |
"""Initialisation. |
wl = wordlength (in bits) of the RadioGatun hash method |
between 8 and 64 (default = 64) |
""" |
if not ( 8 <= wl <= 64) or not (wl%8 == 0 ): |
raise ValueError, "Wordlength should be a multiple of 8" +\ |
" between 8 and 64" |
# word & block length in bytes |
self.wordlength = wl/8 |
self.blocklength = self.wordlength*BELT_WIDTH |
# Initial message length in bits(!). |
self.length = 0 |
self.count = 0 |
# Initial empty message as a sequence of bytes (8 bit characters). |
self.input = "" |
# Call a separate init function, that can be used repeatedly |
# to start from scratch on the same object. |
self.init() |
def init(self): |
"""Initialize the message-digest and set all fields to zero. |
Can be used to reinitialize the hash object |
""" |
self.S = state_init() |
self.length = 0 |
self.count = 0 |
self.input = "" |
def _transform(self, inp): |
"""Basic RadioGatun step transforming the digest based on the input. |
Performs the inside of the first loop of alternating input construction |
of RadioGatun. The only thing that can be done every time new data is |
submitted to the hash object. |
Mangling and output mapping can only follow when all input data has |
been received. |
""" |
T = XOR_F_i(self.S, inp, self.wordlength) |
self.S = R(T, self.wordlength) |
# Down from here all methods follow the Python Standard Library |
# API of the md5 module. |
def update(self, inBuf): |
"""Add to the current message. |
Update the radiogatun object with the string arg. Repeated calls |
are equivalent to a single call with the concatenation of all |
the arguments, i.e. m.update(a); m.update(b) is equivalent |
to m.update(a+b). |
The hash is immediately calculated for all full blocks. The final |
calculation is made in digest(). This allows us to keep an |
intermediate value for the hash, so that we only need to make |
minimal recalculation if we call update() to add moredata to |
the hashed string. |
""" |
# Amount of bytes given at input |
leninBuf = long(len(inBuf)) |
# Compute number of bytes mod 64. |
index = (self.count >> 3) % self.blocklength |
# Update number of bits. |
self.count = self.count + (leninBuf << 3) |
partLen = self.blocklength - index |
# if length of input is at least |
# the amount of bytes needed to fill a block |
if leninBuf >= partLen: |
self.input = self.input[:index] + inBuf[:partLen] |
self._transform(self.input) |
i = partLen |
while i + self.blocklength - 1 < leninBuf: |
self._transform(inBuf[i:i+self.blocklength]) |
i = i + self.blocklength |
else: |
self.input = inBuf[i:leninBuf] |
# if not enough bytes at input to fill a block |
else: |
i = 0 |
self.input = self.input + inBuf |
def digest(self, length=256): |
"""Terminate the message-digest computation and return digest. |
length = output length of the digest in bits |
any multiple of 8 with a minimum of 8 |
default = 256 |
Return the digest of the strings passed to the update() |
method so far. This is a byte string which may contain |
non-ASCII characters, including null bytes. |
Calling digest() doesn't change the internal state. Adding data via |
update() can still continu after asking for an intermediate digest |
value. |
""" |
S = self.S |
inp = "" + self.input |
count = self.count |
index = (self.count >> 3) % self.blocklength |
padLen = self.blocklength - index |
padding = ['\001'] + ['\000'] * (padLen - 1) |
self.update(''.join(padding)) |
# Mangling = blank rounds |
for i in xrange(NUMBER_OF_BLANK_ITERATIONS): |
self.S = R(self.S, self.wordlength) |
# Extraction |
# Store state in digest. |
digest = "" |
for i in xrange((length)/self.wordlength/2): |
self.S = R(self.S, self.wordlength) |
# F_o |
digest += \ |
number2string_N((self.S["A"][1]), self.wordlength)[::-1] +\ |
number2string_N((self.S["A"][2]), self.wordlength)[::-1] |
self.S = S |
self.input = inp |
self.count = count |
return digest[:length/8] |
def hexdigest(self, length=256): |
"""Terminate and return digest in HEX form. |
length = output length of the digest in bits |
any multiple of 8 with a minimum of 8 |
default = 256 |
Like digest() except the digest is returned as a string of |
length 'length', containing only hexadecimal digits. This may be |
used to exchange the value safely in email or other non- |
binary environments. |
Calling hexdigest() doesn't change the internal state. Adding data via |
update() can still continu after asking for an intermediate digest |
value. |
""" |
return ''.join(['%02x' % ord(c) for c in self.digest(length)]) |
def copy(self): |
"""Return a clone object. |
Return a copy ('clone') of the radiogatun object. This can be used |
to efficiently compute the digests of strings that share |
a common initial substring. |
""" |
import copy |
return copy.deepcopy(self) |
# ====================================================================== |
# TOP LEVEL INTERFACE |
# ====================================================================== |
def new(arg=None, wl=64): |
"""Return a new RadioGatun hash object |
wl = wordlength (in bits) of the RadioGatun hash method |
between 1 and 64 (default = 64) |
arg = if present, the method call update(arg) is made |
EXAMPLES: (testvectors from: http://radiogatun.noekeon.org/) |
========== |
>>> import pyradiogatun |
radiogatun[64] |
--------------- |
>>> hasher = pyradiogatun.new() |
>>> hasher.update('1234567890123456') |
>>> hasher.hexdigest() |
'caaec14b5b4a7960d6854709770e3071d635d60224f58aa385867e549ef4cc42' |
>>> hasher = pyradiogatun.new() |
>>> hasher.update('Santa Barbara, California') |
>>> hasher.hexdigest(480) |
'0d08daf2354fa95aaa5b6a50f514384ecdd35940252e0631002e600e13cd285f74adb0c0a666adeb1f2d20b1f2489e3d973dae4efc1f2cc5aaa13f2b' |
radiogatun[32] |
--------------- |
>>> hasher = pyradiogatun.new(wl=32) |
>>> hasher.update('1234567890123456') |
>>> hasher.hexdigest() |
'59612324f3f42d3096e69125d2733b86143ae668ae9ed561ad785e0eac8dba25' |
>>> hasher = pyradiogatun.new(wl=32) |
>>> hasher.update('Santa Barbara, California') |
>>> hasher.hexdigest(512) |
'041666388ef9655d48996a66dada1193d6646012a7b25a24fb10e6075cf0fc54a162949f4022531dbb6f66b64c3579df49f0f3af5951df9d68af310f2703b06d' |
radiogatun[16] |
--------------- |
>>> hasher = pyradiogatun.new(wl=16) |
>>> hasher.update('Santa Barbara, California') |
>>> hasher.hexdigest() |
'ab2203a8c3de943309b685513a29060339c001acce5900dcd6427a02c1fb8011' |
radiogatun[8] |
-------------- |
>>> hasher = pyradiogatun.new(wl=8) |
>>> hasher.update('Santa Barbara, California') |
>>> hasher.hexdigest() |
'e08f5cdbbfd8f5f3c479464a60ac186963e741d28f654e2c961d2f9bebc7de31' |
""" |
crypto = RadioGatunType(wl) |
if arg: |
crypto.update(arg) |
return crypto |
# ====================================================================== |
# HELPER FUNCTIONS |
# ====================================================================== |
def rotateRight(x, amountToShift, totalBits): |
"""Rotate x (consisting of 'totalBits' bits) n bits to right. |
x = integer input to be rotated |
amountToShift = the amount of bits that should be shifted |
totalBits = total amount bits at the input for rotation |
""" |
x = x%(2**totalBits) |
n_mod = ((amountToShift % totalBits) + totalBits) % totalBits |
return ((x >> n_mod) | ((x << (totalBits-n_mod)))&((2**totalBits)-1)) |
def string2number(i): |
""" Convert a string to a number |
Input: string (big-endian) |
Output: long or integer |
""" |
return int(i.encode('hex'), 16) |
def number2string_N(i, N): |
"""Convert a number to a string of fixed size |
i: long or integer |
N: length of string |
Output: string (big-endian) |
""" |
s = '%0*x' % (N*2, i) |
return s.decode('hex') |
# ====================================================================== |
# DOCTEST ENABLER |
# ====================================================================== |
def _test(): |
import doctest |
doctest.testmod() |
if __name__ == "__main__": |
print "DOCTEST running... no messages = all good" |
_test() |
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Hash/python_PBKDF2.py |
---|
0,0 → 1,55 |
import pypbkdf2 |
from CryptoPlus.Hash import SHA as SHA1, HMAC |
__all__ = ['new'] |
def new(passphrase, salt, iterations=1000, digestmodule=SHA1, macmodule=HMAC): |
"""PKCS#5 v2.0 Password-Based Key Derivation |
passphrase = the passphrase, supplied as a raw string, to make a key from |
salt = salt as raw string |
iterations = amount of iterations (default = 1000) |
digestmodule = digest function to use, supply as module |
example: python_SHA from CryptoPlus.Hash |
default: SHA1 |
macmodule = mac function to use, supply as module |
example: HMAC from CryptoPlus.Hash |
default: HMAC |
=> macmodule & digestmodule construct the pseudorandom function |
=> by default: HMAC-SHA1 |
Examples: (from: http://www.ietf.org/rfc/rfc3962.txt) |
========== |
>>> from CryptoPlus.Hash import python_PBKDF2 |
>>> passphrase = "password" |
>>> salt = "ATHENA.MIT.EDUraeburn" |
>>> iterations = 1 |
>>> hasher = python_PBKDF2.new(passphrase,salt,iterations) |
>>> hasher.hexread(16) |
'cdedb5281bb2f801565a1122b2563515' |
>>> passphrase = "password" |
>>> salt = "ATHENA.MIT.EDUraeburn" |
>>> iterations = 1200 |
>>> hasher = python_PBKDF2.new(passphrase,salt,iterations) |
>>> hasher.hexread(32) |
'5c08eb61fdf71e4e4ec3cf6ba1f5512ba7e52ddbc5e5142f708a31e2e62b1e13' |
>>> passphrase = "X"*64 |
>>> salt = "pass phrase equals block size" |
>>> iterations = 1200 |
>>> hasher = python_PBKDF2.new(passphrase,salt,iterations) |
>>> hasher.hexread(32) |
'139c30c0966bc32ba55fdbf212530ac9c5ec59f1a452f5cc9ad940fea0598ed1' |
>>> passphrase = "X"*65 |
>>> salt = "pass phrase exceeds block size" |
>>> iterations = 1200 |
>>> hasher = python_PBKDF2.new(passphrase,salt,iterations) |
>>> hasher.hexread(32) |
'9ccad6d468770cd51b10e6a68721be611a8b4d282601db3b36be9246915ec82a' |
""" |
return pypbkdf2.PBKDF2(passphrase, salt, iterations, digestmodule, macmodule) |
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Hash/python_SHA256.py |
---|
0,0 → 1,30 |
from pysha256 import sha256 |
__all__ = ['new','digest_size'] |
def new(data=None): |
"""Create a new pure python SHA-256 hash object |
data = initial input (raw string) to the hashing object |
if present, the method call update(arg) is made |
EXAMPLE: FIPS 180-2 |
========= |
>>> from CryptoPlus.Hash import python_SHA256 |
>>> message = "abc" |
>>> hasher = python_SHA256.new() |
>>> hasher.update(message) |
>>> hasher.hexdigest() |
'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad' |
>>> message = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" |
>>> hasher = python_SHA256.new() |
>>> hasher.update(message) |
>>> hasher.hexdigest() |
'248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1' |
""" |
return sha256(data) |
digest_size = sha256.digest_size |
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Hash/python_SHA384.py |
---|
0,0 → 1,30 |
from pysha384 import sha384 |
__all__ = ['new','digest_size'] |
def new(data=None): |
"""Create a new pure python SHA-384 hash object |
data = initial input (raw string) to the hashing object |
if present, the method call update(arg) is made |
EXAMPLE: FIPS 180-2 |
========= |
>>> from CryptoPlus.Hash import python_SHA384 |
>>> message = "abc" |
>>> hasher = python_SHA384.new() |
>>> hasher.update(message) |
>>> hasher.hexdigest() |
'cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7' |
>>> message = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" |
>>> hasher = python_SHA384.new() |
>>> hasher.update(message) |
>>> hasher.hexdigest() |
'09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039' |
""" |
return sha384(data) |
digest_size = sha384.digest_size |
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Hash/pysha224.py |
---|
0,0 → 1,14 |
+ digest_size = 28 |
\ No newline at end of file |
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Hash/pysha512.py |
---|
0,0 → 1,111 |
+ |
+ return copy.deepcopy(self) |
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Hash/python_SHA.py |
---|
0,0 → 1,30 |
import pysha |
__all__ = ['new','digest_size'] |
def new(data=None): |
"""Create a new pure python SHA hash object |
data = initial input (raw string) to the hashing object |
if present, the method call update(arg) is made |
EXAMPLE: FIPS 180-2 |
========= |
>>> from CryptoPlus.Hash import python_SHA |
>>> message = "abc" |
>>> hasher = python_SHA.new() |
>>> hasher.update(message) |
>>> hasher.hexdigest() |
'a9993e364706816aba3e25717850c26c9cd0d89d' |
>>> message = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" |
>>> hasher = python_SHA.new() |
>>> hasher.update(message) |
>>> hasher.hexdigest() |
'84983e441c3bd26ebaae4aa1f95129e5e54670f1' |
""" |
return pysha.new(data) |
digest_size = pysha.digest_size |
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Hash/python_whirlpool.py |
---|
0,0 → 1,30 |
import pywhirlpool |
__all__ = ['new','digest_size'] |
def new(data=None): |
"""Create a new pure python Whirlpool hash object |
data = initial input (raw string) to the hashing object |
if present, the method call update(arg) is made |
EXAMPLE: (http://paginas.terra.com.br/informatica/paulobarreto/WhirlpoolPage.html) |
========= |
>>> from CryptoPlus.Hash import python_whirlpool |
>>> message = "abc" |
>>> hasher = python_whirlpool.new() |
>>> hasher.update(message) |
>>> hasher.hexdigest().upper() |
'4E2448A4C6F486BB16B6562C73B4020BF3043E3A731BCE721AE1B303D97E6D4C7181EEBDB6C57E277D0E34957114CBD6C797FC9D95D8B582D225292076D4EEF5' |
>>> message = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" |
>>> hasher = python_whirlpool.new() |
>>> hasher.update(message) |
>>> hasher.hexdigest().upper() |
'DC37E008CF9EE69BF11F00ED9ABA26901DD7C28CDEC066CC6AF42E40F82F3A1E08EBA26629129D8FB7CB57211B9281A65517CC879D7B962142C65F5A7AF01467' |
""" |
return pywhirlpool.new(data) |
digest_size = pywhirlpool.digest_size |
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Hash/RIPEMD.py |
---|
0,0 → 1,26 |
from Crypto.Hash import RIPEMD |
def new(data=None): |
"""Create a new RIPEMD-160 hash object |
data = initial input (raw string) to the hashing object |
if present, the method call update(arg) is made |
EXAMPLE: |
========= |
>>> from CryptoPlus.Hash import RIPEMD |
>>> message = "abc" |
>>> hasher = RIPEMD.new() |
>>> hasher.update(message) |
>>> hasher.hexdigest() |
'8eb208f7e05d987a9b044a8e98c6b087f15a0bfc' |
>>> message = "message digest" |
>>> hasher = RIPEMD.new() |
>>> hasher.update(message) |
>>> hasher.hexdigest() |
'5d0689ef49d2fae572b881b123a85ffa21595f36' |
""" |
return RIPEMD.new(data) |
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Hash/pypbkdf2.py |
---|
0,0 → 1,354 |
#!/usr/bin/python |
# -*- coding: ascii -*- |
########################################################################### |
# PBKDF2.py - PKCS#5 v2.0 Password-Based Key Derivation |
# |
# Copyright (C) 2007, 2008 Dwayne C. Litzenberger <dlitz@dlitz.net> |
# All rights reserved. |
# |
# Permission to use, copy, modify, and distribute this software and its |
# documentation for any purpose and without fee is hereby granted, |
# provided that the above copyright notice appear in all copies and that |
# both that copyright notice and this permission notice appear in |
# supporting documentation. |
# |
# THE AUTHOR PROVIDES THIS SOFTWARE ``AS IS'' AND ANY EXPRESSED OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
# Country of origin: Canada |
# |
########################################################################### |
# Sample PBKDF2 usage: |
# from Crypto.Cipher import AES |
# from PBKDF2 import PBKDF2 |
# import os |
# |
# salt = os.urandom(8) # 64-bit salt |
# key = PBKDF2("This passphrase is a secret.", salt).read(32) # 256-bit key |
# iv = os.urandom(16) # 128-bit IV |
# cipher = AES.new(key, AES.MODE_CBC, iv) |
# ... |
# |
# Sample crypt() usage: |
# from PBKDF2 import crypt |
# pwhash = crypt("secret") |
# alleged_pw = raw_input("Enter password: ") |
# if pwhash == crypt(alleged_pw, pwhash): |
# print "Password good" |
# else: |
# print "Invalid password" |
# |
########################################################################### |
# History: |
# |
# 2007-07-27 Dwayne C. Litzenberger <dlitz@dlitz.net> |
# - Initial Release (v1.0) |
# |
# 2007-07-31 Dwayne C. Litzenberger <dlitz@dlitz.net> |
# - Bugfix release (v1.1) |
# - SECURITY: The PyCrypto XOR cipher (used, if available, in the _strxor |
# function in the previous release) silently truncates all keys to 64 |
# bytes. The way it was used in the previous release, this would only be |
# problem if the pseudorandom function that returned values larger than |
# 64 bytes (so SHA1, SHA256 and SHA512 are fine), but I don't like |
# anything that silently reduces the security margin from what is |
# expected. |
# |
# 2008-06-17 Dwayne C. Litzenberger <dlitz@dlitz.net> |
# - Compatibility release (v1.2) |
# - Add support for older versions of Python (2.2 and 2.3). |
# |
########################################################################### |
__version__ = "1.2" |
from struct import pack |
from binascii import b2a_hex |
from random import randint |
import string |
try: |
# Use PyCrypto (if available) |
from Crypto.Hash import HMAC, SHA as SHA1 |
except ImportError: |
# PyCrypto not available. Use the Python standard library. |
import hmac as HMAC |
import sha as SHA1 |
def strxor(a, b): |
return "".join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a, b)]) |
def b64encode(data, chars="+/"): |
tt = string.maketrans("+/", chars) |
return data.encode('base64').replace("\n", "").translate(tt) |
class PBKDF2(object): |
"""PBKDF2.py : PKCS#5 v2.0 Password-Based Key Derivation |
This implementation takes a passphrase and a salt (and optionally an |
iteration count, a digest module, and a MAC module) and provides a |
file-like object from which an arbitrarily-sized key can be read. |
If the passphrase and/or salt are unicode objects, they are encoded as |
UTF-8 before they are processed. |
The idea behind PBKDF2 is to derive a cryptographic key from a |
passphrase and a salt. |
PBKDF2 may also be used as a strong salted password hash. The |
'crypt' function is provided for that purpose. |
Remember: Keys generated using PBKDF2 are only as strong as the |
passphrases they are derived from. |
""" |
def __init__(self, passphrase, salt, iterations=1000, |
digestmodule=SHA1, macmodule=HMAC): |
self.__macmodule = macmodule |
self.__digestmodule = digestmodule |
self._setup(passphrase, salt, iterations, self._pseudorandom) |
def _pseudorandom(self, key, msg): |
"""Pseudorandom function. e.g. HMAC-SHA1""" |
return self.__macmodule.new(key=key, msg=msg, |
digestmod=self.__digestmodule).digest() |
def read(self, bytes): |
"""Read the specified number of key bytes.""" |
if self.closed: |
raise ValueError("file-like object is closed") |
size = len(self.__buf) |
blocks = [self.__buf] |
i = self.__blockNum |
while size < bytes: |
i += 1 |
if i > 0xffffffffL or i < 1: |
# We could return "" here, but |
raise OverflowError("derived key too long") |
block = self.__f(i) |
blocks.append(block) |
size += len(block) |
buf = "".join(blocks) |
retval = buf[:bytes] |
self.__buf = buf[bytes:] |
self.__blockNum = i |
return retval |
def __f(self, i): |
# i must fit within 32 bits |
assert 1 <= i <= 0xffffffffL |
U = self.__prf(self.__passphrase, self.__salt + pack("!L", i)) |
result = U |
for j in xrange(2, 1+self.__iterations): |
U = self.__prf(self.__passphrase, U) |
result = strxor(result, U) |
return result |
def hexread(self, octets): |
"""Read the specified number of octets. Return them as hexadecimal. |
Note that len(obj.hexread(n)) == 2*n. |
""" |
return b2a_hex(self.read(octets)) |
def _setup(self, passphrase, salt, iterations, prf): |
# Sanity checks: |
# passphrase and salt must be str or unicode (in the latter |
# case, we convert to UTF-8) |
if isinstance(passphrase, unicode): |
passphrase = passphrase.encode("UTF-8") |
if not isinstance(passphrase, str): |
raise TypeError("passphrase must be str or unicode") |
if isinstance(salt, unicode): |
salt = salt.encode("UTF-8") |
if not isinstance(salt, str): |
raise TypeError("salt must be str or unicode") |
# iterations must be an integer >= 1 |
if not isinstance(iterations, (int, long)): |
raise TypeError("iterations must be an integer") |
if iterations < 1: |
raise ValueError("iterations must be at least 1") |
# prf must be callable |
if not callable(prf): |
raise TypeError("prf must be callable") |
self.__passphrase = passphrase |
self.__salt = salt |
self.__iterations = iterations |
self.__prf = prf |
self.__blockNum = 0 |
self.__buf = "" |
self.closed = False |
def close(self): |
"""Close the stream.""" |
if not self.closed: |
del self.__passphrase |
del self.__salt |
del self.__iterations |
del self.__prf |
del self.__blockNum |
del self.__buf |
self.closed = True |
def crypt(word, salt=None, iterations=None): |
"""PBKDF2-based unix crypt(3) replacement. |
The number of iterations specified in the salt overrides the 'iterations' |
parameter. |
The effective hash length is 192 bits. |
""" |
# Generate a (pseudo-)random salt if the user hasn't provided one. |
if salt is None: |
salt = _makesalt() |
# salt must be a string or the us-ascii subset of unicode |
if isinstance(salt, unicode): |
salt = salt.encode("us-ascii") |
if not isinstance(salt, str): |
raise TypeError("salt must be a string") |
# word must be a string or unicode (in the latter case, we convert to UTF-8) |
if isinstance(word, unicode): |
word = word.encode("UTF-8") |
if not isinstance(word, str): |
raise TypeError("word must be a string or unicode") |
# Try to extract the real salt and iteration count from the salt |
if salt.startswith("$p5k2$"): |
(iterations, salt, dummy) = salt.split("$")[2:5] |
if iterations == "": |
iterations = 400 |
else: |
converted = int(iterations, 16) |
if iterations != "%x" % converted: # lowercase hex, minimum digits |
raise ValueError("Invalid salt") |
iterations = converted |
if not (iterations >= 1): |
raise ValueError("Invalid salt") |
# Make sure the salt matches the allowed character set |
allowed = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./" |
for ch in salt: |
if ch not in allowed: |
raise ValueError("Illegal character %r in salt" % (ch,)) |
if iterations is None or iterations == 400: |
iterations = 400 |
salt = "$p5k2$$" + salt |
else: |
salt = "$p5k2$%x$%s" % (iterations, salt) |
rawhash = PBKDF2(word, salt, iterations).read(24) |
return salt + "$" + b64encode(rawhash, "./") |
# Add crypt as a static method of the PBKDF2 class |
# This makes it easier to do "from PBKDF2 import PBKDF2" and still use |
# crypt. |
PBKDF2.crypt = staticmethod(crypt) |
def _makesalt(): |
"""Return a 48-bit pseudorandom salt for crypt(). |
This function is not suitable for generating cryptographic secrets. |
""" |
binarysalt = "".join([pack("@H", randint(0, 0xffff)) for i in range(3)]) |
return b64encode(binarysalt, "./") |
def test_pbkdf2(): |
"""Module self-test""" |
from binascii import a2b_hex |
# |
# Test vectors from RFC 3962 |
# |
# Test 1 |
result = PBKDF2("password", "ATHENA.MIT.EDUraeburn", 1).read(16) |
expected = a2b_hex("cdedb5281bb2f801565a1122b2563515") |
if result != expected: |
raise RuntimeError("self-test failed") |
# Test 2 |
result = PBKDF2("password", "ATHENA.MIT.EDUraeburn", 1200).hexread(32) |
expected = ("5c08eb61fdf71e4e4ec3cf6ba1f5512b" |
"a7e52ddbc5e5142f708a31e2e62b1e13") |
if result != expected: |
raise RuntimeError("self-test failed") |
# Test 3 |
result = PBKDF2("X"*64, "pass phrase equals block size", 1200).hexread(32) |
expected = ("139c30c0966bc32ba55fdbf212530ac9" |
"c5ec59f1a452f5cc9ad940fea0598ed1") |
if result != expected: |
raise RuntimeError("self-test failed") |
# Test 4 |
result = PBKDF2("X"*65, "pass phrase exceeds block size", 1200).hexread(32) |
expected = ("9ccad6d468770cd51b10e6a68721be61" |
"1a8b4d282601db3b36be9246915ec82a") |
if result != expected: |
raise RuntimeError("self-test failed") |
# |
# Other test vectors |
# |
# Chunked read |
f = PBKDF2("kickstart", "workbench", 256) |
result = f.read(17) |
result += f.read(17) |
result += f.read(1) |
result += f.read(2) |
result += f.read(3) |
expected = PBKDF2("kickstart", "workbench", 256).read(40) |
if result != expected: |
raise RuntimeError("self-test failed") |
# |
# crypt() test vectors |
# |
# crypt 1 |
result = crypt("cloadm", "exec") |
expected = '$p5k2$$exec$r1EWMCMk7Rlv3L/RNcFXviDefYa0hlql' |
if result != expected: |
raise RuntimeError("self-test failed") |
# crypt 2 |
result = crypt("gnu", '$p5k2$c$u9HvcT4d$.....') |
expected = '$p5k2$c$u9HvcT4d$Sd1gwSVCLZYAuqZ25piRnbBEoAesaa/g' |
if result != expected: |
raise RuntimeError("self-test failed") |
# crypt 3 |
result = crypt("dcl", "tUsch7fU", iterations=13) |
expected = "$p5k2$d$tUsch7fU$nqDkaxMDOFBeJsTSfABsyn.PYUXilHwL" |
if result != expected: |
raise RuntimeError("self-test failed") |
# crypt 4 (unicode) |
result = crypt(u'\u0399\u03c9\u03b1\u03bd\u03bd\u03b7\u03c2', |
'$p5k2$$KosHgqNo$9mjN8gqjt02hDoP0c2J0ABtLIwtot8cQ') |
expected = '$p5k2$$KosHgqNo$9mjN8gqjt02hDoP0c2J0ABtLIwtot8cQ' |
if result != expected: |
raise RuntimeError("self-test failed") |
if __name__ == '__main__': |
test_pbkdf2() |
# vim:set ts=4 sw=4 sts=4 expandtab: |
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Hash/pysha256.py |
---|
0,0 → 1,107 |
+ |
+ return copy.deepcopy(self) |
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Hash/pysha384.py |
---|
0,0 → 1,14 |
+ digest_size = 48 |
\ No newline at end of file |
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Hash/pysha.py |
---|
0,0 → 1,349 |
#!/usr/bin/env python |
# -*- coding: iso-8859-1 |
# Note that PyPy contains also a built-in module 'sha' which will hide |
# this one if compiled in. |
"""A sample implementation of SHA-1 in pure Python. |
Framework adapted from Dinu Gherman's MD5 implementation by |
J. Hallén and L. Creighton. SHA-1 implementation based directly on |
the text of the NIST standard FIPS PUB 180-1. |
""" |
__date__ = '2004-11-17' |
__version__ = 0.91 # Modernised by J. Hallén and L. Creighton for Pypy |
import struct, copy |
# ====================================================================== |
# Bit-Manipulation helpers |
# |
# _long2bytes() was contributed by Barry Warsaw |
# and is reused here with tiny modifications. |
# ====================================================================== |
def _long2bytesBigEndian(n, blocksize=0): |
"""Convert a long integer to a byte string. |
If optional blocksize is given and greater than zero, pad the front |
of the byte string with binary zeros so that the length is a multiple |
of blocksize. |
""" |
# After much testing, this algorithm was deemed to be the fastest. |
s = '' |
pack = struct.pack |
while n > 0: |
s = pack('>I', n & 0xffffffffL) + s |
n = n >> 32 |
# Strip off leading zeros. |
for i in range(len(s)): |
if s[i] <> '\000': |
break |
else: |
# Only happens when n == 0. |
s = '\000' |
i = 0 |
s = s[i:] |
# Add back some pad bytes. This could be done more efficiently |
# w.r.t. the de-padding being done above, but sigh... |
if blocksize > 0 and len(s) % blocksize: |
s = (blocksize - len(s) % blocksize) * '\000' + s |
return s |
def _bytelist2longBigEndian(list): |
"Transform a list of characters into a list of longs." |
imax = len(list)/4 |
hl = [0L] * imax |
j = 0 |
i = 0 |
while i < imax: |
b0 = long(ord(list[j])) << 24 |
b1 = long(ord(list[j+1])) << 16 |
b2 = long(ord(list[j+2])) << 8 |
b3 = long(ord(list[j+3])) |
hl[i] = b0 | b1 | b2 | b3 |
i = i+1 |
j = j+4 |
return hl |
def _rotateLeft(x, n): |
"Rotate x (32 bit) left n bits circularly." |
return (x << n) | (x >> (32-n)) |
# ====================================================================== |
# The SHA transformation functions |
# |
# ====================================================================== |
def f0_19(B, C, D): |
return (B & C) | ((~ B) & D) |
def f20_39(B, C, D): |
return B ^ C ^ D |
def f40_59(B, C, D): |
return (B & C) | (B & D) | (C & D) |
def f60_79(B, C, D): |
return B ^ C ^ D |
f = [f0_19, f20_39, f40_59, f60_79] |
# Constants to be used |
K = [ |
0x5A827999L, # ( 0 <= t <= 19) |
0x6ED9EBA1L, # (20 <= t <= 39) |
0x8F1BBCDCL, # (40 <= t <= 59) |
0xCA62C1D6L # (60 <= t <= 79) |
] |
class sha: |
"An implementation of the MD5 hash function in pure Python." |
def __init__(self): |
"Initialisation." |
# Initial message length in bits(!). |
self.length = 0L |
self.count = [0, 0] |
# Initial empty message as a sequence of bytes (8 bit characters). |
self.input = [] |
# Call a separate init function, that can be used repeatedly |
# to start from scratch on the same object. |
self.init() |
def init(self): |
"Initialize the message-digest and set all fields to zero." |
self.length = 0L |
self.input = [] |
# Initial 160 bit message digest (5 times 32 bit). |
self.H0 = 0x67452301L |
self.H1 = 0xEFCDAB89L |
self.H2 = 0x98BADCFEL |
self.H3 = 0x10325476L |
self.H4 = 0xC3D2E1F0L |
def _transform(self, W): |
for t in range(16, 80): |
W.append(_rotateLeft( |
W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1) & 0xffffffffL) |
A = self.H0 |
B = self.H1 |
C = self.H2 |
D = self.H3 |
E = self.H4 |
""" |
This loop was unrolled to gain about 10% in speed |
for t in range(0, 80): |
TEMP = _rotateLeft(A, 5) + f[t/20] + E + W[t] + K[t/20] |
E = D |
D = C |
C = _rotateLeft(B, 30) & 0xffffffffL |
B = A |
A = TEMP & 0xffffffffL |
""" |
for t in range(0, 20): |
TEMP = _rotateLeft(A, 5) + ((B & C) | ((~ B) & D)) + E + W[t] + K[0] |
E = D |
D = C |
C = _rotateLeft(B, 30) & 0xffffffffL |
B = A |
A = TEMP & 0xffffffffL |
for t in range(20, 40): |
TEMP = _rotateLeft(A, 5) + (B ^ C ^ D) + E + W[t] + K[1] |
E = D |
D = C |
C = _rotateLeft(B, 30) & 0xffffffffL |
B = A |
A = TEMP & 0xffffffffL |
for t in range(40, 60): |
TEMP = _rotateLeft(A, 5) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2] |
E = D |
D = C |
C = _rotateLeft(B, 30) & 0xffffffffL |
B = A |
A = TEMP & 0xffffffffL |
for t in range(60, 80): |
TEMP = _rotateLeft(A, 5) + (B ^ C ^ D) + E + W[t] + K[3] |
E = D |
D = C |
C = _rotateLeft(B, 30) & 0xffffffffL |
B = A |
A = TEMP & 0xffffffffL |
self.H0 = (self.H0 + A) & 0xffffffffL |
self.H1 = (self.H1 + B) & 0xffffffffL |
self.H2 = (self.H2 + C) & 0xffffffffL |
self.H3 = (self.H3 + D) & 0xffffffffL |
self.H4 = (self.H4 + E) & 0xffffffffL |
# Down from here all methods follow the Python Standard Library |
# API of the sha module. |
def update(self, inBuf): |
"""Add to the current message. |
Update the md5 object with the string arg. Repeated calls |
are equivalent to a single call with the concatenation of all |
the arguments, i.e. m.update(a); m.update(b) is equivalent |
to m.update(a+b). |
The hash is immediately calculated for all full blocks. The final |
calculation is made in digest(). It will calculate 1-2 blocks, |
depending on how much padding we have to add. This allows us to |
keep an intermediate value for the hash, so that we only need to |
make minimal recalculation if we call update() to add more data |
to the hashed string. |
""" |
leninBuf = long(len(inBuf)) |
# Compute number of bytes mod 64. |
index = (self.count[1] >> 3) & 0x3FL |
# Update number of bits. |
self.count[1] = self.count[1] + (leninBuf << 3) |
if self.count[1] < (leninBuf << 3): |
self.count[0] = self.count[0] + 1 |
self.count[0] = self.count[0] + (leninBuf >> 29) |
partLen = 64 - index |
if leninBuf >= partLen: |
self.input[index:] = list(inBuf[:partLen]) |
self._transform(_bytelist2longBigEndian(self.input)) |
i = partLen |
while i + 63 < leninBuf: |
self._transform(_bytelist2longBigEndian(list(inBuf[i:i+64]))) |
i = i + 64 |
else: |
self.input = list(inBuf[i:leninBuf]) |
else: |
i = 0 |
self.input = self.input + list(inBuf) |
def digest(self): |
"""Terminate the message-digest computation and return digest. |
Return the digest of the strings passed to the update() |
method so far. This is a 16-byte string which may contain |
non-ASCII characters, including null bytes. |
""" |
H0 = self.H0 |
H1 = self.H1 |
H2 = self.H2 |
H3 = self.H3 |
H4 = self.H4 |
input = [] + self.input |
count = [] + self.count |
index = (self.count[1] >> 3) & 0x3fL |
if index < 56: |
padLen = 56 - index |
else: |
padLen = 120 - index |
padding = ['\200'] + ['\000'] * 63 |
self.update(padding[:padLen]) |
# Append length (before padding). |
bits = _bytelist2longBigEndian(self.input[:56]) + count |
self._transform(bits) |
# Store state in digest. |
digest = _long2bytesBigEndian(self.H0, 4) + \ |
_long2bytesBigEndian(self.H1, 4) + \ |
_long2bytesBigEndian(self.H2, 4) + \ |
_long2bytesBigEndian(self.H3, 4) + \ |
_long2bytesBigEndian(self.H4, 4) |
self.H0 = H0 |
self.H1 = H1 |
self.H2 = H2 |
self.H3 = H3 |
self.H4 = H4 |
self.input = input |
self.count = count |
return digest |
def hexdigest(self): |
"""Terminate and return digest in HEX form. |
Like digest() except the digest is returned as a string of |
length 32, containing only hexadecimal digits. This may be |
used to exchange the value safely in email or other non- |
binary environments. |
""" |
return ''.join(['%02x' % ord(c) for c in self.digest()]) |
def copy(self): |
"""Return a clone object. |
Return a copy ('clone') of the md5 object. This can be used |
to efficiently compute the digests of strings that share |
a common initial substring. |
""" |
return copy.deepcopy(self) |
# ====================================================================== |
# Mimic Python top-level functions from standard library API |
# for consistency with the md5 module of the standard library. |
# ====================================================================== |
# These are mandatory variables in the module. They have constant values |
# in the SHA standard. |
digest_size = digestsize = 20 |
blocksize = 1 |
def new(arg=None): |
"""Return a new sha crypto object. |
If arg is present, the method call update(arg) is made. |
""" |
crypto = sha() |
if arg: |
crypto.update(arg) |
return crypto |
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Hash/python_MD5.py |
---|
0,0 → 1,30 |
import pymd5 |
__all__ = ['new','digest_size'] |
def new(data=None): |
"""Create a new pure python MD5 hash object |
data = initial input (raw string) to the hashing object |
if present, the method call update(arg) is made |
EXAMPLE: (http://www.rfc-editor.org/rfc/rfc1321.txt) |
========= |
>>> from CryptoPlus.Hash import MD5 |
>>> message = "abc" |
>>> hasher = MD5.new() |
>>> hasher.update(message) |
>>> hasher.hexdigest() |
'900150983cd24fb0d6963f7d28e17f72' |
>>> message = "message digest" |
>>> hasher = MD5.new() |
>>> hasher.update(message) |
>>> hasher.hexdigest() |
'f96b697d7cb7938d525a2f31aaf161d0' |
""" |
return pymd5.new(data) |
digest_size = pymd5.digest_size |
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Hash/pywhirlpool.py |
---|
0,0 → 1,795 |
## whirlpool.py - pure Python implementation of the Whirlpool algorithm. |
## Bjorn Edstrom <be@bjrn.se> 16 december 2007. |
## |
## Copyrights |
## ========== |
## |
## This code is based on the reference implementation by |
## Paulo S.L.M. Barreto and Vincent Rijmen. The reference implementation |
## is placed in the public domain but has the following headers: |
## |
## * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS |
## * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
## * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
## * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE |
## * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
## * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
## * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
## * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
## * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
## * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |
## * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
## * |
## */ |
## /* The code contained in this file (Whirlpool.c) is in the public domain. */ |
## |
## This Python implementation is therefore also placed in the public domain. |
try: |
import psyco |
psyco.full() |
except ImportError: |
pass |
#block_size = 64 |
digest_size = 64 |
digestsize = 64 |
class Whirlpool: |
"""Return a new Whirlpool object. An optional string argument |
may be provided; if present, this string will be automatically |
hashed.""" |
def __init__(self, arg=None): |
self.ctx = WhirlpoolStruct() |
if arg: |
self.update(arg) |
self.digest_status = 0 |
def update(self, arg): |
"""update(arg)""" |
WhirlpoolAdd(arg, len(arg)*8, self.ctx) |
self.digest_status = 0 |
def digest(self): |
"""digest()""" |
if self.digest_status == 0: |
self.dig = WhirlpoolFinalize(self.ctx) |
self.digest_status = 1 |
return self.dig |
def hexdigest(self): |
"""hexdigest()""" |
dig = self.digest() |
tempstr = '' |
for d in dig: |
xxx = '%02x' % (ord(d)) |
tempstr = tempstr + xxx |
return tempstr |
def copy(self): |
"""copy()""" |
import copy |
return copy.deepcopy(self) |
def new(init=None): |
"""Return a new Whirlpool object. An optional string argument |
may be provided; if present, this string will be automatically |
hashed.""" |
return Whirlpool(init) |
# |
# Private. |
# |
R = 10 |
C0 = [ |
0x18186018c07830d8, 0x23238c2305af4626, 0xc6c63fc67ef991b8, 0xe8e887e8136fcdfb, |
0x878726874ca113cb, 0xb8b8dab8a9626d11, 0x0101040108050209, 0x4f4f214f426e9e0d, |
0x3636d836adee6c9b, 0xa6a6a2a6590451ff, 0xd2d26fd2debdb90c, 0xf5f5f3f5fb06f70e, |
0x7979f979ef80f296, 0x6f6fa16f5fcede30, 0x91917e91fcef3f6d, 0x52525552aa07a4f8, |
0x60609d6027fdc047, 0xbcbccabc89766535, 0x9b9b569baccd2b37, 0x8e8e028e048c018a, |
0xa3a3b6a371155bd2, 0x0c0c300c603c186c, 0x7b7bf17bff8af684, 0x3535d435b5e16a80, |
0x1d1d741de8693af5, 0xe0e0a7e05347ddb3, 0xd7d77bd7f6acb321, 0xc2c22fc25eed999c, |
0x2e2eb82e6d965c43, 0x4b4b314b627a9629, 0xfefedffea321e15d, 0x575741578216aed5, |
0x15155415a8412abd, 0x7777c1779fb6eee8, 0x3737dc37a5eb6e92, 0xe5e5b3e57b56d79e, |
0x9f9f469f8cd92313, 0xf0f0e7f0d317fd23, 0x4a4a354a6a7f9420, 0xdada4fda9e95a944, |
0x58587d58fa25b0a2, 0xc9c903c906ca8fcf, 0x2929a429558d527c, 0x0a0a280a5022145a, |
0xb1b1feb1e14f7f50, 0xa0a0baa0691a5dc9, 0x6b6bb16b7fdad614, 0x85852e855cab17d9, |
0xbdbdcebd8173673c, 0x5d5d695dd234ba8f, 0x1010401080502090, 0xf4f4f7f4f303f507, |
0xcbcb0bcb16c08bdd, 0x3e3ef83eedc67cd3, 0x0505140528110a2d, 0x676781671fe6ce78, |
0xe4e4b7e47353d597, 0x27279c2725bb4e02, 0x4141194132588273, 0x8b8b168b2c9d0ba7, |
0xa7a7a6a7510153f6, 0x7d7de97dcf94fab2, 0x95956e95dcfb3749, 0xd8d847d88e9fad56, |
0xfbfbcbfb8b30eb70, 0xeeee9fee2371c1cd, 0x7c7ced7cc791f8bb, 0x6666856617e3cc71, |
0xdddd53dda68ea77b, 0x17175c17b84b2eaf, 0x4747014702468e45, 0x9e9e429e84dc211a, |
0xcaca0fca1ec589d4, 0x2d2db42d75995a58, 0xbfbfc6bf9179632e, 0x07071c07381b0e3f, |
0xadad8ead012347ac, 0x5a5a755aea2fb4b0, 0x838336836cb51bef, 0x3333cc3385ff66b6, |
0x636391633ff2c65c, 0x02020802100a0412, 0xaaaa92aa39384993, 0x7171d971afa8e2de, |
0xc8c807c80ecf8dc6, 0x19196419c87d32d1, 0x494939497270923b, 0xd9d943d9869aaf5f, |
0xf2f2eff2c31df931, 0xe3e3abe34b48dba8, 0x5b5b715be22ab6b9, 0x88881a8834920dbc, |
0x9a9a529aa4c8293e, 0x262698262dbe4c0b, 0x3232c8328dfa64bf, 0xb0b0fab0e94a7d59, |
0xe9e983e91b6acff2, 0x0f0f3c0f78331e77, 0xd5d573d5e6a6b733, 0x80803a8074ba1df4, |
0xbebec2be997c6127, 0xcdcd13cd26de87eb, 0x3434d034bde46889, 0x48483d487a759032, |
0xffffdbffab24e354, 0x7a7af57af78ff48d, 0x90907a90f4ea3d64, 0x5f5f615fc23ebe9d, |
0x202080201da0403d, 0x6868bd6867d5d00f, 0x1a1a681ad07234ca, 0xaeae82ae192c41b7, |
0xb4b4eab4c95e757d, 0x54544d549a19a8ce, 0x93937693ece53b7f, 0x222288220daa442f, |
0x64648d6407e9c863, 0xf1f1e3f1db12ff2a, 0x7373d173bfa2e6cc, 0x12124812905a2482, |
0x40401d403a5d807a, 0x0808200840281048, 0xc3c32bc356e89b95, 0xecec97ec337bc5df, |
0xdbdb4bdb9690ab4d, 0xa1a1bea1611f5fc0, 0x8d8d0e8d1c830791, 0x3d3df43df5c97ac8, |
0x97976697ccf1335b, 0x0000000000000000, 0xcfcf1bcf36d483f9, 0x2b2bac2b4587566e, |
0x7676c57697b3ece1, 0x8282328264b019e6, 0xd6d67fd6fea9b128, 0x1b1b6c1bd87736c3, |
0xb5b5eeb5c15b7774, 0xafaf86af112943be, 0x6a6ab56a77dfd41d, 0x50505d50ba0da0ea, |
0x45450945124c8a57, 0xf3f3ebf3cb18fb38, 0x3030c0309df060ad, 0xefef9bef2b74c3c4, |
0x3f3ffc3fe5c37eda, 0x55554955921caac7, 0xa2a2b2a2791059db, 0xeaea8fea0365c9e9, |
0x656589650fecca6a, 0xbabad2bab9686903, 0x2f2fbc2f65935e4a, 0xc0c027c04ee79d8e, |
0xdede5fdebe81a160, 0x1c1c701ce06c38fc, 0xfdfdd3fdbb2ee746, 0x4d4d294d52649a1f, |
0x92927292e4e03976, 0x7575c9758fbceafa, 0x06061806301e0c36, 0x8a8a128a249809ae, |
0xb2b2f2b2f940794b, 0xe6e6bfe66359d185, 0x0e0e380e70361c7e, 0x1f1f7c1ff8633ee7, |
0x6262956237f7c455, 0xd4d477d4eea3b53a, 0xa8a89aa829324d81, 0x96966296c4f43152, |
0xf9f9c3f99b3aef62, 0xc5c533c566f697a3, 0x2525942535b14a10, 0x59597959f220b2ab, |
0x84842a8454ae15d0, 0x7272d572b7a7e4c5, 0x3939e439d5dd72ec, 0x4c4c2d4c5a619816, |
0x5e5e655eca3bbc94, 0x7878fd78e785f09f, 0x3838e038ddd870e5, 0x8c8c0a8c14860598, |
0xd1d163d1c6b2bf17, 0xa5a5aea5410b57e4, 0xe2e2afe2434dd9a1, 0x616199612ff8c24e, |
0xb3b3f6b3f1457b42, 0x2121842115a54234, 0x9c9c4a9c94d62508, 0x1e1e781ef0663cee, |
0x4343114322528661, 0xc7c73bc776fc93b1, 0xfcfcd7fcb32be54f, 0x0404100420140824, |
0x51515951b208a2e3, 0x99995e99bcc72f25, 0x6d6da96d4fc4da22, 0x0d0d340d68391a65, |
0xfafacffa8335e979, 0xdfdf5bdfb684a369, 0x7e7ee57ed79bfca9, 0x242490243db44819, |
0x3b3bec3bc5d776fe, 0xabab96ab313d4b9a, 0xcece1fce3ed181f0, 0x1111441188552299, |
0x8f8f068f0c890383, 0x4e4e254e4a6b9c04, 0xb7b7e6b7d1517366, 0xebeb8beb0b60cbe0, |
0x3c3cf03cfdcc78c1, 0x81813e817cbf1ffd, 0x94946a94d4fe3540, 0xf7f7fbf7eb0cf31c, |
0xb9b9deb9a1676f18, 0x13134c13985f268b, 0x2c2cb02c7d9c5851, 0xd3d36bd3d6b8bb05, |
0xe7e7bbe76b5cd38c, 0x6e6ea56e57cbdc39, 0xc4c437c46ef395aa, 0x03030c03180f061b, |
0x565645568a13acdc, 0x44440d441a49885e, 0x7f7fe17fdf9efea0, 0xa9a99ea921374f88, |
0x2a2aa82a4d825467, 0xbbbbd6bbb16d6b0a, 0xc1c123c146e29f87, 0x53535153a202a6f1, |
0xdcdc57dcae8ba572, 0x0b0b2c0b58271653, 0x9d9d4e9d9cd32701, 0x6c6cad6c47c1d82b, |
0x3131c43195f562a4, 0x7474cd7487b9e8f3, 0xf6f6fff6e309f115, 0x464605460a438c4c, |
0xacac8aac092645a5, 0x89891e893c970fb5, 0x14145014a04428b4, 0xe1e1a3e15b42dfba, |
0x16165816b04e2ca6, 0x3a3ae83acdd274f7, 0x6969b9696fd0d206, 0x09092409482d1241, |
0x7070dd70a7ade0d7, 0xb6b6e2b6d954716f, 0xd0d067d0ceb7bd1e, 0xeded93ed3b7ec7d6, |
0xcccc17cc2edb85e2, 0x424215422a578468, 0x98985a98b4c22d2c, 0xa4a4aaa4490e55ed, |
0x2828a0285d885075, 0x5c5c6d5cda31b886, 0xf8f8c7f8933fed6b, 0x8686228644a411c2, |
] |
C1 = [ |
0xd818186018c07830, 0x2623238c2305af46, 0xb8c6c63fc67ef991, 0xfbe8e887e8136fcd, |
0xcb878726874ca113, 0x11b8b8dab8a9626d, 0x0901010401080502, 0x0d4f4f214f426e9e, |
0x9b3636d836adee6c, 0xffa6a6a2a6590451, 0x0cd2d26fd2debdb9, 0x0ef5f5f3f5fb06f7, |
0x967979f979ef80f2, 0x306f6fa16f5fcede, 0x6d91917e91fcef3f, 0xf852525552aa07a4, |
0x4760609d6027fdc0, 0x35bcbccabc897665, 0x379b9b569baccd2b, 0x8a8e8e028e048c01, |
0xd2a3a3b6a371155b, 0x6c0c0c300c603c18, 0x847b7bf17bff8af6, 0x803535d435b5e16a, |
0xf51d1d741de8693a, 0xb3e0e0a7e05347dd, 0x21d7d77bd7f6acb3, 0x9cc2c22fc25eed99, |
0x432e2eb82e6d965c, 0x294b4b314b627a96, 0x5dfefedffea321e1, 0xd5575741578216ae, |
0xbd15155415a8412a, 0xe87777c1779fb6ee, 0x923737dc37a5eb6e, 0x9ee5e5b3e57b56d7, |
0x139f9f469f8cd923, 0x23f0f0e7f0d317fd, 0x204a4a354a6a7f94, 0x44dada4fda9e95a9, |
0xa258587d58fa25b0, 0xcfc9c903c906ca8f, 0x7c2929a429558d52, 0x5a0a0a280a502214, |
0x50b1b1feb1e14f7f, 0xc9a0a0baa0691a5d, 0x146b6bb16b7fdad6, 0xd985852e855cab17, |
0x3cbdbdcebd817367, 0x8f5d5d695dd234ba, 0x9010104010805020, 0x07f4f4f7f4f303f5, |
0xddcbcb0bcb16c08b, 0xd33e3ef83eedc67c, 0x2d0505140528110a, 0x78676781671fe6ce, |
0x97e4e4b7e47353d5, 0x0227279c2725bb4e, 0x7341411941325882, 0xa78b8b168b2c9d0b, |
0xf6a7a7a6a7510153, 0xb27d7de97dcf94fa, 0x4995956e95dcfb37, 0x56d8d847d88e9fad, |
0x70fbfbcbfb8b30eb, 0xcdeeee9fee2371c1, 0xbb7c7ced7cc791f8, 0x716666856617e3cc, |
0x7bdddd53dda68ea7, 0xaf17175c17b84b2e, 0x454747014702468e, 0x1a9e9e429e84dc21, |
0xd4caca0fca1ec589, 0x582d2db42d75995a, 0x2ebfbfc6bf917963, 0x3f07071c07381b0e, |
0xacadad8ead012347, 0xb05a5a755aea2fb4, 0xef838336836cb51b, 0xb63333cc3385ff66, |
0x5c636391633ff2c6, 0x1202020802100a04, 0x93aaaa92aa393849, 0xde7171d971afa8e2, |
0xc6c8c807c80ecf8d, 0xd119196419c87d32, 0x3b49493949727092, 0x5fd9d943d9869aaf, |
0x31f2f2eff2c31df9, 0xa8e3e3abe34b48db, 0xb95b5b715be22ab6, 0xbc88881a8834920d, |
0x3e9a9a529aa4c829, 0x0b262698262dbe4c, 0xbf3232c8328dfa64, 0x59b0b0fab0e94a7d, |
0xf2e9e983e91b6acf, 0x770f0f3c0f78331e, 0x33d5d573d5e6a6b7, 0xf480803a8074ba1d, |
0x27bebec2be997c61, 0xebcdcd13cd26de87, 0x893434d034bde468, 0x3248483d487a7590, |
0x54ffffdbffab24e3, 0x8d7a7af57af78ff4, 0x6490907a90f4ea3d, 0x9d5f5f615fc23ebe, |
0x3d202080201da040, 0x0f6868bd6867d5d0, 0xca1a1a681ad07234, 0xb7aeae82ae192c41, |
0x7db4b4eab4c95e75, 0xce54544d549a19a8, 0x7f93937693ece53b, 0x2f222288220daa44, |
0x6364648d6407e9c8, 0x2af1f1e3f1db12ff, 0xcc7373d173bfa2e6, 0x8212124812905a24, |
0x7a40401d403a5d80, 0x4808082008402810, 0x95c3c32bc356e89b, 0xdfecec97ec337bc5, |
0x4ddbdb4bdb9690ab, 0xc0a1a1bea1611f5f, 0x918d8d0e8d1c8307, 0xc83d3df43df5c97a, |
0x5b97976697ccf133, 0x0000000000000000, 0xf9cfcf1bcf36d483, 0x6e2b2bac2b458756, |
0xe17676c57697b3ec, 0xe68282328264b019, 0x28d6d67fd6fea9b1, 0xc31b1b6c1bd87736, |
0x74b5b5eeb5c15b77, 0xbeafaf86af112943, 0x1d6a6ab56a77dfd4, 0xea50505d50ba0da0, |
0x5745450945124c8a, 0x38f3f3ebf3cb18fb, 0xad3030c0309df060, 0xc4efef9bef2b74c3, |
0xda3f3ffc3fe5c37e, 0xc755554955921caa, 0xdba2a2b2a2791059, 0xe9eaea8fea0365c9, |
0x6a656589650fecca, 0x03babad2bab96869, 0x4a2f2fbc2f65935e, 0x8ec0c027c04ee79d, |
0x60dede5fdebe81a1, 0xfc1c1c701ce06c38, 0x46fdfdd3fdbb2ee7, 0x1f4d4d294d52649a, |
0x7692927292e4e039, 0xfa7575c9758fbcea, 0x3606061806301e0c, 0xae8a8a128a249809, |
0x4bb2b2f2b2f94079, 0x85e6e6bfe66359d1, 0x7e0e0e380e70361c, 0xe71f1f7c1ff8633e, |
0x556262956237f7c4, 0x3ad4d477d4eea3b5, 0x81a8a89aa829324d, 0x5296966296c4f431, |
0x62f9f9c3f99b3aef, 0xa3c5c533c566f697, 0x102525942535b14a, 0xab59597959f220b2, |
0xd084842a8454ae15, 0xc57272d572b7a7e4, 0xec3939e439d5dd72, 0x164c4c2d4c5a6198, |
0x945e5e655eca3bbc, 0x9f7878fd78e785f0, 0xe53838e038ddd870, 0x988c8c0a8c148605, |
0x17d1d163d1c6b2bf, 0xe4a5a5aea5410b57, 0xa1e2e2afe2434dd9, 0x4e616199612ff8c2, |
0x42b3b3f6b3f1457b, 0x342121842115a542, 0x089c9c4a9c94d625, 0xee1e1e781ef0663c, |
0x6143431143225286, 0xb1c7c73bc776fc93, 0x4ffcfcd7fcb32be5, 0x2404041004201408, |
0xe351515951b208a2, 0x2599995e99bcc72f, 0x226d6da96d4fc4da, 0x650d0d340d68391a, |
0x79fafacffa8335e9, 0x69dfdf5bdfb684a3, 0xa97e7ee57ed79bfc, 0x19242490243db448, |
0xfe3b3bec3bc5d776, 0x9aabab96ab313d4b, 0xf0cece1fce3ed181, 0x9911114411885522, |
0x838f8f068f0c8903, 0x044e4e254e4a6b9c, 0x66b7b7e6b7d15173, 0xe0ebeb8beb0b60cb, |
0xc13c3cf03cfdcc78, 0xfd81813e817cbf1f, 0x4094946a94d4fe35, 0x1cf7f7fbf7eb0cf3, |
0x18b9b9deb9a1676f, 0x8b13134c13985f26, 0x512c2cb02c7d9c58, 0x05d3d36bd3d6b8bb, |
0x8ce7e7bbe76b5cd3, 0x396e6ea56e57cbdc, 0xaac4c437c46ef395, 0x1b03030c03180f06, |
0xdc565645568a13ac, 0x5e44440d441a4988, 0xa07f7fe17fdf9efe, 0x88a9a99ea921374f, |
0x672a2aa82a4d8254, 0x0abbbbd6bbb16d6b, 0x87c1c123c146e29f, 0xf153535153a202a6, |
0x72dcdc57dcae8ba5, 0x530b0b2c0b582716, 0x019d9d4e9d9cd327, 0x2b6c6cad6c47c1d8, |
0xa43131c43195f562, 0xf37474cd7487b9e8, 0x15f6f6fff6e309f1, 0x4c464605460a438c, |
0xa5acac8aac092645, 0xb589891e893c970f, 0xb414145014a04428, 0xbae1e1a3e15b42df, |
0xa616165816b04e2c, 0xf73a3ae83acdd274, 0x066969b9696fd0d2, 0x4109092409482d12, |
0xd77070dd70a7ade0, 0x6fb6b6e2b6d95471, 0x1ed0d067d0ceb7bd, 0xd6eded93ed3b7ec7, |
0xe2cccc17cc2edb85, 0x68424215422a5784, 0x2c98985a98b4c22d, 0xeda4a4aaa4490e55, |
0x752828a0285d8850, 0x865c5c6d5cda31b8, 0x6bf8f8c7f8933fed, 0xc28686228644a411, |
] |
C2 = [ |
0x30d818186018c078, 0x462623238c2305af, 0x91b8c6c63fc67ef9, 0xcdfbe8e887e8136f, |
0x13cb878726874ca1, 0x6d11b8b8dab8a962, 0x0209010104010805, 0x9e0d4f4f214f426e, |
0x6c9b3636d836adee, 0x51ffa6a6a2a65904, 0xb90cd2d26fd2debd, 0xf70ef5f5f3f5fb06, |
0xf2967979f979ef80, 0xde306f6fa16f5fce, 0x3f6d91917e91fcef, 0xa4f852525552aa07, |
0xc04760609d6027fd, 0x6535bcbccabc8976, 0x2b379b9b569baccd, 0x018a8e8e028e048c, |
0x5bd2a3a3b6a37115, 0x186c0c0c300c603c, 0xf6847b7bf17bff8a, 0x6a803535d435b5e1, |
0x3af51d1d741de869, 0xddb3e0e0a7e05347, 0xb321d7d77bd7f6ac, 0x999cc2c22fc25eed, |
0x5c432e2eb82e6d96, 0x96294b4b314b627a, 0xe15dfefedffea321, 0xaed5575741578216, |
0x2abd15155415a841, 0xeee87777c1779fb6, 0x6e923737dc37a5eb, 0xd79ee5e5b3e57b56, |
0x23139f9f469f8cd9, 0xfd23f0f0e7f0d317, 0x94204a4a354a6a7f, 0xa944dada4fda9e95, |
0xb0a258587d58fa25, 0x8fcfc9c903c906ca, 0x527c2929a429558d, 0x145a0a0a280a5022, |
0x7f50b1b1feb1e14f, 0x5dc9a0a0baa0691a, 0xd6146b6bb16b7fda, 0x17d985852e855cab, |
0x673cbdbdcebd8173, 0xba8f5d5d695dd234, 0x2090101040108050, 0xf507f4f4f7f4f303, |
0x8bddcbcb0bcb16c0, 0x7cd33e3ef83eedc6, 0x0a2d050514052811, 0xce78676781671fe6, |
0xd597e4e4b7e47353, 0x4e0227279c2725bb, 0x8273414119413258, 0x0ba78b8b168b2c9d, |
0x53f6a7a7a6a75101, 0xfab27d7de97dcf94, 0x374995956e95dcfb, 0xad56d8d847d88e9f, |
0xeb70fbfbcbfb8b30, 0xc1cdeeee9fee2371, 0xf8bb7c7ced7cc791, 0xcc716666856617e3, |
0xa77bdddd53dda68e, 0x2eaf17175c17b84b, 0x8e45474701470246, 0x211a9e9e429e84dc, |
0x89d4caca0fca1ec5, 0x5a582d2db42d7599, 0x632ebfbfc6bf9179, 0x0e3f07071c07381b, |
0x47acadad8ead0123, 0xb4b05a5a755aea2f, 0x1bef838336836cb5, 0x66b63333cc3385ff, |
0xc65c636391633ff2, 0x041202020802100a, 0x4993aaaa92aa3938, 0xe2de7171d971afa8, |
0x8dc6c8c807c80ecf, 0x32d119196419c87d, 0x923b494939497270, 0xaf5fd9d943d9869a, |
0xf931f2f2eff2c31d, 0xdba8e3e3abe34b48, 0xb6b95b5b715be22a, 0x0dbc88881a883492, |
0x293e9a9a529aa4c8, 0x4c0b262698262dbe, 0x64bf3232c8328dfa, 0x7d59b0b0fab0e94a, |
0xcff2e9e983e91b6a, 0x1e770f0f3c0f7833, 0xb733d5d573d5e6a6, 0x1df480803a8074ba, |
0x6127bebec2be997c, 0x87ebcdcd13cd26de, 0x68893434d034bde4, 0x903248483d487a75, |
0xe354ffffdbffab24, 0xf48d7a7af57af78f, 0x3d6490907a90f4ea, 0xbe9d5f5f615fc23e, |
0x403d202080201da0, 0xd00f6868bd6867d5, 0x34ca1a1a681ad072, 0x41b7aeae82ae192c, |
0x757db4b4eab4c95e, 0xa8ce54544d549a19, 0x3b7f93937693ece5, 0x442f222288220daa, |
0xc86364648d6407e9, 0xff2af1f1e3f1db12, 0xe6cc7373d173bfa2, 0x248212124812905a, |
0x807a40401d403a5d, 0x1048080820084028, 0x9b95c3c32bc356e8, 0xc5dfecec97ec337b, |
0xab4ddbdb4bdb9690, 0x5fc0a1a1bea1611f, 0x07918d8d0e8d1c83, 0x7ac83d3df43df5c9, |
0x335b97976697ccf1, 0x0000000000000000, 0x83f9cfcf1bcf36d4, 0x566e2b2bac2b4587, |
0xece17676c57697b3, 0x19e68282328264b0, 0xb128d6d67fd6fea9, 0x36c31b1b6c1bd877, |
0x7774b5b5eeb5c15b, 0x43beafaf86af1129, 0xd41d6a6ab56a77df, 0xa0ea50505d50ba0d, |
0x8a5745450945124c, 0xfb38f3f3ebf3cb18, 0x60ad3030c0309df0, 0xc3c4efef9bef2b74, |
0x7eda3f3ffc3fe5c3, 0xaac755554955921c, 0x59dba2a2b2a27910, 0xc9e9eaea8fea0365, |
0xca6a656589650fec, 0x6903babad2bab968, 0x5e4a2f2fbc2f6593, 0x9d8ec0c027c04ee7, |
0xa160dede5fdebe81, 0x38fc1c1c701ce06c, 0xe746fdfdd3fdbb2e, 0x9a1f4d4d294d5264, |
0x397692927292e4e0, 0xeafa7575c9758fbc, 0x0c3606061806301e, 0x09ae8a8a128a2498, |
0x794bb2b2f2b2f940, 0xd185e6e6bfe66359, 0x1c7e0e0e380e7036, 0x3ee71f1f7c1ff863, |
0xc4556262956237f7, 0xb53ad4d477d4eea3, 0x4d81a8a89aa82932, 0x315296966296c4f4, |
0xef62f9f9c3f99b3a, 0x97a3c5c533c566f6, 0x4a102525942535b1, 0xb2ab59597959f220, |
0x15d084842a8454ae, 0xe4c57272d572b7a7, 0x72ec3939e439d5dd, 0x98164c4c2d4c5a61, |
0xbc945e5e655eca3b, 0xf09f7878fd78e785, 0x70e53838e038ddd8, 0x05988c8c0a8c1486, |
0xbf17d1d163d1c6b2, 0x57e4a5a5aea5410b, 0xd9a1e2e2afe2434d, 0xc24e616199612ff8, |
0x7b42b3b3f6b3f145, 0x42342121842115a5, 0x25089c9c4a9c94d6, 0x3cee1e1e781ef066, |
0x8661434311432252, 0x93b1c7c73bc776fc, 0xe54ffcfcd7fcb32b, 0x0824040410042014, |
0xa2e351515951b208, 0x2f2599995e99bcc7, 0xda226d6da96d4fc4, 0x1a650d0d340d6839, |
0xe979fafacffa8335, 0xa369dfdf5bdfb684, 0xfca97e7ee57ed79b, 0x4819242490243db4, |
0x76fe3b3bec3bc5d7, 0x4b9aabab96ab313d, 0x81f0cece1fce3ed1, 0x2299111144118855, |
0x03838f8f068f0c89, 0x9c044e4e254e4a6b, 0x7366b7b7e6b7d151, 0xcbe0ebeb8beb0b60, |
0x78c13c3cf03cfdcc, 0x1ffd81813e817cbf, 0x354094946a94d4fe, 0xf31cf7f7fbf7eb0c, |
0x6f18b9b9deb9a167, 0x268b13134c13985f, 0x58512c2cb02c7d9c, 0xbb05d3d36bd3d6b8, |
0xd38ce7e7bbe76b5c, 0xdc396e6ea56e57cb, 0x95aac4c437c46ef3, 0x061b03030c03180f, |
0xacdc565645568a13, 0x885e44440d441a49, 0xfea07f7fe17fdf9e, 0x4f88a9a99ea92137, |
0x54672a2aa82a4d82, 0x6b0abbbbd6bbb16d, 0x9f87c1c123c146e2, 0xa6f153535153a202, |
0xa572dcdc57dcae8b, 0x16530b0b2c0b5827, 0x27019d9d4e9d9cd3, 0xd82b6c6cad6c47c1, |
0x62a43131c43195f5, 0xe8f37474cd7487b9, 0xf115f6f6fff6e309, 0x8c4c464605460a43, |
0x45a5acac8aac0926, 0x0fb589891e893c97, 0x28b414145014a044, 0xdfbae1e1a3e15b42, |
0x2ca616165816b04e, 0x74f73a3ae83acdd2, 0xd2066969b9696fd0, 0x124109092409482d, |
0xe0d77070dd70a7ad, 0x716fb6b6e2b6d954, 0xbd1ed0d067d0ceb7, 0xc7d6eded93ed3b7e, |
0x85e2cccc17cc2edb, 0x8468424215422a57, 0x2d2c98985a98b4c2, 0x55eda4a4aaa4490e, |
0x50752828a0285d88, 0xb8865c5c6d5cda31, 0xed6bf8f8c7f8933f, 0x11c28686228644a4, |
] |
C3 = [ |
0x7830d818186018c0, 0xaf462623238c2305, 0xf991b8c6c63fc67e, 0x6fcdfbe8e887e813, |
0xa113cb878726874c, 0x626d11b8b8dab8a9, 0x0502090101040108, 0x6e9e0d4f4f214f42, |
0xee6c9b3636d836ad, 0x0451ffa6a6a2a659, 0xbdb90cd2d26fd2de, 0x06f70ef5f5f3f5fb, |
0x80f2967979f979ef, 0xcede306f6fa16f5f, 0xef3f6d91917e91fc, 0x07a4f852525552aa, |
0xfdc04760609d6027, 0x766535bcbccabc89, 0xcd2b379b9b569bac, 0x8c018a8e8e028e04, |
0x155bd2a3a3b6a371, 0x3c186c0c0c300c60, 0x8af6847b7bf17bff, 0xe16a803535d435b5, |
0x693af51d1d741de8, 0x47ddb3e0e0a7e053, 0xacb321d7d77bd7f6, 0xed999cc2c22fc25e, |
0x965c432e2eb82e6d, 0x7a96294b4b314b62, 0x21e15dfefedffea3, 0x16aed55757415782, |
0x412abd15155415a8, 0xb6eee87777c1779f, 0xeb6e923737dc37a5, 0x56d79ee5e5b3e57b, |
0xd923139f9f469f8c, 0x17fd23f0f0e7f0d3, 0x7f94204a4a354a6a, 0x95a944dada4fda9e, |
0x25b0a258587d58fa, 0xca8fcfc9c903c906, 0x8d527c2929a42955, 0x22145a0a0a280a50, |
0x4f7f50b1b1feb1e1, 0x1a5dc9a0a0baa069, 0xdad6146b6bb16b7f, 0xab17d985852e855c, |
0x73673cbdbdcebd81, 0x34ba8f5d5d695dd2, 0x5020901010401080, 0x03f507f4f4f7f4f3, |
0xc08bddcbcb0bcb16, 0xc67cd33e3ef83eed, 0x110a2d0505140528, 0xe6ce78676781671f, |
0x53d597e4e4b7e473, 0xbb4e0227279c2725, 0x5882734141194132, 0x9d0ba78b8b168b2c, |
0x0153f6a7a7a6a751, 0x94fab27d7de97dcf, 0xfb374995956e95dc, 0x9fad56d8d847d88e, |
0x30eb70fbfbcbfb8b, 0x71c1cdeeee9fee23, 0x91f8bb7c7ced7cc7, 0xe3cc716666856617, |
0x8ea77bdddd53dda6, 0x4b2eaf17175c17b8, 0x468e454747014702, 0xdc211a9e9e429e84, |
0xc589d4caca0fca1e, 0x995a582d2db42d75, 0x79632ebfbfc6bf91, 0x1b0e3f07071c0738, |
0x2347acadad8ead01, 0x2fb4b05a5a755aea, 0xb51bef838336836c, 0xff66b63333cc3385, |
0xf2c65c636391633f, 0x0a04120202080210, 0x384993aaaa92aa39, 0xa8e2de7171d971af, |
0xcf8dc6c8c807c80e, 0x7d32d119196419c8, 0x70923b4949394972, 0x9aaf5fd9d943d986, |
0x1df931f2f2eff2c3, 0x48dba8e3e3abe34b, 0x2ab6b95b5b715be2, 0x920dbc88881a8834, |
0xc8293e9a9a529aa4, 0xbe4c0b262698262d, 0xfa64bf3232c8328d, 0x4a7d59b0b0fab0e9, |
0x6acff2e9e983e91b, 0x331e770f0f3c0f78, 0xa6b733d5d573d5e6, 0xba1df480803a8074, |
0x7c6127bebec2be99, 0xde87ebcdcd13cd26, 0xe468893434d034bd, 0x75903248483d487a, |
0x24e354ffffdbffab, 0x8ff48d7a7af57af7, 0xea3d6490907a90f4, 0x3ebe9d5f5f615fc2, |
0xa0403d202080201d, 0xd5d00f6868bd6867, 0x7234ca1a1a681ad0, 0x2c41b7aeae82ae19, |
0x5e757db4b4eab4c9, 0x19a8ce54544d549a, 0xe53b7f93937693ec, 0xaa442f222288220d, |
0xe9c86364648d6407, 0x12ff2af1f1e3f1db, 0xa2e6cc7373d173bf, 0x5a24821212481290, |
0x5d807a40401d403a, 0x2810480808200840, 0xe89b95c3c32bc356, 0x7bc5dfecec97ec33, |
0x90ab4ddbdb4bdb96, 0x1f5fc0a1a1bea161, 0x8307918d8d0e8d1c, 0xc97ac83d3df43df5, |
0xf1335b97976697cc, 0x0000000000000000, 0xd483f9cfcf1bcf36, 0x87566e2b2bac2b45, |
0xb3ece17676c57697, 0xb019e68282328264, 0xa9b128d6d67fd6fe, 0x7736c31b1b6c1bd8, |
0x5b7774b5b5eeb5c1, 0x2943beafaf86af11, 0xdfd41d6a6ab56a77, 0x0da0ea50505d50ba, |
0x4c8a574545094512, 0x18fb38f3f3ebf3cb, 0xf060ad3030c0309d, 0x74c3c4efef9bef2b, |
0xc37eda3f3ffc3fe5, 0x1caac75555495592, 0x1059dba2a2b2a279, 0x65c9e9eaea8fea03, |
0xecca6a656589650f, 0x686903babad2bab9, 0x935e4a2f2fbc2f65, 0xe79d8ec0c027c04e, |
0x81a160dede5fdebe, 0x6c38fc1c1c701ce0, 0x2ee746fdfdd3fdbb, 0x649a1f4d4d294d52, |
0xe0397692927292e4, 0xbceafa7575c9758f, 0x1e0c360606180630, 0x9809ae8a8a128a24, |
0x40794bb2b2f2b2f9, 0x59d185e6e6bfe663, 0x361c7e0e0e380e70, 0x633ee71f1f7c1ff8, |
0xf7c4556262956237, 0xa3b53ad4d477d4ee, 0x324d81a8a89aa829, 0xf4315296966296c4, |
0x3aef62f9f9c3f99b, 0xf697a3c5c533c566, 0xb14a102525942535, 0x20b2ab59597959f2, |
0xae15d084842a8454, 0xa7e4c57272d572b7, 0xdd72ec3939e439d5, 0x6198164c4c2d4c5a, |
0x3bbc945e5e655eca, 0x85f09f7878fd78e7, 0xd870e53838e038dd, 0x8605988c8c0a8c14, |
0xb2bf17d1d163d1c6, 0x0b57e4a5a5aea541, 0x4dd9a1e2e2afe243, 0xf8c24e616199612f, |
0x457b42b3b3f6b3f1, 0xa542342121842115, 0xd625089c9c4a9c94, 0x663cee1e1e781ef0, |
0x5286614343114322, 0xfc93b1c7c73bc776, 0x2be54ffcfcd7fcb3, 0x1408240404100420, |
0x08a2e351515951b2, 0xc72f2599995e99bc, 0xc4da226d6da96d4f, 0x391a650d0d340d68, |
0x35e979fafacffa83, 0x84a369dfdf5bdfb6, 0x9bfca97e7ee57ed7, 0xb44819242490243d, |
0xd776fe3b3bec3bc5, 0x3d4b9aabab96ab31, 0xd181f0cece1fce3e, 0x5522991111441188, |
0x8903838f8f068f0c, 0x6b9c044e4e254e4a, 0x517366b7b7e6b7d1, 0x60cbe0ebeb8beb0b, |
0xcc78c13c3cf03cfd, 0xbf1ffd81813e817c, 0xfe354094946a94d4, 0x0cf31cf7f7fbf7eb, |
0x676f18b9b9deb9a1, 0x5f268b13134c1398, 0x9c58512c2cb02c7d, 0xb8bb05d3d36bd3d6, |
0x5cd38ce7e7bbe76b, 0xcbdc396e6ea56e57, 0xf395aac4c437c46e, 0x0f061b03030c0318, |
0x13acdc565645568a, 0x49885e44440d441a, 0x9efea07f7fe17fdf, 0x374f88a9a99ea921, |
0x8254672a2aa82a4d, 0x6d6b0abbbbd6bbb1, 0xe29f87c1c123c146, 0x02a6f153535153a2, |
0x8ba572dcdc57dcae, 0x2716530b0b2c0b58, 0xd327019d9d4e9d9c, 0xc1d82b6c6cad6c47, |
0xf562a43131c43195, 0xb9e8f37474cd7487, 0x09f115f6f6fff6e3, 0x438c4c464605460a, |
0x2645a5acac8aac09, 0x970fb589891e893c, 0x4428b414145014a0, 0x42dfbae1e1a3e15b, |
0x4e2ca616165816b0, 0xd274f73a3ae83acd, 0xd0d2066969b9696f, 0x2d12410909240948, |
0xade0d77070dd70a7, 0x54716fb6b6e2b6d9, 0xb7bd1ed0d067d0ce, 0x7ec7d6eded93ed3b, |
0xdb85e2cccc17cc2e, 0x578468424215422a, 0xc22d2c98985a98b4, 0x0e55eda4a4aaa449, |
0x8850752828a0285d, 0x31b8865c5c6d5cda, 0x3fed6bf8f8c7f893, 0xa411c28686228644, |
] |
C4 = [ |
0xc07830d818186018, 0x05af462623238c23, 0x7ef991b8c6c63fc6, 0x136fcdfbe8e887e8, |
0x4ca113cb87872687, 0xa9626d11b8b8dab8, 0x0805020901010401, 0x426e9e0d4f4f214f, |
0xadee6c9b3636d836, 0x590451ffa6a6a2a6, 0xdebdb90cd2d26fd2, 0xfb06f70ef5f5f3f5, |
0xef80f2967979f979, 0x5fcede306f6fa16f, 0xfcef3f6d91917e91, 0xaa07a4f852525552, |
0x27fdc04760609d60, 0x89766535bcbccabc, 0xaccd2b379b9b569b, 0x048c018a8e8e028e, |
0x71155bd2a3a3b6a3, 0x603c186c0c0c300c, 0xff8af6847b7bf17b, 0xb5e16a803535d435, |
0xe8693af51d1d741d, 0x5347ddb3e0e0a7e0, 0xf6acb321d7d77bd7, 0x5eed999cc2c22fc2, |
0x6d965c432e2eb82e, 0x627a96294b4b314b, 0xa321e15dfefedffe, 0x8216aed557574157, |
0xa8412abd15155415, 0x9fb6eee87777c177, 0xa5eb6e923737dc37, 0x7b56d79ee5e5b3e5, |
0x8cd923139f9f469f, 0xd317fd23f0f0e7f0, 0x6a7f94204a4a354a, 0x9e95a944dada4fda, |
0xfa25b0a258587d58, 0x06ca8fcfc9c903c9, 0x558d527c2929a429, 0x5022145a0a0a280a, |
0xe14f7f50b1b1feb1, 0x691a5dc9a0a0baa0, 0x7fdad6146b6bb16b, 0x5cab17d985852e85, |
0x8173673cbdbdcebd, 0xd234ba8f5d5d695d, 0x8050209010104010, 0xf303f507f4f4f7f4, |
0x16c08bddcbcb0bcb, 0xedc67cd33e3ef83e, 0x28110a2d05051405, 0x1fe6ce7867678167, |
0x7353d597e4e4b7e4, 0x25bb4e0227279c27, 0x3258827341411941, 0x2c9d0ba78b8b168b, |
0x510153f6a7a7a6a7, 0xcf94fab27d7de97d, 0xdcfb374995956e95, 0x8e9fad56d8d847d8, |
0x8b30eb70fbfbcbfb, 0x2371c1cdeeee9fee, 0xc791f8bb7c7ced7c, 0x17e3cc7166668566, |
0xa68ea77bdddd53dd, 0xb84b2eaf17175c17, 0x02468e4547470147, 0x84dc211a9e9e429e, |
0x1ec589d4caca0fca, 0x75995a582d2db42d, 0x9179632ebfbfc6bf, 0x381b0e3f07071c07, |
0x012347acadad8ead, 0xea2fb4b05a5a755a, 0x6cb51bef83833683, 0x85ff66b63333cc33, |
0x3ff2c65c63639163, 0x100a041202020802, 0x39384993aaaa92aa, 0xafa8e2de7171d971, |
0x0ecf8dc6c8c807c8, 0xc87d32d119196419, 0x7270923b49493949, 0x869aaf5fd9d943d9, |
0xc31df931f2f2eff2, 0x4b48dba8e3e3abe3, 0xe22ab6b95b5b715b, 0x34920dbc88881a88, |
0xa4c8293e9a9a529a, 0x2dbe4c0b26269826, 0x8dfa64bf3232c832, 0xe94a7d59b0b0fab0, |
0x1b6acff2e9e983e9, 0x78331e770f0f3c0f, 0xe6a6b733d5d573d5, 0x74ba1df480803a80, |
0x997c6127bebec2be, 0x26de87ebcdcd13cd, 0xbde468893434d034, 0x7a75903248483d48, |
0xab24e354ffffdbff, 0xf78ff48d7a7af57a, 0xf4ea3d6490907a90, 0xc23ebe9d5f5f615f, |
0x1da0403d20208020, 0x67d5d00f6868bd68, 0xd07234ca1a1a681a, 0x192c41b7aeae82ae, |
0xc95e757db4b4eab4, 0x9a19a8ce54544d54, 0xece53b7f93937693, 0x0daa442f22228822, |
0x07e9c86364648d64, 0xdb12ff2af1f1e3f1, 0xbfa2e6cc7373d173, 0x905a248212124812, |
0x3a5d807a40401d40, 0x4028104808082008, 0x56e89b95c3c32bc3, 0x337bc5dfecec97ec, |
0x9690ab4ddbdb4bdb, 0x611f5fc0a1a1bea1, 0x1c8307918d8d0e8d, 0xf5c97ac83d3df43d, |
0xccf1335b97976697, 0x0000000000000000, 0x36d483f9cfcf1bcf, 0x4587566e2b2bac2b, |
0x97b3ece17676c576, 0x64b019e682823282, 0xfea9b128d6d67fd6, 0xd87736c31b1b6c1b, |
0xc15b7774b5b5eeb5, 0x112943beafaf86af, 0x77dfd41d6a6ab56a, 0xba0da0ea50505d50, |
0x124c8a5745450945, 0xcb18fb38f3f3ebf3, 0x9df060ad3030c030, 0x2b74c3c4efef9bef, |
0xe5c37eda3f3ffc3f, 0x921caac755554955, 0x791059dba2a2b2a2, 0x0365c9e9eaea8fea, |
0x0fecca6a65658965, 0xb9686903babad2ba, 0x65935e4a2f2fbc2f, 0x4ee79d8ec0c027c0, |
0xbe81a160dede5fde, 0xe06c38fc1c1c701c, 0xbb2ee746fdfdd3fd, 0x52649a1f4d4d294d, |
0xe4e0397692927292, 0x8fbceafa7575c975, 0x301e0c3606061806, 0x249809ae8a8a128a, |
0xf940794bb2b2f2b2, 0x6359d185e6e6bfe6, 0x70361c7e0e0e380e, 0xf8633ee71f1f7c1f, |
0x37f7c45562629562, 0xeea3b53ad4d477d4, 0x29324d81a8a89aa8, 0xc4f4315296966296, |
0x9b3aef62f9f9c3f9, 0x66f697a3c5c533c5, 0x35b14a1025259425, 0xf220b2ab59597959, |
0x54ae15d084842a84, 0xb7a7e4c57272d572, 0xd5dd72ec3939e439, 0x5a6198164c4c2d4c, |
0xca3bbc945e5e655e, 0xe785f09f7878fd78, 0xddd870e53838e038, 0x148605988c8c0a8c, |
0xc6b2bf17d1d163d1, 0x410b57e4a5a5aea5, 0x434dd9a1e2e2afe2, 0x2ff8c24e61619961, |
0xf1457b42b3b3f6b3, 0x15a5423421218421, 0x94d625089c9c4a9c, 0xf0663cee1e1e781e, |
0x2252866143431143, 0x76fc93b1c7c73bc7, 0xb32be54ffcfcd7fc, 0x2014082404041004, |
0xb208a2e351515951, 0xbcc72f2599995e99, 0x4fc4da226d6da96d, 0x68391a650d0d340d, |
0x8335e979fafacffa, 0xb684a369dfdf5bdf, 0xd79bfca97e7ee57e, 0x3db4481924249024, |
0xc5d776fe3b3bec3b, 0x313d4b9aabab96ab, 0x3ed181f0cece1fce, 0x8855229911114411, |
0x0c8903838f8f068f, 0x4a6b9c044e4e254e, 0xd1517366b7b7e6b7, 0x0b60cbe0ebeb8beb, |
0xfdcc78c13c3cf03c, 0x7cbf1ffd81813e81, 0xd4fe354094946a94, 0xeb0cf31cf7f7fbf7, |
0xa1676f18b9b9deb9, 0x985f268b13134c13, 0x7d9c58512c2cb02c, 0xd6b8bb05d3d36bd3, |
0x6b5cd38ce7e7bbe7, 0x57cbdc396e6ea56e, 0x6ef395aac4c437c4, 0x180f061b03030c03, |
0x8a13acdc56564556, 0x1a49885e44440d44, 0xdf9efea07f7fe17f, 0x21374f88a9a99ea9, |
0x4d8254672a2aa82a, 0xb16d6b0abbbbd6bb, 0x46e29f87c1c123c1, 0xa202a6f153535153, |
0xae8ba572dcdc57dc, 0x582716530b0b2c0b, 0x9cd327019d9d4e9d, 0x47c1d82b6c6cad6c, |
0x95f562a43131c431, 0x87b9e8f37474cd74, 0xe309f115f6f6fff6, 0x0a438c4c46460546, |
0x092645a5acac8aac, 0x3c970fb589891e89, 0xa04428b414145014, 0x5b42dfbae1e1a3e1, |
0xb04e2ca616165816, 0xcdd274f73a3ae83a, 0x6fd0d2066969b969, 0x482d124109092409, |
0xa7ade0d77070dd70, 0xd954716fb6b6e2b6, 0xceb7bd1ed0d067d0, 0x3b7ec7d6eded93ed, |
0x2edb85e2cccc17cc, 0x2a57846842421542, 0xb4c22d2c98985a98, 0x490e55eda4a4aaa4, |
0x5d8850752828a028, 0xda31b8865c5c6d5c, 0x933fed6bf8f8c7f8, 0x44a411c286862286, |
] |
C5 = [ |
0x18c07830d8181860, 0x2305af462623238c, 0xc67ef991b8c6c63f, 0xe8136fcdfbe8e887, |
0x874ca113cb878726, 0xb8a9626d11b8b8da, 0x0108050209010104, 0x4f426e9e0d4f4f21, |
0x36adee6c9b3636d8, 0xa6590451ffa6a6a2, 0xd2debdb90cd2d26f, 0xf5fb06f70ef5f5f3, |
0x79ef80f2967979f9, 0x6f5fcede306f6fa1, 0x91fcef3f6d91917e, 0x52aa07a4f8525255, |
0x6027fdc04760609d, 0xbc89766535bcbcca, 0x9baccd2b379b9b56, 0x8e048c018a8e8e02, |
0xa371155bd2a3a3b6, 0x0c603c186c0c0c30, 0x7bff8af6847b7bf1, 0x35b5e16a803535d4, |
0x1de8693af51d1d74, 0xe05347ddb3e0e0a7, 0xd7f6acb321d7d77b, 0xc25eed999cc2c22f, |
0x2e6d965c432e2eb8, 0x4b627a96294b4b31, 0xfea321e15dfefedf, 0x578216aed5575741, |
0x15a8412abd151554, 0x779fb6eee87777c1, 0x37a5eb6e923737dc, 0xe57b56d79ee5e5b3, |
0x9f8cd923139f9f46, 0xf0d317fd23f0f0e7, 0x4a6a7f94204a4a35, 0xda9e95a944dada4f, |
0x58fa25b0a258587d, 0xc906ca8fcfc9c903, 0x29558d527c2929a4, 0x0a5022145a0a0a28, |
0xb1e14f7f50b1b1fe, 0xa0691a5dc9a0a0ba, 0x6b7fdad6146b6bb1, 0x855cab17d985852e, |
0xbd8173673cbdbdce, 0x5dd234ba8f5d5d69, 0x1080502090101040, 0xf4f303f507f4f4f7, |
0xcb16c08bddcbcb0b, 0x3eedc67cd33e3ef8, 0x0528110a2d050514, 0x671fe6ce78676781, |
0xe47353d597e4e4b7, 0x2725bb4e0227279c, 0x4132588273414119, 0x8b2c9d0ba78b8b16, |
0xa7510153f6a7a7a6, 0x7dcf94fab27d7de9, 0x95dcfb374995956e, 0xd88e9fad56d8d847, |
0xfb8b30eb70fbfbcb, 0xee2371c1cdeeee9f, 0x7cc791f8bb7c7ced, 0x6617e3cc71666685, |
0xdda68ea77bdddd53, 0x17b84b2eaf17175c, 0x4702468e45474701, 0x9e84dc211a9e9e42, |
0xca1ec589d4caca0f, 0x2d75995a582d2db4, 0xbf9179632ebfbfc6, 0x07381b0e3f07071c, |
0xad012347acadad8e, 0x5aea2fb4b05a5a75, 0x836cb51bef838336, 0x3385ff66b63333cc, |
0x633ff2c65c636391, 0x02100a0412020208, 0xaa39384993aaaa92, 0x71afa8e2de7171d9, |
0xc80ecf8dc6c8c807, 0x19c87d32d1191964, 0x497270923b494939, 0xd9869aaf5fd9d943, |
0xf2c31df931f2f2ef, 0xe34b48dba8e3e3ab, 0x5be22ab6b95b5b71, 0x8834920dbc88881a, |
0x9aa4c8293e9a9a52, 0x262dbe4c0b262698, 0x328dfa64bf3232c8, 0xb0e94a7d59b0b0fa, |
0xe91b6acff2e9e983, 0x0f78331e770f0f3c, 0xd5e6a6b733d5d573, 0x8074ba1df480803a, |
0xbe997c6127bebec2, 0xcd26de87ebcdcd13, 0x34bde468893434d0, 0x487a75903248483d, |
0xffab24e354ffffdb, 0x7af78ff48d7a7af5, 0x90f4ea3d6490907a, 0x5fc23ebe9d5f5f61, |
0x201da0403d202080, 0x6867d5d00f6868bd, 0x1ad07234ca1a1a68, 0xae192c41b7aeae82, |
0xb4c95e757db4b4ea, 0x549a19a8ce54544d, 0x93ece53b7f939376, 0x220daa442f222288, |
0x6407e9c86364648d, 0xf1db12ff2af1f1e3, 0x73bfa2e6cc7373d1, 0x12905a2482121248, |
0x403a5d807a40401d, 0x0840281048080820, 0xc356e89b95c3c32b, 0xec337bc5dfecec97, |
0xdb9690ab4ddbdb4b, 0xa1611f5fc0a1a1be, 0x8d1c8307918d8d0e, 0x3df5c97ac83d3df4, |
0x97ccf1335b979766, 0x0000000000000000, 0xcf36d483f9cfcf1b, 0x2b4587566e2b2bac, |
0x7697b3ece17676c5, 0x8264b019e6828232, 0xd6fea9b128d6d67f, 0x1bd87736c31b1b6c, |
0xb5c15b7774b5b5ee, 0xaf112943beafaf86, 0x6a77dfd41d6a6ab5, 0x50ba0da0ea50505d, |
0x45124c8a57454509, 0xf3cb18fb38f3f3eb, 0x309df060ad3030c0, 0xef2b74c3c4efef9b, |
0x3fe5c37eda3f3ffc, 0x55921caac7555549, 0xa2791059dba2a2b2, 0xea0365c9e9eaea8f, |
0x650fecca6a656589, 0xbab9686903babad2, 0x2f65935e4a2f2fbc, 0xc04ee79d8ec0c027, |
0xdebe81a160dede5f, 0x1ce06c38fc1c1c70, 0xfdbb2ee746fdfdd3, 0x4d52649a1f4d4d29, |
0x92e4e03976929272, 0x758fbceafa7575c9, 0x06301e0c36060618, 0x8a249809ae8a8a12, |
0xb2f940794bb2b2f2, 0xe66359d185e6e6bf, 0x0e70361c7e0e0e38, 0x1ff8633ee71f1f7c, |
0x6237f7c455626295, 0xd4eea3b53ad4d477, 0xa829324d81a8a89a, 0x96c4f43152969662, |
0xf99b3aef62f9f9c3, 0xc566f697a3c5c533, 0x2535b14a10252594, 0x59f220b2ab595979, |
0x8454ae15d084842a, 0x72b7a7e4c57272d5, 0x39d5dd72ec3939e4, 0x4c5a6198164c4c2d, |
0x5eca3bbc945e5e65, 0x78e785f09f7878fd, 0x38ddd870e53838e0, 0x8c148605988c8c0a, |
0xd1c6b2bf17d1d163, 0xa5410b57e4a5a5ae, 0xe2434dd9a1e2e2af, 0x612ff8c24e616199, |
0xb3f1457b42b3b3f6, 0x2115a54234212184, 0x9c94d625089c9c4a, 0x1ef0663cee1e1e78, |
0x4322528661434311, 0xc776fc93b1c7c73b, 0xfcb32be54ffcfcd7, 0x0420140824040410, |
0x51b208a2e3515159, 0x99bcc72f2599995e, 0x6d4fc4da226d6da9, 0x0d68391a650d0d34, |
0xfa8335e979fafacf, 0xdfb684a369dfdf5b, 0x7ed79bfca97e7ee5, 0x243db44819242490, |
0x3bc5d776fe3b3bec, 0xab313d4b9aabab96, 0xce3ed181f0cece1f, 0x1188552299111144, |
0x8f0c8903838f8f06, 0x4e4a6b9c044e4e25, 0xb7d1517366b7b7e6, 0xeb0b60cbe0ebeb8b, |
0x3cfdcc78c13c3cf0, 0x817cbf1ffd81813e, 0x94d4fe354094946a, 0xf7eb0cf31cf7f7fb, |
0xb9a1676f18b9b9de, 0x13985f268b13134c, 0x2c7d9c58512c2cb0, 0xd3d6b8bb05d3d36b, |
0xe76b5cd38ce7e7bb, 0x6e57cbdc396e6ea5, 0xc46ef395aac4c437, 0x03180f061b03030c, |
0x568a13acdc565645, 0x441a49885e44440d, 0x7fdf9efea07f7fe1, 0xa921374f88a9a99e, |
0x2a4d8254672a2aa8, 0xbbb16d6b0abbbbd6, 0xc146e29f87c1c123, 0x53a202a6f1535351, |
0xdcae8ba572dcdc57, 0x0b582716530b0b2c, 0x9d9cd327019d9d4e, 0x6c47c1d82b6c6cad, |
0x3195f562a43131c4, 0x7487b9e8f37474cd, 0xf6e309f115f6f6ff, 0x460a438c4c464605, |
0xac092645a5acac8a, 0x893c970fb589891e, 0x14a04428b4141450, 0xe15b42dfbae1e1a3, |
0x16b04e2ca6161658, 0x3acdd274f73a3ae8, 0x696fd0d2066969b9, 0x09482d1241090924, |
0x70a7ade0d77070dd, 0xb6d954716fb6b6e2, 0xd0ceb7bd1ed0d067, 0xed3b7ec7d6eded93, |
0xcc2edb85e2cccc17, 0x422a578468424215, 0x98b4c22d2c98985a, 0xa4490e55eda4a4aa, |
0x285d8850752828a0, 0x5cda31b8865c5c6d, 0xf8933fed6bf8f8c7, 0x8644a411c2868622, |
] |
C6 = [ |
0x6018c07830d81818, 0x8c2305af46262323, 0x3fc67ef991b8c6c6, 0x87e8136fcdfbe8e8, |
0x26874ca113cb8787, 0xdab8a9626d11b8b8, 0x0401080502090101, 0x214f426e9e0d4f4f, |
0xd836adee6c9b3636, 0xa2a6590451ffa6a6, 0x6fd2debdb90cd2d2, 0xf3f5fb06f70ef5f5, |
0xf979ef80f2967979, 0xa16f5fcede306f6f, 0x7e91fcef3f6d9191, 0x5552aa07a4f85252, |
0x9d6027fdc0476060, 0xcabc89766535bcbc, 0x569baccd2b379b9b, 0x028e048c018a8e8e, |
0xb6a371155bd2a3a3, 0x300c603c186c0c0c, 0xf17bff8af6847b7b, 0xd435b5e16a803535, |
0x741de8693af51d1d, 0xa7e05347ddb3e0e0, 0x7bd7f6acb321d7d7, 0x2fc25eed999cc2c2, |
0xb82e6d965c432e2e, 0x314b627a96294b4b, 0xdffea321e15dfefe, 0x41578216aed55757, |
0x5415a8412abd1515, 0xc1779fb6eee87777, 0xdc37a5eb6e923737, 0xb3e57b56d79ee5e5, |
0x469f8cd923139f9f, 0xe7f0d317fd23f0f0, 0x354a6a7f94204a4a, 0x4fda9e95a944dada, |
0x7d58fa25b0a25858, 0x03c906ca8fcfc9c9, 0xa429558d527c2929, 0x280a5022145a0a0a, |
0xfeb1e14f7f50b1b1, 0xbaa0691a5dc9a0a0, 0xb16b7fdad6146b6b, 0x2e855cab17d98585, |
0xcebd8173673cbdbd, 0x695dd234ba8f5d5d, 0x4010805020901010, 0xf7f4f303f507f4f4, |
0x0bcb16c08bddcbcb, 0xf83eedc67cd33e3e, 0x140528110a2d0505, 0x81671fe6ce786767, |
0xb7e47353d597e4e4, 0x9c2725bb4e022727, 0x1941325882734141, 0x168b2c9d0ba78b8b, |
0xa6a7510153f6a7a7, 0xe97dcf94fab27d7d, 0x6e95dcfb37499595, 0x47d88e9fad56d8d8, |
0xcbfb8b30eb70fbfb, 0x9fee2371c1cdeeee, 0xed7cc791f8bb7c7c, 0x856617e3cc716666, |
0x53dda68ea77bdddd, 0x5c17b84b2eaf1717, 0x014702468e454747, 0x429e84dc211a9e9e, |
0x0fca1ec589d4caca, 0xb42d75995a582d2d, 0xc6bf9179632ebfbf, 0x1c07381b0e3f0707, |
0x8ead012347acadad, 0x755aea2fb4b05a5a, 0x36836cb51bef8383, 0xcc3385ff66b63333, |
0x91633ff2c65c6363, 0x0802100a04120202, 0x92aa39384993aaaa, 0xd971afa8e2de7171, |
0x07c80ecf8dc6c8c8, 0x6419c87d32d11919, 0x39497270923b4949, 0x43d9869aaf5fd9d9, |
0xeff2c31df931f2f2, 0xabe34b48dba8e3e3, 0x715be22ab6b95b5b, 0x1a8834920dbc8888, |
0x529aa4c8293e9a9a, 0x98262dbe4c0b2626, 0xc8328dfa64bf3232, 0xfab0e94a7d59b0b0, |
0x83e91b6acff2e9e9, 0x3c0f78331e770f0f, 0x73d5e6a6b733d5d5, 0x3a8074ba1df48080, |
0xc2be997c6127bebe, 0x13cd26de87ebcdcd, 0xd034bde468893434, 0x3d487a7590324848, |
0xdbffab24e354ffff, 0xf57af78ff48d7a7a, 0x7a90f4ea3d649090, 0x615fc23ebe9d5f5f, |
0x80201da0403d2020, 0xbd6867d5d00f6868, 0x681ad07234ca1a1a, 0x82ae192c41b7aeae, |
0xeab4c95e757db4b4, 0x4d549a19a8ce5454, 0x7693ece53b7f9393, 0x88220daa442f2222, |
0x8d6407e9c8636464, 0xe3f1db12ff2af1f1, 0xd173bfa2e6cc7373, 0x4812905a24821212, |
0x1d403a5d807a4040, 0x2008402810480808, 0x2bc356e89b95c3c3, 0x97ec337bc5dfecec, |
0x4bdb9690ab4ddbdb, 0xbea1611f5fc0a1a1, 0x0e8d1c8307918d8d, 0xf43df5c97ac83d3d, |
0x6697ccf1335b9797, 0x0000000000000000, 0x1bcf36d483f9cfcf, 0xac2b4587566e2b2b, |
0xc57697b3ece17676, 0x328264b019e68282, 0x7fd6fea9b128d6d6, 0x6c1bd87736c31b1b, |
0xeeb5c15b7774b5b5, 0x86af112943beafaf, 0xb56a77dfd41d6a6a, 0x5d50ba0da0ea5050, |
0x0945124c8a574545, 0xebf3cb18fb38f3f3, 0xc0309df060ad3030, 0x9bef2b74c3c4efef, |
0xfc3fe5c37eda3f3f, 0x4955921caac75555, 0xb2a2791059dba2a2, 0x8fea0365c9e9eaea, |
0x89650fecca6a6565, 0xd2bab9686903baba, 0xbc2f65935e4a2f2f, 0x27c04ee79d8ec0c0, |
0x5fdebe81a160dede, 0x701ce06c38fc1c1c, 0xd3fdbb2ee746fdfd, 0x294d52649a1f4d4d, |
0x7292e4e039769292, 0xc9758fbceafa7575, 0x1806301e0c360606, 0x128a249809ae8a8a, |
0xf2b2f940794bb2b2, 0xbfe66359d185e6e6, 0x380e70361c7e0e0e, 0x7c1ff8633ee71f1f, |
0x956237f7c4556262, 0x77d4eea3b53ad4d4, 0x9aa829324d81a8a8, 0x6296c4f431529696, |
0xc3f99b3aef62f9f9, 0x33c566f697a3c5c5, 0x942535b14a102525, 0x7959f220b2ab5959, |
0x2a8454ae15d08484, 0xd572b7a7e4c57272, 0xe439d5dd72ec3939, 0x2d4c5a6198164c4c, |
0x655eca3bbc945e5e, 0xfd78e785f09f7878, 0xe038ddd870e53838, 0x0a8c148605988c8c, |
0x63d1c6b2bf17d1d1, 0xaea5410b57e4a5a5, 0xafe2434dd9a1e2e2, 0x99612ff8c24e6161, |
0xf6b3f1457b42b3b3, 0x842115a542342121, 0x4a9c94d625089c9c, 0x781ef0663cee1e1e, |
0x1143225286614343, 0x3bc776fc93b1c7c7, 0xd7fcb32be54ffcfc, 0x1004201408240404, |
0x5951b208a2e35151, 0x5e99bcc72f259999, 0xa96d4fc4da226d6d, 0x340d68391a650d0d, |
0xcffa8335e979fafa, 0x5bdfb684a369dfdf, 0xe57ed79bfca97e7e, 0x90243db448192424, |
0xec3bc5d776fe3b3b, 0x96ab313d4b9aabab, 0x1fce3ed181f0cece, 0x4411885522991111, |
0x068f0c8903838f8f, 0x254e4a6b9c044e4e, 0xe6b7d1517366b7b7, 0x8beb0b60cbe0ebeb, |
0xf03cfdcc78c13c3c, 0x3e817cbf1ffd8181, 0x6a94d4fe35409494, 0xfbf7eb0cf31cf7f7, |
0xdeb9a1676f18b9b9, 0x4c13985f268b1313, 0xb02c7d9c58512c2c, 0x6bd3d6b8bb05d3d3, |
0xbbe76b5cd38ce7e7, 0xa56e57cbdc396e6e, 0x37c46ef395aac4c4, 0x0c03180f061b0303, |
0x45568a13acdc5656, 0x0d441a49885e4444, 0xe17fdf9efea07f7f, 0x9ea921374f88a9a9, |
0xa82a4d8254672a2a, 0xd6bbb16d6b0abbbb, 0x23c146e29f87c1c1, 0x5153a202a6f15353, |
0x57dcae8ba572dcdc, 0x2c0b582716530b0b, 0x4e9d9cd327019d9d, 0xad6c47c1d82b6c6c, |
0xc43195f562a43131, 0xcd7487b9e8f37474, 0xfff6e309f115f6f6, 0x05460a438c4c4646, |
0x8aac092645a5acac, 0x1e893c970fb58989, 0x5014a04428b41414, 0xa3e15b42dfbae1e1, |
0x5816b04e2ca61616, 0xe83acdd274f73a3a, 0xb9696fd0d2066969, 0x2409482d12410909, |
0xdd70a7ade0d77070, 0xe2b6d954716fb6b6, 0x67d0ceb7bd1ed0d0, 0x93ed3b7ec7d6eded, |
0x17cc2edb85e2cccc, 0x15422a5784684242, 0x5a98b4c22d2c9898, 0xaaa4490e55eda4a4, |
0xa0285d8850752828, 0x6d5cda31b8865c5c, 0xc7f8933fed6bf8f8, 0x228644a411c28686, |
] |
C7 = [ |
0x186018c07830d818, 0x238c2305af462623, 0xc63fc67ef991b8c6, 0xe887e8136fcdfbe8, |
0x8726874ca113cb87, 0xb8dab8a9626d11b8, 0x0104010805020901, 0x4f214f426e9e0d4f, |
0x36d836adee6c9b36, 0xa6a2a6590451ffa6, 0xd26fd2debdb90cd2, 0xf5f3f5fb06f70ef5, |
0x79f979ef80f29679, 0x6fa16f5fcede306f, 0x917e91fcef3f6d91, 0x525552aa07a4f852, |
0x609d6027fdc04760, 0xbccabc89766535bc, 0x9b569baccd2b379b, 0x8e028e048c018a8e, |
0xa3b6a371155bd2a3, 0x0c300c603c186c0c, 0x7bf17bff8af6847b, 0x35d435b5e16a8035, |
0x1d741de8693af51d, 0xe0a7e05347ddb3e0, 0xd77bd7f6acb321d7, 0xc22fc25eed999cc2, |
0x2eb82e6d965c432e, 0x4b314b627a96294b, 0xfedffea321e15dfe, 0x5741578216aed557, |
0x155415a8412abd15, 0x77c1779fb6eee877, 0x37dc37a5eb6e9237, 0xe5b3e57b56d79ee5, |
0x9f469f8cd923139f, 0xf0e7f0d317fd23f0, 0x4a354a6a7f94204a, 0xda4fda9e95a944da, |
0x587d58fa25b0a258, 0xc903c906ca8fcfc9, 0x29a429558d527c29, 0x0a280a5022145a0a, |
0xb1feb1e14f7f50b1, 0xa0baa0691a5dc9a0, 0x6bb16b7fdad6146b, 0x852e855cab17d985, |
0xbdcebd8173673cbd, 0x5d695dd234ba8f5d, 0x1040108050209010, 0xf4f7f4f303f507f4, |
0xcb0bcb16c08bddcb, 0x3ef83eedc67cd33e, 0x05140528110a2d05, 0x6781671fe6ce7867, |
0xe4b7e47353d597e4, 0x279c2725bb4e0227, 0x4119413258827341, 0x8b168b2c9d0ba78b, |
0xa7a6a7510153f6a7, 0x7de97dcf94fab27d, 0x956e95dcfb374995, 0xd847d88e9fad56d8, |
0xfbcbfb8b30eb70fb, 0xee9fee2371c1cdee, 0x7ced7cc791f8bb7c, 0x66856617e3cc7166, |
0xdd53dda68ea77bdd, 0x175c17b84b2eaf17, 0x47014702468e4547, 0x9e429e84dc211a9e, |
0xca0fca1ec589d4ca, 0x2db42d75995a582d, 0xbfc6bf9179632ebf, 0x071c07381b0e3f07, |
0xad8ead012347acad, 0x5a755aea2fb4b05a, 0x8336836cb51bef83, 0x33cc3385ff66b633, |
0x6391633ff2c65c63, 0x020802100a041202, 0xaa92aa39384993aa, 0x71d971afa8e2de71, |
0xc807c80ecf8dc6c8, 0x196419c87d32d119, 0x4939497270923b49, 0xd943d9869aaf5fd9, |
0xf2eff2c31df931f2, 0xe3abe34b48dba8e3, 0x5b715be22ab6b95b, 0x881a8834920dbc88, |
0x9a529aa4c8293e9a, 0x2698262dbe4c0b26, 0x32c8328dfa64bf32, 0xb0fab0e94a7d59b0, |
0xe983e91b6acff2e9, 0x0f3c0f78331e770f, 0xd573d5e6a6b733d5, 0x803a8074ba1df480, |
0xbec2be997c6127be, 0xcd13cd26de87ebcd, 0x34d034bde4688934, 0x483d487a75903248, |
0xffdbffab24e354ff, 0x7af57af78ff48d7a, 0x907a90f4ea3d6490, 0x5f615fc23ebe9d5f, |
0x2080201da0403d20, 0x68bd6867d5d00f68, 0x1a681ad07234ca1a, 0xae82ae192c41b7ae, |
0xb4eab4c95e757db4, 0x544d549a19a8ce54, 0x937693ece53b7f93, 0x2288220daa442f22, |
0x648d6407e9c86364, 0xf1e3f1db12ff2af1, 0x73d173bfa2e6cc73, 0x124812905a248212, |
0x401d403a5d807a40, 0x0820084028104808, 0xc32bc356e89b95c3, 0xec97ec337bc5dfec, |
0xdb4bdb9690ab4ddb, 0xa1bea1611f5fc0a1, 0x8d0e8d1c8307918d, 0x3df43df5c97ac83d, |
0x976697ccf1335b97, 0x0000000000000000, 0xcf1bcf36d483f9cf, 0x2bac2b4587566e2b, |
0x76c57697b3ece176, 0x82328264b019e682, 0xd67fd6fea9b128d6, 0x1b6c1bd87736c31b, |
0xb5eeb5c15b7774b5, 0xaf86af112943beaf, 0x6ab56a77dfd41d6a, 0x505d50ba0da0ea50, |
0x450945124c8a5745, 0xf3ebf3cb18fb38f3, 0x30c0309df060ad30, 0xef9bef2b74c3c4ef, |
0x3ffc3fe5c37eda3f, 0x554955921caac755, 0xa2b2a2791059dba2, 0xea8fea0365c9e9ea, |
0x6589650fecca6a65, 0xbad2bab9686903ba, 0x2fbc2f65935e4a2f, 0xc027c04ee79d8ec0, |
0xde5fdebe81a160de, 0x1c701ce06c38fc1c, 0xfdd3fdbb2ee746fd, 0x4d294d52649a1f4d, |
0x927292e4e0397692, 0x75c9758fbceafa75, 0x061806301e0c3606, 0x8a128a249809ae8a, |
0xb2f2b2f940794bb2, 0xe6bfe66359d185e6, 0x0e380e70361c7e0e, 0x1f7c1ff8633ee71f, |
0x62956237f7c45562, 0xd477d4eea3b53ad4, 0xa89aa829324d81a8, 0x966296c4f4315296, |
0xf9c3f99b3aef62f9, 0xc533c566f697a3c5, 0x25942535b14a1025, 0x597959f220b2ab59, |
0x842a8454ae15d084, 0x72d572b7a7e4c572, 0x39e439d5dd72ec39, 0x4c2d4c5a6198164c, |
0x5e655eca3bbc945e, 0x78fd78e785f09f78, 0x38e038ddd870e538, 0x8c0a8c148605988c, |
0xd163d1c6b2bf17d1, 0xa5aea5410b57e4a5, 0xe2afe2434dd9a1e2, 0x6199612ff8c24e61, |
0xb3f6b3f1457b42b3, 0x21842115a5423421, 0x9c4a9c94d625089c, 0x1e781ef0663cee1e, |
0x4311432252866143, 0xc73bc776fc93b1c7, 0xfcd7fcb32be54ffc, 0x0410042014082404, |
0x515951b208a2e351, 0x995e99bcc72f2599, 0x6da96d4fc4da226d, 0x0d340d68391a650d, |
0xfacffa8335e979fa, 0xdf5bdfb684a369df, 0x7ee57ed79bfca97e, 0x2490243db4481924, |
0x3bec3bc5d776fe3b, 0xab96ab313d4b9aab, 0xce1fce3ed181f0ce, 0x1144118855229911, |
0x8f068f0c8903838f, 0x4e254e4a6b9c044e, 0xb7e6b7d1517366b7, 0xeb8beb0b60cbe0eb, |
0x3cf03cfdcc78c13c, 0x813e817cbf1ffd81, 0x946a94d4fe354094, 0xf7fbf7eb0cf31cf7, |
0xb9deb9a1676f18b9, 0x134c13985f268b13, 0x2cb02c7d9c58512c, 0xd36bd3d6b8bb05d3, |
0xe7bbe76b5cd38ce7, 0x6ea56e57cbdc396e, 0xc437c46ef395aac4, 0x030c03180f061b03, |
0x5645568a13acdc56, 0x440d441a49885e44, 0x7fe17fdf9efea07f, 0xa99ea921374f88a9, |
0x2aa82a4d8254672a, 0xbbd6bbb16d6b0abb, 0xc123c146e29f87c1, 0x535153a202a6f153, |
0xdc57dcae8ba572dc, 0x0b2c0b582716530b, 0x9d4e9d9cd327019d, 0x6cad6c47c1d82b6c, |
0x31c43195f562a431, 0x74cd7487b9e8f374, 0xf6fff6e309f115f6, 0x4605460a438c4c46, |
0xac8aac092645a5ac, 0x891e893c970fb589, 0x145014a04428b414, 0xe1a3e15b42dfbae1, |
0x165816b04e2ca616, 0x3ae83acdd274f73a, 0x69b9696fd0d20669, 0x092409482d124109, |
0x70dd70a7ade0d770, 0xb6e2b6d954716fb6, 0xd067d0ceb7bd1ed0, 0xed93ed3b7ec7d6ed, |
0xcc17cc2edb85e2cc, 0x4215422a57846842, 0x985a98b4c22d2c98, 0xa4aaa4490e55eda4, |
0x28a0285d88507528, 0x5c6d5cda31b8865c, 0xf8c7f8933fed6bf8, 0x86228644a411c286, |
] |
rc = [ |
0x0000000000000000, |
0x1823c6e887b8014f, |
0x36a6d2f5796f9152, |
0x60bc9b8ea30c7b35, |
0x1de0d7c22e4bfe57, |
0x157737e59ff04ada, |
0x58c9290ab1a06b85, |
0xbd5d10f4cb3e0567, |
0xe427418ba77d95d8, |
0xfbee7c66dd17479e, |
0xca2dbf07ad5a8333 |
] |
DIGESTBYTES = 64 |
class WhirlpoolStruct: |
def __init__(self): |
self.bitLength = [0]*32 |
self.buffer = [0]*64 |
self.bufferBits = 0 |
self.bufferPos = 0 |
self.hash = [0]*8 |
def WhirlpoolInit(ctx): |
ctx = WhirlpoolStruct() |
return |
def WhirlpoolAdd(source, sourceBits, ctx): |
source = [ord(s)&0xff for s in source] |
carry = 0 |
value = sourceBits |
i = 31 |
while i >= 0 and value != 0: |
carry += ctx.bitLength[i] + ((value % 0x100000000) & 0xff) |
ctx.bitLength[i] = carry % 0x100 |
carry >>= 8 |
value >>= 8 |
i -= 1 |
bufferBits = ctx.bufferBits |
bufferPos = ctx.bufferPos |
sourcePos = 0 |
sourceGap = (8 - (sourceBits & 7)) & 7 |
bufferRem = ctx.bufferBits & 7 |
buffr = ctx.buffer |
while sourceBits > 8: |
b = ((source[sourcePos] << sourceGap) & 0xff) | ((source[sourcePos + 1] & 0xff) >> (8 - sourceGap)) |
buffr[bufferPos] |= (b >> bufferRem) % 0x100 |
bufferPos += 1 |
bufferBits += 8 - bufferRem |
if bufferBits == 512: |
processBuffer(ctx) |
bufferBits = 0 |
bufferPos = 0 |
buffr[bufferPos] = b << (8 - bufferRem) |
bufferBits += bufferRem |
sourceBits -= 8 |
sourcePos += 1 |
b = (source[sourcePos] << sourceGap) & 0xff |
buffr[bufferPos] |= b >> bufferRem |
if bufferRem + sourceBits < 8: |
bufferBits += sourceBits |
else: |
bufferPos += 1 |
bufferBits += 8 - bufferRem |
sourceBits -= 8 - bufferRem |
if bufferBits == 512: |
processBuffer(ctx) |
bufferBits = 0 |
bufferPos = 0 |
buffr[bufferPos] = b << (8 - bufferRem) |
bufferBits += sourceBits |
ctx.bufferBits = bufferBits |
ctx.bufferPos = bufferPos |
def WhirlpoolFinalize(ctx): |
bufferPos = ctx.bufferPos |
ctx.buffer[bufferPos] |= 0x80 >> (ctx.bufferBits & 7) |
bufferPos += 1 |
if bufferPos > 32: |
if bufferPos < 64: |
for i in xrange(64 - bufferPos): |
ctx.buffer[bufferPos+i] = 0 |
processBuffer(ctx) |
bufferPos = 0 |
if bufferPos < 32: |
for i in xrange(32 - bufferPos): |
ctx.buffer[bufferPos+i] = 0 |
bufferPos = 32 |
for i in xrange(32): |
ctx.buffer[32+i] = ctx.bitLength[i] |
processBuffer(ctx) |
digest = '' |
for i in xrange(8): |
digest += chr((ctx.hash[i] >> 56) % 0x100) |
digest += chr((ctx.hash[i] >> 48) % 0x100) |
digest += chr((ctx.hash[i] >> 40) % 0x100) |
digest += chr((ctx.hash[i] >> 32) % 0x100) |
digest += chr((ctx.hash[i] >> 24) % 0x100) |
digest += chr((ctx.hash[i] >> 16) % 0x100) |
digest += chr((ctx.hash[i] >> 8) % 0x100) |
digest += chr((ctx.hash[i]) % 0x100) |
ctx.bufferPos = bufferPos |
return digest |
def CDo(buf, a0, a1, a2, a3, a4, a5, a6, a7): |
return C0[((buf[a0] >> 56) % 0x100000000) & 0xff] ^ \ |
C1[((buf[a1] >> 48) % 0x100000000) & 0xff] ^ \ |
C2[((buf[a2] >> 40) % 0x100000000) & 0xff] ^ \ |
C3[((buf[a3] >> 32) % 0x100000000) & 0xff] ^ \ |
C4[((buf[a4] >> 24) % 0x100000000) & 0xff] ^ \ |
C5[((buf[a5] >> 16) % 0x100000000) & 0xff] ^ \ |
C6[((buf[a6] >> 8) % 0x100000000) & 0xff] ^ \ |
C7[((buf[a7] >> 0) % 0x100000000) & 0xff] |
def processBuffer(ctx): |
i, r = 0, 0 |
K = [0]*8 |
block = [0]*8 |
state = [0]*8 |
L = [0]*8 |
buffr = ctx.buffer |
buf_cnt = 0 |
for i in xrange(8): |
block[i] = ((buffr[buf_cnt+0] & 0xff) << 56) ^ \ |
((buffr[buf_cnt+1] & 0xff) << 48) ^ \ |
((buffr[buf_cnt+2] & 0xff) << 40) ^ \ |
((buffr[buf_cnt+3] & 0xff) << 32) ^ \ |
((buffr[buf_cnt+4] & 0xff) << 24) ^ \ |
((buffr[buf_cnt+5] & 0xff) << 16) ^ \ |
((buffr[buf_cnt+6] & 0xff) << 8) ^ \ |
((buffr[buf_cnt+7] & 0xff) << 0) |
buf_cnt += 8 |
for i in xrange(8): |
K[i] = ctx.hash[i] |
state[i] = block[i] ^ K[i] |
for r in xrange(1, R+1): |
L[0] = CDo(K, 0, 7, 6, 5, 4, 3, 2, 1) ^ rc[r] |
L[1] = CDo(K, 1, 0, 7, 6, 5, 4, 3, 2) |
L[2] = CDo(K, 2, 1, 0, 7, 6, 5, 4, 3) |
L[3] = CDo(K, 3, 2, 1, 0, 7, 6, 5, 4) |
L[4] = CDo(K, 4, 3, 2, 1, 0, 7, 6, 5) |
L[5] = CDo(K, 5, 4, 3, 2, 1, 0, 7, 6) |
L[6] = CDo(K, 6, 5, 4, 3, 2, 1, 0, 7) |
L[7] = CDo(K, 7, 6, 5, 4, 3, 2, 1, 0) |
for i in xrange(8): |
K[i] = L[i] |
L[0] = CDo(state, 0, 7, 6, 5, 4, 3, 2, 1) ^ K[0] |
L[1] = CDo(state, 1, 0, 7, 6, 5, 4, 3, 2) ^ K[1] |
L[2] = CDo(state, 2, 1, 0, 7, 6, 5, 4, 3) ^ K[2] |
L[3] = CDo(state, 3, 2, 1, 0, 7, 6, 5, 4) ^ K[3] |
L[4] = CDo(state, 4, 3, 2, 1, 0, 7, 6, 5) ^ K[4] |
L[5] = CDo(state, 5, 4, 3, 2, 1, 0, 7, 6) ^ K[5] |
L[6] = CDo(state, 6, 5, 4, 3, 2, 1, 0, 7) ^ K[6] |
L[7] = CDo(state, 7, 6, 5, 4, 3, 2, 1, 0) ^ K[7] |
for i in xrange(8): |
state[i] = L[i] |
# apply the Miyaguchi-Preneel compression function |
for i in xrange(8): |
ctx.hash[i] ^= state[i] ^ block[i] |
return |
# |
# Tests. |
# |
assert Whirlpool('The quick brown fox jumps over the lazy dog').hexdigest() == \ |
'b97de512e91e3828b40d2b0fdce9ceb3c4a71f9bea8d88e75c4fa854df36725fd2b52eb6544edcacd6f8beddfea403cb55ae31f03ad62a5ef54e42ee82c3fb35' |
assert Whirlpool('The quick brown fox jumps over the lazy eog').hexdigest() == \ |
'c27ba124205f72e6847f3e19834f925cc666d0974167af915bb462420ed40cc50900d85a1f923219d832357750492d5c143011a76988344c2635e69d06f2d38c' |
assert Whirlpool('').hexdigest() == \ |
'19fa61d75522a4669b44e39c1d2e1726c530232130d407f89afee0964997f7a73e83be698b288febcf88e3e03c4f0757ea8964e59b63d93708b138cc42a66eb3' |