1
0
mirror of https://gitlab.com/MoonTestUse1/AdministrationItDepartmens.git synced 2025-08-14 00:25:46 +02:00

Initial commit

This commit is contained in:
MoonTestUse1
2024-12-23 19:27:44 +06:00
commit e81df4c87e
4952 changed files with 1705479 additions and 0 deletions

View File

@@ -0,0 +1 @@
"""passlib.crypto -- package containing cryptographic primitives used by passlib"""

View File

@@ -0,0 +1,169 @@
"""passlib.crypto._blowfish - pure-python eks-blowfish implementation for bcrypt
This is a pure-python implementation of the EKS-Blowfish algorithm described by
Provos and Mazieres in `A Future-Adaptable Password Scheme
<http://www.openbsd.org/papers/bcrypt-paper.ps>`_.
This package contains two submodules:
* ``_blowfish/base.py`` contains a class implementing the eks-blowfish algorithm
using easy-to-examine code.
* ``_blowfish/unrolled.py`` contains a subclass which replaces some methods
of the original class with sped-up versions, mainly using unrolled loops
and local variables. this is the class which is actually used by
Passlib to perform BCrypt in pure python.
This module is auto-generated by a script, ``_blowfish/_gen_files.py``.
Status
------
This implementation is usable, but is an order of magnitude too slow to be
usable with real security. For "ok" security, BCrypt hashes should have at
least 2**11 rounds (as of 2011). Assuming a desired response time <= 100ms,
this means a BCrypt implementation should get at least 20 rounds/ms in order
to be both usable *and* secure. On a 2 ghz cpu, this implementation gets
roughly 0.09 rounds/ms under CPython (220x too slow), and 1.9 rounds/ms
under PyPy (10x too slow).
History
-------
While subsequently modified considerly for Passlib, this code was originally
based on `jBcrypt 0.2 <http://www.mindrot.org/projects/jBCrypt/>`_, which was
released under the BSD license::
Copyright (c) 2006 Damien Miller <djm@mindrot.org>
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
"""
#=============================================================================
# imports
#=============================================================================
# core
from itertools import chain
import struct
# pkg
from passlib.utils import getrandbytes, rng
from passlib.utils.binary import bcrypt64
from passlib.utils.compat import BytesIO, unicode, u, native_string_types
from passlib.crypto._blowfish.unrolled import BlowfishEngine
# local
__all__ = [
'BlowfishEngine',
'raw_bcrypt',
]
#=============================================================================
# bcrypt constants
#=============================================================================
# bcrypt constant data "OrpheanBeholderScryDoubt" as 6 integers
BCRYPT_CDATA = [
0x4f727068, 0x65616e42, 0x65686f6c,
0x64657253, 0x63727944, 0x6f756274
]
# struct used to encode ciphertext as digest (last output byte discarded)
digest_struct = struct.Struct(">6I")
#=============================================================================
# base bcrypt helper
#
# interface designed only for use by passlib.handlers.bcrypt:BCrypt
# probably not suitable for other purposes
#=============================================================================
BNULL = b'\x00'
def raw_bcrypt(password, ident, salt, log_rounds):
"""perform central password hashing step in bcrypt scheme.
:param password: the password to hash
:param ident: identifier w/ minor version (e.g. 2, 2a)
:param salt: the binary salt to use (encoded in bcrypt-base64)
:param log_rounds: the log2 of the number of rounds (as int)
:returns: bcrypt-base64 encoded checksum
"""
#===================================================================
# parse inputs
#===================================================================
# parse ident
assert isinstance(ident, native_string_types)
add_null_padding = True
if ident == u('2a') or ident == u('2y') or ident == u('2b'):
pass
elif ident == u('2'):
add_null_padding = False
elif ident == u('2x'):
raise ValueError("crypt_blowfish's buggy '2x' hashes are not "
"currently supported")
else:
raise ValueError("unknown ident: %r" % (ident,))
# decode & validate salt
assert isinstance(salt, bytes)
salt = bcrypt64.decode_bytes(salt)
if len(salt) < 16:
raise ValueError("Missing salt bytes")
elif len(salt) > 16:
salt = salt[:16]
# prepare password
assert isinstance(password, bytes)
if add_null_padding:
password += BNULL
# validate rounds
if log_rounds < 4 or log_rounds > 31:
raise ValueError("Bad number of rounds")
#===================================================================
#
# run EKS-Blowfish algorithm
#
# This uses the "enhanced key schedule" step described by
# Provos and Mazieres in "A Future-Adaptable Password Scheme"
# http://www.openbsd.org/papers/bcrypt-paper.ps
#
#===================================================================
engine = BlowfishEngine()
# convert password & salt into list of 18 32-bit integers (72 bytes total).
pass_words = engine.key_to_words(password)
salt_words = engine.key_to_words(salt)
# truncate salt_words to original 16 byte salt, or loop won't wrap
# correctly when passed to .eks_salted_expand()
salt_words16 = salt_words[:4]
# do EKS key schedule setup
engine.eks_salted_expand(pass_words, salt_words16)
# apply password & salt keys to key schedule a bunch more times.
rounds = 1<<log_rounds
engine.eks_repeated_expand(pass_words, salt_words, rounds)
# encipher constant data, and encode to bytes as digest.
data = list(BCRYPT_CDATA)
i = 0
while i < 6:
data[i], data[i+1] = engine.repeat_encipher(data[i], data[i+1], 64)
i += 2
raw = digest_struct.pack(*data)[:-1]
return bcrypt64.encode_bytes(raw)
#=============================================================================
# eof
#=============================================================================

View File

@@ -0,0 +1,204 @@
"""passlib.crypto._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.crypto._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.crypto._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
#=============================================================================

View File

@@ -0,0 +1,441 @@
"""passlib.crypto._blowfish.base - unoptimized pure-python blowfish engine"""
#=============================================================================
# imports
#=============================================================================
# core
import struct
# pkg
from passlib.utils import repeat_string
# local
__all__ = [
"BlowfishEngine",
]
#=============================================================================
# blowfish constants
#=============================================================================
BLOWFISH_P = BLOWFISH_S = None
def _init_constants():
global BLOWFISH_P, BLOWFISH_S
# NOTE: blowfish's spec states these numbers are the hex representation
# of the fractional portion of PI, in order.
# Initial contents of key schedule - 18 integers
BLOWFISH_P = [
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
0x9216d5d9, 0x8979fb1b,
]
# all 4 blowfish S boxes in one array - 256 integers per S box
BLOWFISH_S = [
# sbox 1
[
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
],
# sbox 2
[
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
],
# sbox 3
[
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
],
# sbox 4
[
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
]
]
#=============================================================================
# engine
#=============================================================================
class BlowfishEngine(object):
def __init__(self):
if BLOWFISH_P is None:
_init_constants()
self.P = list(BLOWFISH_P)
self.S = [ list(box) for box in BLOWFISH_S ]
#===================================================================
# common helpers
#===================================================================
@staticmethod
def key_to_words(data, size=18):
"""convert data to tuple of <size> 4-byte integers, repeating or
truncating data as needed to reach specified size"""
assert isinstance(data, bytes)
dlen = len(data)
if not dlen:
# return all zeros - original C code would just read the NUL after
# the password, so mimicing that behavior for this edge case.
return [0]*size
# repeat data until it fills up 4*size bytes
data = repeat_string(data, size<<2)
# unpack
return struct.unpack(">%dI" % (size,), data)
#===================================================================
# blowfish routines
#===================================================================
def encipher(self, l, r):
"""loop version of blowfish encipher routine"""
P, S = self.P, self.S
l ^= P[0]
i = 1
while i < 17:
# Feistel substitution on left word
r = ((((S[0][l >> 24] + S[1][(l >> 16) & 0xff]) ^ S[2][(l >> 8) & 0xff]) +
S[3][l & 0xff]) & 0xffffffff) ^ P[i] ^ r
# swap vars so even rounds do Feistel substition on right word
l, r = r, l
i += 1
return r ^ P[17], l
# NOTE: decipher is same as above, just with reversed(P) instead.
def expand(self, key_words):
"""perform stock Blowfish keyschedule setup"""
assert len(key_words) >= 18, "key_words must be at least as large as P"
P, S, encipher = self.P, self.S, self.encipher
i = 0
while i < 18:
P[i] ^= key_words[i]
i += 1
i = l = r = 0
while i < 18:
P[i], P[i+1] = l,r = encipher(l,r)
i += 2
for box in S:
i = 0
while i < 256:
box[i], box[i+1] = l,r = encipher(l,r)
i += 2
#===================================================================
# eks-blowfish routines
#===================================================================
def eks_salted_expand(self, key_words, salt_words):
"""perform EKS' salted version of Blowfish keyschedule setup"""
# NOTE: this is the same as expand(), except for the addition
# of the operations involving *salt_words*.
assert len(key_words) >= 18, "key_words must be at least as large as P"
salt_size = len(salt_words)
assert salt_size, "salt_words must not be empty"
assert not salt_size & 1, "salt_words must have even length"
P, S, encipher = self.P, self.S, self.encipher
i = 0
while i < 18:
P[i] ^= key_words[i]
i += 1
s = i = l = r = 0
while i < 18:
l ^= salt_words[s]
r ^= salt_words[s+1]
s += 2
if s == salt_size:
s = 0
P[i], P[i+1] = l,r = encipher(l,r) # next()
i += 2
for box in S:
i = 0
while i < 256:
l ^= salt_words[s]
r ^= salt_words[s+1]
s += 2
if s == salt_size:
s = 0
box[i], box[i+1] = l,r = encipher(l,r) # next()
i += 2
def eks_repeated_expand(self, key_words, salt_words, rounds):
"""perform rounds stage of EKS keyschedule setup"""
expand = self.expand
n = 0
while n < rounds:
expand(key_words)
expand(salt_words)
n += 1
def repeat_encipher(self, l, r, count):
"""repeatedly apply encipher operation to a block"""
encipher = self.encipher
n = 0
while n < count:
l, r = encipher(l, r)
n += 1
return l, r
#===================================================================
# eoc
#===================================================================
#=============================================================================
# eof
#=============================================================================

View File

@@ -0,0 +1,771 @@
"""passlib.crypto._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.crypto._blowfish.base import BlowfishEngine as _BlowfishEngine
# local
__all__ = [
"BlowfishEngine",
]
#=============================================================================
#
#=============================================================================
class BlowfishEngine(_BlowfishEngine):
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
# Feistel substitution on left word (round 0)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p1
# Feistel substitution on right word (round 1)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p2
# Feistel substitution on left word (round 2)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p3
# Feistel substitution on right word (round 3)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p4
# Feistel substitution on left word (round 4)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p5
# Feistel substitution on right word (round 5)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p6
# Feistel substitution on left word (round 6)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p7
# Feistel substitution on right word (round 7)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p8
# Feistel substitution on left word (round 8)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p9
# Feistel substitution on right word (round 9)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p10
# Feistel substitution on left word (round 10)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p11
# Feistel substitution on right word (round 11)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p12
# Feistel substitution on left word (round 12)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p13
# Feistel substitution on right word (round 13)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p14
# Feistel substitution on left word (round 14)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p15
# Feistel substitution on right word (round 15)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p16
return r ^ p17, l
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
#=============================================================
p0 = P[0] ^ key_words[0]
p1 = P[1] ^ key_words[1]
p2 = P[2] ^ key_words[2]
p3 = P[3] ^ key_words[3]
p4 = P[4] ^ key_words[4]
p5 = P[5] ^ key_words[5]
p6 = P[6] ^ key_words[6]
p7 = P[7] ^ key_words[7]
p8 = P[8] ^ key_words[8]
p9 = P[9] ^ key_words[9]
p10 = P[10] ^ key_words[10]
p11 = P[11] ^ key_words[11]
p12 = P[12] ^ key_words[12]
p13 = P[13] ^ key_words[13]
p14 = P[14] ^ key_words[14]
p15 = P[15] ^ key_words[15]
p16 = P[16] ^ key_words[16]
p17 = P[17] ^ key_words[17]
#=============================================================
# update P
#=============================================================
#------------------------------------------------
# update P[0] and P[1]
#------------------------------------------------
l, r = p0, 0
# Feistel substitution on left word (round 0)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p1
# Feistel substitution on right word (round 1)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p2
# Feistel substitution on left word (round 2)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p3
# Feistel substitution on right word (round 3)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p4
# Feistel substitution on left word (round 4)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p5
# Feistel substitution on right word (round 5)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p6
# Feistel substitution on left word (round 6)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p7
# Feistel substitution on right word (round 7)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p8
# Feistel substitution on left word (round 8)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p9
# Feistel substitution on right word (round 9)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p10
# Feistel substitution on left word (round 10)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p11
# Feistel substitution on right word (round 11)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p12
# Feistel substitution on left word (round 12)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p13
# Feistel substitution on right word (round 13)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p14
# Feistel substitution on left word (round 14)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p15
# Feistel substitution on right word (round 15)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p16
p0, p1 = l, r = r ^ p17, l
#------------------------------------------------
# update P[2] and P[3]
#------------------------------------------------
l ^= p0
# Feistel substitution on left word (round 0)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p1
# Feistel substitution on right word (round 1)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p2
# Feistel substitution on left word (round 2)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p3
# Feistel substitution on right word (round 3)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p4
# Feistel substitution on left word (round 4)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p5
# Feistel substitution on right word (round 5)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p6
# Feistel substitution on left word (round 6)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p7
# Feistel substitution on right word (round 7)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p8
# Feistel substitution on left word (round 8)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p9
# Feistel substitution on right word (round 9)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p10
# Feistel substitution on left word (round 10)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p11
# Feistel substitution on right word (round 11)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p12
# Feistel substitution on left word (round 12)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p13
# Feistel substitution on right word (round 13)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p14
# Feistel substitution on left word (round 14)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p15
# Feistel substitution on right word (round 15)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p16
p2, p3 = l, r = r ^ p17, l
#------------------------------------------------
# update P[4] and P[5]
#------------------------------------------------
l ^= p0
# Feistel substitution on left word (round 0)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p1
# Feistel substitution on right word (round 1)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p2
# Feistel substitution on left word (round 2)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p3
# Feistel substitution on right word (round 3)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p4
# Feistel substitution on left word (round 4)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p5
# Feistel substitution on right word (round 5)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p6
# Feistel substitution on left word (round 6)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p7
# Feistel substitution on right word (round 7)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p8
# Feistel substitution on left word (round 8)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p9
# Feistel substitution on right word (round 9)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p10
# Feistel substitution on left word (round 10)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p11
# Feistel substitution on right word (round 11)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p12
# Feistel substitution on left word (round 12)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p13
# Feistel substitution on right word (round 13)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p14
# Feistel substitution on left word (round 14)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p15
# Feistel substitution on right word (round 15)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p16
p4, p5 = l, r = r ^ p17, l
#------------------------------------------------
# update P[6] and P[7]
#------------------------------------------------
l ^= p0
# Feistel substitution on left word (round 0)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p1
# Feistel substitution on right word (round 1)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p2
# Feistel substitution on left word (round 2)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p3
# Feistel substitution on right word (round 3)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p4
# Feistel substitution on left word (round 4)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p5
# Feistel substitution on right word (round 5)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p6
# Feistel substitution on left word (round 6)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p7
# Feistel substitution on right word (round 7)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p8
# Feistel substitution on left word (round 8)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p9
# Feistel substitution on right word (round 9)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p10
# Feistel substitution on left word (round 10)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p11
# Feistel substitution on right word (round 11)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p12
# Feistel substitution on left word (round 12)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p13
# Feistel substitution on right word (round 13)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p14
# Feistel substitution on left word (round 14)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p15
# Feistel substitution on right word (round 15)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p16
p6, p7 = l, r = r ^ p17, l
#------------------------------------------------
# update P[8] and P[9]
#------------------------------------------------
l ^= p0
# Feistel substitution on left word (round 0)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p1
# Feistel substitution on right word (round 1)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p2
# Feistel substitution on left word (round 2)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p3
# Feistel substitution on right word (round 3)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p4
# Feistel substitution on left word (round 4)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p5
# Feistel substitution on right word (round 5)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p6
# Feistel substitution on left word (round 6)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p7
# Feistel substitution on right word (round 7)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p8
# Feistel substitution on left word (round 8)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p9
# Feistel substitution on right word (round 9)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p10
# Feistel substitution on left word (round 10)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p11
# Feistel substitution on right word (round 11)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p12
# Feistel substitution on left word (round 12)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p13
# Feistel substitution on right word (round 13)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p14
# Feistel substitution on left word (round 14)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p15
# Feistel substitution on right word (round 15)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p16
p8, p9 = l, r = r ^ p17, l
#------------------------------------------------
# update P[10] and P[11]
#------------------------------------------------
l ^= p0
# Feistel substitution on left word (round 0)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p1
# Feistel substitution on right word (round 1)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p2
# Feistel substitution on left word (round 2)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p3
# Feistel substitution on right word (round 3)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p4
# Feistel substitution on left word (round 4)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p5
# Feistel substitution on right word (round 5)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p6
# Feistel substitution on left word (round 6)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p7
# Feistel substitution on right word (round 7)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p8
# Feistel substitution on left word (round 8)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p9
# Feistel substitution on right word (round 9)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p10
# Feistel substitution on left word (round 10)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p11
# Feistel substitution on right word (round 11)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p12
# Feistel substitution on left word (round 12)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p13
# Feistel substitution on right word (round 13)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p14
# Feistel substitution on left word (round 14)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p15
# Feistel substitution on right word (round 15)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p16
p10, p11 = l, r = r ^ p17, l
#------------------------------------------------
# update P[12] and P[13]
#------------------------------------------------
l ^= p0
# Feistel substitution on left word (round 0)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p1
# Feistel substitution on right word (round 1)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p2
# Feistel substitution on left word (round 2)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p3
# Feistel substitution on right word (round 3)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p4
# Feistel substitution on left word (round 4)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p5
# Feistel substitution on right word (round 5)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p6
# Feistel substitution on left word (round 6)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p7
# Feistel substitution on right word (round 7)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p8
# Feistel substitution on left word (round 8)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p9
# Feistel substitution on right word (round 9)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p10
# Feistel substitution on left word (round 10)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p11
# Feistel substitution on right word (round 11)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p12
# Feistel substitution on left word (round 12)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p13
# Feistel substitution on right word (round 13)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p14
# Feistel substitution on left word (round 14)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p15
# Feistel substitution on right word (round 15)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p16
p12, p13 = l, r = r ^ p17, l
#------------------------------------------------
# update P[14] and P[15]
#------------------------------------------------
l ^= p0
# Feistel substitution on left word (round 0)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p1
# Feistel substitution on right word (round 1)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p2
# Feistel substitution on left word (round 2)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p3
# Feistel substitution on right word (round 3)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p4
# Feistel substitution on left word (round 4)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p5
# Feistel substitution on right word (round 5)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p6
# Feistel substitution on left word (round 6)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p7
# Feistel substitution on right word (round 7)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p8
# Feistel substitution on left word (round 8)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p9
# Feistel substitution on right word (round 9)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p10
# Feistel substitution on left word (round 10)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p11
# Feistel substitution on right word (round 11)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p12
# Feistel substitution on left word (round 12)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p13
# Feistel substitution on right word (round 13)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p14
# Feistel substitution on left word (round 14)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p15
# Feistel substitution on right word (round 15)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p16
p14, p15 = l, r = r ^ p17, l
#------------------------------------------------
# update P[16] and P[17]
#------------------------------------------------
l ^= p0
# Feistel substitution on left word (round 0)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p1
# Feistel substitution on right word (round 1)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p2
# Feistel substitution on left word (round 2)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p3
# Feistel substitution on right word (round 3)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p4
# Feistel substitution on left word (round 4)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p5
# Feistel substitution on right word (round 5)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p6
# Feistel substitution on left word (round 6)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p7
# Feistel substitution on right word (round 7)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p8
# Feistel substitution on left word (round 8)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p9
# Feistel substitution on right word (round 9)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p10
# Feistel substitution on left word (round 10)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p11
# Feistel substitution on right word (round 11)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p12
# Feistel substitution on left word (round 12)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p13
# Feistel substitution on right word (round 13)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p14
# Feistel substitution on left word (round 14)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p15
# Feistel substitution on right word (round 15)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p16
p16, p17 = l, r = r ^ p17, l
#------------------------------------------------
# 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
# Feistel substitution on left word (round 0)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p1
# Feistel substitution on right word (round 1)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p2
# Feistel substitution on left word (round 2)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p3
# Feistel substitution on right word (round 3)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p4
# Feistel substitution on left word (round 4)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p5
# Feistel substitution on right word (round 5)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p6
# Feistel substitution on left word (round 6)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p7
# Feistel substitution on right word (round 7)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p8
# Feistel substitution on left word (round 8)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p9
# Feistel substitution on right word (round 9)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p10
# Feistel substitution on left word (round 10)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p11
# Feistel substitution on right word (round 11)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p12
# Feistel substitution on left word (round 12)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p13
# Feistel substitution on right word (round 13)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p14
# Feistel substitution on left word (round 14)
r ^= ((((S0[l >> 24] + S1[(l >> 16) & 0xff]) ^ S2[(l >> 8) & 0xff]) +
S3[l & 0xff]) & 0xffffffff) ^ p15
# Feistel substitution on right word (round 15)
l ^= ((((S0[r >> 24] + S1[(r >> 16) & 0xff]) ^ S2[(r >> 8) & 0xff]) +
S3[r & 0xff]) & 0xffffffff) ^ p16
box[j], box[j+1] = l, r = r ^ p17, l
j += 2
#===================================================================
# eoc
#===================================================================
#=============================================================================
# eof
#=============================================================================

View File

@@ -0,0 +1,244 @@
"""
passlib.crypto._md4 -- fallback implementation of MD4
Helper implementing insecure and obsolete md4 algorithm.
used for NTHASH format, which is also insecure and broken,
since it's just md4(password).
Implementated based on rfc at http://www.faqs.org/rfcs/rfc1320.html
.. note::
This shouldn't be imported directly, it's merely used conditionally
by ``passlib.crypto.lookup_hash()`` when a native implementation can't be found.
"""
#=============================================================================
# imports
#=============================================================================
# core
from binascii import hexlify
import struct
# site
from passlib.utils.compat import bascii_to_str, irange, PY3
# local
__all__ = ["md4"]
#=============================================================================
# utils
#=============================================================================
def F(x,y,z):
return (x&y) | ((~x) & z)
def G(x,y,z):
return (x&y) | (x&z) | (y&z)
##def H(x,y,z):
## return x ^ y ^ z
MASK_32 = 2**32-1
#=============================================================================
# main class
#=============================================================================
class md4(object):
"""pep-247 compatible implementation of MD4 hash algorithm
.. attribute:: digest_size
size of md4 digest in bytes (16 bytes)
.. method:: update
update digest by appending additional content
.. method:: copy
create clone of digest object, including current state
.. method:: digest
return bytes representing md4 digest of current content
.. method:: hexdigest
return hexadecimal version of digest
"""
# FIXME: make this follow hash object PEP better.
# FIXME: this isn't threadsafe
name = "md4"
digest_size = digestsize = 16
block_size = 64
_count = 0 # number of 64-byte blocks processed so far (not including _buf)
_state = None # list of [a,b,c,d] 32 bit ints used as internal register
_buf = None # data processed in 64 byte blocks, this holds leftover from last update
def __init__(self, content=None):
self._count = 0
self._state = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476]
self._buf = b''
if content:
self.update(content)
# round 1 table - [abcd k s]
_round1 = [
[0,1,2,3, 0,3],
[3,0,1,2, 1,7],
[2,3,0,1, 2,11],
[1,2,3,0, 3,19],
[0,1,2,3, 4,3],
[3,0,1,2, 5,7],
[2,3,0,1, 6,11],
[1,2,3,0, 7,19],
[0,1,2,3, 8,3],
[3,0,1,2, 9,7],
[2,3,0,1, 10,11],
[1,2,3,0, 11,19],
[0,1,2,3, 12,3],
[3,0,1,2, 13,7],
[2,3,0,1, 14,11],
[1,2,3,0, 15,19],
]
# round 2 table - [abcd k s]
_round2 = [
[0,1,2,3, 0,3],
[3,0,1,2, 4,5],
[2,3,0,1, 8,9],
[1,2,3,0, 12,13],
[0,1,2,3, 1,3],
[3,0,1,2, 5,5],
[2,3,0,1, 9,9],
[1,2,3,0, 13,13],
[0,1,2,3, 2,3],
[3,0,1,2, 6,5],
[2,3,0,1, 10,9],
[1,2,3,0, 14,13],
[0,1,2,3, 3,3],
[3,0,1,2, 7,5],
[2,3,0,1, 11,9],
[1,2,3,0, 15,13],
]
# round 3 table - [abcd k s]
_round3 = [
[0,1,2,3, 0,3],
[3,0,1,2, 8,9],
[2,3,0,1, 4,11],
[1,2,3,0, 12,15],
[0,1,2,3, 2,3],
[3,0,1,2, 10,9],
[2,3,0,1, 6,11],
[1,2,3,0, 14,15],
[0,1,2,3, 1,3],
[3,0,1,2, 9,9],
[2,3,0,1, 5,11],
[1,2,3,0, 13,15],
[0,1,2,3, 3,3],
[3,0,1,2, 11,9],
[2,3,0,1, 7,11],
[1,2,3,0, 15,15],
]
def _process(self, block):
"""process 64 byte block"""
# unpack block into 16 32-bit ints
X = struct.unpack("<16I", block)
# clone state
orig = self._state
state = list(orig)
# round 1 - F function - (x&y)|(~x & z)
for a,b,c,d,k,s in self._round1:
t = (state[a] + F(state[b],state[c],state[d]) + X[k]) & MASK_32
state[a] = ((t<<s) & MASK_32) + (t>>(32-s))
# round 2 - G function
for a,b,c,d,k,s in self._round2:
t = (state[a] + G(state[b],state[c],state[d]) + X[k] + 0x5a827999) & MASK_32
state[a] = ((t<<s) & MASK_32) + (t>>(32-s))
# round 3 - H function - x ^ y ^ z
for a,b,c,d,k,s in self._round3:
t = (state[a] + (state[b] ^ state[c] ^ state[d]) + X[k] + 0x6ed9eba1) & MASK_32
state[a] = ((t<<s) & MASK_32) + (t>>(32-s))
# add back into original state
for i in irange(4):
orig[i] = (orig[i]+state[i]) & MASK_32
def update(self, content):
if not isinstance(content, bytes):
if PY3:
raise TypeError("expected bytes")
else:
# replicate behavior of hashlib under py2
content = content.encode("ascii")
buf = self._buf
if buf:
content = buf + content
idx = 0
end = len(content)
while True:
next = idx + 64
if next <= end:
self._process(content[idx:next])
self._count += 1
idx = next
else:
self._buf = content[idx:]
return
def copy(self):
other = md4()
other._count = self._count
other._state = list(self._state)
other._buf = self._buf
return other
def digest(self):
# NOTE: backing up state so we can restore it after _process is called,
# in case object is updated again (this is only attr altered by this method)
orig = list(self._state)
# final block: buf + 0x80,
# then 0x00 padding until congruent w/ 56 mod 64 bytes
# then last 8 bytes = msg length in bits
buf = self._buf
msglen = self._count*512 + len(buf)*8
block = buf + b'\x80' + b'\x00' * ((119-len(buf)) % 64) + \
struct.pack("<2I", msglen & MASK_32, (msglen>>32) & MASK_32)
if len(block) == 128:
self._process(block[:64])
self._process(block[64:])
else:
assert len(block) == 64
self._process(block)
# render digest & restore un-finalized state
out = struct.pack("<4I", *self._state)
self._state = orig
return out
def hexdigest(self):
return bascii_to_str(hexlify(self.digest()))
#===================================================================
# eoc
#===================================================================
#=============================================================================
# eof
#=============================================================================

View File

@@ -0,0 +1,848 @@
"""passlib.crypto.des -- DES block encryption routines
History
=======
These routines (which have since been drastically modified for python)
are based on a Java implementation of the des-crypt algorithm,
found at `<http://www.dynamic.net.au/christos/crypt/UnixCrypt2.txt>`_.
The copyright & license for that source is as follows::
UnixCrypt.java 0.9 96/11/25
Copyright (c) 1996 Aki Yoshida. All rights reserved.
Permission to use, copy, modify and distribute this software
for non-commercial or commercial purposes and without fee is
hereby granted provided that this copyright notice appears in
all copies.
---
Unix crypt(3C) utility
@version 0.9, 11/25/96
@author Aki Yoshida
---
modified April 2001
by Iris Van den Broeke, Daniel Deville
---
Unix Crypt.
Implements the one way cryptography used by Unix systems for
simple password protection.
@version $Id: UnixCrypt2.txt,v 1.1.1.1 2005/09/13 22:20:13 christos Exp $
@author Greg Wilkins (gregw)
The netbsd des-crypt implementation has some nice notes on how this all works -
http://fxr.googlebit.com/source/lib/libcrypt/crypt.c?v=NETBSD-CURRENT
"""
# TODO: could use an accelerated C version of this module to speed up lmhash,
# des-crypt, and ext-des-crypt
#=============================================================================
# imports
#=============================================================================
# core
import struct
# pkg
from passlib import exc
from passlib.utils.compat import join_byte_values, byte_elem_value, \
irange, irange, int_types
# local
__all__ = [
"expand_des_key",
"des_encrypt_block",
]
#=============================================================================
# constants
#=============================================================================
# masks/upper limits for various integer sizes
INT_24_MASK = 0xffffff
INT_56_MASK = 0xffffffffffffff
INT_64_MASK = 0xffffffffffffffff
# mask to clear parity bits from 64-bit key
_KDATA_MASK = 0xfefefefefefefefe
_KPARITY_MASK = 0x0101010101010101
# mask used to setup key schedule
_KS_MASK = 0xfcfcfcfcffffffff
#=============================================================================
# static DES tables
#=============================================================================
# placeholders filled in by _load_tables()
PCXROT = IE3264 = SPE = CF6464 = None
def _load_tables():
"""delay loading tables until they are actually needed"""
global PCXROT, IE3264, SPE, CF6464
#---------------------------------------------------------------
# Initial key schedule permutation
# PC1ROT - bit reverse, then PC1, then Rotate, then PC2
#---------------------------------------------------------------
# NOTE: this was reordered from original table to make perm3264 logic simpler
PC1ROT=(
( 0x0000000000000000, 0x0000000000000000, 0x0000000000002000, 0x0000000000002000,
0x0000000000000020, 0x0000000000000020, 0x0000000000002020, 0x0000000000002020,
0x0000000000000400, 0x0000000000000400, 0x0000000000002400, 0x0000000000002400,
0x0000000000000420, 0x0000000000000420, 0x0000000000002420, 0x0000000000002420, ),
( 0x0000000000000000, 0x2000000000000000, 0x0000000400000000, 0x2000000400000000,
0x0000800000000000, 0x2000800000000000, 0x0000800400000000, 0x2000800400000000,
0x0008000000000000, 0x2008000000000000, 0x0008000400000000, 0x2008000400000000,
0x0008800000000000, 0x2008800000000000, 0x0008800400000000, 0x2008800400000000, ),
( 0x0000000000000000, 0x0000000000000000, 0x0000000000000040, 0x0000000000000040,
0x0000000020000000, 0x0000000020000000, 0x0000000020000040, 0x0000000020000040,
0x0000000000200000, 0x0000000000200000, 0x0000000000200040, 0x0000000000200040,
0x0000000020200000, 0x0000000020200000, 0x0000000020200040, 0x0000000020200040, ),
( 0x0000000000000000, 0x0002000000000000, 0x0800000000000000, 0x0802000000000000,
0x0100000000000000, 0x0102000000000000, 0x0900000000000000, 0x0902000000000000,
0x4000000000000000, 0x4002000000000000, 0x4800000000000000, 0x4802000000000000,
0x4100000000000000, 0x4102000000000000, 0x4900000000000000, 0x4902000000000000, ),
( 0x0000000000000000, 0x0000000000000000, 0x0000000000040000, 0x0000000000040000,
0x0000020000000000, 0x0000020000000000, 0x0000020000040000, 0x0000020000040000,
0x0000000000000004, 0x0000000000000004, 0x0000000000040004, 0x0000000000040004,
0x0000020000000004, 0x0000020000000004, 0x0000020000040004, 0x0000020000040004, ),
( 0x0000000000000000, 0x0000400000000000, 0x0200000000000000, 0x0200400000000000,
0x0080000000000000, 0x0080400000000000, 0x0280000000000000, 0x0280400000000000,
0x0000008000000000, 0x0000408000000000, 0x0200008000000000, 0x0200408000000000,
0x0080008000000000, 0x0080408000000000, 0x0280008000000000, 0x0280408000000000, ),
( 0x0000000000000000, 0x0000000000000000, 0x0000000010000000, 0x0000000010000000,
0x0000000000001000, 0x0000000000001000, 0x0000000010001000, 0x0000000010001000,
0x0000000040000000, 0x0000000040000000, 0x0000000050000000, 0x0000000050000000,
0x0000000040001000, 0x0000000040001000, 0x0000000050001000, 0x0000000050001000, ),
( 0x0000000000000000, 0x0000001000000000, 0x0000080000000000, 0x0000081000000000,
0x1000000000000000, 0x1000001000000000, 0x1000080000000000, 0x1000081000000000,
0x0004000000000000, 0x0004001000000000, 0x0004080000000000, 0x0004081000000000,
0x1004000000000000, 0x1004001000000000, 0x1004080000000000, 0x1004081000000000, ),
( 0x0000000000000000, 0x0000000000000000, 0x0000000000000080, 0x0000000000000080,
0x0000000000080000, 0x0000000000080000, 0x0000000000080080, 0x0000000000080080,
0x0000000000800000, 0x0000000000800000, 0x0000000000800080, 0x0000000000800080,
0x0000000000880000, 0x0000000000880000, 0x0000000000880080, 0x0000000000880080, ),
( 0x0000000000000000, 0x0000000008000000, 0x0000002000000000, 0x0000002008000000,
0x0000100000000000, 0x0000100008000000, 0x0000102000000000, 0x0000102008000000,
0x0000200000000000, 0x0000200008000000, 0x0000202000000000, 0x0000202008000000,
0x0000300000000000, 0x0000300008000000, 0x0000302000000000, 0x0000302008000000, ),
( 0x0000000000000000, 0x0000000000000000, 0x0000000000400000, 0x0000000000400000,
0x0000000004000000, 0x0000000004000000, 0x0000000004400000, 0x0000000004400000,
0x0000000000000800, 0x0000000000000800, 0x0000000000400800, 0x0000000000400800,
0x0000000004000800, 0x0000000004000800, 0x0000000004400800, 0x0000000004400800, ),
( 0x0000000000000000, 0x0000000000008000, 0x0040000000000000, 0x0040000000008000,
0x0000004000000000, 0x0000004000008000, 0x0040004000000000, 0x0040004000008000,
0x8000000000000000, 0x8000000000008000, 0x8040000000000000, 0x8040000000008000,
0x8000004000000000, 0x8000004000008000, 0x8040004000000000, 0x8040004000008000, ),
( 0x0000000000000000, 0x0000000000000000, 0x0000000000004000, 0x0000000000004000,
0x0000000000000008, 0x0000000000000008, 0x0000000000004008, 0x0000000000004008,
0x0000000000000010, 0x0000000000000010, 0x0000000000004010, 0x0000000000004010,
0x0000000000000018, 0x0000000000000018, 0x0000000000004018, 0x0000000000004018, ),
( 0x0000000000000000, 0x0000000200000000, 0x0001000000000000, 0x0001000200000000,
0x0400000000000000, 0x0400000200000000, 0x0401000000000000, 0x0401000200000000,
0x0020000000000000, 0x0020000200000000, 0x0021000000000000, 0x0021000200000000,
0x0420000000000000, 0x0420000200000000, 0x0421000000000000, 0x0421000200000000, ),
( 0x0000000000000000, 0x0000000000000000, 0x0000010000000000, 0x0000010000000000,
0x0000000100000000, 0x0000000100000000, 0x0000010100000000, 0x0000010100000000,
0x0000000000100000, 0x0000000000100000, 0x0000010000100000, 0x0000010000100000,
0x0000000100100000, 0x0000000100100000, 0x0000010100100000, 0x0000010100100000, ),
( 0x0000000000000000, 0x0000000080000000, 0x0000040000000000, 0x0000040080000000,
0x0010000000000000, 0x0010000080000000, 0x0010040000000000, 0x0010040080000000,
0x0000000800000000, 0x0000000880000000, 0x0000040800000000, 0x0000040880000000,
0x0010000800000000, 0x0010000880000000, 0x0010040800000000, 0x0010040880000000, ),
)
#---------------------------------------------------------------
# Subsequent key schedule rotation permutations
# PC2ROT - PC2 inverse, then Rotate, then PC2
#---------------------------------------------------------------
# NOTE: this was reordered from original table to make perm3264 logic simpler
PC2ROTA=(
( 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000200000, 0x0000000000200000, 0x0000000000200000, 0x0000000000200000,
0x0000000004000000, 0x0000000004000000, 0x0000000004000000, 0x0000000004000000,
0x0000000004200000, 0x0000000004200000, 0x0000000004200000, 0x0000000004200000, ),
( 0x0000000000000000, 0x0000000000000800, 0x0000010000000000, 0x0000010000000800,
0x0000000000002000, 0x0000000000002800, 0x0000010000002000, 0x0000010000002800,
0x0000000010000000, 0x0000000010000800, 0x0000010010000000, 0x0000010010000800,
0x0000000010002000, 0x0000000010002800, 0x0000010010002000, 0x0000010010002800, ),
( 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000100000000, 0x0000000100000000, 0x0000000100000000, 0x0000000100000000,
0x0000000000800000, 0x0000000000800000, 0x0000000000800000, 0x0000000000800000,
0x0000000100800000, 0x0000000100800000, 0x0000000100800000, 0x0000000100800000, ),
( 0x0000000000000000, 0x0000020000000000, 0x0000000080000000, 0x0000020080000000,
0x0000000000400000, 0x0000020000400000, 0x0000000080400000, 0x0000020080400000,
0x0000000008000000, 0x0000020008000000, 0x0000000088000000, 0x0000020088000000,
0x0000000008400000, 0x0000020008400000, 0x0000000088400000, 0x0000020088400000, ),
( 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000040, 0x0000000000000040, 0x0000000000000040, 0x0000000000000040,
0x0000000000001000, 0x0000000000001000, 0x0000000000001000, 0x0000000000001000,
0x0000000000001040, 0x0000000000001040, 0x0000000000001040, 0x0000000000001040, ),
( 0x0000000000000000, 0x0000000000000010, 0x0000000000000400, 0x0000000000000410,
0x0000000000000080, 0x0000000000000090, 0x0000000000000480, 0x0000000000000490,
0x0000000040000000, 0x0000000040000010, 0x0000000040000400, 0x0000000040000410,
0x0000000040000080, 0x0000000040000090, 0x0000000040000480, 0x0000000040000490, ),
( 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000080000, 0x0000000000080000, 0x0000000000080000, 0x0000000000080000,
0x0000000000100000, 0x0000000000100000, 0x0000000000100000, 0x0000000000100000,
0x0000000000180000, 0x0000000000180000, 0x0000000000180000, 0x0000000000180000, ),
( 0x0000000000000000, 0x0000000000040000, 0x0000000000000020, 0x0000000000040020,
0x0000000000000004, 0x0000000000040004, 0x0000000000000024, 0x0000000000040024,
0x0000000200000000, 0x0000000200040000, 0x0000000200000020, 0x0000000200040020,
0x0000000200000004, 0x0000000200040004, 0x0000000200000024, 0x0000000200040024, ),
( 0x0000000000000000, 0x0000000000000008, 0x0000000000008000, 0x0000000000008008,
0x0010000000000000, 0x0010000000000008, 0x0010000000008000, 0x0010000000008008,
0x0020000000000000, 0x0020000000000008, 0x0020000000008000, 0x0020000000008008,
0x0030000000000000, 0x0030000000000008, 0x0030000000008000, 0x0030000000008008, ),
( 0x0000000000000000, 0x0000400000000000, 0x0000080000000000, 0x0000480000000000,
0x0000100000000000, 0x0000500000000000, 0x0000180000000000, 0x0000580000000000,
0x4000000000000000, 0x4000400000000000, 0x4000080000000000, 0x4000480000000000,
0x4000100000000000, 0x4000500000000000, 0x4000180000000000, 0x4000580000000000, ),
( 0x0000000000000000, 0x0000000000004000, 0x0000000020000000, 0x0000000020004000,
0x0001000000000000, 0x0001000000004000, 0x0001000020000000, 0x0001000020004000,
0x0200000000000000, 0x0200000000004000, 0x0200000020000000, 0x0200000020004000,
0x0201000000000000, 0x0201000000004000, 0x0201000020000000, 0x0201000020004000, ),
( 0x0000000000000000, 0x1000000000000000, 0x0004000000000000, 0x1004000000000000,
0x0002000000000000, 0x1002000000000000, 0x0006000000000000, 0x1006000000000000,
0x0000000800000000, 0x1000000800000000, 0x0004000800000000, 0x1004000800000000,
0x0002000800000000, 0x1002000800000000, 0x0006000800000000, 0x1006000800000000, ),
( 0x0000000000000000, 0x0040000000000000, 0x2000000000000000, 0x2040000000000000,
0x0000008000000000, 0x0040008000000000, 0x2000008000000000, 0x2040008000000000,
0x0000001000000000, 0x0040001000000000, 0x2000001000000000, 0x2040001000000000,
0x0000009000000000, 0x0040009000000000, 0x2000009000000000, 0x2040009000000000, ),
( 0x0000000000000000, 0x0400000000000000, 0x8000000000000000, 0x8400000000000000,
0x0000002000000000, 0x0400002000000000, 0x8000002000000000, 0x8400002000000000,
0x0100000000000000, 0x0500000000000000, 0x8100000000000000, 0x8500000000000000,
0x0100002000000000, 0x0500002000000000, 0x8100002000000000, 0x8500002000000000, ),
( 0x0000000000000000, 0x0000800000000000, 0x0800000000000000, 0x0800800000000000,
0x0000004000000000, 0x0000804000000000, 0x0800004000000000, 0x0800804000000000,
0x0000000400000000, 0x0000800400000000, 0x0800000400000000, 0x0800800400000000,
0x0000004400000000, 0x0000804400000000, 0x0800004400000000, 0x0800804400000000, ),
( 0x0000000000000000, 0x0080000000000000, 0x0000040000000000, 0x0080040000000000,
0x0008000000000000, 0x0088000000000000, 0x0008040000000000, 0x0088040000000000,
0x0000200000000000, 0x0080200000000000, 0x0000240000000000, 0x0080240000000000,
0x0008200000000000, 0x0088200000000000, 0x0008240000000000, 0x0088240000000000, ),
)
# NOTE: this was reordered from original table to make perm3264 logic simpler
PC2ROTB=(
( 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000400, 0x0000000000000400, 0x0000000000000400, 0x0000000000000400,
0x0000000000080000, 0x0000000000080000, 0x0000000000080000, 0x0000000000080000,
0x0000000000080400, 0x0000000000080400, 0x0000000000080400, 0x0000000000080400, ),
( 0x0000000000000000, 0x0000000000800000, 0x0000000000004000, 0x0000000000804000,
0x0000000080000000, 0x0000000080800000, 0x0000000080004000, 0x0000000080804000,
0x0000000000040000, 0x0000000000840000, 0x0000000000044000, 0x0000000000844000,
0x0000000080040000, 0x0000000080840000, 0x0000000080044000, 0x0000000080844000, ),
( 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000008, 0x0000000000000008, 0x0000000000000008, 0x0000000000000008,
0x0000000040000000, 0x0000000040000000, 0x0000000040000000, 0x0000000040000000,
0x0000000040000008, 0x0000000040000008, 0x0000000040000008, 0x0000000040000008, ),
( 0x0000000000000000, 0x0000000020000000, 0x0000000200000000, 0x0000000220000000,
0x0000000000000080, 0x0000000020000080, 0x0000000200000080, 0x0000000220000080,
0x0000000000100000, 0x0000000020100000, 0x0000000200100000, 0x0000000220100000,
0x0000000000100080, 0x0000000020100080, 0x0000000200100080, 0x0000000220100080, ),
( 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000002000, 0x0000000000002000, 0x0000000000002000, 0x0000000000002000,
0x0000020000000000, 0x0000020000000000, 0x0000020000000000, 0x0000020000000000,
0x0000020000002000, 0x0000020000002000, 0x0000020000002000, 0x0000020000002000, ),
( 0x0000000000000000, 0x0000000000000800, 0x0000000100000000, 0x0000000100000800,
0x0000000010000000, 0x0000000010000800, 0x0000000110000000, 0x0000000110000800,
0x0000000000000004, 0x0000000000000804, 0x0000000100000004, 0x0000000100000804,
0x0000000010000004, 0x0000000010000804, 0x0000000110000004, 0x0000000110000804, ),
( 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000001000, 0x0000000000001000, 0x0000000000001000, 0x0000000000001000,
0x0000000000000010, 0x0000000000000010, 0x0000000000000010, 0x0000000000000010,
0x0000000000001010, 0x0000000000001010, 0x0000000000001010, 0x0000000000001010, ),
( 0x0000000000000000, 0x0000000000000040, 0x0000010000000000, 0x0000010000000040,
0x0000000000200000, 0x0000000000200040, 0x0000010000200000, 0x0000010000200040,
0x0000000000008000, 0x0000000000008040, 0x0000010000008000, 0x0000010000008040,
0x0000000000208000, 0x0000000000208040, 0x0000010000208000, 0x0000010000208040, ),
( 0x0000000000000000, 0x0000000004000000, 0x0000000008000000, 0x000000000c000000,
0x0400000000000000, 0x0400000004000000, 0x0400000008000000, 0x040000000c000000,
0x8000000000000000, 0x8000000004000000, 0x8000000008000000, 0x800000000c000000,
0x8400000000000000, 0x8400000004000000, 0x8400000008000000, 0x840000000c000000, ),
( 0x0000000000000000, 0x0002000000000000, 0x0200000000000000, 0x0202000000000000,
0x1000000000000000, 0x1002000000000000, 0x1200000000000000, 0x1202000000000000,
0x0008000000000000, 0x000a000000000000, 0x0208000000000000, 0x020a000000000000,
0x1008000000000000, 0x100a000000000000, 0x1208000000000000, 0x120a000000000000, ),
( 0x0000000000000000, 0x0000000000400000, 0x0000000000000020, 0x0000000000400020,
0x0040000000000000, 0x0040000000400000, 0x0040000000000020, 0x0040000000400020,
0x0800000000000000, 0x0800000000400000, 0x0800000000000020, 0x0800000000400020,
0x0840000000000000, 0x0840000000400000, 0x0840000000000020, 0x0840000000400020, ),
( 0x0000000000000000, 0x0080000000000000, 0x0000008000000000, 0x0080008000000000,
0x2000000000000000, 0x2080000000000000, 0x2000008000000000, 0x2080008000000000,
0x0020000000000000, 0x00a0000000000000, 0x0020008000000000, 0x00a0008000000000,
0x2020000000000000, 0x20a0000000000000, 0x2020008000000000, 0x20a0008000000000, ),
( 0x0000000000000000, 0x0000002000000000, 0x0000040000000000, 0x0000042000000000,
0x4000000000000000, 0x4000002000000000, 0x4000040000000000, 0x4000042000000000,
0x0000400000000000, 0x0000402000000000, 0x0000440000000000, 0x0000442000000000,
0x4000400000000000, 0x4000402000000000, 0x4000440000000000, 0x4000442000000000, ),
( 0x0000000000000000, 0x0000004000000000, 0x0000200000000000, 0x0000204000000000,
0x0000080000000000, 0x0000084000000000, 0x0000280000000000, 0x0000284000000000,
0x0000800000000000, 0x0000804000000000, 0x0000a00000000000, 0x0000a04000000000,
0x0000880000000000, 0x0000884000000000, 0x0000a80000000000, 0x0000a84000000000, ),
( 0x0000000000000000, 0x0000000800000000, 0x0000000400000000, 0x0000000c00000000,
0x0000100000000000, 0x0000100800000000, 0x0000100400000000, 0x0000100c00000000,
0x0010000000000000, 0x0010000800000000, 0x0010000400000000, 0x0010000c00000000,
0x0010100000000000, 0x0010100800000000, 0x0010100400000000, 0x0010100c00000000, ),
( 0x0000000000000000, 0x0100000000000000, 0x0001000000000000, 0x0101000000000000,
0x0000001000000000, 0x0100001000000000, 0x0001001000000000, 0x0101001000000000,
0x0004000000000000, 0x0104000000000000, 0x0005000000000000, 0x0105000000000000,
0x0004001000000000, 0x0104001000000000, 0x0005001000000000, 0x0105001000000000, ),
)
#---------------------------------------------------------------
# PCXROT - PC1ROT, PC2ROTA, PC2ROTB listed in order
# of the PC1 rotation schedule, as used by des_setkey
#---------------------------------------------------------------
##ROTATES = (1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1)
##PCXROT = (
## PC1ROT, PC2ROTA, PC2ROTB, PC2ROTB,
## PC2ROTB, PC2ROTB, PC2ROTB, PC2ROTB,
## PC2ROTA, PC2ROTB, PC2ROTB, PC2ROTB,
## PC2ROTB, PC2ROTB, PC2ROTB, PC2ROTA,
## )
# NOTE: modified PCXROT to contain entrys broken into pairs,
# to help generate them in format best used by encoder.
PCXROT = (
(PC1ROT, PC2ROTA), (PC2ROTB, PC2ROTB),
(PC2ROTB, PC2ROTB), (PC2ROTB, PC2ROTB),
(PC2ROTA, PC2ROTB), (PC2ROTB, PC2ROTB),
(PC2ROTB, PC2ROTB), (PC2ROTB, PC2ROTA),
)
#---------------------------------------------------------------
# Bit reverse, intial permupation, expantion
# Initial permutation/expansion table
#---------------------------------------------------------------
# NOTE: this was reordered from original table to make perm3264 logic simpler
IE3264=(
( 0x0000000000000000, 0x0000000000800800, 0x0000000000008008, 0x0000000000808808,
0x0000008008000000, 0x0000008008800800, 0x0000008008008008, 0x0000008008808808,
0x0000000080080000, 0x0000000080880800, 0x0000000080088008, 0x0000000080888808,
0x0000008088080000, 0x0000008088880800, 0x0000008088088008, 0x0000008088888808, ),
( 0x0000000000000000, 0x0080080000000000, 0x0000800800000000, 0x0080880800000000,
0x0800000000000080, 0x0880080000000080, 0x0800800800000080, 0x0880880800000080,
0x8008000000000000, 0x8088080000000000, 0x8008800800000000, 0x8088880800000000,
0x8808000000000080, 0x8888080000000080, 0x8808800800000080, 0x8888880800000080, ),
( 0x0000000000000000, 0x0000000000001000, 0x0000000000000010, 0x0000000000001010,
0x0000000010000000, 0x0000000010001000, 0x0000000010000010, 0x0000000010001010,
0x0000000000100000, 0x0000000000101000, 0x0000000000100010, 0x0000000000101010,
0x0000000010100000, 0x0000000010101000, 0x0000000010100010, 0x0000000010101010, ),
( 0x0000000000000000, 0x0000100000000000, 0x0000001000000000, 0x0000101000000000,
0x1000000000000000, 0x1000100000000000, 0x1000001000000000, 0x1000101000000000,
0x0010000000000000, 0x0010100000000000, 0x0010001000000000, 0x0010101000000000,
0x1010000000000000, 0x1010100000000000, 0x1010001000000000, 0x1010101000000000, ),
( 0x0000000000000000, 0x0000000000002000, 0x0000000000000020, 0x0000000000002020,
0x0000000020000000, 0x0000000020002000, 0x0000000020000020, 0x0000000020002020,
0x0000000000200000, 0x0000000000202000, 0x0000000000200020, 0x0000000000202020,
0x0000000020200000, 0x0000000020202000, 0x0000000020200020, 0x0000000020202020, ),
( 0x0000000000000000, 0x0000200000000000, 0x0000002000000000, 0x0000202000000000,
0x2000000000000000, 0x2000200000000000, 0x2000002000000000, 0x2000202000000000,
0x0020000000000000, 0x0020200000000000, 0x0020002000000000, 0x0020202000000000,
0x2020000000000000, 0x2020200000000000, 0x2020002000000000, 0x2020202000000000, ),
( 0x0000000000000000, 0x0000000000004004, 0x0400000000000040, 0x0400000000004044,
0x0000000040040000, 0x0000000040044004, 0x0400000040040040, 0x0400000040044044,
0x0000000000400400, 0x0000000000404404, 0x0400000000400440, 0x0400000000404444,
0x0000000040440400, 0x0000000040444404, 0x0400000040440440, 0x0400000040444444, ),
( 0x0000000000000000, 0x0000400400000000, 0x0000004004000000, 0x0000404404000000,
0x4004000000000000, 0x4004400400000000, 0x4004004004000000, 0x4004404404000000,
0x0040040000000000, 0x0040440400000000, 0x0040044004000000, 0x0040444404000000,
0x4044040000000000, 0x4044440400000000, 0x4044044004000000, 0x4044444404000000, ),
)
#---------------------------------------------------------------
# Table that combines the S, P, and E operations.
#---------------------------------------------------------------
SPE=(
( 0x0080088008200000, 0x0000008008000000, 0x0000000000200020, 0x0080088008200020,
0x0000000000200000, 0x0080088008000020, 0x0000008008000020, 0x0000000000200020,
0x0080088008000020, 0x0080088008200000, 0x0000008008200000, 0x0080080000000020,
0x0080080000200020, 0x0000000000200000, 0x0000000000000000, 0x0000008008000020,
0x0000008008000000, 0x0000000000000020, 0x0080080000200000, 0x0080088008000000,
0x0080088008200020, 0x0000008008200000, 0x0080080000000020, 0x0080080000200000,
0x0000000000000020, 0x0080080000000000, 0x0080088008000000, 0x0000008008200020,
0x0080080000000000, 0x0080080000200020, 0x0000008008200020, 0x0000000000000000,
0x0000000000000000, 0x0080088008200020, 0x0080080000200000, 0x0000008008000020,
0x0080088008200000, 0x0000008008000000, 0x0080080000000020, 0x0080080000200000,
0x0000008008200020, 0x0080080000000000, 0x0080088008000000, 0x0000000000200020,
0x0080088008000020, 0x0000000000000020, 0x0000000000200020, 0x0000008008200000,
0x0080088008200020, 0x0080088008000000, 0x0000008008200000, 0x0080080000200020,
0x0000000000200000, 0x0080080000000020, 0x0000008008000020, 0x0000000000000000,
0x0000008008000000, 0x0000000000200000, 0x0080080000200020, 0x0080088008200000,
0x0000000000000020, 0x0000008008200020, 0x0080080000000000, 0x0080088008000020, ),
( 0x1000800810004004, 0x0000000000000000, 0x0000800810000000, 0x0000000010004004,
0x1000000000004004, 0x1000800800000000, 0x0000800800004004, 0x0000800810000000,
0x0000800800000000, 0x1000000010004004, 0x1000000000000000, 0x0000800800004004,
0x1000000010000000, 0x0000800810004004, 0x0000000010004004, 0x1000000000000000,
0x0000000010000000, 0x1000800800004004, 0x1000000010004004, 0x0000800800000000,
0x1000800810000000, 0x0000000000004004, 0x0000000000000000, 0x1000000010000000,
0x1000800800004004, 0x1000800810000000, 0x0000800810004004, 0x1000000000004004,
0x0000000000004004, 0x0000000010000000, 0x1000800800000000, 0x1000800810004004,
0x1000000010000000, 0x0000800810004004, 0x0000800800004004, 0x1000800810000000,
0x1000800810004004, 0x1000000010000000, 0x1000000000004004, 0x0000000000000000,
0x0000000000004004, 0x1000800800000000, 0x0000000010000000, 0x1000000010004004,
0x0000800800000000, 0x0000000000004004, 0x1000800810000000, 0x1000800800004004,
0x0000800810004004, 0x0000800800000000, 0x0000000000000000, 0x1000000000004004,
0x1000000000000000, 0x1000800810004004, 0x0000800810000000, 0x0000000010004004,
0x1000000010004004, 0x0000000010000000, 0x1000800800000000, 0x0000800800004004,
0x1000800800004004, 0x1000000000000000, 0x0000000010004004, 0x0000800810000000, ),
( 0x0000000000400410, 0x0010004004400400, 0x0010000000000000, 0x0010000000400410,
0x0000004004000010, 0x0000000000400400, 0x0010000000400410, 0x0010004004000000,
0x0010000000400400, 0x0000004004000000, 0x0000004004400400, 0x0000000000000010,
0x0010004004400410, 0x0010000000000010, 0x0000000000000010, 0x0000004004400410,
0x0000000000000000, 0x0000004004000010, 0x0010004004400400, 0x0010000000000000,
0x0010000000000010, 0x0010004004400410, 0x0000004004000000, 0x0000000000400410,
0x0000004004400410, 0x0010000000400400, 0x0010004004000010, 0x0000004004400400,
0x0010004004000000, 0x0000000000000000, 0x0000000000400400, 0x0010004004000010,
0x0010004004400400, 0x0010000000000000, 0x0000000000000010, 0x0000004004000000,
0x0010000000000010, 0x0000004004000010, 0x0000004004400400, 0x0010000000400410,
0x0000000000000000, 0x0010004004400400, 0x0010004004000000, 0x0000004004400410,
0x0000004004000010, 0x0000000000400400, 0x0010004004400410, 0x0000000000000010,
0x0010004004000010, 0x0000000000400410, 0x0000000000400400, 0x0010004004400410,
0x0000004004000000, 0x0010000000400400, 0x0010000000400410, 0x0010004004000000,
0x0010000000400400, 0x0000000000000000, 0x0000004004400410, 0x0010000000000010,
0x0000000000400410, 0x0010004004000010, 0x0010000000000000, 0x0000004004400400, ),
( 0x0800100040040080, 0x0000100000001000, 0x0800000000000080, 0x0800100040041080,
0x0000000000000000, 0x0000000040041000, 0x0800100000001080, 0x0800000040040080,
0x0000100040041000, 0x0800000000001080, 0x0000000000001000, 0x0800100000000080,
0x0800000000001080, 0x0800100040040080, 0x0000000040040000, 0x0000000000001000,
0x0800000040041080, 0x0000100040040000, 0x0000100000000000, 0x0800000000000080,
0x0000100040040000, 0x0800100000001080, 0x0000000040041000, 0x0000100000000000,
0x0800100000000080, 0x0000000000000000, 0x0800000040040080, 0x0000100040041000,
0x0000100000001000, 0x0800000040041080, 0x0800100040041080, 0x0000000040040000,
0x0800000040041080, 0x0800100000000080, 0x0000000040040000, 0x0800000000001080,
0x0000100040040000, 0x0000100000001000, 0x0800000000000080, 0x0000000040041000,
0x0800100000001080, 0x0000000000000000, 0x0000100000000000, 0x0800000040040080,
0x0000000000000000, 0x0800000040041080, 0x0000100040041000, 0x0000100000000000,
0x0000000000001000, 0x0800100040041080, 0x0800100040040080, 0x0000000040040000,
0x0800100040041080, 0x0800000000000080, 0x0000100000001000, 0x0800100040040080,
0x0800000040040080, 0x0000100040040000, 0x0000000040041000, 0x0800100000001080,
0x0800100000000080, 0x0000000000001000, 0x0800000000001080, 0x0000100040041000, ),
( 0x0000000000800800, 0x0000001000000000, 0x0040040000000000, 0x2040041000800800,
0x2000001000800800, 0x0040040000800800, 0x2040041000000000, 0x0000001000800800,
0x0000001000000000, 0x2000000000000000, 0x2000000000800800, 0x0040041000000000,
0x2040040000800800, 0x2000001000800800, 0x0040041000800800, 0x0000000000000000,
0x0040041000000000, 0x0000000000800800, 0x2000001000000000, 0x2040040000000000,
0x0040040000800800, 0x2040041000000000, 0x0000000000000000, 0x2000000000800800,
0x2000000000000000, 0x2040040000800800, 0x2040041000800800, 0x2000001000000000,
0x0000001000800800, 0x0040040000000000, 0x2040040000000000, 0x0040041000800800,
0x0040041000800800, 0x2040040000800800, 0x2000001000000000, 0x0000001000800800,
0x0000001000000000, 0x2000000000000000, 0x2000000000800800, 0x0040040000800800,
0x0000000000800800, 0x0040041000000000, 0x2040041000800800, 0x0000000000000000,
0x2040041000000000, 0x0000000000800800, 0x0040040000000000, 0x2000001000000000,
0x2040040000800800, 0x0040040000000000, 0x0000000000000000, 0x2040041000800800,
0x2000001000800800, 0x0040041000800800, 0x2040040000000000, 0x0000001000000000,
0x0040041000000000, 0x2000001000800800, 0x0040040000800800, 0x2040040000000000,
0x2000000000000000, 0x2040041000000000, 0x0000001000800800, 0x2000000000800800, ),
( 0x4004000000008008, 0x4004000020000000, 0x0000000000000000, 0x0000200020008008,
0x4004000020000000, 0x0000200000000000, 0x4004200000008008, 0x0000000020000000,
0x4004200000000000, 0x4004200020008008, 0x0000200020000000, 0x0000000000008008,
0x0000200000008008, 0x4004000000008008, 0x0000000020008008, 0x4004200020000000,
0x0000000020000000, 0x4004200000008008, 0x4004000020008008, 0x0000000000000000,
0x0000200000000000, 0x4004000000000000, 0x0000200020008008, 0x4004000020008008,
0x4004200020008008, 0x0000000020008008, 0x0000000000008008, 0x4004200000000000,
0x4004000000000000, 0x0000200020000000, 0x4004200020000000, 0x0000200000008008,
0x4004200000000000, 0x0000000000008008, 0x0000200000008008, 0x4004200020000000,
0x0000200020008008, 0x4004000020000000, 0x0000000000000000, 0x0000200000008008,
0x0000000000008008, 0x0000200000000000, 0x4004000020008008, 0x0000000020000000,
0x4004000020000000, 0x4004200020008008, 0x0000200020000000, 0x4004000000000000,
0x4004200020008008, 0x0000200020000000, 0x0000000020000000, 0x4004200000008008,
0x4004000000008008, 0x0000000020008008, 0x4004200020000000, 0x0000000000000000,
0x0000200000000000, 0x4004000000008008, 0x4004200000008008, 0x0000200020008008,
0x0000000020008008, 0x4004200000000000, 0x4004000000000000, 0x4004000020008008, ),
( 0x0000400400000000, 0x0020000000000000, 0x0020000000100000, 0x0400000000100040,
0x0420400400100040, 0x0400400400000040, 0x0020400400000000, 0x0000000000000000,
0x0000000000100000, 0x0420000000100040, 0x0420000000000040, 0x0000400400100000,
0x0400000000000040, 0x0020400400100000, 0x0000400400100000, 0x0420000000000040,
0x0420000000100040, 0x0000400400000000, 0x0400400400000040, 0x0420400400100040,
0x0000000000000000, 0x0020000000100000, 0x0400000000100040, 0x0020400400000000,
0x0400400400100040, 0x0420400400000040, 0x0020400400100000, 0x0400000000000040,
0x0420400400000040, 0x0400400400100040, 0x0020000000000000, 0x0000000000100000,
0x0420400400000040, 0x0000400400100000, 0x0400400400100040, 0x0420000000000040,
0x0000400400000000, 0x0020000000000000, 0x0000000000100000, 0x0400400400100040,
0x0420000000100040, 0x0420400400000040, 0x0020400400000000, 0x0000000000000000,
0x0020000000000000, 0x0400000000100040, 0x0400000000000040, 0x0020000000100000,
0x0000000000000000, 0x0420000000100040, 0x0020000000100000, 0x0020400400000000,
0x0420000000000040, 0x0000400400000000, 0x0420400400100040, 0x0000000000100000,
0x0020400400100000, 0x0400000000000040, 0x0400400400000040, 0x0420400400100040,
0x0400000000100040, 0x0020400400100000, 0x0000400400100000, 0x0400400400000040, ),
( 0x8008000080082000, 0x0000002080082000, 0x8008002000000000, 0x0000000000000000,
0x0000002000002000, 0x8008000080080000, 0x0000000080082000, 0x8008002080082000,
0x8008000000000000, 0x0000000000002000, 0x0000002080080000, 0x8008002000000000,
0x8008002080080000, 0x8008002000002000, 0x8008000000002000, 0x0000000080082000,
0x0000002000000000, 0x8008002080080000, 0x8008000080080000, 0x0000002000002000,
0x8008002080082000, 0x8008000000002000, 0x0000000000000000, 0x0000002080080000,
0x0000000000002000, 0x0000000080080000, 0x8008002000002000, 0x8008000080082000,
0x0000000080080000, 0x0000002000000000, 0x0000002080082000, 0x8008000000000000,
0x0000000080080000, 0x0000002000000000, 0x8008000000002000, 0x8008002080082000,
0x8008002000000000, 0x0000000000002000, 0x0000000000000000, 0x0000002080080000,
0x8008000080082000, 0x8008002000002000, 0x0000002000002000, 0x8008000080080000,
0x0000002080082000, 0x8008000000000000, 0x8008000080080000, 0x0000002000002000,
0x8008002080082000, 0x0000000080080000, 0x0000000080082000, 0x8008000000002000,
0x0000002080080000, 0x8008002000000000, 0x8008002000002000, 0x0000000080082000,
0x8008000000000000, 0x0000002080082000, 0x8008002080080000, 0x0000000000000000,
0x0000000000002000, 0x8008000080082000, 0x0000002000000000, 0x8008002080080000, ),
)
#---------------------------------------------------------------
# compressed/interleaved => final permutation table
# Compression, final permutation, bit reverse
#---------------------------------------------------------------
# NOTE: this was reordered from original table to make perm6464 logic simpler
CF6464=(
( 0x0000000000000000, 0x0000002000000000, 0x0000200000000000, 0x0000202000000000,
0x0020000000000000, 0x0020002000000000, 0x0020200000000000, 0x0020202000000000,
0x2000000000000000, 0x2000002000000000, 0x2000200000000000, 0x2000202000000000,
0x2020000000000000, 0x2020002000000000, 0x2020200000000000, 0x2020202000000000, ),
( 0x0000000000000000, 0x0000000200000000, 0x0000020000000000, 0x0000020200000000,
0x0002000000000000, 0x0002000200000000, 0x0002020000000000, 0x0002020200000000,
0x0200000000000000, 0x0200000200000000, 0x0200020000000000, 0x0200020200000000,
0x0202000000000000, 0x0202000200000000, 0x0202020000000000, 0x0202020200000000, ),
( 0x0000000000000000, 0x0000000000000020, 0x0000000000002000, 0x0000000000002020,
0x0000000000200000, 0x0000000000200020, 0x0000000000202000, 0x0000000000202020,
0x0000000020000000, 0x0000000020000020, 0x0000000020002000, 0x0000000020002020,
0x0000000020200000, 0x0000000020200020, 0x0000000020202000, 0x0000000020202020, ),
( 0x0000000000000000, 0x0000000000000002, 0x0000000000000200, 0x0000000000000202,
0x0000000000020000, 0x0000000000020002, 0x0000000000020200, 0x0000000000020202,
0x0000000002000000, 0x0000000002000002, 0x0000000002000200, 0x0000000002000202,
0x0000000002020000, 0x0000000002020002, 0x0000000002020200, 0x0000000002020202, ),
( 0x0000000000000000, 0x0000008000000000, 0x0000800000000000, 0x0000808000000000,
0x0080000000000000, 0x0080008000000000, 0x0080800000000000, 0x0080808000000000,
0x8000000000000000, 0x8000008000000000, 0x8000800000000000, 0x8000808000000000,
0x8080000000000000, 0x8080008000000000, 0x8080800000000000, 0x8080808000000000, ),
( 0x0000000000000000, 0x0000000800000000, 0x0000080000000000, 0x0000080800000000,
0x0008000000000000, 0x0008000800000000, 0x0008080000000000, 0x0008080800000000,
0x0800000000000000, 0x0800000800000000, 0x0800080000000000, 0x0800080800000000,
0x0808000000000000, 0x0808000800000000, 0x0808080000000000, 0x0808080800000000, ),
( 0x0000000000000000, 0x0000000000000080, 0x0000000000008000, 0x0000000000008080,
0x0000000000800000, 0x0000000000800080, 0x0000000000808000, 0x0000000000808080,
0x0000000080000000, 0x0000000080000080, 0x0000000080008000, 0x0000000080008080,
0x0000000080800000, 0x0000000080800080, 0x0000000080808000, 0x0000000080808080, ),
( 0x0000000000000000, 0x0000000000000008, 0x0000000000000800, 0x0000000000000808,
0x0000000000080000, 0x0000000000080008, 0x0000000000080800, 0x0000000000080808,
0x0000000008000000, 0x0000000008000008, 0x0000000008000800, 0x0000000008000808,
0x0000000008080000, 0x0000000008080008, 0x0000000008080800, 0x0000000008080808, ),
( 0x0000000000000000, 0x0000001000000000, 0x0000100000000000, 0x0000101000000000,
0x0010000000000000, 0x0010001000000000, 0x0010100000000000, 0x0010101000000000,
0x1000000000000000, 0x1000001000000000, 0x1000100000000000, 0x1000101000000000,
0x1010000000000000, 0x1010001000000000, 0x1010100000000000, 0x1010101000000000, ),
( 0x0000000000000000, 0x0000000100000000, 0x0000010000000000, 0x0000010100000000,
0x0001000000000000, 0x0001000100000000, 0x0001010000000000, 0x0001010100000000,
0x0100000000000000, 0x0100000100000000, 0x0100010000000000, 0x0100010100000000,
0x0101000000000000, 0x0101000100000000, 0x0101010000000000, 0x0101010100000000, ),
( 0x0000000000000000, 0x0000000000000010, 0x0000000000001000, 0x0000000000001010,
0x0000000000100000, 0x0000000000100010, 0x0000000000101000, 0x0000000000101010,
0x0000000010000000, 0x0000000010000010, 0x0000000010001000, 0x0000000010001010,
0x0000000010100000, 0x0000000010100010, 0x0000000010101000, 0x0000000010101010, ),
( 0x0000000000000000, 0x0000000000000001, 0x0000000000000100, 0x0000000000000101,
0x0000000000010000, 0x0000000000010001, 0x0000000000010100, 0x0000000000010101,
0x0000000001000000, 0x0000000001000001, 0x0000000001000100, 0x0000000001000101,
0x0000000001010000, 0x0000000001010001, 0x0000000001010100, 0x0000000001010101, ),
( 0x0000000000000000, 0x0000004000000000, 0x0000400000000000, 0x0000404000000000,
0x0040000000000000, 0x0040004000000000, 0x0040400000000000, 0x0040404000000000,
0x4000000000000000, 0x4000004000000000, 0x4000400000000000, 0x4000404000000000,
0x4040000000000000, 0x4040004000000000, 0x4040400000000000, 0x4040404000000000, ),
( 0x0000000000000000, 0x0000000400000000, 0x0000040000000000, 0x0000040400000000,
0x0004000000000000, 0x0004000400000000, 0x0004040000000000, 0x0004040400000000,
0x0400000000000000, 0x0400000400000000, 0x0400040000000000, 0x0400040400000000,
0x0404000000000000, 0x0404000400000000, 0x0404040000000000, 0x0404040400000000, ),
( 0x0000000000000000, 0x0000000000000040, 0x0000000000004000, 0x0000000000004040,
0x0000000000400000, 0x0000000000400040, 0x0000000000404000, 0x0000000000404040,
0x0000000040000000, 0x0000000040000040, 0x0000000040004000, 0x0000000040004040,
0x0000000040400000, 0x0000000040400040, 0x0000000040404000, 0x0000000040404040, ),
( 0x0000000000000000, 0x0000000000000004, 0x0000000000000400, 0x0000000000000404,
0x0000000000040000, 0x0000000000040004, 0x0000000000040400, 0x0000000000040404,
0x0000000004000000, 0x0000000004000004, 0x0000000004000400, 0x0000000004000404,
0x0000000004040000, 0x0000000004040004, 0x0000000004040400, 0x0000000004040404, ),
)
#===================================================================
# eof _load_tables()
#===================================================================
#=============================================================================
# support
#=============================================================================
def _permute(c, p):
"""Returns the permutation of the given 32-bit or 64-bit code with
the specified permutation table."""
# NOTE: only difference between 32 & 64 bit permutations
# is that len(p)==8 for 32 bit, and len(p)==16 for 64 bit.
out = 0
for r in p:
out |= r[c&0xf]
c >>= 4
return out
#=============================================================================
# packing & unpacking
#=============================================================================
# FIXME: more properly named _uint8_struct...
_uint64_struct = struct.Struct(">Q")
def _pack64(value):
return _uint64_struct.pack(value)
def _unpack64(value):
return _uint64_struct.unpack(value)[0]
def _pack56(value):
return _uint64_struct.pack(value)[1:]
def _unpack56(value):
return _uint64_struct.unpack(b'\x00' + value)[0]
#=============================================================================
# 56->64 key manipulation
#=============================================================================
##def expand_7bit(value):
## "expand 7-bit integer => 7-bits + 1 odd-parity bit"
## # parity calc adapted from 32-bit even parity alg found at
## # http://graphics.stanford.edu/~seander/bithacks.html#ParityParallel
## assert 0 <= value < 0x80, "value out of range"
## return (value<<1) | (0x9669 >> ((value ^ (value >> 4)) & 0xf)) & 1
_EXPAND_ITER = irange(49,-7,-7)
def expand_des_key(key):
"""convert DES from 7 bytes to 8 bytes (by inserting empty parity bits)"""
if isinstance(key, bytes):
if len(key) != 7:
raise ValueError("key must be 7 bytes in size")
elif isinstance(key, int_types):
if key < 0 or key > INT_56_MASK:
raise ValueError("key must be 56-bit non-negative integer")
return _unpack64(expand_des_key(_pack56(key)))
else:
raise exc.ExpectedTypeError(key, "bytes or int", "key")
key = _unpack56(key)
# NOTE: the following would insert correctly-valued parity bits in each key,
# but the parity bit would just be ignored in des_encrypt_block(),
# so not bothering to use it.
# XXX: could make parity-restoring optionally available via flag
##return join_byte_values(expand_7bit((key >> shift) & 0x7f)
## for shift in _EXPAND_ITER)
return join_byte_values(((key>>shift) & 0x7f)<<1 for shift in _EXPAND_ITER)
def shrink_des_key(key):
"""convert DES key from 8 bytes to 7 bytes (by discarding the parity bits)"""
if isinstance(key, bytes):
if len(key) != 8:
raise ValueError("key must be 8 bytes in size")
return _pack56(shrink_des_key(_unpack64(key)))
elif isinstance(key, int_types):
if key < 0 or key > INT_64_MASK:
raise ValueError("key must be 64-bit non-negative integer")
else:
raise exc.ExpectedTypeError(key, "bytes or int", "key")
key >>= 1
result = 0
offset = 0
while offset < 56:
result |= (key & 0x7f)<<offset
key >>= 8
offset += 7
assert not (result & ~INT_64_MASK)
return result
#=============================================================================
# des encryption
#=============================================================================
def des_encrypt_block(key, input, salt=0, rounds=1):
"""encrypt single block of data using DES, operates on 8-byte strings.
:arg key:
DES key as 7 byte string, or 8 byte string with parity bits
(parity bit values are ignored).
:arg input:
plaintext block to encrypt, as 8 byte string.
:arg salt:
Optional 24-bit integer used to mutate the base DES algorithm in a
manner specific to :class:`~passlib.hash.des_crypt` and its variants.
The default value ``0`` provides the normal (unsalted) DES behavior.
The salt functions as follows:
if the ``i``'th bit of ``salt`` is set,
bits ``i`` and ``i+24`` are swapped in the DES E-box output.
:arg rounds:
Optional number of rounds of to apply the DES key schedule.
the default (``rounds=1``) provides the normal DES behavior,
but :class:`~passlib.hash.des_crypt` and its variants use
alternate rounds values.
:raises TypeError: if any of the provided args are of the wrong type.
:raises ValueError:
if any of the input blocks are the wrong size,
or the salt/rounds values are out of range.
:returns:
resulting 8-byte ciphertext block.
"""
# validate & unpack key
if isinstance(key, bytes):
if len(key) == 7:
key = expand_des_key(key)
elif len(key) != 8:
raise ValueError("key must be 7 or 8 bytes")
key = _unpack64(key)
else:
raise exc.ExpectedTypeError(key, "bytes", "key")
# validate & unpack input
if isinstance(input, bytes):
if len(input) != 8:
raise ValueError("input block must be 8 bytes")
input = _unpack64(input)
else:
raise exc.ExpectedTypeError(input, "bytes", "input")
# hand things off to other func
result = des_encrypt_int_block(key, input, salt, rounds)
# repack result
return _pack64(result)
def des_encrypt_int_block(key, input, salt=0, rounds=1):
"""encrypt single block of data using DES, operates on 64-bit integers.
this function is essentially the same as :func:`des_encrypt_block`,
except that it operates on integers, and will NOT automatically
expand 56-bit keys if provided (since there's no way to detect them).
:arg key:
DES key as 64-bit integer (the parity bits are ignored).
:arg input:
input block as 64-bit integer
:arg salt:
optional 24-bit integer used to mutate the base DES algorithm.
defaults to ``0`` (no mutation applied).
:arg rounds:
optional number of rounds of to apply the DES key schedule.
defaults to ``1``.
:raises TypeError: if any of the provided args are of the wrong type.
:raises ValueError:
if any of the input blocks are the wrong size,
or the salt/rounds values are out of range.
:returns:
resulting ciphertext as 64-bit integer.
"""
#---------------------------------------------------------------
# input validation
#---------------------------------------------------------------
# validate salt, rounds
if rounds < 1:
raise ValueError("rounds must be positive integer")
if salt < 0 or salt > INT_24_MASK:
raise ValueError("salt must be 24-bit non-negative integer")
# validate & unpack key
if not isinstance(key, int_types):
raise exc.ExpectedTypeError(key, "int", "key")
elif key < 0 or key > INT_64_MASK:
raise ValueError("key must be 64-bit non-negative integer")
# validate & unpack input
if not isinstance(input, int_types):
raise exc.ExpectedTypeError(input, "int", "input")
elif input < 0 or input > INT_64_MASK:
raise ValueError("input must be 64-bit non-negative integer")
#---------------------------------------------------------------
# DES setup
#---------------------------------------------------------------
# load tables if not already done
global SPE, PCXROT, IE3264, CF6464
if PCXROT is None:
_load_tables()
# load SPE into local vars to speed things up and remove an array access call
SPE0, SPE1, SPE2, SPE3, SPE4, SPE5, SPE6, SPE7 = SPE
# NOTE: parity bits are ignored completely
# (UTs do fuzz testing to ensure this)
# generate key schedule
# NOTE: generation was modified to output two elements at a time,
# so that per-round loop could do two passes at once.
def _iter_key_schedule(ks_odd):
"""given 64-bit key, iterates over the 8 (even,odd) key schedule pairs"""
for p_even, p_odd in PCXROT:
ks_even = _permute(ks_odd, p_even)
ks_odd = _permute(ks_even, p_odd)
yield ks_even & _KS_MASK, ks_odd & _KS_MASK
ks_list = list(_iter_key_schedule(key))
# expand 24 bit salt -> 32 bit per des_crypt & bsdi_crypt
salt = (
((salt & 0x00003f) << 26) |
((salt & 0x000fc0) << 12) |
((salt & 0x03f000) >> 2) |
((salt & 0xfc0000) >> 16)
)
# init L & R
if input == 0:
L = R = 0
else:
L = ((input >> 31) & 0xaaaaaaaa) | (input & 0x55555555)
L = _permute(L, IE3264)
R = ((input >> 32) & 0xaaaaaaaa) | ((input >> 1) & 0x55555555)
R = _permute(R, IE3264)
#---------------------------------------------------------------
# main DES loop - run for specified number of rounds
#---------------------------------------------------------------
while rounds:
rounds -= 1
# run over each part of the schedule, 2 parts at a time
for ks_even, ks_odd in ks_list:
k = ((R>>32) ^ R) & salt # use the salt to flip specific bits
B = (k<<32) ^ k ^ R ^ ks_even
L ^= (SPE0[(B>>58)&0x3f] ^ SPE1[(B>>50)&0x3f] ^
SPE2[(B>>42)&0x3f] ^ SPE3[(B>>34)&0x3f] ^
SPE4[(B>>26)&0x3f] ^ SPE5[(B>>18)&0x3f] ^
SPE6[(B>>10)&0x3f] ^ SPE7[(B>>2)&0x3f])
k = ((L>>32) ^ L) & salt # use the salt to flip specific bits
B = (k<<32) ^ k ^ L ^ ks_odd
R ^= (SPE0[(B>>58)&0x3f] ^ SPE1[(B>>50)&0x3f] ^
SPE2[(B>>42)&0x3f] ^ SPE3[(B>>34)&0x3f] ^
SPE4[(B>>26)&0x3f] ^ SPE5[(B>>18)&0x3f] ^
SPE6[(B>>10)&0x3f] ^ SPE7[(B>>2)&0x3f])
# swap L and R
L, R = R, L
#---------------------------------------------------------------
# return final result
#---------------------------------------------------------------
C = (
((L>>3) & 0x0f0f0f0f00000000)
|
((L<<33) & 0xf0f0f0f000000000)
|
((R>>35) & 0x000000000f0f0f0f)
|
((R<<1) & 0x00000000f0f0f0f0)
)
return _permute(C, CF6464)
#=============================================================================
# eof
#=============================================================================

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,281 @@
"""
passlib.utils.scrypt -- scrypt hash frontend and help utilities
XXX: add this module to public docs?
"""
#==========================================================================
# imports
#==========================================================================
from __future__ import absolute_import
# core
import logging; log = logging.getLogger(__name__)
from warnings import warn
# pkg
from passlib import exc
from passlib.utils import to_bytes
from passlib.utils.compat import PYPY
# local
__all__ =[
"validate",
"scrypt",
]
#==========================================================================
# config validation
#==========================================================================
#: internal global constant for setting stdlib scrypt's maxmem (int bytes).
#: set to -1 to auto-calculate (see _load_stdlib_backend() below)
#: set to 0 for openssl default (32mb according to python docs)
#: TODO: standardize this across backends, and expose support via scrypt hash config;
#: currently not very configurable, and only applies to stdlib backend.
SCRYPT_MAXMEM = -1
#: max output length in bytes
MAX_KEYLEN = ((1 << 32) - 1) * 32
#: max ``r * p`` limit
MAX_RP = (1 << 30) - 1
# TODO: unittests for this function
def validate(n, r, p):
"""
helper which validates a set of scrypt config parameters.
scrypt will take ``O(n * r * p)`` time and ``O(n * r)`` memory.
limitations are that ``n = 2**<positive integer>``, ``n < 2**(16*r)``, ``r * p < 2 ** 30``.
:param n: scrypt rounds
:param r: scrypt block size
:param p: scrypt parallel factor
"""
if r < 1:
raise ValueError("r must be > 0: r=%r" % r)
if p < 1:
raise ValueError("p must be > 0: p=%r" % p)
if r * p > MAX_RP:
# pbkdf2-hmac-sha256 limitation - it will be requested to generate ``p*(2*r)*64`` bytes,
# but pbkdf2 can do max of (2**31-1) blocks, and sha-256 has 32 byte block size...
# so ``(2**31-1)*32 >= p*r*128`` -> ``r*p < 2**30``
raise ValueError("r * p must be < 2**30: r=%r, p=%r" % (r,p))
if n < 2 or n & (n - 1):
raise ValueError("n must be > 1, and a power of 2: n=%r" % n)
return True
UINT32_SIZE = 4
def estimate_maxmem(n, r, p, fudge=1.05):
"""
calculate memory required for parameter combination.
assumes parameters have already been validated.
.. warning::
this is derived from OpenSSL's scrypt maxmem formula;
and may not be correct for other implementations
(additional buffers, different parallelism tradeoffs, etc).
"""
# XXX: expand to provide upper bound for diff backends, or max across all of them?
# NOTE: openssl's scrypt() enforces it's maxmem parameter based on calc located at
# <openssl/providers/default/kdfs/scrypt.c>, ending in line containing "Blen + Vlen > maxmem"
# using the following formula:
# Blen = p * 128 * r
# Vlen = 32 * r * (N + 2) * sizeof(uint32_t)
# total_bytes = Blen + Vlen
maxmem = r * (128 * p + 32 * (n + 2) * UINT32_SIZE)
# add fudge factor so we don't have off-by-one mismatch w/ openssl
maxmem = int(maxmem * fudge)
return maxmem
# TODO: configuration picker (may need psutil for full effect)
#==========================================================================
# hash frontend
#==========================================================================
#: backend function used by scrypt(), filled in by _set_backend()
_scrypt = None
#: name of backend currently in use, exposed for informational purposes.
backend = None
def scrypt(secret, salt, n, r, p=1, keylen=32):
"""run SCrypt key derivation function using specified parameters.
:arg secret:
passphrase string (unicode is encoded to bytes using utf-8).
:arg salt:
salt string (unicode is encoded to bytes using utf-8).
:arg n:
integer 'N' parameter
:arg r:
integer 'r' parameter
:arg p:
integer 'p' parameter
:arg keylen:
number of bytes of key to generate.
defaults to 32 (the internal block size).
:returns:
a *keylen*-sized bytes instance
SCrypt imposes a number of constraints on it's input parameters:
* ``r * p < 2**30`` -- due to a limitation of PBKDF2-HMAC-SHA256.
* ``keylen < (2**32 - 1) * 32`` -- due to a limitation of PBKDF2-HMAC-SHA256.
* ``n`` must a be a power of 2, and > 1 -- internal limitation of scrypt() implementation
:raises ValueError: if the provided parameters are invalid (see constraints above).
.. warning::
Unless the third-party ``scrypt <https://pypi.python.org/pypi/scrypt/>``_ package
is installed, passlib will use a builtin pure-python implementation of scrypt,
which is *considerably* slower (and thus requires a much lower / less secure
``n`` value in order to be usuable). Installing the :mod:`!scrypt` package
is strongly recommended.
"""
validate(n, r, p)
secret = to_bytes(secret, param="secret")
salt = to_bytes(salt, param="salt")
if keylen < 1:
raise ValueError("keylen must be at least 1")
if keylen > MAX_KEYLEN:
raise ValueError("keylen too large, must be <= %d" % MAX_KEYLEN)
return _scrypt(secret, salt, n, r, p, keylen)
def _load_builtin_backend():
"""
Load pure-python scrypt implementation built into passlib.
"""
slowdown = 10 if PYPY else 100
warn("Using builtin scrypt backend, which is %dx slower than is required "
"for adequate security. Installing scrypt support (via 'pip install scrypt') "
"is strongly recommended" % slowdown, exc.PasslibSecurityWarning)
from ._builtin import ScryptEngine
return ScryptEngine.execute
def _load_cffi_backend():
"""
Try to import the ctypes-based scrypt hash function provided by the
``scrypt <https://pypi.python.org/pypi/scrypt/>``_ package.
"""
try:
from scrypt import hash
return hash
except ImportError:
pass
# not available, but check to see if package present but outdated / not installed right
try:
import scrypt
except ImportError as err:
if "scrypt" not in str(err):
# e.g. if cffi isn't set up right
# user should try importing scrypt explicitly to diagnose problem.
warn("'scrypt' package failed to import correctly (possible installation issue?)",
exc.PasslibWarning)
# else: package just isn't installed
else:
warn("'scrypt' package is too old (lacks ``hash()`` method)", exc.PasslibWarning)
return None
def _load_stdlib_backend():
"""
Attempt to load stdlib scrypt() implement and return wrapper.
Returns None if not found.
"""
try:
# new in python 3.6, if compiled with openssl >= 1.1
from hashlib import scrypt as stdlib_scrypt
except ImportError:
return None
def stdlib_scrypt_wrapper(secret, salt, n, r, p, keylen):
# work out appropriate "maxmem" parameter
#
# TODO: would like to enforce a single "maxmem" policy across all backends;
# and maybe expose this via scrypt hasher config.
#
# for now, since parameters should all be coming from internally-controlled sources
# (password hashes), using policy of "whatever memory the parameters needs".
# furthermore, since stdlib scrypt is only place that needs this,
# currently calculating exactly what maxmem needs to make things work for stdlib call.
# as hack, this can be overriden via SCRYPT_MAXMEM above,
# would like to formalize all of this.
maxmem = SCRYPT_MAXMEM
if maxmem < 0:
maxmem = estimate_maxmem(n, r, p)
return stdlib_scrypt(password=secret, salt=salt, n=n, r=r, p=p, dklen=keylen,
maxmem=maxmem)
return stdlib_scrypt_wrapper
#: list of potential backends
backend_values = ("stdlib", "scrypt", "builtin")
#: dict mapping backend name -> loader
_backend_loaders = dict(
stdlib=_load_stdlib_backend,
scrypt=_load_cffi_backend, # XXX: rename backend constant to "cffi"?
builtin=_load_builtin_backend,
)
def _set_backend(name, dryrun=False):
"""
set backend for scrypt(). if name not specified, loads first available.
:raises ~passlib.exc.MissingBackendError: if backend can't be found
.. note:: mainly intended to be called by unittests, and scrypt hash handler
"""
if name == "any":
return
elif name == "default":
for name in backend_values:
try:
return _set_backend(name, dryrun=dryrun)
except exc.MissingBackendError:
continue
raise exc.MissingBackendError("no scrypt backends available")
else:
loader = _backend_loaders.get(name)
if not loader:
raise ValueError("unknown scrypt backend: %r" % (name,))
hash = loader()
if not hash:
raise exc.MissingBackendError("scrypt backend %r not available" % name)
if dryrun:
return
global _scrypt, backend
backend = name
_scrypt = hash
# initialize backend
_set_backend("default")
def _has_backend(name):
try:
_set_backend(name, dryrun=True)
return True
except exc.MissingBackendError:
return False
#==========================================================================
# eof
#==========================================================================

View File

@@ -0,0 +1,244 @@
"""passlib.utils.scrypt._builtin -- scrypt() kdf in pure-python"""
#==========================================================================
# imports
#==========================================================================
# core
import operator
import struct
# pkg
from passlib.utils.compat import izip
from passlib.crypto.digest import pbkdf2_hmac
from passlib.crypto.scrypt._salsa import salsa20
# local
__all__ =[
"ScryptEngine",
]
#==========================================================================
# scrypt engine
#==========================================================================
class ScryptEngine(object):
"""
helper class used to run scrypt kdf, see scrypt() for frontend
.. warning::
this class does NO validation of the input ranges or types.
it's not intended to be used directly,
but only as a backend for :func:`passlib.utils.scrypt.scrypt()`.
"""
#=================================================================
# instance attrs
#=================================================================
# primary scrypt config parameters
n = 0
r = 0
p = 0
# derived values & objects
smix_bytes = 0
iv_bytes = 0
bmix_len = 0
bmix_half_len = 0
bmix_struct = None
integerify = None
#=================================================================
# frontend
#=================================================================
@classmethod
def execute(cls, secret, salt, n, r, p, keylen):
"""create engine & run scrypt() hash calculation"""
return cls(n, r, p).run(secret, salt, keylen)
#=================================================================
# init
#=================================================================
def __init__(self, n, r, p):
# store config
self.n = n
self.r = r
self.p = p
self.smix_bytes = r << 7 # num bytes in smix input - 2*r*16*4
self.iv_bytes = self.smix_bytes * p
self.bmix_len = bmix_len = r << 5 # length of bmix block list - 32*r integers
self.bmix_half_len = r << 4
assert struct.calcsize("I") == 4
self.bmix_struct = struct.Struct("<" + str(bmix_len) + "I")
# use optimized bmix for certain cases
if r == 1:
self.bmix = self._bmix_1
# pick best integerify function - integerify(bmix_block) should
# take last 64 bytes of block and return a little-endian integer.
# since it's immediately converted % n, we only have to extract
# the first 32 bytes if n < 2**32 - which due to the current
# internal representation, is already unpacked as a 32-bit int.
if n <= 0xFFFFffff:
integerify = operator.itemgetter(-16)
else:
assert n <= 0xFFFFffffFFFFffff
ig1 = operator.itemgetter(-16)
ig2 = operator.itemgetter(-17)
def integerify(X):
return ig1(X) | (ig2(X)<<32)
self.integerify = integerify
#=================================================================
# frontend
#=================================================================
def run(self, secret, salt, keylen):
"""
run scrypt kdf for specified secret, salt, and keylen
.. note::
* time cost is ``O(n * r * p)``
* mem cost is ``O(n * r)``
"""
# stretch salt into initial byte array via pbkdf2
iv_bytes = self.iv_bytes
input = pbkdf2_hmac("sha256", secret, salt, rounds=1, keylen=iv_bytes)
# split initial byte array into 'p' mflen-sized chunks,
# and run each chunk through smix() to generate output chunk.
smix = self.smix
if self.p == 1:
output = smix(input)
else:
# XXX: *could* use threading here, if really high p values encountered,
# but would tradeoff for more memory usage.
smix_bytes = self.smix_bytes
output = b''.join(
smix(input[offset:offset+smix_bytes])
for offset in range(0, iv_bytes, smix_bytes)
)
# stretch final byte array into output via pbkdf2
return pbkdf2_hmac("sha256", secret, output, rounds=1, keylen=keylen)
#=================================================================
# smix() helper
#=================================================================
def smix(self, input):
"""run SCrypt smix function on a single input block
:arg input:
byte string containing input data.
interpreted as 32*r little endian 4 byte integers.
:returns:
byte string containing output data
derived by mixing input using n & r parameters.
.. note:: time & mem cost are both ``O(n * r)``
"""
# gather locals
bmix = self.bmix
bmix_struct = self.bmix_struct
integerify = self.integerify
n = self.n
# parse input into 32*r integers ('X' in scrypt source)
# mem cost -- O(r)
buffer = list(bmix_struct.unpack(input))
# starting with initial buffer contents, derive V s.t.
# V[0]=initial_buffer ... V[i] = bmix(V[i-1], V[i-1]) ... V[n-1] = bmix(V[n-2], V[n-2])
# final buffer contents should equal bmix(V[n-1], V[n-1])
#
# time cost -- O(n * r) -- n loops, bmix is O(r)
# mem cost -- O(n * r) -- V is n-element array of r-element tuples
# NOTE: could do time / memory tradeoff to shrink size of V
def vgen():
i = 0
while i < n:
last = tuple(buffer)
yield last
bmix(last, buffer)
i += 1
V = list(vgen())
# generate result from X & V.
#
# time cost -- O(n * r) -- loops n times, calls bmix() which has O(r) time cost
# mem cost -- O(1) -- allocates nothing, calls bmix() which has O(1) mem cost
get_v_elem = V.__getitem__
n_mask = n - 1
i = 0
while i < n:
j = integerify(buffer) & n_mask
result = tuple(a ^ b for a, b in izip(buffer, get_v_elem(j)))
bmix(result, buffer)
i += 1
# # NOTE: we could easily support arbitrary values of ``n``, not just powers of 2,
# # but very few implementations have that ability, so not enabling it for now...
# if not n_is_log_2:
# while i < n:
# j = integerify(buffer) % n
# tmp = tuple(a^b for a,b in izip(buffer, get_v_elem(j)))
# bmix(tmp,buffer)
# i += 1
# repack tmp
return bmix_struct.pack(*buffer)
#=================================================================
# bmix() helper
#=================================================================
def bmix(self, source, target):
"""
block mixing function used by smix()
uses salsa20/8 core to mix block contents.
:arg source:
source to read from.
should be list of 32*r 4-byte integers
(2*r salsa20 blocks).
:arg target:
target to write to.
should be list with same size as source.
the existing value of this buffer is ignored.
.. warning::
this operates *in place* on target,
so source & target should NOT be same list.
.. note::
* time cost is ``O(r)`` -- loops 16*r times, salsa20() has ``O(1)`` cost.
* memory cost is ``O(1)`` -- salsa20() uses 16 x uint4,
all other operations done in-place.
"""
## assert source is not target
# Y[-1] = B[2r-1], Y[i] = hash( Y[i-1] xor B[i])
# B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
half = self.bmix_half_len # 16*r out of 32*r - start of Y_1
tmp = source[-16:] # 'X' in scrypt source
siter = iter(source)
j = 0
while j < half:
jn = j+16
target[j:jn] = tmp = salsa20(a ^ b for a, b in izip(tmp, siter))
target[half+j:half+jn] = tmp = salsa20(a ^ b for a, b in izip(tmp, siter))
j = jn
def _bmix_1(self, source, target):
"""special bmix() method optimized for ``r=1`` case"""
B = source[16:]
target[:16] = tmp = salsa20(a ^ b for a, b in izip(B, iter(source)))
target[16:] = salsa20(a ^ b for a, b in izip(tmp, B))
#=================================================================
# eoc
#=================================================================
#==========================================================================
# eof
#==========================================================================

View File

@@ -0,0 +1,154 @@
"""passlib.utils.scrypt._gen_files - meta script that generates _salsa.py"""
#==========================================================================
# imports
#==========================================================================
# core
import os
# pkg
# local
#==========================================================================
# constants
#==========================================================================
_SALSA_OPS = [
# row = (target idx, source idx 1, source idx 2, rotate)
# interpreted as salsa operation over uint32...
# target = (source1+source2)<<rotate
##/* Operate on columns. */
##define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
##x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9);
##x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18);
( 4, 0, 12, 7),
( 8, 4, 0, 9),
( 12, 8, 4, 13),
( 0, 12, 8, 18),
##x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9);
##x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18);
( 9, 5, 1, 7),
( 13, 9, 5, 9),
( 1, 13, 9, 13),
( 5, 1, 13, 18),
##x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9);
##x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18);
( 14, 10, 6, 7),
( 2, 14, 10, 9),
( 6, 2, 14, 13),
( 10, 6, 2, 18),
##x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9);
##x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18);
( 3, 15, 11, 7),
( 7, 3, 15, 9),
( 11, 7, 3, 13),
( 15, 11, 7, 18),
##/* Operate on rows. */
##x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9);
##x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18);
( 1, 0, 3, 7),
( 2, 1, 0, 9),
( 3, 2, 1, 13),
( 0, 3, 2, 18),
##x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9);
##x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18);
( 6, 5, 4, 7),
( 7, 6, 5, 9),
( 4, 7, 6, 13),
( 5, 4, 7, 18),
##x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9);
##x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18);
( 11, 10, 9, 7),
( 8, 11, 10, 9),
( 9, 8, 11, 13),
( 10, 9, 8, 18),
##x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9);
##x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18);
( 12, 15, 14, 7),
( 13, 12, 15, 9),
( 14, 13, 12, 13),
( 15, 14, 13, 18),
]
def main():
target = os.path.join(os.path.dirname(__file__), "_salsa.py")
fh = file(target, "w")
write = fh.write
VNAMES = ["v%d" % i for i in range(16)]
PAD = " " * 4
PAD2 = " " * 8
PAD3 = " " * 12
TLIST = ", ".join("b%d" % i for i in range(16))
VLIST = ", ".join(VNAMES)
kwds = dict(
VLIST=VLIST,
TLIST=TLIST,
)
write('''\
"""passlib.utils.scrypt._salsa - salsa 20/8 core, autogenerated by _gen_salsa.py"""
#=================================================================
# salsa function
#=================================================================
def salsa20(input):
\"""apply the salsa20/8 core to the provided input
:args input: input list containing 16 32-bit integers
:returns: result list containing 16 32-bit integers
\"""
%(TLIST)s = input
%(VLIST)s = \\
%(TLIST)s
i = 0
while i < 4:
''' % kwds)
for idx, (target, source1, source2, rotate) in enumerate(_SALSA_OPS):
write('''\
# salsa op %(idx)d: [%(it)d] ^= ([%(is1)d]+[%(is2)d])<<<%(rot1)d
t = (%(src1)s + %(src2)s) & 0xffffffff
%(dst)s ^= ((t & 0x%(rmask)08x) << %(rot1)d) | (t >> %(rot2)d)
''' % dict(
idx=idx, is1 = source1, is2=source2, it=target,
src1=VNAMES[source1],
src2=VNAMES[source2],
dst=VNAMES[target],
rmask=(1<<(32-rotate))-1,
rot1=rotate,
rot2=32-rotate,
))
write('''\
i += 1
''')
for idx in range(16):
write(PAD + "b%d = (b%d + v%d) & 0xffffffff\n" % (idx,idx,idx))
write('''\
return %(TLIST)s
#=================================================================
# eof
#=================================================================
''' % kwds)
if __name__ == "__main__":
main()
#==========================================================================
# eof
#==========================================================================

View File

@@ -0,0 +1,170 @@
"""passlib.utils.scrypt._salsa - salsa 20/8 core, autogenerated by _gen_salsa.py"""
#=================================================================
# salsa function
#=================================================================
def salsa20(input):
"""apply the salsa20/8 core to the provided input
:args input: input list containing 16 32-bit integers
:returns: result list containing 16 32-bit integers
"""
b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15 = input
v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 = \
b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15
i = 0
while i < 4:
# salsa op 0: [4] ^= ([0]+[12])<<<7
t = (v0 + v12) & 0xffffffff
v4 ^= ((t & 0x01ffffff) << 7) | (t >> 25)
# salsa op 1: [8] ^= ([4]+[0])<<<9
t = (v4 + v0) & 0xffffffff
v8 ^= ((t & 0x007fffff) << 9) | (t >> 23)
# salsa op 2: [12] ^= ([8]+[4])<<<13
t = (v8 + v4) & 0xffffffff
v12 ^= ((t & 0x0007ffff) << 13) | (t >> 19)
# salsa op 3: [0] ^= ([12]+[8])<<<18
t = (v12 + v8) & 0xffffffff
v0 ^= ((t & 0x00003fff) << 18) | (t >> 14)
# salsa op 4: [9] ^= ([5]+[1])<<<7
t = (v5 + v1) & 0xffffffff
v9 ^= ((t & 0x01ffffff) << 7) | (t >> 25)
# salsa op 5: [13] ^= ([9]+[5])<<<9
t = (v9 + v5) & 0xffffffff
v13 ^= ((t & 0x007fffff) << 9) | (t >> 23)
# salsa op 6: [1] ^= ([13]+[9])<<<13
t = (v13 + v9) & 0xffffffff
v1 ^= ((t & 0x0007ffff) << 13) | (t >> 19)
# salsa op 7: [5] ^= ([1]+[13])<<<18
t = (v1 + v13) & 0xffffffff
v5 ^= ((t & 0x00003fff) << 18) | (t >> 14)
# salsa op 8: [14] ^= ([10]+[6])<<<7
t = (v10 + v6) & 0xffffffff
v14 ^= ((t & 0x01ffffff) << 7) | (t >> 25)
# salsa op 9: [2] ^= ([14]+[10])<<<9
t = (v14 + v10) & 0xffffffff
v2 ^= ((t & 0x007fffff) << 9) | (t >> 23)
# salsa op 10: [6] ^= ([2]+[14])<<<13
t = (v2 + v14) & 0xffffffff
v6 ^= ((t & 0x0007ffff) << 13) | (t >> 19)
# salsa op 11: [10] ^= ([6]+[2])<<<18
t = (v6 + v2) & 0xffffffff
v10 ^= ((t & 0x00003fff) << 18) | (t >> 14)
# salsa op 12: [3] ^= ([15]+[11])<<<7
t = (v15 + v11) & 0xffffffff
v3 ^= ((t & 0x01ffffff) << 7) | (t >> 25)
# salsa op 13: [7] ^= ([3]+[15])<<<9
t = (v3 + v15) & 0xffffffff
v7 ^= ((t & 0x007fffff) << 9) | (t >> 23)
# salsa op 14: [11] ^= ([7]+[3])<<<13
t = (v7 + v3) & 0xffffffff
v11 ^= ((t & 0x0007ffff) << 13) | (t >> 19)
# salsa op 15: [15] ^= ([11]+[7])<<<18
t = (v11 + v7) & 0xffffffff
v15 ^= ((t & 0x00003fff) << 18) | (t >> 14)
# salsa op 16: [1] ^= ([0]+[3])<<<7
t = (v0 + v3) & 0xffffffff
v1 ^= ((t & 0x01ffffff) << 7) | (t >> 25)
# salsa op 17: [2] ^= ([1]+[0])<<<9
t = (v1 + v0) & 0xffffffff
v2 ^= ((t & 0x007fffff) << 9) | (t >> 23)
# salsa op 18: [3] ^= ([2]+[1])<<<13
t = (v2 + v1) & 0xffffffff
v3 ^= ((t & 0x0007ffff) << 13) | (t >> 19)
# salsa op 19: [0] ^= ([3]+[2])<<<18
t = (v3 + v2) & 0xffffffff
v0 ^= ((t & 0x00003fff) << 18) | (t >> 14)
# salsa op 20: [6] ^= ([5]+[4])<<<7
t = (v5 + v4) & 0xffffffff
v6 ^= ((t & 0x01ffffff) << 7) | (t >> 25)
# salsa op 21: [7] ^= ([6]+[5])<<<9
t = (v6 + v5) & 0xffffffff
v7 ^= ((t & 0x007fffff) << 9) | (t >> 23)
# salsa op 22: [4] ^= ([7]+[6])<<<13
t = (v7 + v6) & 0xffffffff
v4 ^= ((t & 0x0007ffff) << 13) | (t >> 19)
# salsa op 23: [5] ^= ([4]+[7])<<<18
t = (v4 + v7) & 0xffffffff
v5 ^= ((t & 0x00003fff) << 18) | (t >> 14)
# salsa op 24: [11] ^= ([10]+[9])<<<7
t = (v10 + v9) & 0xffffffff
v11 ^= ((t & 0x01ffffff) << 7) | (t >> 25)
# salsa op 25: [8] ^= ([11]+[10])<<<9
t = (v11 + v10) & 0xffffffff
v8 ^= ((t & 0x007fffff) << 9) | (t >> 23)
# salsa op 26: [9] ^= ([8]+[11])<<<13
t = (v8 + v11) & 0xffffffff
v9 ^= ((t & 0x0007ffff) << 13) | (t >> 19)
# salsa op 27: [10] ^= ([9]+[8])<<<18
t = (v9 + v8) & 0xffffffff
v10 ^= ((t & 0x00003fff) << 18) | (t >> 14)
# salsa op 28: [12] ^= ([15]+[14])<<<7
t = (v15 + v14) & 0xffffffff
v12 ^= ((t & 0x01ffffff) << 7) | (t >> 25)
# salsa op 29: [13] ^= ([12]+[15])<<<9
t = (v12 + v15) & 0xffffffff
v13 ^= ((t & 0x007fffff) << 9) | (t >> 23)
# salsa op 30: [14] ^= ([13]+[12])<<<13
t = (v13 + v12) & 0xffffffff
v14 ^= ((t & 0x0007ffff) << 13) | (t >> 19)
# salsa op 31: [15] ^= ([14]+[13])<<<18
t = (v14 + v13) & 0xffffffff
v15 ^= ((t & 0x00003fff) << 18) | (t >> 14)
i += 1
b0 = (b0 + v0) & 0xffffffff
b1 = (b1 + v1) & 0xffffffff
b2 = (b2 + v2) & 0xffffffff
b3 = (b3 + v3) & 0xffffffff
b4 = (b4 + v4) & 0xffffffff
b5 = (b5 + v5) & 0xffffffff
b6 = (b6 + v6) & 0xffffffff
b7 = (b7 + v7) & 0xffffffff
b8 = (b8 + v8) & 0xffffffff
b9 = (b9 + v9) & 0xffffffff
b10 = (b10 + v10) & 0xffffffff
b11 = (b11 + v11) & 0xffffffff
b12 = (b12 + v12) & 0xffffffff
b13 = (b13 + v13) & 0xffffffff
b14 = (b14 + v14) & 0xffffffff
b15 = (b15 + v15) & 0xffffffff
return b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15
#=================================================================
# eof
#=================================================================