mirror of
https://github.com/GAM-team/GAM.git
synced 2025-05-12 12:17:20 +00:00
205 lines
6.0 KiB
Python
205 lines
6.0 KiB
Python
"""passlib.utils._blowfish._gen_files - meta script that generates unrolled.py"""
|
|
#=============================================================================
|
|
# imports
|
|
#=============================================================================
|
|
# core
|
|
import os
|
|
import textwrap
|
|
# pkg
|
|
from passlib.utils.compat import irange
|
|
# local
|
|
|
|
#=============================================================================
|
|
# helpers
|
|
#=============================================================================
|
|
def varlist(name, count):
|
|
return ", ".join(name + str(x) for x in irange(count))
|
|
|
|
|
|
def indent_block(block, padding):
|
|
"ident block of text"
|
|
lines = block.split("\n")
|
|
return "\n".join(
|
|
padding + line if line else ""
|
|
for line in lines
|
|
)
|
|
|
|
BFSTR = """\
|
|
((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
|
|
S3[l & 0xff]) & 0xffffffff)
|
|
""".strip()
|
|
|
|
def render_encipher(write, indent=0):
|
|
for i in irange(0, 15, 2):
|
|
write(indent, """\
|
|
# Feistel substitution on left word (round %(i)d)
|
|
r ^= %(left)s ^ p%(i1)d
|
|
|
|
# Feistel substitution on right word (round %(i1)d)
|
|
l ^= %(right)s ^ p%(i2)d
|
|
""", i=i, i1=i+1, i2=i+2,
|
|
left=BFSTR, right=BFSTR.replace("l","r"),
|
|
)
|
|
|
|
def write_encipher_function(write, indent=0):
|
|
write(indent, """\
|
|
def encipher(self, l, r):
|
|
\"""blowfish encipher a single 64-bit block encoded as two 32-bit ints\"""
|
|
|
|
(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9,
|
|
p10, p11, p12, p13, p14, p15, p16, p17) = self.P
|
|
S0, S1, S2, S3 = self.S
|
|
|
|
l ^= p0
|
|
|
|
""")
|
|
render_encipher(write, indent+1)
|
|
|
|
write(indent+1, """\
|
|
|
|
return r ^ p17, l
|
|
|
|
""")
|
|
|
|
def write_expand_function(write, indent=0):
|
|
write(indent, """\
|
|
def expand(self, key_words):
|
|
\"""unrolled version of blowfish key expansion\"""
|
|
##assert len(key_words) >= 18, "size of key_words must be >= 18"
|
|
|
|
P, S = self.P, self.S
|
|
S0, S1, S2, S3 = S
|
|
|
|
#=============================================================
|
|
# integrate key
|
|
#=============================================================
|
|
""")
|
|
for i in irange(18):
|
|
write(indent+1, """\
|
|
p%(i)d = P[%(i)d] ^ key_words[%(i)d]
|
|
""", i=i)
|
|
write(indent+1, """\
|
|
|
|
#=============================================================
|
|
# update P
|
|
#=============================================================
|
|
|
|
#------------------------------------------------
|
|
# update P[0] and P[1]
|
|
#------------------------------------------------
|
|
l, r = p0, 0
|
|
|
|
""")
|
|
|
|
render_encipher(write, indent+1)
|
|
|
|
write(indent+1, """\
|
|
|
|
p0, p1 = l, r = r ^ p17, l
|
|
|
|
""")
|
|
|
|
for i in irange(2, 18, 2):
|
|
write(indent+1, """\
|
|
#------------------------------------------------
|
|
# update P[%(i)d] and P[%(i1)d]
|
|
#------------------------------------------------
|
|
l ^= p0
|
|
|
|
""", i=i, i1=i+1)
|
|
|
|
render_encipher(write, indent+1)
|
|
|
|
write(indent+1, """\
|
|
p%(i)d, p%(i1)d = l, r = r ^ p17, l
|
|
|
|
""", i=i, i1=i+1)
|
|
|
|
write(indent+1, """\
|
|
|
|
#------------------------------------------------
|
|
# save changes to original P array
|
|
#------------------------------------------------
|
|
P[:] = (p0, p1, p2, p3, p4, p5, p6, p7, p8, p9,
|
|
p10, p11, p12, p13, p14, p15, p16, p17)
|
|
|
|
#=============================================================
|
|
# update S
|
|
#=============================================================
|
|
|
|
for box in S:
|
|
j = 0
|
|
while j < 256:
|
|
l ^= p0
|
|
|
|
""")
|
|
|
|
render_encipher(write, indent+3)
|
|
|
|
write(indent+3, """\
|
|
|
|
box[j], box[j+1] = l, r = r ^ p17, l
|
|
j += 2
|
|
""")
|
|
|
|
#=============================================================================
|
|
# main
|
|
#=============================================================================
|
|
|
|
def main():
|
|
target = os.path.join(os.path.dirname(__file__), "unrolled.py")
|
|
fh = file(target, "w")
|
|
|
|
def write(indent, msg, **kwds):
|
|
literal = kwds.pop("literal", False)
|
|
if kwds:
|
|
msg %= kwds
|
|
if not literal:
|
|
msg = textwrap.dedent(msg.rstrip(" "))
|
|
if indent:
|
|
msg = indent_block(msg, " " * (indent*4))
|
|
fh.write(msg)
|
|
|
|
write(0, """\
|
|
\"""passlib.utils._blowfish.unrolled - unrolled loop implementation of bcrypt,
|
|
autogenerated by _gen_files.py
|
|
|
|
currently this override the encipher() and expand() methods
|
|
with optimized versions, and leaves the other base.py methods alone.
|
|
\"""
|
|
#=================================================================
|
|
# imports
|
|
#=================================================================
|
|
# pkg
|
|
from passlib.utils._blowfish.base import BlowfishEngine as _BlowfishEngine
|
|
# local
|
|
__all__ = [
|
|
"BlowfishEngine",
|
|
]
|
|
#=================================================================
|
|
#
|
|
#=================================================================
|
|
class BlowfishEngine(_BlowfishEngine):
|
|
|
|
""")
|
|
|
|
write_encipher_function(write, indent=1)
|
|
write_expand_function(write, indent=1)
|
|
|
|
write(0, """\
|
|
#=================================================================
|
|
# eoc
|
|
#=================================================================
|
|
|
|
#=================================================================
|
|
# eof
|
|
#=================================================================
|
|
""")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
|
|
#=============================================================================
|
|
# eof
|
|
#=============================================================================
|