blowfish.bend
bend-osdev-blowfish@0.1.0.0 · 384 lines · 0 definitions
1# Blowfish (B. Schneier, "Description of a New Variable-Length Key, 64-Bit
2# Block Cipher (Blowfish)", Fast Software Encryption 1993): a 64-bit block
3# cipher with a key of 32 to 448 bits.
4#
5# The block is two big-endian 32-bit halves xL, xR. Each of the sixteen
6# rounds is xL = xL xor P_i, xR = F(xL) xor xR, then the halves exchanged;
7# after the last round the exchange is undone and xR = xR xor P17,
8# xL = xL xor P18. F(x) = ((S1[a] + S2[b]) xor S3[c]) + S4[d], a .. d the
9# bytes of x, most significant first. The key schedule starts from the
10# digits of pi (P1 .. P18, then the four S-boxes), XORs the key into the
11# P-array, and replaces P1 .. P18 and then every S-box entry, two at a time,
12# with successive encryptions of the zero block.
13#
14# The key holds the cipher as a list of steps: sixteen rounds
15# (L, R) -> (R xor F(L xor P_i), L xor P_i)
16# and the final (L, R) -> (R xor P18, L xor P17). Decryption undoes them last
17# to first (the specification's decryption, P in reverse order), so
18# decrypt(encrypt(b)) == b is provable for every key and block, whatever the
19# S-boxes hold.
20import Base
21import bend-osdev-bytes@0.1.1.0/bytes.bend as B
22import bend-osdev-cipher-core@0.1.0.0/cipher_core.bend as L
23
24# BEGIN GENERATED by gen/tables.py: tables
25# the first 1042 words of the fractional part of pi: P1 .. P18, then
26# S1, S2, S3, S4 (256 words each)
27def bf.pi.list() -> List<&2, U32>:
28 [608135816, 2242054355, 320440878, 57701188, 2752067618, 698298832, 137296536, 3964562569,
29 1160258022, 953160567, 3193202383, 887688300, 3232508343, 3380367581, 1065670069, 3041331479,
30 2450970073, 2306472731, 3509652390, 2564797868, 805139163, 3491422135, 3101798381, 1780907670,
31 3128725573, 4046225305, 614570311, 3012652279, 134345442, 2240740374, 1667834072, 1901547113,
32 2757295779, 4103290238, 227898511, 1921955416, 1904987480, 2182433518, 2069144605, 3260701109,
33 2620446009, 720527379, 3318853667, 677414384, 3393288472, 3101374703, 2390351024, 1614419982,
34 1822297739, 2954791486, 3608508353, 3174124327, 2024746970, 1432378464, 3864339955, 2857741204,
35 1464375394, 1676153920, 1439316330, 715854006, 3033291828, 289532110, 2706671279, 2087905683,
36 3018724369, 1668267050, 732546397, 1947742710, 3462151702, 2609353502, 2950085171, 1814351708,
37 2050118529, 680887927, 999245976, 1800124847, 3300911131, 1713906067, 1641548236, 4213287313,
38 1216130144, 1575780402, 4018429277, 3917837745, 3693486850, 3949271944, 596196993, 3549867205,
39 258830323, 2213823033, 772490370, 2760122372, 1774776394, 2652871518, 566650946, 4142492826,
40 1728879713, 2882767088, 1783734482, 3629395816, 2517608232, 2874225571, 1861159788, 326777828,
41 3124490320, 2130389656, 2716951837, 967770486, 1724537150, 2185432712, 2364442137, 1164943284,
42 2105845187, 998989502, 3765401048, 2244026483, 1075463327, 1455516326, 1322494562, 910128902,
43 469688178, 1117454909, 936433444, 3490320968, 3675253459, 1240580251, 122909385, 2157517691,
44 634681816, 4142456567, 3825094682, 3061402683, 2540495037, 79693498, 3249098678, 1084186820,
45 1583128258, 426386531, 1761308591, 1047286709, 322548459, 995290223, 1845252383, 2603652396,
46 3431023940, 2942221577, 3202600964, 3727903485, 1712269319, 422464435, 3234572375, 1170764815,
47 3523960633, 3117677531, 1434042557, 442511882, 3600875718, 1076654713, 1738483198, 4213154764,
48 2393238008, 3677496056, 1014306527, 4251020053, 793779912, 2902807211, 842905082, 4246964064,
49 1395751752, 1040244610, 2656851899, 3396308128, 445077038, 3742853595, 3577915638, 679411651,
50 2892444358, 2354009459, 1767581616, 3150600392, 3791627101, 3102740896, 284835224, 4246832056,
51 1258075500, 768725851, 2589189241, 3069724005, 3532540348, 1274779536, 3789419226, 2764799539,
52 1660621633, 3471099624, 4011903706, 913787905, 3497959166, 737222580, 2514213453, 2928710040,
53 3937242737, 1804850592, 3499020752, 2949064160, 2386320175, 2390070455, 2415321851, 4061277028,
54 2290661394, 2416832540, 1336762016, 1754252060, 3520065937, 3014181293, 791618072, 3188594551,
55 3933548030, 2332172193, 3852520463, 3043980520, 413987798, 3465142937, 3030929376, 4245938359,
56 2093235073, 3534596313, 375366246, 2157278981, 2479649556, 555357303, 3870105701, 2008414854,
57 3344188149, 4221384143, 3956125452, 2067696032, 3594591187, 2921233993, 2428461, 544322398,
58 577241275, 1471733935, 610547355, 4027169054, 1432588573, 1507829418, 2025931657, 3646575487,
59 545086370, 48609733, 2200306550, 1653985193, 298326376, 1316178497, 3007786442, 2064951626,
60 458293330, 2589141269, 3591329599, 3164325604, 727753846, 2179363840, 146436021, 1461446943,
61 4069977195, 705550613, 3059967265, 3887724982, 4281599278, 3313849956, 1404054877, 2845806497,
62 146425753, 1854211946, 1266315497, 3048417604, 3681880366, 3289982499, 2909710000, 1235738493,
63 2632868024, 2414719590, 3970600049, 1771706367, 1449415276, 3266420449, 422970021, 1963543593,
64 2690192192, 3826793022, 1062508698, 1531092325, 1804592342, 2583117782, 2714934279, 4024971509,
65 1294809318, 4028980673, 1289560198, 2221992742, 1669523910, 35572830, 157838143, 1052438473,
66 1016535060, 1802137761, 1753167236, 1386275462, 3080475397, 2857371447, 1040679964, 2145300060,
67 2390574316, 1461121720, 2956646967, 4031777805, 4028374788, 33600511, 2920084762, 1018524850,
68 629373528, 3691585981, 3515945977, 2091462646, 2486323059, 586499841, 988145025, 935516892,
69 3367335476, 2599673255, 2839830854, 265290510, 3972581182, 2759138881, 3795373465, 1005194799,
70 847297441, 406762289, 1314163512, 1332590856, 1866599683, 4127851711, 750260880, 613907577,
71 1450815602, 3165620655, 3734664991, 3650291728, 3012275730, 3704569646, 1427272223, 778793252,
72 1343938022, 2676280711, 2052605720, 1946737175, 3164576444, 3914038668, 3967478842, 3682934266,
73 1661551462, 3294938066, 4011595847, 840292616, 3712170807, 616741398, 312560963, 711312465,
74 1351876610, 322626781, 1910503582, 271666773, 2175563734, 1594956187, 70604529, 3617834859,
75 1007753275, 1495573769, 4069517037, 2549218298, 2663038764, 504708206, 2263041392, 3941167025,
76 2249088522, 1514023603, 1998579484, 1312622330, 694541497, 2582060303, 2151582166, 1382467621,
77 776784248, 2618340202, 3323268794, 2497899128, 2784771155, 503983604, 4076293799, 907881277,
78 423175695, 432175456, 1378068232, 4145222326, 3954048622, 3938656102, 3820766613, 2793130115,
79 2977904593, 26017576, 3274890735, 3194772133, 1700274565, 1756076034, 4006520079, 3677328699,
80 720338349, 1533947780, 354530856, 688349552, 3973924725, 1637815568, 332179504, 3949051286,
81 53804574, 2852348879, 3044236432, 1282449977, 3583942155, 3416972820, 4006381244, 1617046695,
82 2628476075, 3002303598, 1686838959, 431878346, 2686675385, 1700445008, 1080580658, 1009431731,
83 832498133, 3223435511, 2605976345, 2271191193, 2516031870, 1648197032, 4164389018, 2548247927,
84 300782431, 375919233, 238389289, 3353747414, 2531188641, 2019080857, 1475708069, 455242339,
85 2609103871, 448939670, 3451063019, 1395535956, 2413381860, 1841049896, 1491858159, 885456874,
86 4264095073, 4001119347, 1565136089, 3898914787, 1108368660, 540939232, 1173283510, 2745871338,
87 3681308437, 4207628240, 3343053890, 4016749493, 1699691293, 1103962373, 3625875870, 2256883143,
88 3830138730, 1031889488, 3479347698, 1535977030, 4236805024, 3251091107, 2132092099, 1774941330,
89 1199868427, 1452454533, 157007616, 2904115357, 342012276, 595725824, 1480756522, 206960106,
90 497939518, 591360097, 863170706, 2375253569, 3596610801, 1814182875, 2094937945, 3421402208,
91 1082520231, 3463918190, 2785509508, 435703966, 3908032597, 1641649973, 2842273706, 3305899714,
92 1510255612, 2148256476, 2655287854, 3276092548, 4258621189, 236887753, 3681803219, 274041037,
93 1734335097, 3815195456, 3317970021, 1899903192, 1026095262, 4050517792, 356393447, 2410691914,
94 3873677099, 3682840055, 3913112168, 2491498743, 4132185628, 2489919796, 1091903735, 1979897079,
95 3170134830, 3567386728, 3557303409, 857797738, 1136121015, 1342202287, 507115054, 2535736646,
96 337727348, 3213592640, 1301675037, 2528481711, 1895095763, 1721773893, 3216771564, 62756741,
97 2142006736, 835421444, 2531993523, 1442658625, 3659876326, 2882144922, 676362277, 1392781812,
98 170690266, 3921047035, 1759253602, 3611846912, 1745797284, 664899054, 1329594018, 3901205900,
99 3045908486, 2062866102, 2865634940, 3543621612, 3464012697, 1080764994, 553557557, 3656615353,
100 3996768171, 991055499, 499776247, 1265440854, 648242737, 3940784050, 980351604, 3713745714,
101 1749149687, 3396870395, 4211799374, 3640570775, 1161844396, 3125318951, 1431517754, 545492359,
102 4268468663, 3499529547, 1437099964, 2702547544, 3433638243, 2581715763, 2787789398, 1060185593,
103 1593081372, 2418618748, 4260947970, 69676912, 2159744348, 86519011, 2512459080, 3838209314,
104 1220612927, 3339683548, 133810670, 1090789135, 1078426020, 1569222167, 845107691, 3583754449,
105 4072456591, 1091646820, 628848692, 1613405280, 3757631651, 526609435, 236106946, 48312990,
106 2942717905, 3402727701, 1797494240, 859738849, 992217954, 4005476642, 2243076622, 3870952857,
107 3732016268, 765654824, 3490871365, 2511836413, 1685915746, 3888969200, 1414112111, 2273134842,
108 3281911079, 4080962846, 172450625, 2569994100, 980381355, 4109958455, 2819808352, 2716589560,
109 2568741196, 3681446669, 3329971472, 1835478071, 660984891, 3704678404, 4045999559, 3422617507,
110 3040415634, 1762651403, 1719377915, 3470491036, 2693910283, 3642056355, 3138596744, 1364962596,
111 2073328063, 1983633131, 926494387, 3423689081, 2150032023, 4096667949, 1749200295, 3328846651,
112 309677260, 2016342300, 1779581495, 3079819751, 111262694, 1274766160, 443224088, 298511866,
113 1025883608, 3806446537, 1145181785, 168956806, 3641502830, 3584813610, 1689216846, 3666258015,
114 3200248200, 1692713982, 2646376535, 4042768518, 1618508792, 1610833997, 3523052358, 4130873264,
115 2001055236, 3610705100, 2202168115, 4028541809, 2961195399, 1006657119, 2006996926, 3186142756,
116 1430667929, 3210227297, 1314452623, 4074634658, 4101304120, 2273951170, 1399257539, 3367210612,
117 3027628629, 1190975929, 2062231137, 2333990788, 2221543033, 2438960610, 1181637006, 548689776,
118 2362791313, 3372408396, 3104550113, 3145860560, 296247880, 1970579870, 3078560182, 3769228297,
119 1714227617, 3291629107, 3898220290, 166772364, 1251581989, 493813264, 448347421, 195405023,
120 2709975567, 677966185, 3703036547, 1463355134, 2715995803, 1338867538, 1343315457, 2802222074,
121 2684532164, 233230375, 2599980071, 2000651841, 3277868038, 1638401717, 4028070440, 3237316320,
122 6314154, 819756386, 300326615, 590932579, 1405279636, 3267499572, 3150704214, 2428286686,
123 3959192993, 3461946742, 1862657033, 1266418056, 963775037, 2089974820, 2263052895, 1917689273,
124 448879540, 3550394620, 3981727096, 150775221, 3627908307, 1303187396, 508620638, 2975983352,
125 2726630617, 1817252668, 1876281319, 1457606340, 908771278, 3720792119, 3617206836, 2455994898,
126 1729034894, 1080033504, 976866871, 3556439503, 2881648439, 1522871579, 1555064734, 1336096578,
127 3548522304, 2579274686, 3574697629, 3205460757, 3593280638, 3338716283, 3079412587, 564236357,
128 2993598910, 1781952180, 1464380207, 3163844217, 3332601554, 1699332808, 1393555694, 1183702653,
129 3581086237, 1288719814, 691649499, 2847557200, 2895455976, 3193889540, 2717570544, 1781354906,
130 1676643554, 2592534050, 3230253752, 1126444790, 2770207658, 2633158820, 2210423226, 2615765581,
131 2414155088, 3127139286, 673620729, 2805611233, 1269405062, 4015350505, 3341807571, 4149409754,
132 1057255273, 2012875353, 2162469141, 2276492801, 2601117357, 993977747, 3918593370, 2654263191,
133 753973209, 36408145, 2530585658, 25011837, 3520020182, 2088578344, 530523599, 2918365339,
134 1524020338, 1518925132, 3760827505, 3759777254, 1202760957, 3985898139, 3906192525, 674977740,
135 4174734889, 2031300136, 2019492241, 3983892565, 4153806404, 3822280332, 352677332, 2297720250,
136 60907813, 90501309, 3286998549, 1016092578, 2535922412, 2839152426, 457141659, 509813237,
137 4120667899, 652014361, 1966332200, 2975202805, 55981186, 2327461051, 676427537, 3255491064,
138 2882294119, 3433927263, 1307055953, 942726286, 933058658, 2468411793, 3933900994, 4215176142,
139 1361170020, 2001714738, 2830558078, 3274259782, 1222529897, 1679025792, 2729314320, 3714953764,
140 1770335741, 151462246, 3013232138, 1682292957, 1483529935, 471910574, 1539241949, 458788160,
141 3436315007, 1807016891, 3718408830, 978976581, 1043663428, 3165965781, 1927990952, 4200891579,
142 2372276910, 3208408903, 3533431907, 1412390302, 2931980059, 4132332400, 1947078029, 3881505623,
143 4168226417, 2941484381, 1077988104, 1320477388, 886195818, 18198404, 3786409000, 2509781533,
144 112762804, 3463356488, 1866414978, 891333506, 18488651, 661792760, 1628790961, 3885187036,
145 3141171499, 876946877, 2693282273, 1372485963, 791857591, 2686433993, 3759982718, 3167212022,
146 3472953795, 2716379847, 445679433, 3561995674, 3504004811, 3574258232, 54117162, 3331405415,
147 2381918588, 3769707343, 4154350007, 1140177722, 4074052095, 668550556, 3214352940, 367459370,
148 261225585, 2610173221, 4209349473, 3468074219, 3265815641, 314222801, 3066103646, 3808782860,
149 282218597, 3406013506, 3773591054, 379116347, 1285071038, 846784868, 2669647154, 3771962079,
150 3550491691, 2305946142, 453669953, 1268987020, 3317592352, 3279303384, 3744833421, 2610507566,
151 3859509063, 266596637, 3847019092, 517658769, 3462560207, 3443424879, 370717030, 4247526661,
152 2224018117, 4143653529, 4112773975, 2788324899, 2477274417, 1456262402, 2901442914, 1517677493,
153 1846949527, 2295493580, 3734397586, 2176403920, 1280348187, 1908823572, 3871786941, 846861322,
154 1172426758, 3287448474, 3383383037, 1655181056, 3139813346, 901632758, 1897031941, 2986607138,
155 3066810236, 3447102507, 1393639104, 373351379, 950779232, 625454576, 3124240540, 4148612726,
156 2007998917, 544563296, 2244738638, 2330496472, 2058025392, 1291430526, 424198748, 50039436,
157 29584100, 3605783033, 2429876329, 2791104160, 1057563949, 3255363231, 3075367218, 3463963227,
158 1469046755, 985887462]
159# END GENERATED: tables
160
161# The four S-boxes (internal)
162type LcBfTabs is Data:
163 LcBfTabs{s1: L.LcTab, s2: L.LcTab, s3: L.LcTab, s4: L.LcTab}
164
165# F
166def bf.f(t: LcBfTabs, +x: U32) -> U32:
167 match t:
168 case LcBfTabs{s1, s2, s3, s4}:
169 U32.add(U32.xor(U32.add(L.lc.tab.get(8n, s1, L.lc.byte(x, 3n)), L.lc.tab.get(8n, s2, L.lc.byte(x, 2n))), L.lc.tab.get(8n, s3, L.lc.byte(x, 1n))), L.lc.tab.get(8n, s4, L.lc.byte(x, 0n)))
170
171# The steps of the cipher (internal)
172type LcBfOp is Data:
173 LcBfRound{p: U32, t: LcBfTabs}
174 LcBfFinal{p17: U32, p18: U32}
175
176def bf.op(o: LcBfOp, b: L.LcBlock64) -> L.LcBlock64:
177 match o:
178 case LcBfRound{p, t}:
179 match b:
180 case L.LcBlock64{l, r}:
181 +a = U32.xor(l, p)
182 L.LcBlock64{U32.xor(r, bf.f(t, a)), a}
183 case LcBfFinal{p17, p18}:
184 match b:
185 case L.LcBlock64{l, r}:
186 L.LcBlock64{U32.xor(r, p18), U32.xor(l, p17)}
187
188def bf.unop(o: LcBfOp, b: L.LcBlock64) -> L.LcBlock64:
189 match o:
190 case LcBfRound{p, t}:
191 match b:
192 case L.LcBlock64{x, +y}:
193 L.LcBlock64{U32.xor(y, p), U32.xor(x, bf.f(t, y))}
194 case LcBfFinal{p17, p18}:
195 match b:
196 case L.LcBlock64{x, y}:
197 L.LcBlock64{U32.xor(y, p17), U32.xor(x, p18)}
198
199def bf.run(os: List<&2, LcBfOp>, b: L.LcBlock64) -> L.LcBlock64:
200 match os:
201 case Nil{}:
202 b
203 case Con{o, t}:
204 bf.run(t, bf.op(o, b))
205
206def bf.unrun(os: List<&2, LcBfOp>, b: L.LcBlock64) -> L.LcBlock64:
207 match os:
208 case Nil{}:
209 b
210 case Con{o, t}:
211 bf.unop(o, bf.unrun(t, b))
212
213# The key schedule
214
215# the steps from a P-array of 18 words (n = 16 rounds, then the final)
216def bf.ops(n: Nat, ps: List<&2, U32>, +t: LcBfTabs) -> List<&2, LcBfOp>:
217 match n:
218 case 0n:
219 match ps:
220 case Con{p17, Con{p18, rest}}:
221 [LcBfFinal{p17, p18}]
222 case _:
223 Nil{}
224 case 1n+m:
225 match ps:
226 case Con{p, rest}:
227 Con{LcBfRound{p, t}, bf.ops(m, rest, t)}
228 case Nil{}:
229 Nil{}
230
231# n words of xs from offset i
232def bf.slice(xs: List<&2, U32>, i: Nat, n: Nat) -> List<&2, U32>:
233 B.take(n, B.drop(i, xs))
234
235# the key bytes repeated cyclically: n bytes, from the rest of the key ys
236# (the whole key xs when ys runs out)
237def bf.cycle(n: Nat, ys: List<&2, U32>, +xs: List<&2, U32>) -> List<&2, U32>:
238 match n:
239 case 0n:
240 Nil{}
241 case 1n+p:
242 match ys:
243 case Con{y, t}:
244 Con{y, bf.cycle(p, t, xs)}
245 case Nil{}:
246 match xs:
247 case Nil{}:
248 Nil{}
249 case Con{x, t}:
250 Con{x, bf.cycle(p, t, xs)}
251
252# P xored with the key bytes as big-endian words
253def bf.pkey(ps: List<&2, U32>, ks: List<&2, U32>) -> List<&2, U32>:
254 match ps ks:
255 case Con{p, pt} Con{a, Con{b, Con{c, Con{d, kt}}}}:
256 Con{U32.xor(p, L.lc.be(a, b, c, d)), bf.pkey(pt, kt)}
257 case _ _:
258 Nil{}
259
260# P entries i and i + 1 replaced by h and l
261def bf.set_p(i: Nat, ps: List<&2, U32>, +h: U32, +l: U32) -> List<&2, U32>:
262 match i:
263 case 0n:
264 match ps:
265 case Con{p, Con{q, u}}:
266 Con{h, Con{l, u}}
267 case _:
268 Nil{}
269 case 1n+j:
270 match ps:
271 case Con{p, t}:
272 Con{p, bf.set_p(j, t, h, l)}
273 case Nil{}:
274 Nil{}
275
276# entry j of the S-box k (0 to 3) set to v
277def bf.set_s(t: LcBfTabs, k: Nat, +j: U32, v: U32) -> LcBfTabs:
278 match t:
279 case LcBfTabs{s1, s2, s3, s4}:
280 match k:
281 case 0n:
282 LcBfTabs{L.lc.tab.set(8n, s1, j, v), s2, s3, s4}
283 case 1n+k1:
284 match k1:
285 case 0n:
286 LcBfTabs{s1, L.lc.tab.set(8n, s2, j, v), s3, s4}
287 case 1n+k2:
288 match k2:
289 case 0n:
290 LcBfTabs{s1, s2, L.lc.tab.set(8n, s3, j, v), s4}
291 case 1n+k3:
292 LcBfTabs{s1, s2, s3, L.lc.tab.set(8n, s4, j, v)}
293
294# The state of the key schedule: the P-array, the S-boxes, and the last
295# block encrypted
296type LcBfSt is Data:
297 LcBfSt{ps: List<&2, U32>, t: LcBfTabs, b: L.LcBlock64}
298
299def bf.fill_p.go(n: Nat, +i: Nat, +ps: List<&2, U32>, +t: LcBfTabs, c: L.LcBlock64) -> LcBfSt:
300 match n:
301 case 0n:
302 match c:
303 case L.LcBlock64{+h, +l}:
304 LcBfSt{bf.set_p(i, ps, h, l), t, L.LcBlock64{h, l}}
305 case 1n+m:
306 match c:
307 case L.LcBlock64{+h, +l}:
308 +ps2 = bf.set_p(i, ps, h, l)
309 bf.fill_p.go(m, Nat.add(i, 2n), ps2, t, bf.run(bf.ops(16n, ps2, t), L.LcBlock64{h, l}))
310
311# P1 .. P18 replaced, two at a time, by successive encryptions (nine)
312def bf.fill_p(s: LcBfSt) -> LcBfSt:
313 match s:
314 case LcBfSt{+ps, +t, b}:
315 bf.fill_p.go(8n, 0n, ps, t, bf.run(bf.ops(16n, ps, t), b))
316
317def bf.fill_s.go(n: Nat, +k: Nat, +j: U32, +ps: List<&2, U32>, +t: LcBfTabs, c: L.LcBlock64) -> LcBfSt:
318 match n:
319 case 0n:
320 match c:
321 case L.LcBlock64{+h, +l}:
322 LcBfSt{ps, bf.set_s(bf.set_s(t, k, j, h), k, U32.add(j, 1), l), L.LcBlock64{h, l}}
323 case 1n+m:
324 match c:
325 case L.LcBlock64{+h, +l}:
326 +t1 = bf.set_s(bf.set_s(t, k, j, h), k, U32.add(j, 1), l)
327 bf.fill_s.go(m, k, U32.add(j, 2), ps, t1, bf.run(bf.ops(16n, ps, t1), L.LcBlock64{h, l}))
328
329# the S-box k's 256 entries replaced, two at a time (128 encryptions)
330def bf.fill_s(+k: Nat, s: LcBfSt) -> LcBfSt:
331 match s:
332 case LcBfSt{+ps, +t, b}:
333 bf.fill_s.go(127n, k, 0, ps, t, bf.run(bf.ops(16n, ps, t), b))
334
335# A Blowfish key: the steps of the cipher (opaque; built by LcBlowfish.key)
336type LcBlowfishKey is Data:
337 LcBlowfishKey{ops: List<&2, LcBfOp>}
338
339# the S-boxes before the key: pi's words 18 to 1041
340def bf.tables(+pi: List<&2, U32>) -> LcBfTabs:
341 LcBfTabs{L.lc.tab(8n, bf.slice(pi, 18n, 256n)), L.lc.tab(8n, bf.slice(pi, 274n, 256n)), L.lc.tab(8n, bf.slice(pi, 530n, 256n)), L.lc.tab(8n, bf.slice(pi, 786n, 256n))}
342
343def bf.key.of(s: LcBfSt) -> LcBlowfishKey:
344 match s:
345 case LcBfSt{ps, +t, b}:
346 LcBlowfishKey{bf.ops(16n, ps, t)}
347
348def bf.key(+xs: List<&2, U32>) -> LcBlowfishKey:
349 +pi = bf.pi.list()
350 +t = bf.tables(pi)
351 +s0 : LcBfSt = LcBfSt{bf.pkey(B.take(18n, pi), bf.cycle(72n, xs, xs)), t, L.LcBlock64{0, 0}}
352 bf.key.of(bf.fill_s(3n, bf.fill_s(2n, bf.fill_s(1n, bf.fill_s(0n, bf.fill_p(s0))))))
353
354def bf.key.pick(ok: Bool, +xs: List<&2, U32>) -> Result<&2, &2, L.LcError, LcBlowfishKey>:
355 match ok:
356 case True{}:
357 Done{bf.key(xs)}
358 case False{}:
359 Fail{L.LcBadKeyLength{B.len(xs)}}
360
361# The cipher
362
363# a key of 4 to 56 bytes (32 to 448 bits, as the specification says)
364def LcBlowfish.key(o: B.Octets) -> Result<&2, &2, L.LcError, LcBlowfishKey>:
365 +xs = B.Octets.to_list(o)
366 +n = B.len(xs)
367 bf.key.pick(Bool.and(Nat.is_le(4n, n), Nat.is_le(n, 56n)), xs)
368
369# a key of 1 to 72 bytes: the key schedule takes up to 72 (18 words of P),
370# and some test sets use keys shorter than 4 bytes
371def LcBlowfish.key_any(o: B.Octets) -> Result<&2, &2, L.LcError, LcBlowfishKey>:
372 +xs = B.Octets.to_list(o)
373 +n = B.len(xs)
374 bf.key.pick(Bool.and(Nat.is_le(1n, n), Nat.is_le(n, 72n)), xs)
375
376def LcBlowfish.encrypt(k: LcBlowfishKey, b: L.LcBlock64) -> L.LcBlock64:
377 match k:
378 case LcBlowfishKey{ops}:
379 bf.run(ops, b)
380
381def LcBlowfish.decrypt(k: LcBlowfishKey, b: L.LcBlock64) -> L.LcBlock64:
382 match k:
383 case LcBlowfishKey{ops}:
384 bf.unrun(ops, b)