msg_tool\utils/
blowfish.rs

1//! Blowfish encryption and decryption utilities
2mod consts {
3    pub const P: [u32; 18] = [
4        0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, 0x082efa98,
5        0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd,
6        0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b,
7    ];
8
9    pub const S: [[u32; 256]; 4] = [
10        [
11            0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045,
12            0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69,
13            0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d,
14            0xc25a59b5, 0x9c30d539, 0x2af26013, 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
15            0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda,
16            0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
17            0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 0x2ba9c55d,
18            0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
19            0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60,
20            0x5dec8032, 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5,
21            0x0f6d6ff3, 0x83f44239, 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842,
22            0xf6e96c9a, 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
23            0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, 0x66ca593e,
24            0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, 0xe06f75d8, 0x85c12073,
25            0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724,
26            0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
27            0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2,
28            0x196a2463, 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
29            0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857,
30            0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
31            0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 0x3c7516df, 0xfd616b15, 0x2f501ec8,
32            0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0,
33            0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0,
34            0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
35            0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341,
36            0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198,
37            0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb,
38            0xf2122b64, 0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
39            0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6,
40            0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
41            0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, 0xebcdaf0c,
42            0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
43            0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2,
44            0x02e5b9c5, 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a,
45            0x1b510052, 0x9a532915, 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5,
46            0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
47            0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
48        ],
49        [
50            0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8,
51            0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29,
52            0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07,
53            0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
54            0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305,
55            0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
56            0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xd19113f9,
57            0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
58            0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1,
59            0x183eb331, 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79,
60            0x5679b072, 0xbcaf89af, 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f,
61            0x2e6b7124, 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
62            0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, 0xdd433b37,
63            0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, 0x71dff89e, 0x10314e55,
64            0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, 0xf28fe6ed,
65            0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
66            0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978,
67            0x9c10b36a, 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
68            0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595,
69            0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
70            0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 0x1521b628, 0x29076170, 0xecdd4775,
71            0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239,
72            0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf,
73            0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
74            0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f,
75            0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263,
76            0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef,
77            0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
78            0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d,
79            0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
80            0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, 0x095bbf00,
81            0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
82            0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7,
83            0xce77326e, 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2,
84            0x5a04abfc, 0x800bcadc, 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3,
85            0x105588cd, 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
86            0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
87        ],
88        [
89            0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e,
90            0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546,
91            0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec,
92            0x03bd9785, 0x7fac6dd0, 0x31cb8504, 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
93            0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4,
94            0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec,
95            0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, 0x1dc9faf7,
96            0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
97            0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7,
98            0xd096954b, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9,
99            0x5ef47e1c, 0x9029317c, 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548,
100            0xe4c66d22, 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
101            0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, 0xdff8e8a3,
102            0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1,
103            0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, 0xd0127845,
104            0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
105            0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c,
106            0xdb6e6b0d, 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3,
107            0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88,
108            0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
109            0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, 0x6a124237, 0xb79251e7, 0x06a1bbe6,
110            0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386,
111            0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057,
112            0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
113            0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299,
114            0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74,
115            0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e,
116            0x20b45770, 0x8cd55591, 0xc902de4c, 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
117            0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025,
118            0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe,
119            0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, 0x9af88c27,
120            0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
121            0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1,
122            0xce591d76, 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9,
123            0x1ac15bb4, 0xd39eb8fc, 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e,
124            0xb161e6f8, 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
125            0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
126        ],
127        [
128            0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740,
129            0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045,
130            0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee,
131            0x468dde7d, 0xd5730a1d, 0x4cd04dc6, 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
132            0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa,
133            0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
134            0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, 0x80e4a915,
135            0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
136            0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472,
137            0x5a88f54c, 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc,
138            0xf8d56629, 0x79132e28, 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4,
139            0x88f46dba, 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
140            0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, 0x03563482,
141            0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, 0x4de81751, 0x3830dc8e,
142            0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, 0xa8b6e37e,
143            0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
144            0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f,
145            0x6bb4e3bb, 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
146            0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d,
147            0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
148            0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, 0x6f3f3b82, 0x3520ab82, 0x011a1d4b,
149            0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b,
150            0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749,
151            0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
152            0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, 0x0f91fc71,
153            0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c,
154            0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532,
155            0xe0d392df, 0xd3a0342b, 0x8971f21e, 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
156            0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf,
157            0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
158            0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 0xde966292,
159            0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
160            0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c,
161            0xcd769c2b, 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76,
162            0x77afa1c5, 0x20756060, 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c,
163            0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
164            0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
165        ],
166    ];
167}
168
169use anyhow::Result;
170use byteorder::{BE, ByteOrder, LE};
171use std::io::{Read, Seek, Write};
172use std::marker::PhantomData;
173
174/// Blowfish variant which uses Little Endian byte order read/writes.s.
175pub type BlowfishLE = Blowfish<LE>;
176
177/// Blowfish block cipher instance.
178#[derive(Clone)]
179pub struct Blowfish<T: ByteOrder = BE> {
180    s: [[u32; 256]; 4],
181    p: [u32; 18],
182    _pd: PhantomData<T>,
183}
184
185impl<T: ByteOrder> std::fmt::Debug for Blowfish<T> {
186    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
187        f.write_str("Blowfish { ... }")
188    }
189}
190
191fn next_u32_wrap(buf: &[u8], offset: &mut usize) -> u32 {
192    let mut v = 0;
193    for _ in 0..4 {
194        if *offset >= buf.len() {
195            *offset = 0;
196        }
197        v = (v << 8) | buf[*offset] as u32;
198        *offset += 1;
199    }
200    v
201}
202
203impl<T: ByteOrder> Blowfish<T> {
204    fn init_state() -> Blowfish<T> {
205        Blowfish {
206            p: consts::P,
207            s: consts::S,
208            _pd: PhantomData,
209        }
210    }
211
212    fn expand_key(&mut self, key: &[u8]) {
213        let mut key_pos = 0;
214        for i in 0..18 {
215            self.p[i] ^= next_u32_wrap(key, &mut key_pos);
216        }
217        let mut lr = [0u32; 2];
218        for i in 0..9 {
219            lr = self.encrypt(lr);
220            self.p[2 * i] = lr[0];
221            self.p[2 * i + 1] = lr[1];
222        }
223        for i in 0..4 {
224            for j in 0..128 {
225                lr = self.encrypt(lr);
226                self.s[i][2 * j] = lr[0];
227                self.s[i][2 * j + 1] = lr[1];
228            }
229        }
230    }
231
232    #[allow(clippy::many_single_char_names)]
233    fn round_function(&self, x: u32) -> u32 {
234        let a = self.s[0][(x >> 24) as usize];
235        let b = self.s[1][((x >> 16) & 0xff) as usize];
236        let c = self.s[2][((x >> 8) & 0xff) as usize];
237        let d = self.s[3][(x & 0xff) as usize];
238        (a.wrapping_add(b) ^ c).wrapping_add(d)
239    }
240
241    ///Encrypts a 64-bit block of data using the Blowfish algorithm.
242    pub fn encrypt(&self, [mut l, mut r]: [u32; 2]) -> [u32; 2] {
243        for i in 0..8 {
244            l ^= self.p[2 * i];
245            r ^= self.round_function(l);
246            r ^= self.p[2 * i + 1];
247            l ^= self.round_function(r);
248        }
249        l ^= self.p[16];
250        r ^= self.p[17];
251        [r, l]
252    }
253
254    /// Decrypts a 64-bit block of data using the Blowfish algorithm.
255    pub fn decrypt(&self, [mut l, mut r]: [u32; 2]) -> [u32; 2] {
256        for i in (1..9).rev() {
257            l ^= self.p[2 * i + 1];
258            r ^= self.round_function(l);
259            r ^= self.p[2 * i];
260            l ^= self.round_function(r);
261        }
262        l ^= self.p[1];
263        r ^= self.p[0];
264        [r, l]
265    }
266
267    /// Decrypts a block of data in-place.
268    pub fn decrypt_block(&self, buf: &mut [u8]) {
269        for i in 0..buf.len() / 8 {
270            let mut l = T::read_u32(&buf[i * 8..]);
271            let mut r = T::read_u32(&buf[i * 8 + 4..]);
272            [l, r] = self.decrypt([l, r]);
273            T::write_u32(&mut buf[i * 8..], l);
274            T::write_u32(&mut buf[i * 8 + 4..], r);
275        }
276    }
277
278    /// Encrypts a block of data in-place.
279    pub fn encrypt_block(&self, buf: &mut [u8]) {
280        for i in 0..buf.len() / 8 {
281            let mut l = T::read_u32(&buf[i * 8..]);
282            let mut r = T::read_u32(&buf[i * 8 + 4..]);
283            [l, r] = self.encrypt([l, r]);
284            T::write_u32(&mut buf[i * 8..], l);
285            T::write_u32(&mut buf[i * 8 + 4..], r);
286        }
287    }
288
289    /// Creates a new Blowfish cipher instance with the given key.
290    pub fn new(key: &[u8]) -> Result<Self> {
291        if key.len() < 4 || key.len() > 56 {
292            return Err(anyhow::anyhow!("Key length must be between 4 and 56 bytes"));
293        }
294        let mut blowfish = Blowfish::init_state();
295        blowfish.expand_key(key);
296        Ok(blowfish)
297    }
298}
299
300#[derive(Debug)]
301/// Blowfish decryption stream wrapper.
302pub struct BlowfishDecryptor<B: ByteOrder, T> {
303    cipher: Blowfish<B>,
304    buffer: [u8; 8],
305    buffer_len: usize,
306    buffer_is_decrypted: bool,
307    stream: T,
308}
309
310impl<B: ByteOrder, T: Read> BlowfishDecryptor<B, T> {
311    pub fn new(cipher: Blowfish<B>, stream: T) -> Self {
312        Self {
313            cipher,
314            buffer: [0u8; 8],
315            buffer_len: 0,
316            buffer_is_decrypted: false,
317            stream,
318        }
319    }
320
321    pub fn new_with_key(key: &[u8], stream: T) -> Result<Self> {
322        let cipher = Blowfish::new(key)?;
323        Ok(Self::new(cipher, stream))
324    }
325}
326
327impl<B: ByteOrder, T: Read> Read for BlowfishDecryptor<B, T> {
328    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
329        if self.buffer_is_decrypted && self.buffer_len > 0 {
330            let to_copy = std::cmp::min(buf.len(), self.buffer_len);
331            buf[..to_copy].copy_from_slice(&self.buffer[..to_copy]);
332            if to_copy < self.buffer_len {
333                for i in 0..(self.buffer_len - to_copy) {
334                    self.buffer[i] = self.buffer[to_copy + i];
335                }
336            }
337            self.buffer_len -= to_copy;
338            self.buffer_is_decrypted = self.buffer_len > 0;
339            return Ok(to_copy);
340        }
341        if buf.len() < 8 {
342            if self.buffer_len < 8 {
343                self.stream
344                    .read_exact(&mut self.buffer[self.buffer_len..])?;
345            }
346            self.cipher.decrypt_block(&mut self.buffer);
347            self.buffer_len = 8;
348            self.buffer_is_decrypted = true;
349            let to_copy = std::cmp::min(buf.len(), self.buffer_len);
350            buf[..to_copy].copy_from_slice(&self.buffer[..to_copy]);
351            if to_copy < self.buffer_len {
352                for i in 0..(self.buffer_len - to_copy) {
353                    self.buffer[i] = self.buffer[to_copy + i];
354                }
355            }
356            self.buffer_len -= to_copy;
357            self.buffer_is_decrypted = self.buffer_len > 0;
358            return Ok(to_copy);
359        }
360        let mut start_index = 0;
361        if self.buffer_len > 0 {
362            buf[..self.buffer_len].copy_from_slice(&self.buffer[..self.buffer_len]);
363            start_index += self.buffer_len;
364        }
365        let readed = self.stream.read(&mut buf[start_index..])?;
366        let total_readed = start_index + readed;
367        let total_decrypted = total_readed - (total_readed % 8);
368        self.cipher.decrypt_block(&mut buf[..total_decrypted]);
369        if total_readed != total_decrypted {
370            self.buffer_len = total_readed - total_decrypted;
371            self.buffer[..self.buffer_len].copy_from_slice(&buf[total_decrypted..total_readed]);
372        } else {
373            self.buffer_len = 0;
374        }
375        self.buffer_is_decrypted = false;
376        Ok(total_decrypted)
377    }
378}
379
380impl<T: Read + Seek, B: ByteOrder> Seek for BlowfishDecryptor<B, T> {
381    fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
382        if matches!(pos, std::io::SeekFrom::End(0)) {
383            let newpos = self.stream.seek(pos)?;
384            self.buffer_len = 0;
385            self.buffer_is_decrypted = false;
386            return Ok(newpos);
387        }
388        let newpos = self.stream.seek(pos)?;
389        if newpos % 8 != 0 {
390            let block_start = newpos - (newpos % 8);
391            self.stream.seek(std::io::SeekFrom::Start(block_start))?;
392            self.buffer_len = (newpos - block_start) as usize;
393            self.stream
394                .read_exact(&mut self.buffer[..self.buffer_len])?;
395        } else {
396            self.buffer_len = 0;
397        }
398        self.buffer_is_decrypted = false;
399        Ok(newpos)
400    }
401}
402
403pub struct BlowfishEncryptor<B: ByteOrder, T: Write> {
404    cipher: Blowfish<B>,
405    buffer: [u8; 8],
406    buffer_len: usize,
407    stream: T,
408}
409
410impl<B: ByteOrder, T: Write> BlowfishEncryptor<B, T> {
411    pub fn new(cipher: Blowfish<B>, stream: T) -> Self {
412        Self {
413            cipher,
414            buffer: [0u8; 8],
415            buffer_len: 0,
416            stream,
417        }
418    }
419
420    pub fn new_with_key(key: &[u8], stream: T) -> Result<Self> {
421        let cipher = Blowfish::new(key)?;
422        Ok(Self::new(cipher, stream))
423    }
424}
425
426impl<B: ByteOrder, T: Write> Write for BlowfishEncryptor<B, T> {
427    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
428        let total_bytes = buf.len() + self.buffer_len;
429        let mut wbuf = vec![0u8; total_bytes];
430        if self.buffer_len > 0 {
431            wbuf[..self.buffer_len].copy_from_slice(&self.buffer[..self.buffer_len]);
432        }
433        wbuf[self.buffer_len..].copy_from_slice(buf);
434        self.cipher.encrypt_block(&mut wbuf);
435        self.buffer_len = total_bytes % 8;
436        if self.buffer_len > 0 {
437            let start = total_bytes - self.buffer_len;
438            self.buffer[..self.buffer_len].copy_from_slice(&wbuf[start..]);
439            self.stream.write_all(&wbuf[..start])?;
440        } else {
441            self.stream.write_all(&wbuf)?;
442        }
443        Ok(buf.len())
444    }
445
446    fn flush(&mut self) -> std::io::Result<()> {
447        self.stream.flush()
448    }
449}
450
451impl<B: ByteOrder, T: Write> Drop for BlowfishEncryptor<B, T> {
452    fn drop(&mut self) {
453        if self.buffer_len > 0 {
454            for i in self.buffer_len..8 {
455                self.buffer[i] = 0;
456            }
457            self.cipher.encrypt_block(&mut self.buffer);
458            if let Err(e) = self.stream.write_all(&self.buffer) {
459                eprintln!("Error writing final block in BlowfishEncryptor drop: {}", e);
460                crate::COUNTER.inc_error();
461            }
462        }
463    }
464}