PNG  IHDRQgAMA a cHRMz&u0`:pQ<bKGDgmIDATxwUﹻ& ^CX(J I@ "% (** BX +*i"]j(IH{~R)[~>h{}gy)I$Ij .I$I$ʊy@}x.: $I$Ii}VZPC)I$IF ^0ʐJ$I$Q^}{"r=OzI$gRZeC.IOvH eKX $IMpxsk.쒷/&r[޳<v| .I~)@$updYRa$I |M.e JaֶpSYR6j>h%IRز if&uJ)M$I vLi=H;7UJ,],X$I1AҒJ$ XY XzI@GNҥRT)E@;]K*Mw;#5_wOn~\ DC&$(A5 RRFkvIR}l!RytRl;~^ǷJj اy뷦BZJr&ӥ8Pjw~vnv X^(I;4R=P[3]J,]ȏ~:3?[ a&e)`e*P[4]T=Cq6R[ ~ޤrXR Հg(t_HZ-Hg M$ãmL5R uk*`%C-E6/%[t X.{8P9Z.vkXŐKjgKZHg(aK9ڦmKjѺm_ \#$5,)-  61eJ,5m| r'= &ڡd%-]J on Xm|{ RҞe $eڧY XYrԮ-a7RK6h>n$5AVڴi*ֆK)mѦtmr1p| q:흺,)Oi*ֺK)ܬ֦K-5r3>0ԔHjJئEZj,%re~/z%jVMڸmrt)3]J,T K֦OvԒgii*bKiNO~%PW0=dii2tJ9Jݕ{7"I P9JKTbu,%r"6RKU}Ij2HKZXJ,妝 XYrP ެ24c%i^IK|.H,%rb:XRl1X4Pe/`x&P8Pj28Mzsx2r\zRPz4J}yP[g=L) .Q[6RjWgp FIH*-`IMRaK9TXcq*I y[jE>cw%gLRԕiFCj-ďa`#e~I j,%r,)?[gp FI˨mnWX#>mʔ XA DZf9,nKҲzIZXJ,L#kiPz4JZF,I,`61%2s $,VOϚ2/UFJfy7K> X+6 STXIeJILzMfKm LRaK9%|4p9LwJI!`NsiazĔ)%- XMq>pk$-$Q2x#N ؎-QR}ᶦHZډ)J,l#i@yn3LN`;nڔ XuX5pF)m|^0(>BHF9(cզEerJI rg7 4I@z0\JIi䵙RR0s;$s6eJ,`n 䂦0a)S)A 1eJ,堌#635RIgpNHuTH_SԕqVe ` &S)>p;S$魁eKIuX`I4춒o}`m$1":PI<[v9^\pTJjriRŭ P{#{R2,`)e-`mgj~1ϣLKam7&U\j/3mJ,`F;M'䱀 .KR#)yhTq;pcK9(q!w?uRR,n.yw*UXj#\]ɱ(qv2=RqfB#iJmmL<]Y͙#$5 uTU7ӦXR+q,`I}qL'`6Kͷ6r,]0S$- [RKR3oiRE|nӦXR.(i:LDLTJjY%o:)6rxzҒqTJjh㞦I.$YR.ʼnGZ\ֿf:%55 I˼!6dKxm4E"mG_ s? .e*?LRfK9%q#uh$)i3ULRfK9yxm܌bj84$i1U^@Wbm4uJ,ҪA>_Ij?1v32[gLRD96oTaR׿N7%L2 NT,`)7&ƝL*꽙yp_$M2#AS,`)7$rkTA29_Iye"|/0t)$n XT2`YJ;6Jx".e<`$) PI$5V4]29SRI>~=@j]lp2`K9Jaai^" Ԋ29ORI%:XV5]JmN9]H;1UC39NI%Xe78t)a;Oi Ҙ>Xt"~G>_mn:%|~ޅ_+]$o)@ǀ{hgN;IK6G&rp)T2i୦KJuv*T=TOSV>(~D>dm,I*Ɛ:R#ۙNI%D>G.n$o;+#RR!.eU˽TRI28t)1LWϚ>IJa3oFbu&:tJ*(F7y0ZR ^p'Ii L24x| XRI%ۄ>S1]Jy[zL$adB7.eh4%%누>WETf+3IR:I3Xה)3אOۦSRO'ٺ)S}"qOr[B7ϙ.edG)^ETR"RtRݜh0}LFVӦDB^k_JDj\=LS(Iv─aTeZ%eUAM-0;~˃@i|l @S4y72>sX-vA}ϛBI!ݎߨWl*)3{'Y|iSlEڻ(5KtSI$Uv02,~ԩ~x;P4ցCrO%tyn425:KMlD ^4JRxSهF_}شJTS6uj+ﷸk$eZO%G*^V2u3EMj3k%)okI]dT)URKDS 7~m@TJR~荪fT"֛L \sM -0T KfJz+nإKr L&j()[E&I ߴ>e FW_kJR|!O:5/2跌3T-'|zX ryp0JS ~^F>-2< `*%ZFP)bSn"L :)+pʷf(pO3TMW$~>@~ū:TAIsV1}S2<%ޟM?@iT ,Eūoz%i~g|`wS(]oȤ8)$ ntu`өe`6yPl IzMI{ʣzʨ )IZ2= ld:5+請M$-ї;U>_gsY$ÁN5WzWfIZ)-yuXIfp~S*IZdt;t>KūKR|$#LcԀ+2\;kJ`]YǔM1B)UbG"IRߊ<xܾӔJ0Z='Y嵤 Leveg)$znV-º^3Ւof#0Tfk^Zs[*I꯳3{)ˬW4Ւ4 OdpbZRS|*I 55#"&-IvT&/윚Ye:i$ 9{LkuRe[I~_\ؠ%>GL$iY8 9ܕ"S`kS.IlC;Ҏ4x&>u_0JLr<J2(^$5L s=MgV ~,Iju> 7r2)^=G$1:3G< `J3~&IR% 6Tx/rIj3O< ʔ&#f_yXJiގNSz; Tx(i8%#4 ~AS+IjerIUrIj362v885+IjAhK__5X%nV%Iͳ-y|7XV2v4fzo_68"S/I-qbf; LkF)KSM$ Ms>K WNV}^`-큧32ŒVؙGdu,^^m%6~Nn&͓3ŒVZMsRpfEW%IwdǀLm[7W&bIRL@Q|)* i ImsIMmKmyV`i$G+R 0tV'!V)֏28vU7͒vHꦼtxꗞT ;S}7Mf+fIRHNZUkUx5SAJㄌ9MqμAIRi|j5)o*^'<$TwI1hEU^c_j?Е$%d`z cyf,XO IJnTgA UXRD }{H}^S,P5V2\Xx`pZ|Yk:$e ~ @nWL.j+ϝYb퇪bZ BVu)u/IJ_ 1[p.p60bC >|X91P:N\!5qUB}5a5ja `ubcVxYt1N0Zzl4]7­gKj]?4ϻ *[bg$)+À*x쳀ogO$~,5 زUS9 lq3+5mgw@np1sso Ӻ=|N6 /g(Wv7U;zωM=wk,0uTg_`_P`uz?2yI!b`kĸSo+Qx%!\οe|އԁKS-s6pu_(ֿ$i++T8=eY; צP+phxWQv*|p1. ά. XRkIQYP,drZ | B%wP|S5`~́@i޾ E;Չaw{o'Q?%iL{u D?N1BD!owPHReFZ* k_-~{E9b-~P`fE{AܶBJAFO wx6Rox5 K5=WwehS8 (JClJ~ p+Fi;ŗo+:bD#g(C"wA^ r.F8L;dzdIHUX݆ϞXg )IFqem%I4dj&ppT{'{HOx( Rk6^C٫O.)3:s(۳(Z?~ٻ89zmT"PLtw䥈5&b<8GZ-Y&K?e8,`I6e(֍xb83 `rzXj)F=l($Ij 2*(F?h(/9ik:I`m#p3MgLaKjc/U#n5S# m(^)=y=đx8ŬI[U]~SцA4p$-F i(R,7Cx;X=cI>{Km\ o(Tv2vx2qiiDJN,Ҏ!1f 5quBj1!8 rDFd(!WQl,gSkL1Bxg''՞^ǘ;pQ P(c_ IRujg(Wz bs#P­rz> k c&nB=q+ؔXn#r5)co*Ũ+G?7< |PQӣ'G`uOd>%Mctz# Ԫڞ&7CaQ~N'-P.W`Oedp03C!IZcIAMPUۀ5J<\u~+{9(FbbyAeBhOSܳ1 bÈT#ŠyDžs,`5}DC-`̞%r&ڙa87QWWp6e7 Rϫ/oY ꇅ Nܶըtc!LA T7V4Jsū I-0Pxz7QNF_iZgúWkG83 0eWr9 X]㾮݁#Jˢ C}0=3ݱtBi]_ &{{[/o[~ \q鯜00٩|cD3=4B_b RYb$óBRsf&lLX#M*C_L܄:gx)WΘsGSbuL rF$9';\4Ɍq'n[%p.Q`u hNb`eCQyQ|l_C>Lb꟟3hSb #xNxSs^ 88|Mz)}:](vbۢamŖ࿥ 0)Q7@0=?^k(*J}3ibkFn HjB׻NO z x}7p 0tfDX.lwgȔhԾŲ }6g E |LkLZteu+=q\Iv0쮑)QٵpH8/2?Σo>Jvppho~f>%bMM}\//":PTc(v9v!gոQ )UfVG+! 35{=x\2+ki,y$~A1iC6#)vC5^>+gǵ@1Hy٪7u;p psϰu/S <aʸGu'tD1ԝI<pg|6j'p:tպhX{o(7v],*}6a_ wXRk,O]Lܳ~Vo45rp"N5k;m{rZbΦ${#)`(Ŵg,;j%6j.pyYT?}-kBDc3qA`NWQū20/^AZW%NQ MI.X#P#,^Ebc&?XR tAV|Y.1!؅⨉ccww>ivl(JT~ u`ٵDm q)+Ri x/x8cyFO!/*!/&,7<.N,YDŽ&ܑQF1Bz)FPʛ?5d 6`kQձ λc؎%582Y&nD_$Je4>a?! ͨ|ȎWZSsv8 j(I&yj Jb5m?HWp=g}G3#|I,5v珿] H~R3@B[☉9Ox~oMy=J;xUVoj bUsl_35t-(ՃɼRB7U!qc+x4H_Qo֮$[GO<4`&č\GOc[.[*Af%mG/ ňM/r W/Nw~B1U3J?P&Y )`ѓZ1p]^l“W#)lWZilUQu`-m|xĐ,_ƪ|9i:_{*(3Gѧ}UoD+>m_?VPۅ15&}2|/pIOʵ> GZ9cmíتmnz)yߐbD >e}:) r|@R5qVSA10C%E_'^8cR7O;6[eKePGϦX7jb}OTGO^jn*媓7nGMC t,k31Rb (vyܴʭ!iTh8~ZYZp(qsRL ?b}cŨʊGO^!rPJO15MJ[c&~Z`"ѓޔH1C&^|Ш|rʼ,AwĴ?b5)tLU)F| &g٣O]oqSUjy(x<Ϳ3 .FSkoYg2 \_#wj{u'rQ>o;%n|F*O_L"e9umDds?.fuuQbIWz |4\0 sb;OvxOSs; G%T4gFRurj(֍ڑb uԖKDu1MK{1^ q; C=6\8FR艇!%\YÔU| 88m)֓NcLve C6z;o&X x59:q61Z(T7>C?gcļxѐ Z oo-08jہ x,`' ҔOcRlf~`jj".Nv+sM_]Zk g( UOPyεx%pUh2(@il0ݽQXxppx-NS( WO+轾 nFߢ3M<;z)FBZjciu/QoF 7R¥ ZFLF~#ȣߨ^<쩡ݛкvџ))ME>ώx4m#!-m!L;vv#~Y[đKmx9.[,UFS CVkZ +ߟrY٧IZd/ioi$%͝ب_ֶX3ܫhNU ZZgk=]=bbJS[wjU()*I =ώ:}-蹞lUj:1}MWm=̛ _ ¾,8{__m{_PVK^n3esw5ӫh#$-q=A̟> ,^I}P^J$qY~Q[ Xq9{#&T.^GVj__RKpn,b=`żY@^՝;z{paVKkQXj/)y TIc&F;FBG7wg ZZDG!x r_tƢ!}i/V=M/#nB8 XxЫ ^@CR<{䤭YCN)eKOSƟa $&g[i3.C6xrOc8TI;o hH6P&L{@q6[ Gzp^71j(l`J}]e6X☉#͕ ׈$AB1Vjh㭦IRsqFBjwQ_7Xk>y"N=MB0 ,C #o6MRc0|$)ف"1!ixY<B9mx `,tA>)5ػQ?jQ?cn>YZe Tisvh# GMމȇp:ԴVuږ8ɼH]C.5C!UV;F`mbBk LTMvPʍϤj?ԯ/Qr1NB`9s"s TYsz &9S%U԰> {<ؿSMxB|H\3@!U| k']$U+> |HHMLޢ?V9iD!-@x TIî%6Z*9X@HMW#?nN ,oe6?tQwڱ.]-y':mW0#!J82qFjH -`ѓ&M0u Uγmxϵ^-_\])@0Rt.8/?ٰCY]x}=sD3ojަЫNuS%U}ԤwHH>ڗjܷ_3gN q7[q2la*ArǓԖ+p8/RGM ]jacd(JhWko6ڎbj]i5Bj3+3!\j1UZLsLTv8HHmup<>gKMJj0@H%,W΃7R) ">c, xixј^ aܖ>H[i.UIHc U1=yW\=S*GR~)AF=`&2h`DzT󑓶J+?W+}C%P:|0H܆}-<;OC[~o.$~i}~HQ TvXΈr=b}$vizL4:ȰT|4~*!oXQR6Lk+#t/g lԁߖ[Jڶ_N$k*". xsxX7jRVbAAʯKҎU3)zSNN _'s?f)6X!%ssAkʱ>qƷb hg %n ~p1REGMHH=BJiy[<5 ǁJҖgKR*倳e~HUy)Ag,K)`Vw6bRR:qL#\rclK/$sh*$ 6덤 KԖc 3Z9=Ɣ=o>X Ώ"1 )a`SJJ6k(<c e{%kϊP+SL'TcMJWRm ŏ"w)qc ef꒵i?b7b('"2r%~HUS1\<(`1Wx9=8HY9m:X18bgD1u ~|H;K-Uep,, C1 RV.MR5άh,tWO8WC$ XRVsQS]3GJ|12 [vM :k#~tH30Rf-HYݺ-`I9%lIDTm\ S{]9gOڒMNCV\G*2JRŨ;Rҏ^ڽ̱mq1Eu?To3I)y^#jJw^Ńj^vvlB_⋌P4x>0$c>K†Aļ9s_VjTt0l#m>E-,,x,-W)سo&96RE XR.6bXw+)GAEvL)͞K4$p=Ũi_ѱOjb HY/+@θH9޼]Nԥ%n{ &zjT? Ty) s^ULlb,PiTf^<À] 62R^V7)S!nllS6~͝V}-=%* ʻ>G DnK<y&>LPy7'r=Hj 9V`[c"*^8HpcO8bnU`4JȪAƋ#1_\ XϘHPRgik(~G~0DAA_2p|J묭a2\NCr]M_0 ^T%e#vD^%xy-n}-E\3aS%yN!r_{ )sAw ڼp1pEAk~v<:`'ӭ^5 ArXOI驻T (dk)_\ PuA*BY]yB"l\ey hH*tbK)3 IKZ򹞋XjN n *n>k]X_d!ryBH ]*R 0(#'7 %es9??ښFC,ՁQPjARJ\Ρw K#jahgw;2$l*) %Xq5!U᢯6Re] |0[__64ch&_}iL8KEgҎ7 M/\`|.p,~`a=BR?xܐrQ8K XR2M8f ?`sgWS%" Ԉ 7R%$ N}?QL1|-эټwIZ%pvL3Hk>,ImgW7{E xPHx73RA @RS CC !\ȟ5IXR^ZxHл$Q[ŝ40 (>+ _C >BRt<,TrT {O/H+˟Pl6 I B)/VC<6a2~(XwV4gnXR ϱ5ǀHٻ?tw똤Eyxp{#WK qG%5],(0ӈH HZ])ג=K1j&G(FbM@)%I` XRg ʔ KZG(vP,<`[ Kn^ SJRsAʠ5xՅF`0&RbV tx:EaUE/{fi2;.IAwW8/tTxAGOoN?G}l L(n`Zv?pB8K_gI+ܗ #i?ޙ.) p$utc ~DžfՈEo3l/)I-U?aԅ^jxArA ΧX}DmZ@QLےbTXGd.^|xKHR{|ΕW_h] IJ`[G9{).y) 0X YA1]qp?p_k+J*Y@HI>^?gt.06Rn ,` ?);p pSF9ZXLBJPWjgQ|&)7! HjQt<| ؅W5 x W HIzYoVMGP Hjn`+\(dNW)F+IrS[|/a`K|ͻ0Hj{R,Q=\ (F}\WR)AgSG`IsnAR=|8$}G(vC$)s FBJ?]_u XRvύ6z ŨG[36-T9HzpW̞ú Xg큽=7CufzI$)ki^qk-) 0H*N` QZkk]/tnnsI^Gu't=7$ Z;{8^jB% IItRQS7[ϭ3 $_OQJ`7!]W"W,)Iy W AJA;KWG`IY{8k$I$^%9.^(`N|LJ%@$I}ֽp=FB*xN=gI?Q{٥4B)mw $Igc~dZ@G9K X?7)aK%݅K$IZ-`IpC U6$I\0>!9k} Xa IIS0H$I H ?1R.Чj:4~Rw@p$IrA*u}WjWFPJ$I➓/6#! LӾ+ X36x8J |+L;v$Io4301R20M I$-E}@,pS^ޟR[/s¹'0H$IKyfŸfVOπFT*a$I>He~VY/3R/)>d$I>28`Cjw,n@FU*9ttf$I~<;=/4RD~@ X-ѕzἱI$: ԍR a@b X{+Qxuq$IЛzo /~3\8ڒ4BN7$IҀj V]n18H$IYFBj3̵̚ja pp $Is/3R Ӻ-Yj+L;.0ŔI$Av? #!5"aʄj}UKmɽH$IjCYs?h$IDl843.v}m7UiI=&=0Lg0$I4: embe` eQbm0u? $IT!Sƍ'-sv)s#C0:XB2a w I$zbww{."pPzO =Ɔ\[ o($Iaw]`E).Kvi:L*#gР7[$IyGPI=@R 4yR~̮´cg I$I/<tPͽ hDgo 94Z^k盇΄8I56^W$I^0̜N?4*H`237}g+hxoq)SJ@p|` $I%>-hO0eO>\ԣNߌZD6R=K ~n($I$y3D>o4b#px2$yڪtzW~a $I~?x'BwwpH$IZݑnC㧄Pc_9sO gwJ=l1:mKB>Ab<4Lp$Ib o1ZQ@85b̍ S'F,Fe,^I$IjEdù{l4 8Ys_s Z8.x m"+{~?q,Z D!I$ϻ'|XhB)=…']M>5 rgotԎ 獽PH$IjIPhh)n#cÔqA'ug5qwU&rF|1E%I$%]!'3AFD/;Ck_`9 v!ٴtPV;x`'*bQa w I$Ix5 FC3D_~A_#O݆DvV?<qw+I$I{=Z8".#RIYyjǪ=fDl9%M,a8$I$Ywi[7ݍFe$s1ՋBVA?`]#!oz4zjLJo8$I$%@3jAa4(o ;p,,dya=F9ً[LSPH$IJYЉ+3> 5"39aZ<ñh!{TpBGkj}Sp $IlvF.F$I z< '\K*qq.f<2Y!S"-\I$IYwčjF$ w9 \ߪB.1v!Ʊ?+r:^!I$BϹB H"B;L'G[ 4U#5>੐)|#o0aڱ$I>}k&1`U#V?YsV x>{t1[I~D&(I$I/{H0fw"q"y%4 IXyE~M3 8XψL}qE$I[> nD?~sf ]o΁ cT6"?'_Ἣ $I>~.f|'!N?⟩0G KkXZE]ޡ;/&?k OۘH$IRۀwXӨ<7@PnS04aӶp.:@\IWQJ6sS%I$e5ڑv`3:x';wq_vpgHyXZ 3gЂ7{{EuԹn±}$I$8t;b|591nءQ"P6O5i }iR̈́%Q̄p!I䮢]O{H$IRϻ9s֧ a=`- aB\X0"+5"C1Hb?߮3x3&gşggl_hZ^,`5?ߎvĸ%̀M!OZC2#0x LJ0 Gw$I$I}<{Eb+y;iI,`ܚF:5ܛA8-O-|8K7s|#Z8a&><a&/VtbtLʌI$I$I$I$I$I$IRjDD%tEXtdate:create2022-05-31T04:40:26+00:00!Î%tEXtdate:modify2022-05-31T04:40:26+00:00|{2IENDB`Mini Shell

HOME


Mini Shell 1.0
DIR:/usr/lib/python2.7/site-packages/passlib/crypto/
Upload File :
Current File : //usr/lib/python2.7/site-packages/passlib/crypto/des.py
"""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
#=============================================================================