Skip to main content

cryptocol/symmetric/
rijndael.rs

1// Copyright 2025, 2026 PARK Youngho.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
6// This file may not be copied, modified, or distributed
7// except according to those terms.
8
9
10// #![allow(missing_docs)]
11// #![allow(unused_must_use)]
12// #![allow(dead_code)]
13// #![allow(unused_variables)]
14// #![warn(rustdoc::missing_doc_code_examples)]
15
16use std::ptr::{ copy_nonoverlapping, copy };
17use crate::number::{ IntUnion, LongUnion, LongerUnion };
18
19
20// macro_rules! rijndael_pre_encrypt_into_vec {
21//     ($to:expr, $length_in_bytes:expr, $type:ty) => {
22//         let len = ($length_in_bytes + 1).next_multiple_of(4 * NB as u64) as usize / <$type>::size_in_bytes() as usize;
23//         $to.truncate(len);
24//         $to.resize(len + 1, <$type>::zero());
25//     };
26// }
27// pub(super) use rijndael_pre_encrypt_into_vec;
28
29
30// macro_rules! GF_rot_left {
31//     ($r:expr, $n:expr) => {
32//         $r.rotate_left_assign($n);
33//     };
34// }
35
36macro_rules! GF_mul {
37    ($a:expr, $b:expr) => {
38        {
39            let mut a = $a;
40            let mut b = $b;
41            let mut ret = 0_u8;
42            while b != 0
43            {
44                if (b & 1 == 1)
45                    { ret ^= a; }
46                if (a & 0b1000_0000 != 0)
47                    { a = (a << 1) ^ (IRREDUCIBLE as u8); }
48                else
49                    { a <<= 1; }
50                b >>= 1;
51            }
52            ret
53        }
54    };
55}
56
57macro_rules! GF_is_candidate {
58    ($a:expr) => {
59        {
60            let a_1 = $a;
61            let a_2 = GF_mul!(a_1, a_1);
62            let a_4 = GF_mul!(a_2, a_2);
63            let a_8 = GF_mul!(a_4, a_4);
64            let a_16 = GF_mul!(a_8, a_8);
65            let a_32 = GF_mul!(a_16, a_16);
66            // let a_64 = GF_mul!(a_32, a_32);
67
68            let a_3 = GF_mul!(a_1, a_2);
69            let mut ret = GF_mul!(a_3, a_4);
70            ret = GF_mul!(ret, a_8);
71            if ret == 1
72            {
73                false
74            }
75            else
76            {
77                ret = GF_mul!(a_3, a_16);
78                ret = GF_mul!(ret, a_32);
79                if ret == 1
80                {
81                    false
82                }
83                else
84                {
85                    ret = GF_mul!(a_1, a_4);
86                    ret = GF_mul!(ret, a_16);
87                    ret = GF_mul!(ret, a_32);
88                    ret != 1
89                }
90            }
91        }
92    };
93}
94
95macro_rules! GF_generator {
96    () => {
97        {
98            let mut ret = 0_u8;
99            let mut j = 2_u16;
100            while j < 256
101            {
102                if GF_is_candidate!(j as u8)
103                {
104                    ret = j as u8;
105                    break;
106                }
107                j += 1;
108            }
109            ret
110        }
111    };
112}
113
114macro_rules! GF_inverse_of {
115    ($a:expr) => {
116        {
117            let mut ret = 0_u8;
118            let mut inv = 255_u8;
119            while inv > 1
120            {
121                if GF_mul!($a, inv) == 1
122                {
123                    ret = inv;
124                    break;
125                }
126                inv -= 1;
127            }
128            ret
129        }
130    }
131}
132
133macro_rules! make_SBOX {
134    () => {
135        {
136            let mut out = [0_u8; 256];
137            let mut p = 1_u8;
138            let mut q = 1_u8;
139            let generator = GF_generator!();
140            let inverse = GF_inverse_of!(generator);
141            let mut j = 255_u16;
142            while j > 0
143            {
144                p = GF_mul!(p, generator);
145                q = GF_mul!(q, inverse);
146                let mut transformed = 0_u8;
147                let mut i = 0_u8;
148                while i < 8
149                {
150                    let affine_u8 = (AFFINE_MUL >> (i << 3)) as u8;
151                    let bits = affine_u8 & q;
152                    if bits.count_ones() & 1 == 1
153                        { transformed |= 1 << i; }
154                    i += 1;
155                }
156                out[p as usize] = transformed ^ AFFINE_ADD;
157                if p == 1
158                    { break; }
159                j -= 1;
160            }
161            out[0] = AFFINE_ADD;
162            out
163        }
164    };
165}
166
167macro_rules! make_INV_SBOX {
168    () => {
169        {
170            let mut out = [0_u8; 256];
171            let mut i = 0_u16;
172            while i < 256
173            {
174                out[Self::SBOX[i as usize] as usize] = i as u8;
175                i += 1;
176            }
177            out
178        }
179    }
180}
181
182macro_rules! make_INV_MC {
183    () => {
184        {
185            let mut aug = [[0_u8; 4]; 4];
186            let mut inv = [[0_u8; 4]; 4];
187            let mut i = 0_usize;
188            let mut j: usize;
189            while i < 4
190            {
191                j = 0;
192                while j < 4
193                {
194                    aug[i][j] = Self::MC[i][j];
195                    j += 1;
196                }
197                inv[i][i] = 1;
198                i += 1;
199            }
200
201            let generator = GF_generator!();
202            let inverse = GF_inverse_of!(generator);
203            let mut row = 0_usize;
204            while row < 4
205            {
206                let mut pivot = aug[row][row];
207                if pivot == 0
208                {
209                    i = row + 1;
210                    while i < 4
211                    {
212                        if aug[i][row] != 0
213                        {
214                            j = 0;
215                            while j < 4
216                            {
217                                (aug[row][j], aug[i][j]) = (aug[i][j], aug[row][j]);
218                                (inv[row][j], inv[i][j]) = (inv[i][j], inv[row][j]);
219                                j += 1;
220                            }
221                            pivot = aug[row][row];
222                            break;
223                        }
224                        i += 1;
225                    }
226                    if pivot == 0
227                        { panic!("Singular Matrix"); }
228                }
229
230                let mut p = 1_u8;
231                let mut q = 1_u8;
232                while p != pivot
233                {
234                    p = GF_mul!(p, generator);
235                    q = GF_mul!(q, inverse);
236                }
237                j = 0;
238                while j < 4
239                {
240                    aug[row][j] = GF_mul!(aug[row][j], q);
241                    inv[row][j] = GF_mul!(inv[row][j], q);
242                    j += 1;
243                }
244                let mut r = 0;
245                while r < 4
246                {
247                    if r != row
248                    {
249                        let factor = aug[r][row];
250                        j = 0;
251                        while j < 4
252                        {
253                            inv[r][j] ^= GF_mul!(inv[row][j], factor);
254                            aug[r][j] ^= GF_mul!(aug[row][j], factor);
255                            j += 1;
256                        }
257                    }
258                    r += 1;
259                }
260                row += 1;
261            }
262            inv
263        }
264    }
265}
266
267macro_rules! make_RC_ARRAY {
268    () => {
269        {
270            let mut out = [0u32; ROUND];
271            let round = [ RC0.to_le(), RC1.to_le(), RC2.to_le(), RC3.to_le(), RC4.to_le(),
272                          RC5.to_le(), RC6.to_le(), RC7.to_le(), RC8.to_le(), RC9.to_le() ];
273            let nr = if ROUND <= 10 { ROUND } else { 10 };
274            let mut i = 0;
275            while i < nr
276            {
277                out[i] = round[i];
278                i += 1;
279            }
280            while i < ROUND
281            {
282                out[i] = (GF_mul!(out[i-1].to_le() as u8, 2) as u32).to_le();
283                i += 1;
284            }
285            out
286        }
287    }
288}
289
290
291/// Rijndael_32_32 is not really practical but only educational to understand
292/// AES or Rijndael cryptographic algorithm. Its key is 32-bit and its
293/// encryption block is 32-bit.
294#[allow(non_camel_case_types)]
295pub type Rijndael_32_32 = Rijndael_Generic<7, 1, 1>;
296
297/// Rijndael_64_64 is not really practical too, but it can be used with DES
298/// cryptographic algorithm along or as random number generator engine.
299/// Its key is 64-bit and its encryption block is 64-bit.
300/// So, it can work with DES.
301#[allow(non_camel_case_types)]
302pub type Rijndael_64_64 = Rijndael_Generic<8, 2, 2>;
303
304/// Rijndael_512_512 can be used as one of post-Quantum algorithms for a
305/// while because even Grover algorithm takes long enough to break
306/// Rijndael_512_512. Its key is 512-bit and its encryption block is 512-bit.
307#[allow(non_camel_case_types)]
308pub type Rijndael_512_512 = Rijndael_Generic<22, 16, 16>;
309
310/// Rijndael_512_384 is one of Rijndael series. Its key is 384-bit and its
311/// encryption block is 512-bit.
312#[allow(non_camel_case_types)]
313pub type Rijndael_512_384 = Rijndael_Generic<18, 16, 12>;
314
315/// Rijndael_384_256 is one of Rijndael series. Its key is 256-bit and its
316/// encryption block is 512-bit.
317#[allow(non_camel_case_types)]
318pub type Rijndael_512_256 = Rijndael_Generic<14, 16, 8>;
319
320/// Rijndael_384_192 is one of Rijndael series. Its key is 192-bit and its
321/// encryption block is 512-bit.
322#[allow(non_camel_case_types)]
323pub type Rijndael_512_192 = Rijndael_Generic<14, 16, 6>;
324
325/// Rijndael_512_128 is one of Rijndael series. Its key is 128-bit and its
326/// encryption block is 512-bit.
327#[allow(non_camel_case_types)]
328pub type Rijndael_512_128 = Rijndael_Generic<14, 16, 4>;
329
330/// Rijndael_384_512 can be used as one of post-Quantum algorithms for a
331/// while because even Grover algorithm takes long enough to break
332/// Rijndael_384_512. Its key is 512-bit and its encryption block is 384-bit.
333#[allow(non_camel_case_types)]
334pub type Rijndael_384_512 = Rijndael_Generic<22, 12, 16>;
335
336/// Rijndael_384_384 is one of Rijndael series. Its key is 384-bit and its
337/// encryption block is 384-bit.
338#[allow(non_camel_case_types)]
339pub type Rijndael_384_384 = Rijndael_Generic<18, 12, 12>;
340
341/// Rijndael_384_256 is one of Rijndael series. Its key is 256-bit and its
342/// encryption block is 384-bit.
343#[allow(non_camel_case_types)]
344pub type Rijndael_384_256 = Rijndael_Generic<14, 12, 8>;
345
346/// Rijndael_384_192 is one of Rijndael series. Its key is 192-bit and its
347/// encryption block is 384-bit.
348#[allow(non_camel_case_types)]
349pub type Rijndael_384_192 = Rijndael_Generic<14, 12, 6>;
350
351/// Rijndael_384_128 is one of Rijndael series. Its key is 128-bit and its
352/// encryption block is 384-bit.
353#[allow(non_camel_case_types)]
354pub type Rijndael_384_128 = Rijndael_Generic<14, 12, 4>;
355
356/// Rijndael_256_512 can be used as one of post-Quantum algorithms for a
357/// while because even Grover algorithm takes long enough to break
358/// Rijndael_256_512. Its key is 512-bit and its encryption block is 256-bit.
359#[allow(non_camel_case_types)]
360pub type Rijndael_256_512 = Rijndael_Generic<22, 8, 16>;
361
362/// Rijndael_256_384 is one of Rijndael series. Its key is 384-bit and its
363/// encryption block is 256-bit.
364#[allow(non_camel_case_types)]
365pub type Rijndael_256_384 = Rijndael_Generic<18, 8, 12>;
366
367/// Rijndael_256_256 is one of Rijndael series. Its key is 256-bit and its
368/// encryption block is 256-bit.
369#[allow(non_camel_case_types)]
370pub type Rijndael_256_256 = Rijndael_Generic<14, 8, 8>;
371
372/// Rijndael_256_192 is one of Rijndael series. Its key is 192-bit and its
373/// encryption block is 256-bit.
374#[allow(non_camel_case_types)]
375pub type Rijndael_256_192 = Rijndael_Generic<14, 8, 6>;
376
377/// Rijndael_256_128 is one of Rijndael series. Its key is 128-bit and its
378/// encryption block is 256-bit.
379#[allow(non_camel_case_types)]
380pub type Rijndael_256_128 = Rijndael_Generic<14, 8, 4>;
381
382/// Rijndael_192_512 can be used as one of post-Quantum algorithms for a
383/// while because even Grover algorithm takes long enough to break
384/// Rijndael_192_512. Its key is 512-bit and its encryption block is 192-bit.
385#[allow(non_camel_case_types)]
386pub type Rijndael_192_512 = Rijndael_Generic<22, 6, 16>;
387
388/// Rijndael_192_384 is one of Rijndael series. Its key is 384-bit and its
389/// encryption block is 192-bit.
390#[allow(non_camel_case_types)]
391pub type Rijndael_192_384 = Rijndael_Generic<18, 6, 12>;
392
393/// Rijndael_192_256 is one of Rijndael series. Its key is 256-bit and its
394/// encryption block is 192-bit.
395#[allow(non_camel_case_types)]
396pub type Rijndael_192_256 = Rijndael_Generic<14, 6, 8>;
397
398/// Rijndael_192_192 is one of Rijndael series. Its key is 192-bit and its
399/// encryption block is 192-bit.
400#[allow(non_camel_case_types)]
401pub type Rijndael_192_192 = Rijndael_Generic<12, 6, 6>;
402
403/// Rijndael_256_128 is one of Rijndael series. Its key is 128-bit and its
404/// encryption block is 192-bit.
405#[allow(non_camel_case_types)]
406pub type Rijndael_192_128 = Rijndael_Generic<12, 6, 4>;
407
408/// Rijndael_128_512 can be used as one of post-Quantum algorithms for a
409/// while because even Grover algorithm takes long enough to break
410/// Rijndael_128_512. Its key is 512-bit and its encryption block is 128-bit.
411#[allow(non_camel_case_types)]
412pub type Rijndael_128_512 = Rijndael_Generic<22, 4, 16>;
413
414/// Rijndael_128_384 is one of Rijndael series. Its key is 384-bit and its
415/// encryption block is 128-bit.
416#[allow(non_camel_case_types)]
417pub type Rijndael_128_384 = Rijndael_Generic<18, 4, 12>;
418
419/// Rijndael_128_256 is one of Rijndael series. Its key is 256-bit and its
420/// encryption block is 128-bit. It is the same as the AES_256.
421#[allow(non_camel_case_types)]
422pub type Rijndael_128_256 = Rijndael_Generic<14, 4, 8>;
423
424/// Rijndael_128_192 is one of Rijndael series. Its key is 192-bit and its
425/// encryption block is 128-bit. It is the same as the AES_192.
426#[allow(non_camel_case_types)]
427pub type Rijndael_128_192 = Rijndael_Generic<12, 4, 6>;
428
429/// Rijndael_128_128 is one of Rijndael series. Its key is 128-bit and its
430/// encryption block is 128-bit. It is the same as the AES_128.
431#[allow(non_camel_case_types)]
432pub type Rijndael_128_128 = Rijndael_Generic;
433
434/// AES_256 is one of AES series. Its key is 256-bit and its encryption
435/// block is 128-bit. It is the same as the Rijndael_128_256.
436#[allow(non_camel_case_types)]
437pub type AES_256 = Rijndael_Generic<14, 4, 8>;
438
439/// AES_192 is one of AES series. Its key is 192-bit and its encryption
440/// block is 128-bit. It is the same as the Rijndael_128_192.
441#[allow(non_camel_case_types)]
442pub type AES_192 = Rijndael_Generic<12, 4, 6>;
443
444/// AES_128 is one of AES series. Its key is 128-bit and its encryption
445/// block is 128-bit. It is the same as the Rijndael_128_128.
446#[allow(non_camel_case_types)]
447pub type AES_128 = Rijndael_Generic;
448
449
450/// A Rijndael or AES (Advanced Encryption Standard) symmetric-key algorithm
451/// for the encryption of digital data
452/// 
453/// # Note
454/// __This descryption about Rijndael is according to little endianness.__
455/// MSB (Most Significant Bit) is the 64th bit and LSB (Least Significant Bit)
456/// is the first bit in this descryption unless otherwise mentioned.
457/// 
458/// # Introduction
459/// The name, AES, is the acronym of Advanced Encryption Standard. The name,
460/// Rijndael, is created out of the names of the Belgian cryptographers, Joan
461/// Daemen and Vincent Rijmen. Rijndael means Rhine valley in Dutch though it is
462/// not known whether the name Rijndael was made with that intention. AES is the
463/// subset of Rijndael. AES has three versions: AES-128, AES-192 and AES-256.
464/// All of them have the 128-bit data block. AES-128 has the 128-bit key length.
465/// AES-192 has the 192-bit key length. AES-256 has the 256-bit key length.
466/// On the other hand, Rijndael has nine versions: Rijndael-128-128,
467/// Rijndael-128-192, Rijndael-128-256, Rijndael-192-128, Rijndael-192-192,
468/// Rijndael-192-256, Rijndael-256-128, Rijndael-256-192, and Rijndael-256-256.
469/// Rijndael-128-*, Rijndael-192-*, and Rijndael-256-* have 128-bit data block,
470/// 192-bit data block, and 256-bit data block, respectively. Rijndael-*-128,
471/// Rijndael-*-192, and Rijndael-*-256 have 128-bit key length, 192-bit key
472/// length, and 256-bit key length, respectively. However, this module,
473/// Rijndael_Generic provides more expanded versions such as 32-bit and 64-bit
474/// data blocks and key lengths and more than 256-bit data blocks and key
475/// lengths.
476/// 
477/// # Short History of birth of AES
478/// On 2nd, January, 1997, NIST announced that they wished to choose the
479/// encryption algorithm standard in replacement of DES, which is called AES.   
480/// The contest held three rounds. At the first round, fifteen were submitted:
481/// CAST-256, CRYPTON, DEAL, DFC, E2, FROG, HPC, LOKI97, MAGENTA, MARS, RC6,
482/// Rijndael, SAFER+, Serpent, and Twofish. At the second round, five remained:
483/// MARS, RC6, Rijndael, Serpent, and Twofish. At the third round, Rijndael was
484/// chosen out of the remained five. However, all the five algorithms are
485/// commonly referred to as "AES finalists", and they are also considered
486/// well-known and respected in the community. So, the other four algorithms
487/// are also being actively used as well as Rijndael, today.
488/// 
489/// # Use of AES or Rijndael and its variants
490/// This algorithm is implemented generic way. Most of the constants are
491/// implemented as generic constants. So, without changing any line of code, you
492/// can change the algorithm by changing the generic parameter. You can design
493/// and implement your own algorithm based on Rijndael which uses SPN
494/// (Substitution–Permutation Network). You can also use the the source code of
495/// Rijndael_Generic in order to find the weakness of SPN.
496/// 
497/// # Generic Parameters
498///   You can change the generic parameters if you want to make your own
499///   encryption/decryption algorithm based on Rijndael. However, your own
500///   algorithm may or may not be securer than AES. It is a high chance that
501///   your own algorithm is less secure than AES unless you have performed the
502///   security test for your own algorithm and proved that your algorithm is
503///   at least as secure as AES.
504/// - ROUND: Indicates the number of rounds. You can change how many times the
505///   Substitution-Permutation Network will be repeated. Its minimum value is 0.
506///   Original Rijndael has the number of rounds as follows:
507///   |  data \ key  | 128-bit key | 192-bit key | 256-bit key |
508///   |--------------|-------------|-------------|-------------|
509///   | 128-bit data | 10 rounds   | 12 rounds   | 14 rounds   |
510///   | 192-bit data | 12 rounds   | 12 rounds   | 14 rounds   |
511///   | 256-bit data | 14 rounds   | 14 rounds   | 14 rounds   |
512/// 
513///   The default of `ROUND` is 10. The default value `10` is for AES-128
514///   which is most frequently used.
515/// - NB: Indicates the size of block. The block size is (`NB` * 4) bytes.
516///   You can change the size of block by changing the value `NB`.
517///   The default value of `NB` is `4`. The default value `4` is for AES
518///   which is most frequently used.
519///   If `NB` is `0`, the behavior is not defined.
520/// - NK: Indicates the size of key. The key size is (`NK` * 4) bytes.
521///   You can change the size of Key by changing the value `NK`.
522///   The default value of `NK` is `4`. The default value `4` is for AES-128
523///   which is most frequently used.
524///   If `NK` is `0`, the behavior is not defined.
525/// - IRREDUCIBLE: Indicates the irreducible polynomial. You can change the
526///   irreducible polynomial by changing `IRREDUCIBLE`. The default value of
527///   `IRREDUCIBLE` is `0b_0001_1011` which means x^8 + x^4 + x^3 + x + 1. In
528///   `IRREDUCIBLE`, the term `x^8` is always omitted. The default value
529///   `0b_0001_1011` is for Rijndael or AES.
530/// - AFFINE_MUL: Indicates the two-dimensional matrix that is used to make
531///   S-Box. `AFFINE_MUL` is the linear part of the affine transformation.
532///   You can change the S-Box by changing `AFFINE_MUL` with `AFFINE_ADD`
533///   along. The default value of `AFFINE_MUL` is
534///   `0b_11111000_01111100_00111110_00011111_10001111_11000111_11100011_11110001`
535///   which means the matrix as follows.
536///   | Matrix          |
537///   |-----------------|
538///   | 1 1 1 1 1 0 0 0 |
539///   | 0 1 1 1 1 1 0 0 |
540///   | 0 0 1 1 1 1 1 0 |
541///   | 0 0 0 1 1 1 1 1 |
542///   | 1 0 0 0 1 1 1 1 |
543///   | 1 1 0 0 0 1 1 1 |
544///   | 1 1 1 0 0 0 1 1 |
545///   | 1 1 1 1 0 0 0 1 |
546/// 
547///   The default value of `AFFINE_MUL` is for Rijndael or AES.
548/// - AFFINE_ADD: Indicates the one-dimensional matrix that is used to make
549///   S-Box. `AFFINE_ADD` is the non-linear part of the affine transformation.
550///   You can change the S-Box by changing `AFFINE_ADD` with `AFFINE_MUL` along.
551///   The default value of `AFFINE_ADD` is `0b_01100011` which means the matrix
552///   as follows.
553///   | Matrix |
554///   |--------|
555///   | 0      |
556///   | 1      |
557///   | 1      |
558///   | 0      |
559///   | 0      |
560///   | 0      |
561///   | 1      |
562///   | 1      |
563/// 
564///   The default value of `AFFINE_ADD` is for Rijndael or AES.
565/// - SR0 ~ SR3: Indicates how many bytes to shift (rotate) in each row in
566///   ShiftRows step. You can change the amounts of shifting (rotating) in each
567///   row by changing `SR0`, `SR1`, `SR2`, and `SR3`. The default values of
568///   `SR0`, `SR1`, `SR2`, and `SR3` are `0`, `1`, `2`, and `3`, respectively.
569///   The default values `0`, `1`, `2`, and `3` are for Rijndael or AES.
570/// - MC00 ~ MC33: Indicates the two-dimensional matrix that is used as
571///   MixColumns matrix in MixColumn step. `MC00`, `MC01`, `MC02`, `MC03`,
572///   `MC10`, `MC11`, `MC12`, `MC13`, `MC20`, `MC21`, `MC22`, `MC23`, `MC30`,
573///   `MC31`, `MC32`, and `MC33` are the elements of the two-dimensional
574///   MixColumns matrix. You can change the MixColumns matrix to change the
575///   MixColumn step by changing `MC00` ~ `MC33`. The default values of `MC00`,
576///   `MC01`, `MC02`, `MC03`, `MC10`, `MC11`, `MC12`, `MC13`, `MC20`, `MC21`,
577///   `MC22`, `MC23`, `MC30`, `MC31`, `MC32`, and `MC33` are `2`, `3`, `1`,
578///   `1`, `1`, `2`, `3`, `1`, `1`, `1`, `2`, `3`, `3`, `1`, `1`, and `2`,
579///   respectively, which means the matrix as follows.
580///   | Matrix  |
581///   |---------|
582///   | 2 3 1 1 |
583///   | 1 2 3 1 |
584///   | 1 1 2 3 |
585///   | 3 1 1 2 |
586/// 
587///   The default values of `MC00` ~ `MC33` are for Rijndael or AES.
588/// - RC0 ~ RC9: Indicates Round Constants that are used to make round keys.
589///   The round keys are used in the AddRoundKey step. You can change the
590///   round keys by changing `RC0` ~ `RC9`. The default values of `RC0`, `RC1`,
591///   `RC2`, `RC3`, `RC4`, `RC5`, `RC6`, `RC7`, `RC8`, and `RC9` are
592///   `0b_0000_0001`, `0b_0000_0010`, `0b_0000_0100`, `0b_0000_1000`,
593///   `0b_0001_0000`, `0b_0010_0000`,`0b_0100_0000`, `0b_1000_0000`,
594///   `0b_0001_1011`, and `0b_001_10110`, respectively. The default values are
595///   for Rijndael or AES. If `Round` is greater than 10, the round constants
596///   after RC9 will be determined by multiplying previous round constant by `2`
597///   on Galois Field. So, So-called RC10 is double of `RC9` on Galois Field and
598///   RC11 is double of `RC10` on Galois Field, and so on.
599/// - ROT: Indicates how may bytes to shift (rotate) in making round keys. You
600///   can change round keys by changing `ROT`. The default value of `ROT` is
601///   `1`. The default value `1` is for for Rijndael or AES.
602/// 
603/// # Reference
604/// [Read more](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard)
605/// about AES in brief.
606/// Watch [this video](https://www.youtube.com/watch?v=x1v2tX4_dkQ) and then
607/// [this video](https://www.youtube.com/watch?v=NHuibtoL_qk) in series
608/// for more (or deeper or full) understanding of AES.
609/// 
610/// # Quick Start
611/// You have to import (use) one of the modules: `AES_128`, `AES_192`, and
612/// `AES_256` in order to use official AES as shown in Example 1. And, in the
613/// same way you can import (use) the modules:
614/// `Rijndael_128_128`, `Rijndael_128_192`, `Rijndael_128_256`,
615/// `Rijndael_128_384`, `Rijndael_128_512`,
616/// `Rijndael_192_128`, `Rijndael_192_192`, `Rijndael_192_256`,
617/// `Rijndael_192_384`, `Rijndael_192_512`,
618/// `Rijndael_256_128`, `Rijndael_256_192`, `Rijndael_256_256`,
619/// `Rijndael_256_384`, `Rijndael_256_512`,
620/// `Rijndael_384_128`, `Rijndael_384_192`, `Rijndael_384_256`,
621/// `Rijndael_384_384`, `Rijndael_384_512`,
622/// `Rijndael_512_128`, `Rijndael_512_192`, `Rijndael_512_256`,
623/// `Rijndael_512_384`, and `Rijndael_512_512`.
624/// Of course, you can also expand Rijndael by changing the generic parameters.
625/// Also, there are some predefined modules:
626/// `Rijndael_32_32` for 32 bit key and 32-bit encryption data, and
627/// `Rijndael_64_64` for 64 bit key and 64-bit encryption data for educational
628/// purpose, though they are not very practical.
629/// 
630/// # Example 1
631/// ```
632/// use cryptocol::symmetric::AES_128;
633/// use cryptocol::symmetric::AES_192;
634/// use cryptocol::symmetric::AES_256;
635/// 
636/// use cryptocol::symmetric::Rijndael_128_128;
637/// use cryptocol::symmetric::Rijndael_128_192;
638/// use cryptocol::symmetric::Rijndael_128_256;
639/// use cryptocol::symmetric::Rijndael_128_384;
640/// use cryptocol::symmetric::Rijndael_128_512;
641/// 
642/// use cryptocol::symmetric::Rijndael_192_128;
643/// use cryptocol::symmetric::Rijndael_192_192;
644/// use cryptocol::symmetric::Rijndael_192_256;
645/// use cryptocol::symmetric::Rijndael_192_384;
646/// use cryptocol::symmetric::Rijndael_192_512;
647/// 
648/// use cryptocol::symmetric::Rijndael_256_128;
649/// use cryptocol::symmetric::Rijndael_256_192;
650/// use cryptocol::symmetric::Rijndael_256_256;
651/// use cryptocol::symmetric::Rijndael_256_384;
652/// use cryptocol::symmetric::Rijndael_256_512;
653/// 
654/// use cryptocol::symmetric::Rijndael_384_128;
655/// use cryptocol::symmetric::Rijndael_384_192;
656/// use cryptocol::symmetric::Rijndael_384_256;
657/// use cryptocol::symmetric::Rijndael_384_384;
658/// use cryptocol::symmetric::Rijndael_384_512;
659/// 
660/// use cryptocol::symmetric::Rijndael_512_128;
661/// use cryptocol::symmetric::Rijndael_512_192;
662/// use cryptocol::symmetric::Rijndael_512_256;
663/// use cryptocol::symmetric::Rijndael_512_384;
664/// use cryptocol::symmetric::Rijndael_512_512;
665/// 
666/// use cryptocol::symmetric::Rijndael_64_64;
667/// use cryptocol::symmetric::Rijndael_32_32;
668/// ```
669/// 
670/// You can instantiate the AES object with `u128` key as Example 2.
671/// In this case, you have to take endianness into account.
672/// In little-endianness, 0x_1234567890ABCDEF1234567890ABCDEF_u128 is [0xEFu8,
673/// 0xCDu8, 0xABu8, 0x90u8, 0x78u8, 0x56u8, 0x34u8, 0x12u8, 0xEFu8, 0xCDu8,
674/// 0xABu8, 0x90u8, 0x78u8, 0x56u8, 0x34u8, 0x12u8] while the same 
675/// 0x_1234567890ABCDEF1234567890ABCDEF_u128 is [0x12u8, 0x34u8, 0x56u8, 0x78u8,
676/// 0x90u8, 0xABu8, 0xCDu8, 0xEF_u64, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x90u8,
677/// 0xABu8, 0xCDu8, 0xEF_u64] in big-endianness.
678/// The instantiated object should be mutable.
679/// 
680/// # Example 2
681/// ```
682/// use cryptocol::symmetric::AES_128;
683/// let key = 0x_1234567890ABCDEF1234567890ABCDEF_u128;
684/// let mut _a_aes = AES_128::new_with_key_u128(key);
685/// ```
686/// 
687/// Note that the object should be intantiated as mutable object.
688/// Also, you can instantiate the AES object with `[u8; 16]` key as shown in
689/// Example 3. In this case, you don't have to take endianness into account.
690/// The instantiated object should be mutable.
691/// 
692/// # Example 3
693/// ```
694/// use cryptocol::symmetric::AES_128;
695/// let key = [0xEFu8, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12, 0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12];
696/// let mut _a_aes = AES_128::new_with_key(&key);
697/// ```
698/// 
699/// You can instantiate the AES object without key and set a `u128` key later as
700/// shown in Example 4 or a `[u8; 16]` key later as shown in Example 5.
701/// 
702/// # Example 4
703/// ```
704/// use cryptocol::symmetric::AES_128;
705/// let mut a_aes = AES_128::new();
706/// let key = 0x_1234567890ABCDEF1234567890ABCDEF_u128;
707/// a_aes.set_key_u128(key);
708/// ```
709/// 
710/// # Example 5
711/// ```
712/// use cryptocol::symmetric::AES_128;
713/// let mut a_aes = AES_128::new();
714/// let key = [0xEFu8, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12, 0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12];
715/// a_aes.set_key(&key);
716/// ```
717/// 
718/// Now, you can freely use any operation mode. This crate provide
719/// ECB (Electronic CodeBook), CBC(Cipher Block Chaining), PCBC (Propagation
720/// Cipher Block Chaining), CFB (Cipher FeedBack) OFB (Output FeedBack), and
721/// CTR (CounTeR). You can choose the way of padding bits according to either
722/// [PKCS #7](https://node-security.com/posts/cryptography-pkcs-7-padding/) or
723/// [ISO 7816-4](https://en.wikipedia.org/wiki/Padding_(cryptography)#ISO/IEC_7816-4).
724/// So, you can import (use) one of the following traits: ECB_PKCS7, ECB_ISO,
725/// CBC_PKCS7, CBC_ISO, PCBC_PKCS7, PCBC_ISO, CFB, OFB, and CTR. The following
726/// example 6 shows the case that you choose CBC operation mode and padding bits
727/// according to PKCS #7.
728/// 
729/// # Example 6
730/// ```
731/// use std::io::Write;
732/// use std::fmt::Write as _;
733/// use cryptocol::symmetric::{ AES_128, CBC_PKCS7 };
734///
735/// let mut a_aes = AES_128::new_with_key(&[0xEFu8, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12, 0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12]);
736/// let message = "In the beginning God created the heavens and the earth.";
737/// println!("M =\t{}", message);
738/// let iv = [0x87654321_u32, 0xFEDCBA09_u32, 0x87654321_u32, 0xFEDCBA09_u32];
739/// println!("IV =\t{:08X}{:08X}{:08X}{:08X}", iv[0].to_be(), iv[1].to_be(), iv[2].to_be(), iv[3].to_be());
740/// let mut cipher = Vec::<u8>::new();
741/// a_aes.encrypt_str_into_vec(iv, message, &mut cipher);
742/// print!("C =\t");
743/// for c in cipher.clone()
744///     { print!("{:02X} ", c); }
745/// println!();
746/// let mut txt = String::new();
747/// for c in cipher.clone()
748///     { write!(txt, "{:02X} ", c); }
749/// assert_eq!(txt, "C9 1C 27 CE 83 92 A1 CF 7D A4 64 35 16 48 01 72 CC E3 6D CD BB 19 FC D0 80 22 09 9F 23 32 73 27 58 37 F9 9B 3C 44 7B 03 B3 80 7E 99 DF 97 4E E9 A3 89 67 0C 21 29 3E 4D DC AD B6 44 09 D4 3B 02 ");
750///
751/// let mut recovered = String::new();
752/// a_aes.decrypt_vec_into_string(iv, &cipher, &mut recovered);
753/// println!("B =\t{}", recovered);
754/// assert_eq!(recovered, "In the beginning God created the heavens and the earth.");
755/// assert_eq!(recovered, message);
756/// println!();
757/// ```
758/// 
759/// You can modify the Rijndael encryption/decryption algorithm as you want. All
760/// the constants are implemented as generic parameters. For instance, you can
761/// change S-box, the number of rounds of Substitution - Permutation network,
762/// the irreducible polynormial, key length, etc. The following Example 7 shows
763/// the variation of Rijndael which has 512-bit data block and 512-bit key.
764/// 
765/// # Example 7
766/// ```
767/// use std::io::Write;
768/// use std::fmt::Write as _;
769/// use cryptocol::symmetric::{ Rijndael_Generic, CBC_PKCS7 };
770///
771/// let mut a_rijndael = Rijndael_Generic::<22, 16, 16>::new_with_key(&[0xEFu8, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12, 0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12, 0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12, 0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12, 0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12, 0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12, 0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12, 0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12]);
772/// let message = "In the beginning God created the heavens and the earth.";
773/// println!("M =\t{}", message);
774/// let iv = [0x_FEDCBA09_u32, 87654321_u32, 0x_FEDCBA09_u32, 87654321_u32, 0x_FEDCBA09_u32, 87654321_u32, 0x_FEDCBA09_u32, 87654321_u32, 0x_FEDCBA09_u32, 87654321_u32, 0x_FEDCBA09_u32, 87654321_u32, 0x_FEDCBA09_u32, 87654321_u32, 0x_FEDCBA09_u32, 87654321_u32];
775/// println!("IV =\t{:08X}{:08X}{:08X}{:08X}", iv[0].to_be(), iv[1].to_be(), iv[2].to_be(), iv[3].to_be());
776///
777/// let mut cipher = Vec::<u8>::new();
778/// a_rijndael.encrypt_str_into_vec(iv, message, &mut cipher);
779/// print!("C =\t");
780/// for c in cipher.clone()
781///     { print!("{:02X} ", c); }
782/// println!();
783/// let mut txt = String::new();
784/// for c in cipher.clone()
785///     { write!(txt, "{:02X} ", c); }
786/// assert_eq!(txt, "B1 C0 1F 84 17 46 35 12 D9 16 52 44 5F 40 A1 7F 3B 55 F7 E6 42 E5 1F 42 57 43 AD E4 00 19 54 1D B6 F3 1B 20 C8 D3 08 92 B7 C4 0C E2 77 73 A5 E4 0D E7 0F F4 B0 38 FE 78 30 56 E4 A7 9E CE 0E 50 ");
787///
788/// let mut recovered = String::new();
789/// a_rijndael.decrypt_vec_into_string(iv, &cipher, &mut recovered);
790/// println!("B =\t{}", recovered);
791/// assert_eq!(recovered, "In the beginning God created the heavens and the earth.");
792/// assert_eq!(recovered, message);
793/// ```
794/// 
795/// You can use Rijndael_512_512 as one of post-Quantum algorithms for a
796/// while because even Grover algorithm takes long enough to break
797/// Rijndael_512_512. Its key is 512-bit and its encryption block is 512-bit.
798/// 
799/// # Example 8 for Post-Quantum
800/// ```
801/// use std::io::Write;
802/// use std::fmt::Write as _;
803/// use cryptocol::number::SharedArrays;
804/// use cryptocol::hash::SHA3_512;
805/// use cryptocol::symmetric::{ Rijndael_512_512, CBC_ISO };
806/// 
807/// let mut sha3 = SHA3_512::new();
808/// sha3.absorb_str("Post-Quantum");
809/// let key: [u8; 64] = sha3.get_hash_value_in_array();
810/// print!("K =\t");
811/// for i in 0..64
812///     { print!("{:02X}", key[i]); }
813/// println!();
814/// let mut a_rijndael = Rijndael_512_512::new_with_key(&key);
815/// sha3.absorb_str("Initialize");
816/// let mut iv = SharedArrays::<u32, 16, u8, 64>::new();
817/// iv.src = sha3.get_hash_value_in_array();
818/// let iv = unsafe { iv.des };
819/// print!("IV =\t");
820/// for i in 0..16
821///     { print!("{:08X}", iv[i].to_be()); }
822/// println!();
823/// let message = "In the beginning God created the heavens and the earth.";
824/// println!("M =\t{}", message);
825/// let mut cipher = [0_u8; 64];
826/// a_rijndael.encrypt(iv.clone(), message.as_ptr(), message.len() as u64, cipher.as_mut_ptr());
827/// print!("C =\t");
828/// for c in cipher.clone()
829///     { print!("{:02X} ", c); }
830/// println!();
831/// let mut txt = String::new();
832/// for c in cipher.clone()
833///     { write!(txt, "{:02X} ", c); }
834/// assert_eq!(txt, "C2 C4 1C 91 EE 50 F0 04 B6 73 00 B2 81 05 01 25 C1 87 24 27 7E CE 01 65 C5 CB 87 38 99 9F 5B 0C D1 DF 8D 52 C4 C4 C8 D8 F5 D5 AD F3 FD DA 35 C2 33 F6 5D 83 02 85 F1 20 8C 56 0B 72 9C 91 84 42 ");
835/// 
836/// let mut recovered = vec![0; 55];
837/// a_rijndael.decrypt(iv, cipher.as_ptr(), cipher.len() as u64, recovered.as_mut_ptr());
838/// print!("Ba =\t");
839/// for b in recovered.clone()
840///     { print!("{:02X} ", b); }
841/// println!();
842/// let mut txt = String::new();
843/// for c in recovered.clone()
844///     { write!(txt, "{:02X} ", c); }
845/// assert_eq!(txt, "49 6E 20 74 68 65 20 62 65 67 69 6E 6E 69 6E 67 20 47 6F 64 20 63 72 65 61 74 65 64 20 74 68 65 20 68 65 61 76 65 6E 73 20 61 6E 64 20 74 68 65 20 65 61 72 74 68 2E ");
846/// 
847/// let mut converted = String::new();
848/// unsafe { converted.as_mut_vec() }.append(&mut recovered);
849/// 
850/// println!("Bb =\t{}", converted);
851/// assert_eq!(converted, "In the beginning God created the heavens and the earth.");
852/// assert_eq!(converted, message);
853/// ```
854/// 
855/// # Notice for Practical Use
856/// Now, you can freely use any methods with any paddings
857/// in any operation modes.
858/// - This crate provides six operation modes:
859///   ECB, CBC, PCBC, CFB, OFB, and CTR.
860/// - This crate provides two padding ways: ISO 7816-4 and PKCS #7.
861/// - The operation modes ECB, CBC and PCBC requires padding bytes.
862/// - You can combine three operation modes and two padding ways.
863/// - The operation modes
864///   [`CFB`](./trait.CFB.html#trait.CFB),
865///   [`OFB`](./trait.OFB.html#trait.OFB), and
866///   [`CTR`](./trait.CTR.html#trait.CTR)
867///   does not require padding bytes.
868/// - The traits that implements combination of operation modes and padding
869///   ways are provided such as
870///   [`ECB_PKCS7`](./trait.ECB_PKCS7.html#trait.ECB_PKCS7),
871///   [`ECB_ISO`](./trait.ECB_ISO.html#trait.ECB_ISO),
872///   [`CBC_PKCS7`](./trait.CBC_PKCS7.html#trait.ECB_PKCS7),
873///   [`CBC_ISO`](./trait.CBC_ISO.html#trait.CBC_ISO),
874///   [`PCBC_PKCS7`](./trait.PCBC_PKCS7.html#trait.PCBC_PKCS7), and
875///   [`PCBC_ISO`](./trait.PCBC_ISO.html#trait.PCBC_ISO).
876/// - You can find detaild instructions and their helpful examples
877///   if you go through those links.
878///
879/// In summary,
880///
881/// |      | padding PKCS7                                          | padding ISO                                      | no padding                        |
882/// |------|--------------------------------------------------------|--------------------------------------------------|-----------------------------------|
883/// | ECB  | [ECB_PKCS7](./trait.ECB_PKCS7.html#trait.ECB_PKCS7)    | [ECB_ISO](./trait.ECB_ISO.html#trait.ECB_ISO)    |                                   |
884/// | CBC  | [CBC_PKCS7](./trait.CBC_PKCS7.html#trait.ECB_PKCS7)    | [CBC_ISO](./trait.CBC_ISO.html#trait.CBC_ISO)    |                                   |
885/// | PCBC | [PCBC_PKCS7](./trait.PCBC_PKCS7.html#trait.PCBC_PKCS7) | [PCBC_ISO](./trait.PCBC_ISO.html#trait.PCBC_ISO) |                                   |
886/// | CFB  |                                                        |                                                  | [CFB](./trait.CFB.html#trait.CFB) |
887/// | OFB  |                                                        |                                                  | [OFB](./trait.OFB.html#trait.OFB) |
888/// | CTR  |                                                        |                                                  | [CTR](./trait.CTR.html#trait.CTR) |
889/// 
890#[allow(non_camel_case_types)]
891#[derive(Debug, Clone)]
892pub struct Rijndael_Generic<const ROUND: usize = 10, const NB: usize = 4, const NK: usize = 4,
893            const IRREDUCIBLE: u8 = 0b_0001_1011,
894            const AFFINE_MUL: u64 = 0b_11111000_01111100_00111110_00011111_10001111_11000111_11100011_11110001,
895            const AFFINE_ADD: u8 = 0b_01100011,
896            const SR0: usize = 0, const SR1: usize = 1, const SR2: usize = 2, const SR3: usize = 3,
897            const MC00: u8 = 2, const MC01: u8 = 3, const MC02: u8 = 1, const MC03: u8 = 1,
898            const MC10: u8 = 1, const MC11: u8 = 2, const MC12: u8 = 3, const MC13: u8 = 1,
899            const MC20: u8 = 1, const MC21: u8 = 1, const MC22: u8 = 2, const MC23: u8 = 3,
900            const MC30: u8 = 3, const MC31: u8 = 1, const MC32: u8 = 1, const MC33: u8 = 2,
901            const RC0: u32 = 0b_0000_0001, const RC1: u32 = 0b_0000_0010, const RC2: u32 = 0b_0000_0100,
902            const RC3: u32 = 0b_0000_1000, const RC4: u32 = 0b_0001_0000, const RC5: u32 = 0b_0010_0000,
903            const RC6: u32 = 0b_0100_0000, const RC7: u32 = 0b_1000_0000, const RC8: u32 = 0b_0001_1011,
904            const RC9: u32 = 0b_001_10110, const ROT: u32 = 1>
905{
906    key:        [IntUnion; NK],
907    block:      [[u8; NB]; 4],
908    round_key:  Vec<[IntUnion; NB]>,
909    enc:        fn (s: &mut Self, message: &[IntUnion; NB]) -> [IntUnion; NB],
910    dec:        fn (s: &mut Self, cipher: &[IntUnion; NB]) -> [IntUnion; NB],
911}
912
913impl <const ROUND: usize, const NB: usize, const NK: usize, const IRREDUCIBLE: u8, const AFFINE_MUL: u64,
914        const AFFINE_ADD: u8, const SR0: usize, const SR1: usize, const SR2: usize, const SR3: usize,
915        const MC00: u8, const MC01: u8, const MC02: u8, const MC03: u8,
916        const MC10: u8, const MC11: u8, const MC12: u8, const MC13: u8,
917        const MC20: u8, const MC21: u8, const MC22: u8, const MC23: u8,
918        const MC30: u8, const MC31: u8, const MC32: u8, const MC33: u8,
919        const RC0: u32, const RC1: u32, const RC2: u32, const RC3: u32, const RC4: u32,
920        const RC5: u32, const RC6: u32, const RC7: u32, const RC8: u32, const RC9: u32, const ROT: u32>
921Rijndael_Generic<ROUND, NB, NK, IRREDUCIBLE, AFFINE_MUL, AFFINE_ADD, SR0, SR1, SR2, SR3,
922        MC00, MC01, MC02, MC03, MC10, MC11, MC12, MC13, MC20, MC21, MC22, MC23, MC30, MC31, MC32, MC33,
923        RC0, RC1, RC2, RC3, RC4, RC5, RC6, RC7, RC8, RC9, ROT>
924{
925    pub(super) const BLOCK_SIZE: usize = 4 * NB;
926
927    const SUCCESS: u8 = !0;
928    const FAILURE: u8 = 0;
929    const SBOX: [u8; 256] = make_SBOX!();
930    const INV_SBOX: [u8; 256] = make_INV_SBOX!();
931    const SR: [usize; 4] = [SR0, SR1, SR2, SR3];
932    const MC: [[u8; 4]; 4] = [  [ MC00, MC01, MC02, MC03 ],
933                                [ MC10, MC11, MC12, MC13 ],
934                                [ MC20, MC21, MC22, MC23 ],
935                                [ MC30, MC31, MC32, MC33 ] ];
936    const INV_MC: [[u8; 4]; 4] = make_INV_MC!();
937    const RC: [u32; ROUND] = make_RC_ARRAY!();
938
939    #[allow(non_upper_case_globals)]
940    const method_shift_rows: fn (&mut Self) =   if (SR0 == 0) && (SR1 == 1) && (SR2 == 2) && (SR3 == 3)
941                                                    { Self::optimal_shift_rows }
942                                                else
943                                                    { Self::shift_rows };
944
945    #[allow(non_upper_case_globals)]
946    const method_inv_shift_rows: fn (&mut Self) =   if (SR0 == 0) && (SR1 == 1) && (SR2 == 2) && (SR3 == 3)
947                                                        { Self::optimal_inv_shift_rows }
948                                                    else
949                                                        { Self::inv_shift_rows };
950
951    #[allow(non_upper_case_globals)]
952    const method_make_round_keys: fn (&mut Self) =  if NK > 6
953                                                    {
954                                                        if NK == NB
955                                                            { Self::make_round_keys_nk_greater_than_6_and_nk_equal_to_nb }
956                                                        else
957                                                            { Self::make_round_keys_nk_greater_than_6_and_nk_diff_from_nb }
958                                                    }
959                                                    else
960                                                    {
961                                                        if NK == NB
962                                                            { Self::make_round_keys_nk_up_to_6_and_nk_equal_to_nb }
963                                                        else
964                                                            { Self::make_round_keys_nk_up_to_6_and_nk_diff_from_nb }
965                                                    };
966
967    #[allow(non_upper_case_globals)]
968    const method_mix_columns: fn (&mut Self) =  if (MC00 == 2) && (MC01 == 3) && (MC02 == 1) && (MC03 == 1)
969                                                && (MC10 == 1) && (MC11 == 2) && (MC12 == 3) && (MC13 == 1)
970                                                && (MC20 == 1) && (MC21 == 1) && (MC22 == 2) && (MC23 == 3)
971                                                && (MC30 == 3) && (MC31 == 1) && (MC32 == 1) && (MC33 == 2)
972                                                    { Self::optimal_mix_columns }
973                                                else
974                                                    { Self::mix_columns };
975
976    // pub fn new() -> Self
977    /// Constructs a new object Rijndael_Generic.
978    ///
979    /// # Features
980    /// - In order to encrypt data, object should be instantiated mutable.
981    /// - This method sets the key to have all bits zeros.
982    /// - The default key which has all bits zeros is not a weak key unlike DES.
983    ///
984    /// # Example 1
985    /// ```
986    /// use cryptocol::symmetric::AES_128;
987    /// let mut _a_aes = AES_128::new();
988    /// let plaintext = 0x1234567890ABCDEF1234567890ABCDEF_u128;
989    /// let ciphertext = _a_aes.encrypt_u128(plaintext);
990    ///
991    /// println!("Plaintext:\t\t{:#032X}", plaintext);
992    /// println!("Ciphertext:\t\t{:#032X}", ciphertext);
993    /// assert_eq!(ciphertext, 0xE2C8CD3BFD4D72366A4806B100659867);
994    ///
995    /// let recovered_cipher_text = _a_aes.decrypt_u128(ciphertext);
996    /// println!("Recovered-ciphertext:\t{:#032X}", recovered_cipher_text);
997    /// assert_eq!(recovered_cipher_text, 0x1234567890ABCDEF1234567890ABCDEF_u128);
998    /// assert_eq!(recovered_cipher_text, plaintext);
999    /// ```
1000    ///
1001    /// # For more examples,
1002    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.new)
1003    pub fn new() -> Self
1004    {
1005        let mut rijndael = Self
1006        {
1007            key:        [IntUnion::new(); NK],
1008            block:      [[0_u8; NB]; 4],
1009            round_key:  vec![[IntUnion::new(); NB]; ROUND + 1],
1010            enc:        Self::encrypt_unit,
1011            dec:        Self::decrypt_unit,
1012        };
1013        Self::method_make_round_keys(&mut rijndael);
1014        rijndael
1015    }
1016
1017    // pub fn box_new() -> Box<Self>
1018    /// Constructs a new object Rijndael_Generic wrapped by Box.
1019    ///
1020    /// # Features
1021    /// - In order to encrypt data, object should be instantiated mutable.
1022    /// - This method sets the key to have all bits zeros.
1023    /// - The default key which has all bits zeros is not a weak key unlike DES.
1024    ///
1025    /// # Example 1
1026    /// ```
1027    /// use cryptocol::symmetric::AES_128;
1028    /// let mut _a_aes = AES_128::box_new();
1029    /// let plaintext = 0x1234567890ABCDEF1234567890ABCDEF_u128;
1030    /// let ciphertext = _a_aes.encrypt_u128(plaintext);
1031    ///
1032    /// println!("Plaintext:\t\t{:#032X}", plaintext);
1033    /// println!("Ciphertext:\t\t{:#032X}", ciphertext);
1034    /// assert_eq!(ciphertext, 0xE2C8CD3BFD4D72366A4806B100659867);
1035    ///
1036    /// let recovered_cipher_text = _a_aes.decrypt_u128(ciphertext);
1037    /// println!("Recovered-ciphertext:\t{:#032X}", recovered_cipher_text);
1038    /// assert_eq!(recovered_cipher_text, 0x1234567890ABCDEF1234567890ABCDEF_u128);
1039    /// assert_eq!(recovered_cipher_text, plaintext);
1040    /// ```
1041    ///
1042    /// # For more examples,
1043    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.box_new)
1044    #[inline]
1045    pub fn box_new() -> Box<Self>
1046    {
1047        Box::new(Self::new())
1048    }
1049
1050    // pub fn new_with_key<const K: usize>(key: &[u8; K]) -> Self
1051    /// Constructs a new object Rijndael_Generic.
1052    ///
1053    /// # Arguments
1054    /// - The argument `key` is the array of u8 that has `K` elements.
1055    ///
1056    /// # Features
1057    /// - This method sets the key to be the given argument `key`.
1058    /// - If `K` is less than `4 * NK`, the rest bits of
1059    ///   the key to be set after `K` bits will be set to be `zero`.
1060    /// - If `K` is greater than `4 * NK`, the rest bits after `4 * NK` bits
1061    ///   of the key given as the argument will be ignored.
1062    ///
1063    /// # Example 1 for normal case
1064    /// ```
1065    /// use cryptocol::symmetric::AES_128;
1066    ///
1067    /// let mut aes = AES_128::new_with_key(&[0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF]);
1068    /// let plaintext = 0x1234567890ABCDEF1234567890ABCDEF_u128;
1069    /// let ciphertext = aes.encrypt_u128(plaintext);
1070    ///
1071    /// println!("Plaintext:\t\t{:#034X}", plaintext);
1072    /// println!("Ciphertext:\t\t{:#034X}", ciphertext);
1073    /// assert_eq!(ciphertext, 0x01CCF8264AECB5D644E2BAE927584D87_u128);
1074    ///
1075    /// let cipher_cipher_text = aes.encrypt_u128(ciphertext);
1076    /// println!("Recovered-ciphertext:\t{:#034X}", recovered_cipher_text);
1077    /// assert_eq!(recovered_cipher_text, 0x1234567890ABCDEF1234567890ABCDEF_u128);
1078    /// assert_eq!(recovered_cipher_text, plaintext);
1079    /// ```
1080    ///
1081    /// # For more examples,
1082    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.new_with_key)
1083    pub fn new_with_key<const K: usize>(key: &[u8; K]) -> Self
1084    {
1085        let mut rijndael = Self
1086        {
1087            key:        [IntUnion::new(); NK],
1088            block:      [[0_u8; NB]; 4],
1089            round_key:  vec![[IntUnion::new(); NB]; ROUND + 1],
1090            enc:        Self::encrypt_unit,
1091            dec:        Self::decrypt_unit,
1092        };
1093        rijndael.set_key(key);
1094        rijndael
1095    }
1096
1097    // pub fn new_with_key_u128(key: u128) -> Self
1098    /// Constructs a new object Rijndael_Generic.
1099    ///
1100    /// # Arguments
1101    /// - The argument `key` is of `u128`.
1102    /// - It should be in the same endianness of machine. For example,
1103    ///   if the intended key is [0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD,
1104    ///   0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF], the key in
1105    ///   `u128` for this argument is 0x_1234567890ABCDEF1234567890ABCDEF_u128
1106    ///   for big-endian machine, and the key in `u128` for this argument is
1107    ///   0x_EFCDAB9078563412EFCDAB9078563412_u128 for little-endian machine.
1108    ///
1109    /// # Features
1110    /// - This method sets the key to be the given argument `key`.
1111    /// - If `NK` is less than `4`, the rest bits at the address higher than
1112    ///   `4 * NK * 8` bits of the key given as the argument will be ignored.
1113    /// - If `NK` is greater than `4`, the rest bits of the key to be set after
1114    ///   128 bits will be set to be `zero`.
1115    ///
1116    /// # Example 1 for normal case
1117    /// ```
1118    /// use cryptocol::symmetric::AES_128;
1119    ///
1120    /// let mut aes = AES_128::new_with_key_u128(0xEFCDAB9078563412EFCDAB9078563412);
1121    /// let plaintext = 0x1234567890ABCDEF1234567890ABCDEF_u128;
1122    /// let ciphertext = aes.encrypt_u128(plaintext);
1123    ///
1124    /// println!("Plaintext:\t\t{:#034X}", plaintext);
1125    /// println!("Ciphertext:\t\t{:#034X}", ciphertext);
1126    /// assert_eq!(ciphertext, 0x01CCF8264AECB5D644E2BAE927584D87_u128);
1127    ///
1128    /// let recovered_cipher_text = aes.decrypt_u128(ciphertext);
1129    /// println!("Recovered-ciphertext:\t{:#034X}\n", recovered_cipher_text);
1130    /// assert_eq!(recovered_cipher_text, 0x1234567890ABCDEF1234567890ABCDEF_u128);
1131    /// assert_eq!(recovered_cipher_text, plaintext);
1132    /// ```
1133    ///
1134    /// # For more examples,
1135    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.new_with_key_u128)
1136    pub fn new_with_key_u128(key: u128) -> Self
1137    {
1138        let mut rijndael = Self
1139        {
1140            key:        [IntUnion::new(); NK],
1141            block:      [[0_u8; NB]; 4],
1142            round_key:  vec![[IntUnion::new(); NB]; ROUND + 1],
1143            enc:        Self::encrypt_unit,
1144            dec:        Self::decrypt_unit,
1145        };
1146        rijndael.set_key_u128(key);
1147        rijndael
1148    }
1149
1150    // pub fn encryptor_with_key<const K: usize>(key: &[u8; K]) -> Self
1151    /// Constructs a new object Rijndael_Generic as a positive encryptor (or
1152    /// an encryptor) for the component of BigCryptor128 and NAES.
1153    ///
1154    /// # Arguments
1155    /// - The argument `key` is the array of u8 that has `K` elements.
1156    ///
1157    /// # Features
1158    /// - You won't use this method unless you use BigCryptor128 and NAES
1159    ///   for such as Triple AES.
1160    /// - This method constructs the encryptor component of BigCryptor128
1161    ///   and NAES.
1162    /// - This method sets the key to be the given argument `key`.
1163    /// - If `K` is less than `4 * NK`, the rest bits of
1164    ///   the key to be set after `K` bits will be set to be `zero`.
1165    /// - If `K` is greater than `4 * NK`, the rest bits after `4 * NB` bits
1166    ///   of the key given as the argument will be ignored.
1167    ///
1168    /// # Example 1
1169    /// ```
1170    /// use cryptocol::symmetric::{ AES_128, BigCryptor128, SmallCryptor };
1171    /// 
1172    /// let keys: [Box<dyn SmallCryptor<u128, 16>>; 3]
1173    ///         = [ Box::new(AES_128::encryptor_with_key(&[0xEF_u8, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12, 0x21, 0x43, 0x65, 0x87, 0x09, 0xBA, 0xDC, 0xFE])),
1174    ///             Box::new(AES_128::decryptor_with_key(&[0x21_u8, 0x43, 0x65, 0x87, 0x09, 0xBA, 0xDC, 0xFE, 0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12])),
1175    ///             Box::new(AES_128::encryptor_with_key(&[0xEF_u8, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12, 0x21, 0x43, 0x65, 0x87, 0x09, 0xBA, 0xDC, 0xFE])) ];
1176    /// let mut taes = BigCryptor128::new_with_small_cryptor_array(keys);
1177    /// let plaintext = 0x_1234567890ABCDEFFEDCA0987654321_u128;
1178    /// let ciphertext = taes.encrypt_u128(plaintext);
1179    /// 
1180    /// println!("Plaintext:\t\t{:#034X}", plaintext);
1181    /// println!("Ciphertext:\t\t{:#034X}", ciphertext);
1182    /// assert_eq!(ciphertext, 0x_E301940B5A5DE1600D78C375BF58F232_u128);
1183    /// 
1184    /// let recovered_text = taes.decrypt_u128(ciphertext);
1185    /// println!("Recovered text:\t{:#034X}", recovered_text);
1186    /// assert_eq!(recovered_text, 0x_1234567890ABCDEFFEDCA0987654321_u128);
1187    /// assert_eq!(recovered_text, plaintext);
1188    /// ```
1189    ///
1190    /// # For more examples,
1191    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.encryptor_with_key)
1192    #[inline]
1193    pub fn encryptor_with_key<const K: usize>(key: &[u8; K]) -> Self
1194    {
1195        Self::new_with_key(key)
1196    }
1197
1198    // pub fn encryptor_with_key_u128(key: u128) -> Self
1199    /// Constructs a new object Rijndael_Generic as a positive encryptor (or
1200    /// an encryptor) for the component of BigCryptor128 and NAES.
1201    ///
1202    /// # Arguments
1203    /// - The argument `key` is of `u128`.
1204    /// - It should be in the same endianness of machine. For example,
1205    ///   if the intended key is [0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD,
1206    ///   0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF], the key in
1207    ///   `u128` for this argument is 0x_1234567890ABCDEF1234567890ABCDEF_u128
1208    ///   for big-endian machine, and the key in `u128` for this argument is
1209    ///   0x_EFCDAB9078563412EFCDAB9078563412_u128 for little-endian machine.
1210    ///
1211    /// # Features
1212    /// - You won't use this method unless you use BigCryptor128 and NAES
1213    ///   for such as Triple AES.
1214    /// - This method constructs the encryptor component of BigCryptor128
1215    ///   and NAES.
1216    /// - This method sets the key to be the given argument `key`.
1217    /// - If `NK` is less than `4`, the rest bits at the address higher than
1218    ///   `4 * NK * 8` bits of the key given as the argument will be ignored.
1219    /// - If `NK` is greater than `4`, the rest bits of the key to be set after
1220    ///   128 bits will be set to be `zero`.
1221    ///
1222    /// # Example 1
1223    /// ```
1224    /// use cryptocol::symmetric::{ AES_128, BigCryptor128, SmallCryptor };
1225    /// 
1226    /// let mut taes = BigCryptor128::new_with_small_cryptor_array(
1227    ///             [Box::new(AES_128::encryptor_with_key_u128(0x_1234567890ABCDEFFEDCA0987654321_u128)),
1228    ///             Box::new(AES_128::decryptor_with_key_u128(0x_FEDCBA09876543211234567890ABCDEF_u128)),
1229    ///             Box::new(AES_128::encryptor_with_key_u128(0x_1234567890ABCDEFFEDCA0987654321_u128))]
1230    /// );
1231    /// let plaintext = 0x_11223344556677889900AABBCCDDEEFF_u128;
1232    /// let ciphertext = taes.encrypt_u128(plaintext);
1233    /// 
1234    /// println!("Plaintext:\t\t{:#034X}", plaintext);
1235    /// println!("Ciphertext:\t\t{:#034X}", ciphertext);
1236    /// assert_eq!(ciphertext, 0x_DB56B1B7D320D7481BF40A1964E9C7C4_u128);
1237    /// 
1238    /// let recovered_text = taes.decrypt_u128(ciphertext);
1239    /// println!("Recovered text:\t{:#034X}", recovered_text);
1240    /// assert_eq!(recovered_text, 0x_11223344556677889900AABBCCDDEEFF_u128);
1241    /// assert_eq!(recovered_text, plaintext);
1242    /// ```
1243    ///
1244    /// # For more examples,
1245    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.encryptor_with_key_u128)
1246    #[inline]
1247    pub fn encryptor_with_key_u128(key: u128) -> Self
1248    {
1249        Self::new_with_key_u128(key)
1250    }
1251
1252    // pub fn decryptor_with_key<const K: usize>(key: &[u8; K]) -> Self
1253    /// Constructs a new object Rijndael_Generic as a negative encryptor (or
1254    /// a decryptor) for the component of BigCryptor128 and NAES.
1255    ///
1256    /// # Arguments
1257    /// - The argument `key` is the array of u8 that has `K` elements.
1258    ///
1259    /// # Features
1260    /// - You won't use this method unless you use BigCryptor128 and NAES
1261    ///   for such as Triple AES.
1262    /// - This method constructs the encryptor component of BigCryptor128
1263    ///   and NAES.
1264    /// - This method sets the key to be the given argument `key`.
1265    /// - If `K` is less than `4 * NK`, the rest bits of
1266    ///   the key to be set after `K * 8` bits will be set to be `zero`.
1267    /// - If `K` is greater than `4 * NK`, the rest bits after `4 * NB * 8` bits
1268    ///   of the key given as the argument will be ignored.
1269    ///
1270    /// # Example 1
1271    /// ```
1272    /// use cryptocol::symmetric::{ AES_128, BigCryptor128, SmallCryptor };
1273    /// 
1274    /// let keys: [Box<dyn SmallCryptor<u128, 16>>; 3]
1275    ///         = [ Box::new(AES_128::encryptor_with_key(&[0xEF_u8, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12, 0x21, 0x43, 0x65, 0x87, 0x09, 0xBA, 0xDC, 0xFE])),
1276    ///             Box::new(AES_128::decryptor_with_key(&[0x21_u8, 0x43, 0x65, 0x87, 0x09, 0xBA, 0xDC, 0xFE, 0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12])),
1277    ///             Box::new(AES_128::encryptor_with_key(&[0xEF_u8, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12, 0x21, 0x43, 0x65, 0x87, 0x09, 0xBA, 0xDC, 0xFE])) ];
1278    /// let mut taes = BigCryptor128::new_with_small_cryptor_array(keys);
1279    /// let plaintext = 0x_1234567890ABCDEFFEDCA0987654321_u128;
1280    /// let ciphertext = taes.encrypt_u128(plaintext);
1281    /// 
1282    /// println!("Plaintext:\t\t{:#034X}", plaintext);
1283    /// println!("Ciphertext:\t\t{:#034X}", ciphertext);
1284    /// assert_eq!(ciphertext, 0x_E301940B5A5DE1600D78C375BF58F232_u128);
1285    /// 
1286    /// let recovered_text = taes.decrypt_u128(ciphertext);
1287    /// println!("Recovered text:\t{:#034X}", recovered_text);
1288    /// assert_eq!(recovered_text, 0x_1234567890ABCDEFFEDCA0987654321_u128);
1289    /// assert_eq!(recovered_text, plaintext);
1290    /// ```
1291    ///
1292    /// # For more examples,
1293    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.decryptor_with_key)
1294    pub fn decryptor_with_key<const K: usize>(key: &[u8; K]) -> Self
1295    {
1296        let mut rijndael = Self::new_with_key(key);
1297        rijndael.turn_inverse();
1298        rijndael
1299    }
1300
1301    // pub fn decryptor_with_key_u128(key: u128) -> Self
1302    /// Constructs a new object Rijndael_Generic as a negative encryptor (or
1303    /// a decryptor) for the component of BigCryptor128 and NAES.
1304    ///
1305    /// # Arguments
1306    /// - The argument `key` is of `u128`.
1307    /// - It should be in the same endianness of machine. For example,
1308    ///   if the intended key is [0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD,
1309    ///   0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF], the key in
1310    ///   `u128` for this argument is 0x_1234567890ABCDEF1234567890ABCDEF_u128
1311    ///   for big-endian machine, and the key in `u128` for this argument is
1312    ///   0x_EFCDAB9078563412EFCDAB9078563412_u128 for little-endian machine.
1313    ///
1314    /// # Features
1315    /// - You won't use this method unless you use BigCryptor128 and NAES
1316    ///   for such as Triple AES.
1317    /// - This method constructs the encryptor component of BigCryptor128
1318    ///   and NAES.
1319    /// - This method sets the key to be the given argument `key`.
1320    /// - If `NK` is less than `4`, the rest bits at the address higher than
1321    ///   `4 * NK * 8` bits of the key given as the argument will be ignored.
1322    /// - If `NK` is greater than `4`, the rest bits of the key to be set after
1323    ///   128 bits will be set to be `zero`.
1324    ///
1325    /// # Example 1
1326    /// ```
1327    /// use cryptocol::symmetric::{ AES_128, BigCryptor128, SmallCryptor };
1328    /// 
1329    /// let mut taes = BigCryptor128::new_with_small_cryptor_array(
1330    ///             [Box::new(AES_128::encryptor_with_key_u128(0x_1234567890ABCDEFFEDCA0987654321_u128)),
1331    ///             Box::new(AES_128::decryptor_with_key_u128(0x_FEDCBA09876543211234567890ABCDEF_u128)),
1332    ///             Box::new(AES_128::encryptor_with_key_u128(0x_1234567890ABCDEFFEDCA0987654321_u128))]
1333    /// );
1334    /// let plaintext = 0x_11223344556677889900AABBCCDDEEFF_u128;
1335    /// let ciphertext = taes.encrypt_u128(plaintext);
1336    /// 
1337    /// println!("Plaintext:\t\t{:#034X}", plaintext);
1338    /// println!("Ciphertext:\t\t{:#034X}", ciphertext);
1339    /// assert_eq!(ciphertext, 0x_DB56B1B7D320D7481BF40A1964E9C7C4_u128);
1340    /// 
1341    /// let recovered_text = taes.decrypt_u128(ciphertext);
1342    /// println!("Recovered text:\t{:#034X}", recovered_text);
1343    /// assert_eq!(recovered_text, 0x_11223344556677889900AABBCCDDEEFF_u128);
1344    /// assert_eq!(recovered_text, plaintext);
1345    /// ```
1346    ///
1347    /// # For more examples,
1348    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.decryptor_with_key_u128)
1349    pub fn decryptor_with_key_u128(key: u128) -> Self
1350    {
1351        let mut rijndael = Self::new_with_key_u128(key);
1352        rijndael.turn_inverse();
1353        rijndael
1354    }
1355
1356    // pub fn get_key(&mut self) -> [u32; NK]
1357    /// Gets the key.
1358    ///
1359    /// # Output
1360    /// This method returns the key in the form of array of `u32`.
1361    ///
1362    /// # Example 1 for AES_128
1363    /// ```
1364    /// use cryptocol::symmetric::AES_128;
1365    ///
1366    /// let mut _aes = AES_128::new_with_key(&[0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF]);
1367    /// let key = _aes.get_key();
1368    /// print!("K = ");
1369    /// for k in key
1370    ///     { print!("{:#010X} ", k); }
1371    /// println!();
1372    /// assert_eq!(key, [0x78563412, 0xEFCDAB90, 0x78563412, 0xEFCDAB90]);
1373    /// ```
1374    ///
1375    /// # For more examples,
1376    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.get_key)
1377    pub fn get_key(&mut self) -> [u32; NK]
1378    {
1379        let mut key = [0_u32; NK];
1380        unsafe { copy_nonoverlapping(self.key.as_ptr() as *const u32,
1381                                 &mut key as *mut u32, NK); }
1382        key
1383    }
1384
1385    // pub fn get_key_u128(&self) -> u128
1386    /// Gets the key.
1387    ///
1388    /// # Output
1389    /// This method returns the key in the form of `u128`.
1390    ///
1391    /// # Features
1392    /// - If `NK` is less than `4`, the rest bits at the address higher than
1393    ///   `4 * NK * 8` bits of the returned key will be set to be `zero`.
1394    /// - If `NK` is greater than `4`, the rest bits of the key to be returned
1395    ///   after 128 bits will be ignored.
1396    ///
1397    /// # Example 1 for 128-bit key
1398    /// ```
1399    /// use cryptocol::symmetric::AES_128;
1400    ///
1401    /// let mut _aes = AES_128::new_with_key(&[0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF]);
1402    /// let key = _aes.get_key_u128();
1403    /// println!("Key = {:#034X}", key);
1404    /// assert_eq!(key, 0xEFCDAB9078563412EFCDAB9078563412_u128);
1405    /// ```
1406    ///
1407    /// # For more examples,
1408    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.get_key_u128)
1409    pub fn get_key_u128(&self) -> u128
1410    {
1411        let len = if 16 < NK * 4 { 16 } else { NK * 4 };
1412        let mut key = 0_u128;
1413        unsafe { copy_nonoverlapping(self.key.as_ptr() as *const u8,
1414                                     &mut key as *mut u128 as *mut u8, len); }
1415        key
1416    }
1417
1418    // pub fn set_key<const K: usize>(&mut self, key: &[u8; K])
1419    /// Sets the key.
1420    ///
1421    /// # Arguments
1422    /// - The argument `key` is the array of `u8` that has `K` elements.
1423    ///
1424    /// # Features
1425    /// - This method sets the key to be the given argument `key`.
1426    /// - If `K` is less than `4 * NK`, the rest bits of
1427    ///   the key to be set after `K * 8` bits will be set to be `zero`.
1428    /// - If `K` is greater than `4 * NK`, the rest bits after `4 * NK * 8` bits
1429    ///   of the key given as the argument will be ignored.
1430    ///
1431    /// # Example 1 for normal case
1432    /// ```
1433    /// use cryptocol::symmetric::AES_128;
1434    ///
1435    /// let mut aes = AES_128::new();
1436    /// aes.set_key(&[0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF]);
1437    /// let key = aes.get_key();
1438    /// print!("K = ");
1439    /// for k in key
1440    ///     { print!("{:#010X} ", k); }
1441    /// println!();
1442    /// assert_eq!(key, [0x78563412, 0xEFCDAB90, 0x78563412, 0xEFCDAB90]);
1443    /// ```
1444    ///
1445    /// # For more examples,
1446    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.set_key)
1447    pub fn set_key<const K: usize>(&mut self, key: &[u8; K])
1448    {
1449        let len = if K < NK * 4 { K } else { NK * 4 };
1450        unsafe {
1451            copy_nonoverlapping(key.as_ptr(), self.key.as_mut_ptr() as *mut u8, len);
1452        }
1453        Self::method_make_round_keys(self);
1454    }
1455
1456    //  pub fn set_key_u128(&mut self, key: u128)
1457    /// Constructs a new object Rijndael_Generic.
1458    ///
1459    /// # Arguments
1460    /// - The argument `key` is of `u128`.
1461    /// - It should be in the same endianness of machine. For example,
1462    ///   if the intended key is [0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD,
1463    ///   0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF], the key in
1464    ///   `u128` for this argument is 0x_1234567890ABCDEF1234567890ABCDEF_u128
1465    ///   for big-endian machine, and the key in `u128` for this argument is
1466    ///   0x_EFCDAB9078563412EFCDAB9078563412_u128 for little-endian machine.
1467    ///
1468    /// # Features
1469    /// - This method sets the key to be the given argument `key`.
1470    /// - If `NK` is less than `4`, the rest bits at the address higher than
1471    ///   `4 * NK * 8` bits of the key given as the argument will be ignored.
1472    /// - If `NK` is greater than `4`, the rest bits of the key to be set after
1473    ///   128 bits will be set to be `zero`.
1474    ///
1475    /// # Example 1 for normal case
1476    /// ```
1477    /// use cryptocol::symmetric::AES_128;
1478    ///
1479    /// let mut aes = AES_128::new();
1480    /// aes.set_key_u128(0xEFCDAB9078563412EFCDAB9078563412);
1481    /// let key = aes.get_key();
1482    /// print!("K = ");
1483    /// for k in key
1484    ///     { print!("{:#010X} ", k); }
1485    /// println!();
1486    /// assert_eq!(key, [0x78563412, 0xEFCDAB90, 0x78563412, 0xEFCDAB90]);
1487    /// ```
1488    ///
1489    /// # For more examples,
1490    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.set_key_u128)
1491    pub fn set_key_u128(&mut self, key: u128)
1492    {
1493        let len = if 16 < NK * 4 { 16 } else { NK * 4 };
1494        unsafe {
1495            copy_nonoverlapping(&key as *const u128 as *const u8,
1496                                self.key.as_mut_ptr() as *mut u8, len);
1497        }
1498        Self::method_make_round_keys(self);
1499    }
1500
1501    pub(crate) fn set_original_key(&mut self, key: &[u32; NK])
1502    {
1503        for i in 0..NK
1504            { self.key[i].set(key[i]); }
1505    }
1506
1507    pub(crate) fn move_to_next_key(&mut self)
1508    {
1509        let mut key = self.get_key();
1510        let mut carry = 1;
1511        let mut old: u32;
1512        for i in 0..NK
1513        {
1514            old = key[i];
1515            key[i] = key[i].wrapping_add(carry);
1516            carry = if key[i] < old {1} else {0};
1517        }
1518        self.set_original_key(&key);
1519    }
1520
1521    // pub fn turn_inverse(&mut self)
1522    /// Flips its role in BigCryptor128 or NAES.
1523    ///
1524    /// # Features
1525    /// - You won't use this method unless you use BigCryptor128 or NAES
1526    ///   for such as Triple DES.
1527    /// - Even if you are writing codes in the context of using BigCryptor128
1528    ///   or NAES, you will hardly use this method because it is high chance
1529    ///   that you will have constructed components with the methods,
1530    ///   encryptor_with_key(struct@Rijndael_Generic#method.encryptor_with_key),
1531    ///   encryptor_with_key_u64(struct@Rijndael_Generic#method.encryptor_with_key_u128),
1532    ///   decryptor_with_key(struct@Rijndael_Generic#method.decryptor_with_key), and
1533    ///   decryptor_with_key_u64(struct@Rijndael_Generic#method.decryptor_with_key_u128).
1534    /// - If it is constructed as encryptor for BigCryptor128 or NAES,
1535    ///   it will be changed into decryptor.
1536    /// - If it is constructed as decryptor for BigCryptor128 or NAES,
1537    ///   it will be changed into encryptor.
1538    ///
1539    /// # Example 1
1540    /// ```
1541    /// use cryptocol::symmetric::{ AES_128, BigCryptor128, SmallCryptor };
1542    /// 
1543    /// let mut keys: [Box<dyn SmallCryptor<u128, 16>>; 3]
1544    ///             = [ Box::new(AES_128::new_with_key_u128(0x_1234567890ABCDEFFEDCA0987654321_u128)),
1545    ///                 Box::new(AES_128::new_with_key_u128(0x_FEDCBA09876543211234567890ABCDEF_u128)),
1546    ///                 Box::new(AES_128::new_with_key_u128(0x_1234567890ABCDEFFEDCA0987654321_u128)) ];
1547    /// keys[1].turn_inverse();
1548    /// 
1549    /// let mut taes = BigCryptor128::new_with_small_cryptor_array(keys);
1550    /// let plaintext = 0x_11223344556677889900AABBCCDDEEFF_u128;
1551    /// let ciphertext = taes.encrypt_u128(plaintext);
1552    /// 
1553    /// println!("Plaintext:\t\t{:#034X}", plaintext);
1554    /// println!("Ciphertext:\t\t{:#034X}", ciphertext);
1555    /// assert_eq!(ciphertext, 0x_DB56B1B7D320D7481BF40A1964E9C7C4_u128);
1556    /// 
1557    /// let recovered_text = taes.decrypt_u128(ciphertext);
1558    /// println!("Recovered text:\t{:#034X}", recovered_text);
1559    /// assert_eq!(recovered_text, 0x_11223344556677889900AABBCCDDEEFF_u128);
1560    /// assert_eq!(recovered_text, plaintext);
1561    /// ```
1562    ///
1563    /// # For more examples,
1564    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.turn_inverse)
1565    #[inline]
1566    pub fn turn_inverse(&mut self)
1567    {
1568        (self.enc, self.dec) = (self.dec, self.enc);
1569    }
1570
1571    // pub fn turn_encryptor(&mut self)
1572    /// Changes its role in BigCryptor128 or NAES to encryptor.
1573    ///
1574    /// # Features
1575    /// - You won't use this method unless you use BigCryptor128 or NAES
1576    ///   for such as Triple AES.
1577    /// - Even if you are writing codes in the context of using BigCryptor128
1578    ///   or NAES, you will hardly use this method because it is high chance
1579    ///   that you will have constructed components with the methods,
1580    ///   [encryptor_with_key](struct@Rijndael_Generic#method.encryptor_with_key),
1581    ///   [encryptor_with_key_u128](struct@Rijndael_Generic#method.encryptor_with_key_u128),
1582    ///   [decryptor_with_key](struct@Rijndael_Generic#method.decryptor_with_key), and
1583    ///   [decryptor_with_key_u128](struct@Rijndael_Generic#method.decryptor_with_key_u128).
1584    /// - If it is constructed as encryptor for BigCryptor128 or NAES,
1585    ///   it will not be changed at all.
1586    /// - If it is constructed as decryptor for BigCryptor128 or NAES,
1587    ///   it will be changed into encryptor.
1588    ///
1589    /// # Example 1
1590    /// ```
1591    /// use cryptocol::symmetric::{ AES_128, BigCryptor128, SmallCryptor };
1592    /// 
1593    /// let mut keys: [Box<dyn SmallCryptor<u128, 16>>; 3]
1594    ///         = [ Box::new(AES_128::new_with_key_u128(0x_1234567890ABCDEFFEDCA0987654321_u128)),
1595    ///             Box::new(AES_128::new_with_key_u128(0x_FEDCBA09876543211234567890ABCDEF_u128)),
1596    ///             Box::new(AES_128::new_with_key_u128(0x_1234567890ABCDEFFEDCA0987654321_u128)) ];
1597    /// keys[0].turn_encryptor();
1598    /// 
1599    /// let mut taes = BigCryptor128::new_with_small_cryptor_array(keys);
1600    /// let plaintext = 0x_11223344556677889900AABBCCDDEEFF_u128;
1601    /// let ciphertext = taes.encrypt_u128(plaintext);
1602    /// 
1603    /// println!("Plaintext:\t\t{:#034X}", plaintext);
1604    /// println!("Ciphertext:\t\t{:#034X}", ciphertext);
1605    /// assert_eq!(ciphertext, 0x_5C842CA9ECB742B2F3164BC33E0BDCB6_u128);
1606    /// 
1607    /// let recovered_text = taes.decrypt_u128(ciphertext);
1608    /// println!("Recovered text:\t{:#034X}", recovered_text);
1609    /// assert_eq!(recovered_text, 0x_11223344556677889900AABBCCDDEEFF_u128);
1610    /// assert_eq!(recovered_text, plaintext);
1611    /// ```
1612    ///
1613    /// # For more examples,
1614    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.turn_encryptor)
1615    pub fn turn_encryptor(&mut self)
1616    {
1617        self.enc = Self::encrypt_unit;
1618        self.dec = Self::decrypt_unit;
1619    }
1620
1621    // pub fn turn_decryptor(&mut self)
1622    /// Changes its role in BigCryptor128 or NAES to decryptor.
1623    ///
1624    /// # Features
1625    /// - You won't use this method unless you use BBigCryptor128 or NAES
1626    ///   for such as Triple DES.
1627    /// - Even if you are writing codes in the context of using BigCryptor128
1628    ///   or NAES, you will hardly use this method because it is high chance
1629    ///   that you will have constructed components with the methods,
1630    ///   [encryptor_with_key](struct@Rijndael_Generic#method.encryptor_with_key),
1631    ///   [encryptor_with_key_u128](struct@Rijndael_Generic#method.encryptor_with_key_u128),
1632    ///   [decryptor_with_key](struct@Rijndael_Generic#method.decryptor_with_key), and
1633    ///   [decryptor_with_key_u128](struct@Rijndael_Generic#method.decryptor_with_key_u128).
1634    /// - If it is constructed as encryptor for BigCryptor128 or NAES,
1635    ///   it will be changed into decryptor.
1636    /// - If it is constructed as decryptor for BigCryptor128 or NAES,
1637    ///   it will not be changed at all.
1638    ///
1639    /// # Example 1
1640    /// ```
1641    /// use cryptocol::symmetric::{ AES_128, BigCryptor128, SmallCryptor };
1642    /// 
1643    /// let mut keys: [Box<dyn SmallCryptor<u128, 16>>; 3]
1644    ///             = [ Box::new(AES_128::new_with_key_u128(0x_1234567890ABCDEFFEDCA0987654321_u128)),
1645    ///                 Box::new(AES_128::new_with_key_u128(0x_FEDCBA09876543211234567890ABCDEF_u128)),
1646    ///                 Box::new(AES_128::new_with_key_u128(0x_1234567890ABCDEFFEDCA0987654321_u128)) ];
1647    /// keys[1].turn_decryptor();
1648    /// 
1649    /// let mut taes = BigCryptor128::new_with_small_cryptor_array(keys);
1650    /// let plaintext = 0x_11223344556677889900AABBCCDDEEFF_u128;
1651    /// let ciphertext = taes.encrypt_u128(plaintext);
1652    /// 
1653    /// println!("Plaintext:\t\t{:#034X}", plaintext);
1654    /// println!("Ciphertext:\t\t{:#034X}", ciphertext);
1655    /// assert_eq!(ciphertext, 0x_DB56B1B7D320D7481BF40A1964E9C7C4_u128);
1656    /// 
1657    /// let recovered_text = taes.decrypt_u128(ciphertext);
1658    /// println!("Recovered text:\t{:#034X}", recovered_text);
1659    /// assert_eq!(recovered_text, 0x_11223344556677889900AABBCCDDEEFF_u128);
1660    /// assert_eq!(recovered_text, plaintext);
1661    /// ```
1662    ///
1663    /// # For more examples,
1664    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.turn_decryptor)
1665    pub fn turn_decryptor(&mut self)
1666    {
1667        self.enc = Self::decrypt_unit;
1668        self.dec = Self::encrypt_unit;
1669    }
1670
1671    //  pub fn encrypt_unit(&mut self, message: &[IntUnion; NB]) -> [IntUnion; NB]
1672    /// Encrypts data in the form of an array of IntUnion with `NB` elements.
1673    ///
1674    /// # Arguments
1675    /// `message` is of the type `&[IntUnion; NB]`
1676    /// and the plaintext to be encrypted.
1677    ///
1678    /// # Output
1679    /// This method returns the encrypted data in the array of `IntUnion`
1680    /// with `NB` elements.
1681    ///
1682    /// # Counterpart methods
1683    /// For each trait
1684    /// [`ECB_PKCS7`](symmetric/trait.ECB_PKCS7.html#trait.ECB_PKCS7),
1685    /// [`ECB_ISO`](symmetric/trait.ECB_ISO.html#trait.ECB_ISO),
1686    /// [`CBC_PKCS7`](symmetric/trait.CBC_PKCS7.html#trait.ECB_PKCS7),
1687    /// [`CBC_ISO`](symmetric/trait.CBC_ISO.html#trait.CBC_ISO),
1688    /// [`PCBC_PKCS7`](symmetric/trait.PCBC_PKCS7.html#trait.PCBC_PKCS7),
1689    /// [`PCBC_ISO`](symmetric/trait.PCBC_ISO.html#trait.PCBC_ISO).
1690    /// [`CFB`](symmetric/trait.CFB.html#trait.CFB),
1691    /// [`OFB`](symmetric/trait.OFB.html#trait.OFB), and
1692    /// [`CTR`](symmetric/trait.CTR.html#trait.CTR),
1693    /// there are provided useful counterpart methods:
1694    /// encrypt(), encrypt_into_vec(), encrypt_into_array(),
1695    /// encrypt_str(), encrypt_str_into_vec(), encrypt_str_into_array(),
1696    /// encrypt_string(), encrypt_string_into_vec(), encrypt_string_into_array(),
1697    /// encrypt_vec(), encrypt_vec_into_vec(), encrypt_vec_into_array(),
1698    /// encrypt_array(), encrypt_array_into_vec(), and encrypt_array_into_array().
1699    ///
1700    /// # Example 1 for AES_128
1701    /// ```
1702    /// use cryptocol::number::IntUnion;
1703    /// use cryptocol::symmetric::AES_128;
1704    ///
1705    /// let mut aes = AES_128::new_with_key(&[0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF]);
1706    /// let plaintext = [IntUnion::new_with(0x90ABCDEF), IntUnion::new_with(0x12345678), IntUnion::new_with(0x90ABCDEF), IntUnion::new_with(0x12345678)];
1707    /// let ciphertext = aes.encrypt_unit(&plaintext);
1708    ///
1709    /// println!("Plaintext:\t{:08X}{:08X}{:08X}{:08X}", plaintext[0].get(), plaintext[1].get(), plaintext[2].get(), plaintext[3].get());
1710    /// println!("Ciphertext:\t{:08X}{:08X}{:08X}{:08X}", ciphertext[0].get(), ciphertext[1].get(), ciphertext[2].get(), ciphertext[3].get());
1711    /// assert_eq!(ciphertext[0].get(), 0x27584D87);
1712    /// assert_eq!(ciphertext[1].get(), 0x44E2BAE9);
1713    /// assert_eq!(ciphertext[2].get(), 0x4AECB5D6);
1714    /// assert_eq!(ciphertext[3].get(), 0x01CCF826);
1715    /// ```
1716    ///
1717    /// # For more examples,
1718    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.encrypt_unit)
1719    pub fn encrypt_unit(&mut self, message: &[IntUnion; NB]) -> [IntUnion; NB]
1720    {
1721        self.set_block(message);
1722        self.encrypt_block();
1723        self.get_block()
1724    }
1725
1726    // pub fn encrypt_u128(&mut self, message: u128) -> u128
1727    /// Encrypts a 128-bit data.
1728    ///
1729    /// # Arguments
1730    /// `message` is of `u128`-type and the plaintext to be encrypted.
1731    ///
1732    /// # Output
1733    /// This method returns the encrypted data of `u128`-type from `message`.
1734    /// 
1735    /// # Caution
1736    /// - This method is meaningful only when `NB` is `4`. 
1737    /// - If `NB` is other than `4`, this method may panic.
1738    /// - Even if this method does not panic, its behaviour is not defined.
1739    /// 
1740    /// # Counterpart Methods
1741    /// For each trait
1742    /// [`ECB_PKCS7`](symmetric/trait.ECB_PKCS7.html#trait.ECB_PKCS7),
1743    /// [`ECB_ISO`](symmetric/trait.ECB_ISO.html#trait.ECB_ISO),
1744    /// [`CBC_PKCS7`](symmetric/trait.CBC_PKCS7.html#trait.ECB_PKCS7),
1745    /// [`CBC_ISO`](symmetric/trait.CBC_ISO.html#trait.CBC_ISO),
1746    /// [`PCBC_PKCS7`](symmetric/trait.PCBC_PKCS7.html#trait.PCBC_PKCS7),
1747    /// [`PCBC_ISO`](symmetric/trait.PCBC_ISO.html#trait.PCBC_ISO).
1748    /// [`CFB`](symmetric/trait.CFB.html#trait.CFB),
1749    /// [`OFB`](symmetric/trait.OFB.html#trait.OFB), and
1750    /// [`CTR`](symmetric/trait.CTR.html#trait.CTR),
1751    /// there are provided useful counterpart methods:
1752    /// encrypt(), encrypt_into_vec(), encrypt_into_array(),
1753    /// encrypt_str(), encrypt_str_into_vec(), encrypt_str_into_array(),
1754    /// encrypt_string(), encrypt_string_into_vec(), encrypt_string_into_array(),
1755    /// encrypt_vec(), encrypt_vec_into_vec(), encrypt_vec_into_array(),
1756    /// encrypt_array(), encrypt_array_into_vec(), and encrypt_array_into_array().
1757    ///
1758    /// # Example 1 for AES_128
1759    /// ```
1760    /// use cryptocol::symmetric::AES_128;
1761    ///
1762    /// let mut aes = AES_128::new_with_key(&[0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF]);
1763    /// let plaintext = 0x1234567890ABCDEF1234567890ABCDEF;
1764    /// let ciphertext = aes.encrypt_u128(plaintext);
1765    /// 
1766    /// println!("Plaintext:\t{:#034X}", plaintext);
1767    /// println!("Ciphertext:\t{:#034X}", ciphertext);
1768    /// assert_eq!(ciphertext, 0x01CCF8264AECB5D644E2BAE927584D87_u128);
1769    /// ```
1770    ///
1771    /// # For more examples,
1772    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.encrypt_u128)
1773    pub fn encrypt_u128(&mut self, message: u128) -> u128
1774    {
1775        self.set_block_u128(message);
1776        self.encrypt_block();
1777        self.get_block_u128()
1778    }
1779
1780    // pub fn encrypt_u64(&mut self, message: u64) -> u64
1781    /// Encrypts a 64-bit data.
1782    ///
1783    /// # Arguments
1784    /// `message` is of `u64`-type and the plaintext to be encrypted.
1785    ///
1786    /// # Output
1787    /// This method returns the encrypted data of `u64`-type from `message`.
1788    /// 
1789    /// # Caution
1790    /// - This method is meaningful only when `NB` is `2`. 
1791    /// - If `NB` is other than `2`, this method may panic.
1792    /// - Even if this method does not panic, its behaviour is not defined.
1793    /// 
1794    /// # Counterpart Methods
1795    /// For each trait
1796    /// [`ECB_PKCS7`](symmetric/trait.ECB_PKCS7.html#trait.ECB_PKCS7),
1797    /// [`ECB_ISO`](symmetric/trait.ECB_ISO.html#trait.ECB_ISO),
1798    /// [`CBC_PKCS7`](symmetric/trait.CBC_PKCS7.html#trait.ECB_PKCS7),
1799    /// [`CBC_ISO`](symmetric/trait.CBC_ISO.html#trait.CBC_ISO),
1800    /// [`PCBC_PKCS7`](symmetric/trait.PCBC_PKCS7.html#trait.PCBC_PKCS7),
1801    /// [`PCBC_ISO`](symmetric/trait.PCBC_ISO.html#trait.PCBC_ISO).
1802    /// [`CFB`](symmetric/trait.CFB.html#trait.CFB),
1803    /// [`OFB`](symmetric/trait.OFB.html#trait.OFB), and
1804    /// [`CTR`](symmetric/trait.CTR.html#trait.CTR),
1805    /// there are provided useful counterpart methods:
1806    /// encrypt(), encrypt_into_vec(), encrypt_into_array(),
1807    /// encrypt_str(), encrypt_str_into_vec(), encrypt_str_into_array(),
1808    /// encrypt_string(), encrypt_string_into_vec(), encrypt_string_into_array(),
1809    /// encrypt_vec(), encrypt_vec_into_vec(), encrypt_vec_into_array(),
1810    /// encrypt_array(), encrypt_array_into_vec(), and encrypt_array_into_array().
1811    ///
1812    /// # Example 1 for Rijndael_64_64
1813    /// ```
1814    /// use cryptocol::symmetric::Rijndael_64_64;
1815    /// 
1816    /// let mut rijndael = Rijndael_64_64::new_with_key(&[0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF]);
1817    /// let plaintext = 0x1234567890ABCDEF;
1818    /// println!("Plaintext:\t{:#018X}", plaintext);
1819    /// let ciphertext = rijndael.encrypt_u64(plaintext);
1820    /// println!("Ciphertext:\t{:#018X}", ciphertext);
1821    /// assert_eq!(ciphertext, 0x4FAA3F0E49CC4DCF_u64);
1822    /// ```
1823    ///
1824    /// # For more examples,
1825    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.encrypt_u64)
1826    pub fn encrypt_u64(&mut self, message: u64) -> u64
1827    {
1828        self.set_block_u64(message);
1829        self.encrypt_block();
1830        self.get_block_u64()
1831    }
1832
1833    // pub fn encrypt_u32(&mut self, message: u32) -> u32
1834    /// Encrypts a 32-bit data.
1835    ///
1836    /// # Arguments
1837    /// `message` is of `u32`-type and the plaintext to be encrypted.
1838    ///
1839    /// # Output
1840    /// This method returns the encrypted data of `u32`-type from `message`.
1841    /// 
1842    /// # Caution
1843    /// - This method is meaningful only when `NB` is `1`. 
1844    /// - If `NB` is other than `1`, this method may panic.
1845    /// - Even if this method does not panic, its behaviour is not defined.
1846    /// 
1847    /// # Counterpart Methods
1848    /// For each trait
1849    /// [`ECB_PKCS7`](symmetric/trait.ECB_PKCS7.html#trait.ECB_PKCS7),
1850    /// [`ECB_ISO`](symmetric/trait.ECB_ISO.html#trait.ECB_ISO),
1851    /// [`CBC_PKCS7`](symmetric/trait.CBC_PKCS7.html#trait.ECB_PKCS7),
1852    /// [`CBC_ISO`](symmetric/trait.CBC_ISO.html#trait.CBC_ISO),
1853    /// [`PCBC_PKCS7`](symmetric/trait.PCBC_PKCS7.html#trait.PCBC_PKCS7),
1854    /// [`PCBC_ISO`](symmetric/trait.PCBC_ISO.html#trait.PCBC_ISO).
1855    /// [`CFB`](symmetric/trait.CFB.html#trait.CFB),
1856    /// [`OFB`](symmetric/trait.OFB.html#trait.OFB), and
1857    /// [`CTR`](symmetric/trait.CTR.html#trait.CTR),
1858    /// there are provided useful counterpart methods:
1859    /// encrypt(), encrypt_into_vec(), encrypt_into_array(),
1860    /// encrypt_str(), encrypt_str_into_vec(), encrypt_str_into_array(),
1861    /// encrypt_string(), encrypt_string_into_vec(), encrypt_string_into_array(),
1862    /// encrypt_vec(), encrypt_vec_into_vec(), encrypt_vec_into_array(),
1863    /// encrypt_array(), encrypt_array_into_vec(), and encrypt_array_into_array().
1864    ///
1865    /// # Example 1 for Rijndael_32_32
1866    /// ```
1867    /// use cryptocol::symmetric::Rijndael_32_32;
1868    /// 
1869    /// let mut rijndael = Rijndael_32_32::new_with_key(&[0x12, 0x34, 0x56, 0x78]);
1870    /// let plaintext = 0x1234567;
1871    /// println!("Plaintext:\t{:#010X}", plaintext);
1872    /// let ciphertext = rijndael.encrypt_u32(plaintext);
1873    /// println!("Ciphertext:\t{:#010X}", ciphertext);
1874    /// assert_eq!(ciphertext, 0xB25E4E09_u32);
1875    /// ```
1876    ///
1877    /// # For more examples,
1878    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.encrypt_u32)
1879    pub fn encrypt_u32(&mut self, message: u32) -> u32
1880    {
1881        self.set_block_u32(message);
1882        self.encrypt_block();
1883        self.get_block_u32()
1884    }
1885
1886    // pub fn decrypt_unit(&mut self, cipher: &[IntUnion; NB]) -> [IntUnion; NB]
1887    /// Decrypts data in the form of an array of IntUnion with `NB` elements.
1888    ///
1889    /// # Arguments
1890    /// `cipher` is of the type `&[IntUnion; NB]`
1891    /// and the ciphertext to be decrypted.
1892    ///
1893    /// # Output
1894    /// This method returns the decrypted data in the array of `IntUnion`
1895    /// with `NB` elements.
1896    /// 
1897    /// # Counterpart Methods
1898    /// For each trait
1899    /// [`ECB_PKCS7`](symmetric/trait.ECB_PKCS7.html#trait.ECB_PKCS7),
1900    /// [`ECB_ISO`](symmetric/trait.ECB_ISO.html#trait.ECB_ISO),
1901    /// [`CBC_PKCS7`](symmetric/trait.CBC_PKCS7.html#trait.ECB_PKCS7),
1902    /// [`CBC_ISO`](symmetric/trait.CBC_ISO.html#trait.CBC_ISO),
1903    /// [`PCBC_PKCS7`](symmetric/trait.PCBC_PKCS7.html#trait.PCBC_PKCS7),
1904    /// [`PCBC_ISO`](symmetric/trait.PCBC_ISO.html#trait.PCBC_ISO).
1905    /// [`CFB`](symmetric/trait.CFB.html#trait.CFB),
1906    /// [`OFB`](symmetric/trait.OFB.html#trait.OFB), and
1907    /// [`CTR`](symmetric/trait.CTR.html#trait.CTR),
1908    /// there are provided useful counterpart methods:
1909    /// decrypt(), decrypt_into_vec(), decrypt_into_array(),
1910    /// decrypt_into_string(),
1911    /// decrypt_vec(), decrypt_vec_into_vec(), decrypt_vec_into_array(),
1912    /// decrypt_vec_into_string(),
1913    /// decrypt_array(), decrypt_array_into_vec(), decrypt_array_into_array(),
1914    /// and decrypt_array_into_string().
1915    ///
1916    /// # Example 1 for AES_128
1917    /// ```
1918    /// use cryptocol::number::IntUnion;
1919    /// use cryptocol::symmetric::AES_128;
1920    ///
1921    /// let mut aes = AES_128::new_with_key(&[0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF]);
1922    /// let ciphertext = [IntUnion::new_with(0x27584D87), IntUnion::new_with(0x44E2BAE9), IntUnion::new_with(0x4AECB5D6), IntUnion::new_with(0x01CCF826)];
1923    /// let plaintext = aes.decrypt_unit(&ciphertext);
1924    ///
1925    /// println!("Ciphertext:\t{:08X}{:08X}{:08X}{:08X}", ciphertext[0].get(), ciphertext[1].get(), ciphertext[2].get(), ciphertext[3].get());
1926    /// println!("Plaintext:\t{:08X}{:08X}{:08X}{:08X}", plaintext[0].get(), plaintext[1].get(), plaintext[2].get(), plaintext[3].get());
1927    /// assert_eq!(plaintext[0].get(), 0x90ABCDEF);
1928    /// assert_eq!(plaintext[1].get(), 0x12345678);
1929    /// assert_eq!(plaintext[2].get(), 0x90ABCDEF);
1930    /// assert_eq!(plaintext[3].get(), 0x12345678);
1931    /// ```
1932    ///
1933    /// # For more examples,
1934    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.decrypt_unit)
1935    pub fn decrypt_unit(&mut self, cipher: &[IntUnion; NB]) -> [IntUnion; NB]
1936    {
1937        self.set_block(cipher);
1938        self.decrypt_block();
1939        self.get_block()
1940    }
1941
1942    // pub fn decrypt_u128(&mut self, cipher: u128) -> u128
1943    /// Decrypts a 128-bit data.
1944    ///
1945    /// # Arguments
1946    /// `cioher` is of `u128`-type and the ciphertext to be decrypted.
1947    ///
1948    /// # Output
1949    /// This method returns the decrypted data of `u128`-type from `cipher`.
1950    /// 
1951    /// # Caution
1952    /// - This method is meaningful only when `NB` is `4`. 
1953    /// - If `NB` is other than `4`, this method may panic.
1954    /// - Even if this method does not panic, its behaviour is not defined.
1955    /// 
1956    /// # Counterpart Methods
1957    /// For each trait
1958    /// [`ECB_PKCS7`](symmetric/trait.ECB_PKCS7.html#trait.ECB_PKCS7),
1959    /// [`ECB_ISO`](symmetric/trait.ECB_ISO.html#trait.ECB_ISO),
1960    /// [`CBC_PKCS7`](symmetric/trait.CBC_PKCS7.html#trait.ECB_PKCS7),
1961    /// [`CBC_ISO`](symmetric/trait.CBC_ISO.html#trait.CBC_ISO),
1962    /// [`PCBC_PKCS7`](symmetric/trait.PCBC_PKCS7.html#trait.PCBC_PKCS7),
1963    /// [`PCBC_ISO`](symmetric/trait.PCBC_ISO.html#trait.PCBC_ISO).
1964    /// [`CFB`](symmetric/trait.CFB.html#trait.CFB),
1965    /// [`OFB`](symmetric/trait.OFB.html#trait.OFB), and
1966    /// [`CTR`](symmetric/trait.CTR.html#trait.CTR),
1967    /// there are provided useful counterpart methods:
1968    /// decrypt(), decrypt_into_vec(), decrypt_into_array(),
1969    /// decrypt_into_string(),
1970    /// decrypt_vec(), decrypt_vec_into_vec(), decrypt_vec_into_array(),
1971    /// decrypt_vec_into_string(),
1972    /// decrypt_array(), decrypt_array_into_vec(), decrypt_array_into_array(),
1973    /// and decrypt_array_into_string().
1974    ///
1975    /// # Example 1 for AES_128
1976    /// ```
1977    /// use cryptocol::number::IntUnion;
1978    /// use cryptocol::symmetric::AES_128;
1979    ///
1980    /// let mut aes = AES_128::new_with_key(&[0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF]);
1981    /// let ciphertext = 0x01CCF8264AECB5D644E2BAE927584D87_u128;
1982    /// let plaintext = aes.decrypt_u128(ciphertext);
1983    ///
1984    /// println!("Ciphertext:\t{:#034X}", ciphertext);
1985    /// println!("Plaintext:\t{:#034X}", plaintext);
1986    /// assert_eq!(plaintext, 0x1234567890ABCDEF1234567890ABCDEF);
1987    /// ```
1988    ///
1989    /// # For more examples,
1990    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.decrypt_u128)
1991    pub fn decrypt_u128(&mut self, cipher: u128) -> u128
1992    {
1993        self.set_block_u128(cipher);
1994        self.decrypt_block();
1995        self.get_block_u128()
1996    }
1997
1998    // pub fn decrypt_u64(&mut self, cipher: u64) -> u64
1999    /// Decrypts a 64-bit data.
2000    ///
2001    /// # Arguments
2002    /// `cioher` is of `u64`-type and the ciphertext to be decrypted.
2003    ///
2004    /// # Output
2005    /// This method returns the decrypted data of `u64`-type from `cipher`.
2006    /// 
2007    /// # Caution
2008    /// - This method is meaningful only when `NB` is `2`. 
2009    /// - If `NB` is other than `2`, this method may panic.
2010    /// - Even if this method does not panic, its behaviour is not defined.
2011    /// 
2012    /// # Counterpart Methods
2013    /// For each trait
2014    /// [`ECB_PKCS7`](symmetric/trait.ECB_PKCS7.html#trait.ECB_PKCS7),
2015    /// [`ECB_ISO`](symmetric/trait.ECB_ISO.html#trait.ECB_ISO),
2016    /// [`CBC_PKCS7`](symmetric/trait.CBC_PKCS7.html#trait.ECB_PKCS7),
2017    /// [`CBC_ISO`](symmetric/trait.CBC_ISO.html#trait.CBC_ISO),
2018    /// [`PCBC_PKCS7`](symmetric/trait.PCBC_PKCS7.html#trait.PCBC_PKCS7),
2019    /// [`PCBC_ISO`](symmetric/trait.PCBC_ISO.html#trait.PCBC_ISO).
2020    /// [`CFB`](symmetric/trait.CFB.html#trait.CFB),
2021    /// [`OFB`](symmetric/trait.OFB.html#trait.OFB), and
2022    /// [`CTR`](symmetric/trait.CTR.html#trait.CTR),
2023    /// there are provided useful counterpart methods:
2024    /// decrypt(), decrypt_into_vec(), decrypt_into_array(),
2025    /// decrypt_into_string(),
2026    /// decrypt_vec(), decrypt_vec_into_vec(), decrypt_vec_into_array(),
2027    /// decrypt_vec_into_string(),
2028    /// decrypt_array(), decrypt_array_into_vec(), decrypt_array_into_array(),
2029    /// and decrypt_array_into_string().
2030    ///
2031    /// # Example 1 for Rijndael_64_64
2032    /// ```
2033    /// use cryptocol::symmetric::Rijndael_64_64;
2034    /// 
2035    /// let mut rijndael = Rijndael_64_64::new_with_key(&[0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF]);
2036    /// let ciphertext = 0x4FAA3F0E49CC4DCF_u64;
2037    /// println!("Ciphertext:\t{:#018X}", ciphertext);
2038    /// let plaintext = rijndael.decrypt_u64(ciphertext);
2039    /// println!("Plaintext:\t{:#018X}", plaintext);
2040    /// assert_eq!(plaintext, 0x1234567890ABCDEF_u64);
2041    /// ```
2042    ///
2043    /// # For more examples,
2044    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.decrypt_u64)
2045    pub fn decrypt_u64(&mut self, cipher: u64) -> u64
2046    {
2047        self.set_block_u64(cipher);
2048        self.decrypt_block();
2049        self.get_block_u64()
2050    }
2051
2052    // pub fn decrypt_u32(&mut self, cipher: u32) -> u32
2053    /// Decrypts a 32-bit data.
2054    ///
2055    /// # Arguments
2056    /// `cioher` is of `u32`-type and the ciphertext to be decrypted.
2057    ///
2058    /// # Output
2059    /// This method returns the decrypted data of `u32`-type from `cipher`.
2060    /// 
2061    /// # Caution
2062    /// - This method is meaningful only when `NB` is `1`. 
2063    /// - If `NB` is other than `1`, this method may panic.
2064    /// - Even if this method does not panic, its behaviour is not defined.
2065    /// 
2066    /// # Counterpart Methods
2067    /// For each trait
2068    /// [`ECB_PKCS7`](symmetric/trait.ECB_PKCS7.html#trait.ECB_PKCS7),
2069    /// [`ECB_ISO`](symmetric/trait.ECB_ISO.html#trait.ECB_ISO),
2070    /// [`CBC_PKCS7`](symmetric/trait.CBC_PKCS7.html#trait.ECB_PKCS7),
2071    /// [`CBC_ISO`](symmetric/trait.CBC_ISO.html#trait.CBC_ISO),
2072    /// [`PCBC_PKCS7`](symmetric/trait.PCBC_PKCS7.html#trait.PCBC_PKCS7),
2073    /// [`PCBC_ISO`](symmetric/trait.PCBC_ISO.html#trait.PCBC_ISO).
2074    /// [`CFB`](symmetric/trait.CFB.html#trait.CFB),
2075    /// [`OFB`](symmetric/trait.OFB.html#trait.OFB), and
2076    /// [`CTR`](symmetric/trait.CTR.html#trait.CTR),
2077    /// there are provided useful counterpart methods:
2078    /// decrypt(), decrypt_into_vec(), decrypt_into_array(),
2079    /// decrypt_into_string(),
2080    /// decrypt_vec(), decrypt_vec_into_vec(), decrypt_vec_into_array(),
2081    /// decrypt_vec_into_string(),
2082    /// decrypt_array(), decrypt_array_into_vec(), decrypt_array_into_array(),
2083    /// and decrypt_array_into_string().
2084    ///
2085    /// # Example 1 for Rijndael_32_32
2086    /// ```
2087    /// use cryptocol::symmetric::Rijndael_32_32;
2088    /// 
2089    /// let mut rijndael = Rijndael_32_32::new_with_key(&[0x12, 0x34, 0x56, 0x78]);
2090    /// let ciphertext = 0xB25E4E09_u32;
2091    /// println!("Ciphertext:\t{:#010X}", ciphertext);
2092    /// let plaintext = rijndael.decrypt_u32(ciphertext);
2093    /// println!("Plaintext:\t{:#010X}", plaintext);
2094    /// assert_eq!(plaintext, 0x1234567_u32);
2095    /// ```
2096    ///
2097    /// # For more examples,
2098    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.decrypt_u32)
2099    pub fn decrypt_u32(&mut self, cipher: u32) -> u32
2100    {
2101        self.set_block_u32(cipher);
2102        self.decrypt_block();
2103        self.get_block_u32()
2104    }
2105
2106    #[inline]
2107    pub(super) fn _encrypt(&mut self, message: &[IntUnion; NB]) -> [IntUnion; NB]
2108    {
2109        (self.enc)(self, message)
2110    }
2111
2112    #[inline]
2113    pub(super) fn _decrypt(&mut self, cipher: &[IntUnion; NB]) -> [IntUnion; NB]
2114    {
2115        (self.dec)(self, cipher)
2116    }
2117
2118    // pub fn encrypt_array_unit<const N: usize>(&mut self, message: &[[IntUnion; NB]; N], cipher: &mut [[IntUnion; NB]; N])
2119    /// Encrypts an array of unit data, `[[IntUnion; NB]; N]`.
2120    ///
2121    /// # Arguments
2122    /// - `message` is of an array of `[IntUnion; NB]`-type and the plaintext
2123    ///   to be encrypted.
2124    /// - `cipher` is of an array of `[IntUnion; NB]`-type and the ciphertext
2125    ///   to be stored.
2126    ///
2127    /// # Features
2128    /// This method encrypts multiple of 64-bit data without padding anything
2129    /// in ECB (Electronic CodeBook) mode.
2130    /// 
2131    /// # Counterpart Methods
2132    /// For each trait
2133    /// [`ECB_PKCS7`](symmetric/trait.ECB_PKCS7.html#trait.ECB_PKCS7),
2134    /// [`ECB_ISO`](symmetric/trait.ECB_ISO.html#trait.ECB_ISO),
2135    /// [`CBC_PKCS7`](symmetric/trait.CBC_PKCS7.html#trait.ECB_PKCS7),
2136    /// [`CBC_ISO`](symmetric/trait.CBC_ISO.html#trait.CBC_ISO),
2137    /// [`PCBC_PKCS7`](symmetric/trait.PCBC_PKCS7.html#trait.PCBC_PKCS7),
2138    /// [`PCBC_ISO`](symmetric/trait.PCBC_ISO.html#trait.PCBC_ISO).
2139    /// [`CFB`](symmetric/trait.CFB.html#trait.CFB),
2140    /// [`OFB`](symmetric/trait.OFB.html#trait.OFB), and
2141    /// [`CTR`](symmetric/trait.CTR.html#trait.CTR),
2142    /// there are provided useful counterpart methods:
2143    /// encrypt(), encrypt_into_vec(), encrypt_into_array(),
2144    /// encrypt_str(), encrypt_str_into_vec(), encrypt_str_into_array(),
2145    /// encrypt_string(), encrypt_string_into_vec(), encrypt_string_into_array(),
2146    /// encrypt_vec(), encrypt_vec_into_vec(), encrypt_vec_into_array(),
2147    /// encrypt_array(), encrypt_array_into_vec(), and encrypt_array_into_array().
2148    /// 
2149    /// # Example 1 for AES_128
2150    /// ```
2151    /// use cryptocol::number::IntUnion;
2152    /// use cryptocol::symmetric::AES_128;
2153    ///
2154    /// let mut aes = AES_128::new_with_key(&[0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF]);
2155    /// let plaintext = [[IntUnion::new_with(0x90ABCDEF), IntUnion::new_with(0x12345678), IntUnion::new_with(0x90ABCDEF), IntUnion::new_with(0x12345678)]; 3];
2156    /// let mut ciphertext = [[IntUnion::new(); 4]; 3];
2157    /// aes.encrypt_array_unit(&plaintext, &mut ciphertext);
2158    /// 
2159    /// println!("Plaintext:\t{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}",
2160    ///         plaintext[0][0].get(), plaintext[0][1].get(), plaintext[0][2].get(), plaintext[0][3].get(),
2161    ///         plaintext[1][0].get(), plaintext[1][1].get(), plaintext[1][2].get(), plaintext[1][3].get(),
2162    ///         plaintext[2][0].get(), plaintext[2][1].get(), plaintext[2][2].get(), plaintext[2][3].get());
2163    /// println!("Ciphertext:\t{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}",
2164    ///         ciphertext[0][0].get(), ciphertext[0][1].get(), ciphertext[0][2].get(), ciphertext[0][3].get(),
2165    ///         ciphertext[1][0].get(), ciphertext[1][1].get(), ciphertext[1][2].get(), ciphertext[1][3].get(),
2166    ///         ciphertext[2][0].get(), ciphertext[2][1].get(), ciphertext[2][2].get(), ciphertext[2][3].get());
2167    /// assert_eq!(ciphertext[0][0].get(), 0x27584D87);
2168    /// assert_eq!(ciphertext[0][1].get(), 0x44E2BAE9);
2169    /// assert_eq!(ciphertext[0][2].get(), 0x4AECB5D6);
2170    /// assert_eq!(ciphertext[0][3].get(), 0x01CCF826);
2171    /// assert_eq!(ciphertext[1][0].get(), 0x27584D87);
2172    /// assert_eq!(ciphertext[1][1].get(), 0x44E2BAE9);
2173    /// assert_eq!(ciphertext[1][2].get(), 0x4AECB5D6);
2174    /// assert_eq!(ciphertext[1][3].get(), 0x01CCF826);
2175    /// assert_eq!(ciphertext[2][0].get(), 0x27584D87);
2176    /// assert_eq!(ciphertext[2][1].get(), 0x44E2BAE9);
2177    /// assert_eq!(ciphertext[2][2].get(), 0x4AECB5D6);
2178    /// assert_eq!(ciphertext[2][3].get(), 0x01CCF826);
2179    /// ```
2180    ///
2181    /// # For more examples,
2182    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.encrypt_array_unit)
2183    pub fn encrypt_array_unit<const N: usize>(&mut self, message: &[[IntUnion; NB]; N], cipher: &mut [[IntUnion; NB]; N])
2184    {
2185        for i in 0..N
2186        {
2187            self.set_block(&message[i]);
2188            self.encrypt_block();
2189            cipher[i] = self.get_block();
2190        }
2191    }
2192
2193    // pub fn encrypt_array_u128<const N: usize>(&mut self, message: &[u128; N], cipher: &mut [u128; N])
2194    /// Encrypts an array of 128-bit data.
2195    ///
2196    /// # Arguments
2197    /// - `message` is of an array of `u128`-type and the plaintext
2198    ///   to be encrypted.
2199    /// - `cipher` is of an array of `u128`-type and the ciphertext
2200    ///   to be stored.
2201    ///
2202    /// # Features
2203    /// This method encrypts multiple of 128-bit data without padding anything
2204    /// in ECB (Electronic CodeBook) mode.
2205    /// 
2206    /// # Caution
2207    /// - This method is meaningful only when `NB` is `4`. 
2208    /// - If `NB` is other than `4`, this method may panic.
2209    /// - Even if this method does not panic, its behaviour is not defined.
2210    /// 
2211    /// # Counterpart Methods
2212    /// For each trait
2213    /// [`ECB_PKCS7`](symmetric/trait.ECB_PKCS7.html#trait.ECB_PKCS7),
2214    /// [`ECB_ISO`](symmetric/trait.ECB_ISO.html#trait.ECB_ISO),
2215    /// [`CBC_PKCS7`](symmetric/trait.CBC_PKCS7.html#trait.ECB_PKCS7),
2216    /// [`CBC_ISO`](symmetric/trait.CBC_ISO.html#trait.CBC_ISO),
2217    /// [`PCBC_PKCS7`](symmetric/trait.PCBC_PKCS7.html#trait.PCBC_PKCS7),
2218    /// [`PCBC_ISO`](symmetric/trait.PCBC_ISO.html#trait.PCBC_ISO).
2219    /// [`CFB`](symmetric/trait.CFB.html#trait.CFB),
2220    /// [`OFB`](symmetric/trait.OFB.html#trait.OFB), and
2221    /// [`CTR`](symmetric/trait.CTR.html#trait.CTR),
2222    /// there are provided useful counterpart methods:
2223    /// encrypt(), encrypt_into_vec(), encrypt_into_array(),
2224    /// encrypt_str(), encrypt_str_into_vec(), encrypt_str_into_array(),
2225    /// encrypt_string(), encrypt_string_into_vec(), encrypt_string_into_array(),
2226    /// encrypt_vec(), encrypt_vec_into_vec(), encrypt_vec_into_array(),
2227    /// encrypt_array(), encrypt_array_into_vec(), and encrypt_array_into_array().
2228    /// 
2229    /// # Example 1 for AES_128
2230    /// ```
2231    /// use cryptocol::symmetric::AES_128;
2232    /// 
2233    /// let mut aes = AES_128::new_with_key(&[0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF]);
2234    /// let plaintext = [0x1234567890ABCDEF1234567890ABCDEF_u128, 0x11223344556677889900AABBCCDDEEFF, 0xFFEEDDCCBBAA00998877665544332211];
2235    /// let mut ciphertext = [0_u128; 3];
2236    /// aes.encrypt_array_u128(&plaintext, &mut ciphertext);
2237    /// 
2238    /// println!("Plaintext:\t{:#034X} {:#034X} {:#034X}", plaintext[0], plaintext[1], plaintext[2]);
2239    /// println!("Ciphertext:\t{:#034X} {:#034X} {:#034X}", ciphertext[0], ciphertext[1], ciphertext[2]);
2240    /// assert_eq!(ciphertext[0], 0x01CCF8264AECB5D644E2BAE927584D87_u128);
2241    /// assert_eq!(ciphertext[1], 0x7601C1D6EA61791544C28D4004577BB9_u128);
2242    /// assert_eq!(ciphertext[2], 0xB7225E77C077541D5055FE9C8D3894B9_u128);
2243    /// ```
2244    ///
2245    /// # For more examples,
2246    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.encrypt_array_u128)
2247    pub fn encrypt_array_u128<const N: usize>(&mut self, message: &[u128; N], cipher: &mut [u128; N])
2248    {
2249        for i in 0..N
2250        {
2251            self.set_block_u128(message[i]);
2252            self.encrypt_block();
2253            cipher[i] = self.get_block_u128();
2254        }
2255    }
2256
2257    // pub fn encrypt_array_u64<const N: usize>(&mut self, message: &[u64; N], cipher: &mut [u64; N])
2258    /// Encrypts an array of 64-bit data.
2259    ///
2260    /// # Arguments
2261    /// - `message` is of an array of `u64`-type and the plaintext
2262    ///   to be encrypted.
2263    /// - `cipher` is of an array of `u64`-type and the ciphertext
2264    ///   to be stored.
2265    ///
2266    /// # Features
2267    /// This method encrypts multiple of 64-bit data without padding anything
2268    /// in ECB (Electronic CodeBook) mode.
2269    /// 
2270    /// # Caution
2271    /// - This method is meaningful only when `NB` is `2`. 
2272    /// - If `NB` is other than `2`, this method may panic.
2273    /// - Even if this method does not panic, its behaviour is not defined.
2274    /// 
2275    /// # Counterpart Methods
2276    /// For each trait
2277    /// [`ECB_PKCS7`](symmetric/trait.ECB_PKCS7.html#trait.ECB_PKCS7),
2278    /// [`ECB_ISO`](symmetric/trait.ECB_ISO.html#trait.ECB_ISO),
2279    /// [`CBC_PKCS7`](symmetric/trait.CBC_PKCS7.html#trait.ECB_PKCS7),
2280    /// [`CBC_ISO`](symmetric/trait.CBC_ISO.html#trait.CBC_ISO),
2281    /// [`PCBC_PKCS7`](symmetric/trait.PCBC_PKCS7.html#trait.PCBC_PKCS7),
2282    /// [`PCBC_ISO`](symmetric/trait.PCBC_ISO.html#trait.PCBC_ISO).
2283    /// [`CFB`](symmetric/trait.CFB.html#trait.CFB),
2284    /// [`OFB`](symmetric/trait.OFB.html#trait.OFB), and
2285    /// [`CTR`](symmetric/trait.CTR.html#trait.CTR),
2286    /// there are provided useful counterpart methods:
2287    /// encrypt(), encrypt_into_vec(), encrypt_into_array(),
2288    /// encrypt_str(), encrypt_str_into_vec(), encrypt_str_into_array(),
2289    /// encrypt_string(), encrypt_string_into_vec(), encrypt_string_into_array(),
2290    /// encrypt_vec(), encrypt_vec_into_vec(), encrypt_vec_into_array(),
2291    /// encrypt_array(), encrypt_array_into_vec(), and encrypt_array_into_array().
2292    /// 
2293    /// # Example 1 for Rijndael_64_64
2294    /// ```
2295    /// use cryptocol::symmetric::Rijndael_64_64;
2296    /// 
2297    /// let mut rijndael = Rijndael_64_64::new_with_key(&[0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF]);
2298    /// let plaintext = [0x1234567890ABCDEF_u64, 0x1122334455667788, 0xFFEEDDCCBBAA0099];
2299    /// let mut ciphertext = [0_u64; 3];
2300    /// rijndael.encrypt_array_u64(&plaintext, &mut ciphertext);
2301    /// 
2302    /// println!("Plaintext:\t{:#018X} {:#018X} {:#018X}", plaintext[0], plaintext[1], plaintext[2]);
2303    /// println!("Ciphertext:\t{:#018X} {:#018X} {:#018X}", ciphertext[0], ciphertext[1], ciphertext[2]);
2304    /// assert_eq!(ciphertext[0], 0x4FAA3F0E49CC4DCF_u64);
2305    /// assert_eq!(ciphertext[1], 0x036AAEDC0F1A5BEC_u64);
2306    /// assert_eq!(ciphertext[2], 0x99B8209339BCC1EB_u64);
2307    /// ```
2308    ///
2309    /// # For more examples,
2310    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.encrypt_array_u64)
2311    pub fn encrypt_array_u64<const N: usize>(&mut self, message: &[u64; N], cipher: &mut [u64; N])
2312    {
2313        for i in 0..N
2314        {
2315            self.set_block_u64(message[i]);
2316            self.encrypt_block();
2317            cipher[i] = self.get_block_u64();
2318        }
2319    }
2320
2321    // pub fn encrypt_array_u32<const N: usize>(&mut self, message: &[u32; N], cipher: &mut [u32; N])
2322    /// Encrypts an array of 32-bit data.
2323    ///
2324    /// # Arguments
2325    /// - `message` is of an array of `u32`-type and the plaintext
2326    ///   to be encrypted.
2327    /// - `cipher` is of an array of `u32`-type and the ciphertext
2328    ///   to be stored.
2329    ///
2330    /// # Features
2331    /// This method encrypts multiple of 32-bit data without padding anything
2332    /// in ECB (Electronic CodeBook) mode.
2333    /// 
2334    /// # Caution
2335    /// - This method is meaningful only when `NB` is `1`. 
2336    /// - If `NB` is other than `1`, this method may panic.
2337    /// - Even if this method does not panic, its behaviour is not defined.
2338    /// 
2339    /// # Counterpart Methods
2340    /// For each trait
2341    /// [`ECB_PKCS7`](symmetric/trait.ECB_PKCS7.html#trait.ECB_PKCS7),
2342    /// [`ECB_ISO`](symmetric/trait.ECB_ISO.html#trait.ECB_ISO),
2343    /// [`CBC_PKCS7`](symmetric/trait.CBC_PKCS7.html#trait.ECB_PKCS7),
2344    /// [`CBC_ISO`](symmetric/trait.CBC_ISO.html#trait.CBC_ISO),
2345    /// [`PCBC_PKCS7`](symmetric/trait.PCBC_PKCS7.html#trait.PCBC_PKCS7),
2346    /// [`PCBC_ISO`](symmetric/trait.PCBC_ISO.html#trait.PCBC_ISO).
2347    /// [`CFB`](symmetric/trait.CFB.html#trait.CFB),
2348    /// [`OFB`](symmetric/trait.OFB.html#trait.OFB), and
2349    /// [`CTR`](symmetric/trait.CTR.html#trait.CTR),
2350    /// there are provided useful counterpart methods:
2351    /// encrypt(), encrypt_into_vec(), encrypt_into_array(),
2352    /// encrypt_str(), encrypt_str_into_vec(), encrypt_str_into_array(),
2353    /// encrypt_string(), encrypt_string_into_vec(), encrypt_string_into_array(),
2354    /// encrypt_vec(), encrypt_vec_into_vec(), encrypt_vec_into_array(),
2355    /// encrypt_array(), encrypt_array_into_vec(), and encrypt_array_into_array().
2356    /// 
2357    /// # Example 1 for Rijndael_32_32
2358    /// ```
2359    /// use cryptocol::symmetric::Rijndael_32_32;
2360    /// 
2361    /// let mut rijndael = Rijndael_32_32::new_with_key(&[0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF]);
2362    /// let plaintext = [0x12345678_u32, 0x90ABCDEF, 0xFFEEDDCC];
2363    /// let mut ciphertext = [0_u32; 3];
2364    /// rijndael.encrypt_array_u32(&plaintext, &mut ciphertext);
2365    /// 
2366    /// println!("Plaintext:\t{:#010X} {:#010X} {:#010X}", plaintext[0], plaintext[1], plaintext[2]);
2367    /// println!("Ciphertext:\t{:#010X} {:#010X} {:#010X}", ciphertext[0], ciphertext[1], ciphertext[2]);
2368    /// assert_eq!(ciphertext[0], 0x335228F6_u32);
2369    /// assert_eq!(ciphertext[1], 0xBFB99AFB_u32);
2370    /// assert_eq!(ciphertext[2], 0x2D114838_u32);
2371    /// ```
2372    ///
2373    /// # For more examples,
2374    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.encrypt_array_u32)
2375    pub fn encrypt_array_u32<const N: usize>(&mut self, message: &[u32; N], cipher: &mut [u32; N])
2376    {
2377        for i in 0..N
2378        {
2379            self.set_block_u32(message[i]);
2380            self.encrypt_block();
2381            cipher[i] = self.get_block_u32();
2382        }
2383    }
2384
2385    // pub fn decrypt_array_unit<const N: usize>(&mut self, cipher: &[[IntUnion; NB]; N], message: &mut [[IntUnion; NB]; N])
2386    /// Decrypts an array of unit data, `[[IntUnion; NB]; N]`.
2387    ///
2388    /// # Arguments
2389    /// - `cipher` is of an array of `[IntUnion; NB]`-type and the ciphertext
2390    ///   to be encrypted.
2391    /// - `message` is of an array of `[IntUnion; NB]`-type and the plaintext
2392    ///   to be stored.
2393    ///
2394    /// # Features
2395    /// This method decrypts multiple of 64-bit data without padding anything
2396    /// in ECB (Electronic CodeBook) mode.
2397    /// 
2398    /// # Counterpart Methods
2399    /// For each trait
2400    /// [`ECB_PKCS7`](symmetric/trait.ECB_PKCS7.html#trait.ECB_PKCS7),
2401    /// [`ECB_ISO`](symmetric/trait.ECB_ISO.html#trait.ECB_ISO),
2402    /// [`CBC_PKCS7`](symmetric/trait.CBC_PKCS7.html#trait.ECB_PKCS7),
2403    /// [`CBC_ISO`](symmetric/trait.CBC_ISO.html#trait.CBC_ISO),
2404    /// [`PCBC_PKCS7`](symmetric/trait.PCBC_PKCS7.html#trait.PCBC_PKCS7),
2405    /// [`PCBC_ISO`](symmetric/trait.PCBC_ISO.html#trait.PCBC_ISO).
2406    /// [`CFB`](symmetric/trait.CFB.html#trait.CFB),
2407    /// [`OFB`](symmetric/trait.OFB.html#trait.OFB), and
2408    /// [`CTR`](symmetric/trait.CTR.html#trait.CTR),
2409    /// there are provided useful counterpart methods:
2410    /// decrypt(), decrypt_into_vec(), decrypt_into_array(),
2411    /// decrypt_into_string(),
2412    /// decrypt_vec(), decrypt_vec_into_vec(), decrypt_vec_into_array(),
2413    /// decrypt_vec_into_string(),
2414    /// decrypt_array(), decrypt_array_into_vec(), decrypt_array_into_array(),
2415    /// and decrypt_array_into_string().
2416    /// 
2417    /// # Example 1 for AES_128
2418    /// ```
2419    /// use cryptocol::number::IntUnion;
2420    /// use cryptocol::symmetric::AES_128;
2421    /// 
2422    /// let mut aes = AES_128::new_with_key(&[0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF]);
2423    /// let ciphertext = [[IntUnion::new_with(0x27584D87), IntUnion::new_with(0x44E2BAE9), IntUnion::new_with(0x4AECB5D6), IntUnion::new_with(0x01CCF826)]; 3];
2424    /// let mut plaintext = [[IntUnion::new(); 4]; 3];
2425    /// aes.decrypt_array_unit(&ciphertext, &mut plaintext);
2426    /// 
2427    /// println!("Ciphertext:\t{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}",
2428    ///         ciphertext[0][0].get(), ciphertext[0][1].get(), ciphertext[0][2].get(), ciphertext[0][3].get(),
2429    ///         ciphertext[1][0].get(), ciphertext[1][1].get(), ciphertext[1][2].get(), ciphertext[1][3].get(),
2430    ///         ciphertext[2][0].get(), ciphertext[2][1].get(), ciphertext[2][2].get(), ciphertext[2][3].get());
2431    /// println!("Plaintext:\t{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}{:08X}",
2432    ///         plaintext[0][0].get(), plaintext[0][1].get(), plaintext[0][2].get(), plaintext[0][3].get(),
2433    ///         plaintext[1][0].get(), plaintext[1][1].get(), plaintext[1][2].get(), plaintext[1][3].get(),
2434    ///         plaintext[2][0].get(), plaintext[2][1].get(), plaintext[2][2].get(), plaintext[2][3].get());
2435    /// assert_eq!(plaintext[0][0].get(), 0x90ABCDEF);
2436    /// assert_eq!(plaintext[0][1].get(), 0x12345678);
2437    /// assert_eq!(plaintext[0][2].get(), 0x90ABCDEF);
2438    /// assert_eq!(plaintext[0][3].get(), 0x12345678);
2439    /// assert_eq!(plaintext[1][0].get(), 0x90ABCDEF);
2440    /// assert_eq!(plaintext[1][1].get(), 0x12345678);
2441    /// assert_eq!(plaintext[1][2].get(), 0x90ABCDEF);
2442    /// assert_eq!(plaintext[1][3].get(), 0x12345678);
2443    /// assert_eq!(plaintext[2][0].get(), 0x90ABCDEF);
2444    /// assert_eq!(plaintext[2][1].get(), 0x12345678);
2445    /// assert_eq!(plaintext[2][2].get(), 0x90ABCDEF);
2446    /// assert_eq!(plaintext[2][3].get(), 0x12345678);
2447    /// ```
2448    ///
2449    /// # For more examples,
2450    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.decrypt_array_unit)
2451    pub fn decrypt_array_unit<const N: usize>(&mut self, cipher: &[[IntUnion; NB]; N], message: &mut [[IntUnion; NB]; N])
2452    {
2453        for i in 0..N
2454        {
2455            self.set_block(&cipher[i]);
2456            self.decrypt_block();
2457            message[i] = self.get_block();
2458        }
2459    }
2460
2461    // pub fn decrypt_array_u128<const N: usize>(&mut self, cipher: &[u128; N], message: &mut [u128; N])
2462    /// Decrypts an array of 128-bit data.
2463    ///
2464    /// # Arguments
2465    /// - `cipher` is of an array of `u128`-type and the ciphertext to be
2466    ///   decrypted.
2467    /// - `message` is of an array of `u128`-type and the plaintext to be stored.
2468    ///
2469    /// # Features
2470    /// This method decrypts multiple of 64-bit data without padding anything
2471    /// in ECB (Electronic CodeBook) mode.
2472    /// 
2473    /// # Caution
2474    /// - This method is meaningful only when `NB` is `4`. 
2475    /// - If `NB` is other than `4`, this method may panic.
2476    /// - Even if this method does not panic, its behaviour is not defined.
2477    /// 
2478    /// # Caution
2479    /// - This method is meaningful only when `NB` is `4`. 
2480    /// - If `NB` is other than `4`, this method may panic.
2481    /// - Even if this method does not panic, its behaviour is not defined.
2482    /// 
2483    /// # Counterpart Methods
2484    /// For each trait
2485    /// [`ECB_PKCS7`](symmetric/trait.ECB_PKCS7.html#trait.ECB_PKCS7),
2486    /// [`ECB_ISO`](symmetric/trait.ECB_ISO.html#trait.ECB_ISO),
2487    /// [`CBC_PKCS7`](symmetric/trait.CBC_PKCS7.html#trait.ECB_PKCS7),
2488    /// [`CBC_ISO`](symmetric/trait.CBC_ISO.html#trait.CBC_ISO),
2489    /// [`PCBC_PKCS7`](symmetric/trait.PCBC_PKCS7.html#trait.PCBC_PKCS7),
2490    /// [`PCBC_ISO`](symmetric/trait.PCBC_ISO.html#trait.PCBC_ISO).
2491    /// [`CFB`](symmetric/trait.CFB.html#trait.CFB),
2492    /// [`OFB`](symmetric/trait.OFB.html#trait.OFB), and
2493    /// [`CTR`](symmetric/trait.CTR.html#trait.CTR),
2494    /// there are provided useful counterpart methods:
2495    /// decrypt(), decrypt_into_vec(), decrypt_into_array(),
2496    /// decrypt_into_string(),
2497    /// decrypt_vec(), decrypt_vec_into_vec(), decrypt_vec_into_array(),
2498    /// decrypt_vec_into_string(),
2499    /// decrypt_array(), decrypt_array_into_vec(), decrypt_array_into_array(),
2500    /// and decrypt_array_into_string().
2501    /// 
2502    /// # Example 1 for AES_128
2503    /// ```
2504    /// use cryptocol::number::IntUnion;
2505    /// use cryptocol::symmetric::AES_128;
2506    /// 
2507    /// let mut aes = AES_128::new_with_key(&[0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF]);
2508    /// let plaintext = [0x1234567890ABCDEF1234567890ABCDEF_u128, 0x11223344556677889900AABBCCDDEEFF, 0xFFEEDDCCBBAA00998877665544332211];
2509    /// println!("Plaintext:\t{:#034X} {:#034X} {:#034X}", plaintext[0], plaintext[1], plaintext[2]);
2510    /// let mut ciphertext = [0_u128; 3];
2511    /// aes.encrypt_array_u128(&plaintext, &mut ciphertext);
2512    /// println!("Ciphertext:\t{:#034X} {:#034X} {:#034X}", ciphertext[0], ciphertext[1], ciphertext[2]);
2513    /// assert_eq!(ciphertext[0], 0x01CCF8264AECB5D644E2BAE927584D87_u128);
2514    /// assert_eq!(ciphertext[1], 0x7601C1D6EA61791544C28D4004577BB9_u128);
2515    /// assert_eq!(ciphertext[2], 0xB7225E77C077541D5055FE9C8D3894B9_u128);
2516    /// 
2517    /// let mut recovered = [0_u128; 3];
2518    /// aes.decrypt_array_u128(&ciphertext, &mut recovered);
2519    /// println!("Recovered:\t{:#034X} {:#034X} {:#034X}", recovered[0], recovered[1], recovered[2]);
2520    /// assert_eq!(recovered[0], 0x1234567890ABCDEF1234567890ABCDEF_u128);
2521    /// assert_eq!(recovered[1], 0x11223344556677889900AABBCCDDEEFF_u128);
2522    /// assert_eq!(recovered[2], 0xFFEEDDCCBBAA00998877665544332211_u128);
2523    /// assert_eq!(recovered[0], plaintext[0]);
2524    /// assert_eq!(recovered[1], plaintext[1]);
2525    /// assert_eq!(recovered[2], plaintext[2]);
2526    /// ```
2527    ///
2528    /// # For more examples,
2529    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.decrypt_array_u128)
2530    pub fn decrypt_array_u128<const N: usize>(&mut self, cipher: &[u128; N], message: &mut [u128; N])
2531    {
2532        for i in 0..N
2533        {
2534            self.set_block_u128(cipher[i]);
2535            self.decrypt_block();
2536            message[i] = self.get_block_u128();
2537        }
2538    }
2539
2540    // pub fn decrypt_array_u64<const N: usize>(&mut self, cipher: &[u64; N], message: &mut [u64; N])
2541    /// Decrypts an array of 64-bit data.
2542    ///
2543    /// # Arguments
2544    /// - `cipher` is of an array of `u64`-type and the ciphertext
2545    ///   to be decrypted.
2546    /// - `message` is of an array of `u64`-type and the plaintext
2547    ///   to be stored.
2548    ///
2549    /// # Features
2550    /// This method encrypts multiple of 64-bit data without padding anything
2551    /// in ECB (Electronic CodeBook) mode.
2552    /// 
2553    /// # Caution
2554    /// - This method is meaningful only when `NB` is `2`. 
2555    /// - If `NB` is other than `2`, this method may panic.
2556    /// - Even if this method does not panic, its behaviour is not defined.
2557    /// 
2558    /// # Counterpart Methods
2559    /// For each trait
2560    /// [`ECB_PKCS7`](symmetric/trait.ECB_PKCS7.html#trait.ECB_PKCS7),
2561    /// [`ECB_ISO`](symmetric/trait.ECB_ISO.html#trait.ECB_ISO),
2562    /// [`CBC_PKCS7`](symmetric/trait.CBC_PKCS7.html#trait.ECB_PKCS7),
2563    /// [`CBC_ISO`](symmetric/trait.CBC_ISO.html#trait.CBC_ISO),
2564    /// [`PCBC_PKCS7`](symmetric/trait.PCBC_PKCS7.html#trait.PCBC_PKCS7),
2565    /// [`PCBC_ISO`](symmetric/trait.PCBC_ISO.html#trait.PCBC_ISO).
2566    /// [`CFB`](symmetric/trait.CFB.html#trait.CFB),
2567    /// [`OFB`](symmetric/trait.OFB.html#trait.OFB), and
2568    /// [`CTR`](symmetric/trait.CTR.html#trait.CTR),
2569    /// there are provided useful counterpart methods:
2570    /// decrypt(), decrypt_into_vec(), decrypt_into_array(),
2571    /// decrypt_into_string(),
2572    /// decrypt_vec(), decrypt_vec_into_vec(), decrypt_vec_into_array(),
2573    /// decrypt_vec_into_string(),
2574    /// decrypt_array(), decrypt_array_into_vec(), decrypt_array_into_array(),
2575    /// and decrypt_array_into_string().
2576    /// 
2577    /// # Example 1 for Rijndael_64_64
2578    /// ```
2579    /// use cryptocol::symmetric::Rijndael_64_64;
2580    /// 
2581    /// let mut rijndael = Rijndael_64_64::new_with_key(&[0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF]);
2582    /// let plaintext = [0x1234567890ABCDEF_u64, 0x1122334455667788, 0xFFEEDDCCBBAA0099];
2583    /// println!("Plaintext:\t{:#018X} {:#018X} {:#018X}", plaintext[0], plaintext[1], plaintext[2]);
2584    /// let mut ciphertext = [0_u64; 3];
2585    /// rijndael.encrypt_array_u64(&plaintext, &mut ciphertext);
2586    /// println!("Ciphertext:\t{:#018X} {:#018X} {:#018X}", ciphertext[0], ciphertext[1], ciphertext[2]);
2587    /// assert_eq!(ciphertext[0], 0x4FAA3F0E49CC4DCF_u64);
2588    /// assert_eq!(ciphertext[1], 0x036AAEDC0F1A5BEC_u64);
2589    /// assert_eq!(ciphertext[2], 0x99B8209339BCC1EB_u64);
2590    /// 
2591    /// let mut recovered = [0_u64; 3];
2592    /// rijndael.decrypt_array_u64(&ciphertext, &mut recovered);
2593    /// println!("Recovered:\t{:#018X} {:#018X} {:#018X}", recovered[0], recovered[1], recovered[2]);
2594    /// assert_eq!(recovered[0], 0x1234567890ABCDEF_u64);
2595    /// assert_eq!(recovered[1], 0x1122334455667788_u64);
2596    /// assert_eq!(recovered[2], 0xFFEEDDCCBBAA0099_u64);
2597    /// assert_eq!(recovered[0], plaintext[0]);
2598    /// assert_eq!(recovered[1], plaintext[1]);
2599    /// assert_eq!(recovered[2], plaintext[2]);
2600    /// ```
2601    ///
2602    /// # For more examples,
2603    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.decrypt_array_u64)
2604    pub fn decrypt_array_u64<const N: usize>(&mut self, cipher: &[u64; N], message: &mut [u64; N])
2605    {
2606        for i in 0..N
2607        {
2608            self.set_block_u64(cipher[i]);
2609            self.decrypt_block();
2610            message[i] = self.get_block_u64();
2611        }
2612    }
2613
2614    // pub fn decrypt_array_u32<const N: usize>(&mut self, cipher: &[u32; N], message: &mut [u32; N])
2615    /// Decrypts an array of 32-bit data.
2616    ///
2617    /// # Arguments
2618    /// - `cipher` is of an array of `u32`-type and the ciphertext
2619    ///   to be decrypted.
2620    /// - `message` is of an array of `u32`-type and the plaintext
2621    ///   to be stored.
2622    ///
2623    /// # Features
2624    /// This method encrypts multiple of 32-bit data without padding anything
2625    /// in ECB (Electronic CodeBook) mode.
2626    /// 
2627    /// # Caution
2628    /// - This method is meaningful only when `NB` is `1`. 
2629    /// - If `NB` is other than `1`, this method may panic.
2630    /// - Even if this method does not panic, its behaviour is not defined.
2631    /// 
2632    /// # Counterpart Methods
2633    /// For each trait
2634    /// [`ECB_PKCS7`](symmetric/trait.ECB_PKCS7.html#trait.ECB_PKCS7),
2635    /// [`ECB_ISO`](symmetric/trait.ECB_ISO.html#trait.ECB_ISO),
2636    /// [`CBC_PKCS7`](symmetric/trait.CBC_PKCS7.html#trait.ECB_PKCS7),
2637    /// [`CBC_ISO`](symmetric/trait.CBC_ISO.html#trait.CBC_ISO),
2638    /// [`PCBC_PKCS7`](symmetric/trait.PCBC_PKCS7.html#trait.PCBC_PKCS7),
2639    /// [`PCBC_ISO`](symmetric/trait.PCBC_ISO.html#trait.PCBC_ISO).
2640    /// [`CFB`](symmetric/trait.CFB.html#trait.CFB),
2641    /// [`OFB`](symmetric/trait.OFB.html#trait.OFB), and
2642    /// [`CTR`](symmetric/trait.CTR.html#trait.CTR),
2643    /// there are provided useful counterpart methods:
2644    /// decrypt(), decrypt_into_vec(), decrypt_into_array(),
2645    /// decrypt_into_string(),
2646    /// decrypt_vec(), decrypt_vec_into_vec(), decrypt_vec_into_array(),
2647    /// decrypt_vec_into_string(),
2648    /// decrypt_array(), decrypt_array_into_vec(), decrypt_array_into_array(),
2649    /// and decrypt_array_into_string().
2650    /// 
2651    /// # Example 1 for Rijndael_32_32
2652    /// ```
2653    /// use cryptocol::symmetric::Rijndael_32_32;
2654    /// 
2655    /// let mut rijndael = Rijndael_32_32::new_with_key(&[0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF]);
2656    /// let plaintext = [0x12345678_u32, 0x90ABCDEF, 0xFFEEDDCC];
2657    /// println!("Plaintext:\t{:#010X} {:#010X} {:#010X}", plaintext[0], plaintext[1], plaintext[2]);
2658    /// let mut ciphertext = [0_u32; 3];
2659    /// rijndael.encrypt_array_u32(&plaintext, &mut ciphertext);
2660    /// println!("Ciphertext:\t{:#010X} {:#010X} {:#010X}", ciphertext[0], ciphertext[1], ciphertext[2]);
2661    /// assert_eq!(ciphertext[0], 0x335228F6_u32);
2662    /// assert_eq!(ciphertext[1], 0xBFB99AFB_u32);
2663    /// assert_eq!(ciphertext[2], 0x2D114838_u32);
2664    /// 
2665    /// let mut recovered = [0_u32; 3];
2666    /// rijndael.decrypt_array_u32(&ciphertext, &mut recovered);
2667    /// println!("Recovered:\t{:#010X} {:#010X} {:#010X}", recovered[0], recovered[1], recovered[2]);
2668    /// assert_eq!(recovered[0], 0x12345678_u32);
2669    /// assert_eq!(recovered[1], 0x90ABCDEF_u32);
2670    /// assert_eq!(recovered[2], 0xFFEEDDCC_u32);
2671    /// assert_eq!(recovered[0], plaintext[0]);
2672    /// assert_eq!(recovered[1], plaintext[1]);
2673    /// assert_eq!(recovered[2], plaintext[2]);
2674    /// ```
2675    ///
2676    /// # For more examples,
2677    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.decrypt_array_u32)
2678    pub fn decrypt_array_u32<const N: usize>(&mut self, cipher: &[u32; N], message: &mut [u32; N])
2679    {
2680        for i in 0..N
2681        {
2682            self.set_block_u32(cipher[i]);
2683            self.decrypt_block();
2684            message[i] = self.get_block_u32();
2685        }
2686    }
2687
2688    // pub fn is_succeful(&self) -> bool
2689    /// Checks whether the previous encryption or decryption was successful.
2690    ///
2691    /// # Output
2692    /// If the previous encryption or decryption was successful, this method
2693    /// returns true. Otherwise, it returns false.
2694    ///
2695    /// # Features
2696    /// - Usually, you don't have to use this method because the encryption
2697    ///   methods returns the length of ciphertext and the decryption methods
2698    ///   returns the length of plaintext but they returns `0` when they failed.
2699    /// - If the ciphertext is 8 bytes for decryption with the padding either
2700    ///   pkcs7 or iso, the return value `0` of the decryption methods is not
2701    ///   discriminatory. You don't know whether the previous decryption was
2702    ///   failed or the original plaintext was just null string or "". In this
2703    ///   case you can check its success with this method.
2704    ///
2705    /// # Example 1 for the message of 0 bytes
2706    /// ```
2707    /// use std::io::Write;
2708    /// use std::fmt::Write as _;
2709    /// use cryptocol::symmetric::{ AES_128, ECB_PKCS7 };
2710    /// 
2711    /// let key = 0xEFCDAB9078563412EFCDAB9078563412_u128;
2712    /// println!("K =\t{:#034X}", key);
2713    /// let mut a_aes = AES_128::new_with_key_u128(key);
2714    /// let message = "";
2715    /// println!("M =\t{}", message);
2716    /// let mut cipher = [0_u8; 16];
2717    /// let len = a_aes.encrypt_into_array(message.as_ptr(), message.len() as u64, &mut cipher);
2718    /// println!("The length of ciphertext = {}", len);
2719    /// assert_eq!(len, 16);
2720    /// let success = a_aes.is_successful();
2721    /// assert_eq!(success, true);
2722    /// print!("C =\t");
2723    /// for c in cipher.clone()
2724    ///     { print!("{:02X} ", c); }
2725    /// println!();
2726    /// let mut txt = String::new();
2727    /// for c in cipher.clone()
2728    ///     { write!(txt, "{:02X} ", c); }
2729    /// assert_eq!(txt, "26 F2 F8 B7 B7 FD 46 9A 97 97 F3 24 E7 51 99 47 ");
2730    /// ```
2731    ///
2732    /// # For more examples,
2733    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.is_successful)
2734    #[inline]
2735    pub fn is_successful(&self) -> bool
2736    {
2737        self.block[0][0] == Self::SUCCESS
2738    }
2739
2740    // pub fn is_failed(&self) -> bool
2741    /// Checks whether the previous encryption or decryption was failed.
2742    ///
2743    /// # Output
2744    /// If the previous encryption or decryption was failed, this method
2745    /// returns true. Otherwise, it returns false.
2746    ///
2747    /// # Features
2748    /// - Usually, you don't have to use this method because the encryption
2749    ///   methods returns the length of ciphertext and the decryption methods
2750    ///   returns the length of plaintext but they returns `0` when they failed.
2751    /// - If the ciphertext is 8 bytes for decryption with the padding either
2752    ///   pkcs7 or iso, the return value `0` of the decryption methods is not
2753    ///   discriminatory. You don't know whether the previous decryption was
2754    ///   failed or the original plaintext was just null string or "". In this
2755    ///   case you can check its success with this method.
2756    ///
2757    /// # Example 1 for the message of 0 bytes
2758    /// ```
2759    /// use std::io::Write;
2760    /// use std::fmt::Write as _;
2761    /// use cryptocol::symmetric::{ AES_128, ECB_PKCS7 };
2762    /// 
2763    /// let key = 0xEFCDAB9078563412EFCDAB9078563412_u128;
2764    /// println!("K =\t{:#034X}", key);
2765    /// let mut a_aes = AES_128::new_with_key_u128(key);
2766    /// let message = "";
2767    /// println!("M =\t{}", message);
2768    /// let mut cipher = [0_u8; 16];
2769    /// let len = a_aes.encrypt_into_array(message.as_ptr(), message.len() as u64, &mut cipher);
2770    /// println!("The length of ciphertext = {}", len);
2771    /// assert_eq!(len, 16);
2772    /// let failure = a_aes.is_failed();
2773    /// assert_eq!(failure, false);
2774    /// print!("C =\t");
2775    /// for c in cipher.clone()
2776    ///     { print!("{:02X} ", c); }
2777    /// println!();
2778    /// let mut txt = String::new();
2779    /// for c in cipher.clone()
2780    ///     { write!(txt, "{:02X} ", c); }
2781    /// assert_eq!(txt, "26 F2 F8 B7 B7 FD 46 9A 97 97 F3 24 E7 51 99 47 ");
2782    /// ```
2783    ///
2784    /// # For more examples,
2785    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.is_failed)
2786    #[inline]
2787    pub fn is_failed(&self) -> bool
2788    {
2789        self.block[0][0] == Self::FAILURE
2790    }
2791
2792    // pub(super) fn set_successful(&mut self)
2793    /// Sets the flag to mean that the previous encryption or decryption
2794    /// was successful.
2795    ///
2796    /// # Features
2797    /// You won't use this method unless you write codes for implementation
2798    /// of a trait for BigCryptor128.
2799    #[inline]
2800    pub(super) fn set_successful(&mut self)
2801    {
2802        self.block[0][0] = Self::SUCCESS;
2803    }
2804
2805    // pub(super) fn set_failed(&mut self)
2806    /// Sets the flag to mean that the previous encryption or decryption
2807    /// was failed.
2808    ///
2809    /// # Features
2810    /// You won't use this method unless you write codes for implementation
2811    /// of a trait for BigCryptor64 or NDES.
2812    #[inline]
2813    pub(super) fn set_failed(&mut self)
2814    {
2815        self.block[0][0] = Self::FAILURE;
2816    }
2817
2818    // pub fn get_desirable_round() -> usize
2819    /// Returns the desirable number of rounds
2820    /// according to the Rijndael documents
2821    /// 
2822    /// # Example 1 for AES_128
2823    /// ```
2824    /// use cryptocol::symmetric::AES_128;
2825    /// let rounds = AES_128::get_desirable_round();
2826    /// println!("The desirable number of rounds of AES_128 is {}", rounds);
2827    /// assert_eq!(rounds, 10);
2828    /// ```
2829    ///
2830    /// # For more examples,
2831    /// click [here](./documentation/rijndael_basic/struct.Rijndael_Generic.html#method.get_desirable_round)
2832    #[inline]
2833    pub fn get_desirable_round() -> usize
2834    {
2835        6 + if NB > NK { NB } else { NK }
2836    }
2837
2838    fn encrypt_block(&mut self)
2839    {
2840        self.add_round_key(0);
2841        for round in 1..ROUND
2842        {
2843            self.sub_bytes();
2844            Self::method_shift_rows(self);
2845            Self::method_mix_columns(self);
2846            self.add_round_key(round);
2847        }
2848        self.sub_bytes();
2849        Self::method_shift_rows(self);
2850        self.add_round_key(ROUND);
2851    }
2852
2853    fn sub_bytes(&mut self)
2854    {
2855        for i in 0..4
2856        {
2857            for j in 0..NB
2858            {
2859                self.block[i][j] = Self::SBOX[self.block[i][j] as usize];
2860            }
2861        }
2862    }
2863
2864    fn optimal_shift_rows(&mut self)
2865    {
2866        let mut tmp = [0_u8; 3];
2867        let tmp_ptr = tmp.as_mut_ptr();
2868        for i in 1..4
2869        {
2870            unsafe {
2871                let j = i % NB;
2872                let ptr_block_0 = self.block[i].as_mut_ptr();
2873                let ptr_block_i = self.block[i].as_ptr().add(j);
2874                let ptr_block_nb_i = self.block[i].as_mut_ptr().add(NB - j);
2875                copy_nonoverlapping(ptr_block_0, tmp_ptr, j);
2876                copy(ptr_block_i, ptr_block_0, NB - j);
2877                copy_nonoverlapping(tmp_ptr, ptr_block_nb_i, j);
2878            }
2879        }
2880    }
2881
2882    fn shift_rows(&mut self)
2883    {
2884        let mut tmp = [0_u8; NB];
2885        let tmp_ptr = tmp.as_mut_ptr();
2886        for i in 0..4
2887        {
2888            unsafe {
2889                let j = Self::SR[i] % NB;
2890                let ptr_block_0 = self.block[i].as_mut_ptr();
2891                let ptr_block_i = self.block[i].as_ptr().add(j);
2892                let ptr_block_nb_i = self.block[i].as_mut_ptr().add(NB - j);
2893                copy_nonoverlapping(ptr_block_0, tmp_ptr, j);
2894                copy(ptr_block_i, ptr_block_0, NB - j);
2895                copy_nonoverlapping(tmp_ptr, ptr_block_nb_i, j);
2896            }
2897        }
2898    }
2899
2900    fn optimal_mix_columns(&mut self)
2901    {
2902        let mut new_block = [[0_u8; NB]; 4];
2903        for col in 0..NB
2904        {
2905            new_block[0][col] = GF_mul!(2, self.block[0][col]) ^ GF_mul!(3, self.block[1][col])
2906                                ^ self.block[2][col] ^ self.block[3][col];
2907            new_block[1][col] = self.block[0][col] ^ GF_mul!(2, self.block[1][col])
2908                                ^ GF_mul!(3, self.block[2][col]) ^ self.block[3][col];
2909            new_block[2][col] = self.block[0][col] ^ self.block[1][col]
2910                                ^ GF_mul!(2, self.block[2][col]) ^ GF_mul!(3, self.block[3][col]);
2911            new_block[3][col] = GF_mul!(3, self.block[0][col]) ^ self.block[1][col]
2912                                ^ self.block[2][col] ^ GF_mul!(2, self.block[3][col]);
2913        }
2914        self.block = new_block;
2915    }
2916
2917    fn mix_columns(&mut self)
2918    {
2919        let mut new_block = [[0_u8; NB]; 4];
2920        for row in 0..4
2921        {
2922            for col in 0..NB
2923            {
2924                for i in 0..4
2925                {
2926                    new_block[row][col] ^= GF_mul!(Self::MC[row][i], self.block[i][col]);
2927                }
2928            }
2929        }
2930        self.block = new_block;
2931    }
2932
2933    fn add_round_key(&mut self, round: usize)
2934    {
2935        for i in 0..4
2936        {
2937            for j in 0..NB
2938            {
2939                self.block[i][j] ^= self.round_key[round][j].get_ubyte_(i);
2940            }
2941        }
2942    }
2943
2944    fn decrypt_block(&mut self)
2945    {
2946        self.add_round_key(ROUND);
2947        let mut round = ROUND-1;
2948        while round > 0
2949        {
2950            Self::method_inv_shift_rows(self);
2951            self.inv_sub_bytes();
2952            self.add_round_key(round);
2953            self.inv_mix_columns();
2954            round -= 1;
2955        }
2956        Self::method_inv_shift_rows(self);
2957        self.inv_sub_bytes();
2958        self.add_round_key(round);
2959    }
2960
2961    fn inv_sub_bytes(&mut self)
2962    {
2963        for i in 0..4
2964        {
2965            for j in 0..NB
2966            {
2967                self.block[i][j] = Self::INV_SBOX[self.block[i][j] as usize];
2968            }
2969        }
2970    }
2971
2972    fn optimal_inv_shift_rows(&mut self)
2973    {
2974        let mut tmp = [0_u8; 3];
2975        let tmp_ptr = tmp.as_mut_ptr();
2976        for i in 1..4
2977        {
2978            unsafe {
2979                let j = i % NB;
2980                let ptr_block_0 = self.block[i].as_mut_ptr();
2981                let ptr_block_i = self.block[i].as_mut_ptr().add(j);
2982                let ptr_block_nb_i = self.block[i].as_ptr().add(NB - j);
2983                copy_nonoverlapping(ptr_block_nb_i, tmp_ptr, j);
2984                copy(ptr_block_0, ptr_block_i, NB - j);
2985                copy_nonoverlapping(tmp_ptr, ptr_block_0, j);
2986            }
2987        }
2988    }
2989
2990    fn inv_shift_rows(&mut self)
2991    {
2992        let mut tmp = [0_u8; NB];
2993        let tmp_ptr = tmp.as_mut_ptr();
2994        for i in 0..4
2995        {
2996            unsafe {
2997                let j = Self::SR[i] % NB;
2998                let ptr_block_0 = self.block[i].as_mut_ptr();
2999                let ptr_block_i = self.block[i].as_mut_ptr().add(j);
3000                let ptr_block_nb_i = self.block[i].as_ptr().add(NB - j);
3001                copy_nonoverlapping(ptr_block_nb_i, tmp_ptr, j);
3002                copy(ptr_block_0, ptr_block_i, NB - j);
3003                copy_nonoverlapping(tmp_ptr, ptr_block_0, j);
3004            }
3005        }
3006    }
3007
3008    fn inv_mix_columns(&mut self)
3009    {
3010        let mut new_block = [[0_u8; NB]; 4];
3011        for row in 0..4
3012        {
3013            for col in 0..NB
3014            {
3015                for i in 0..4
3016                {
3017                    new_block[row][col] ^= GF_mul!(Self::INV_MC[row][i], self.block[i][col]);
3018                }
3019            }
3020        }
3021        self.block = new_block;
3022    }
3023
3024    fn make_round_keys_nk_up_to_6_and_nk_equal_to_nb(&mut self)
3025    {
3026        self.set_zeroth_round_key();
3027        for round in 1..=ROUND
3028        {
3029            let mut tmp = self.round_key[round-1][NB-1];
3030            #[cfg(target_endian = "little")] { tmp = tmp.rotate_right(8 * ROT); }
3031            #[cfg(target_endian = "big")] { tmp = tmp.rotate_left(8 * ROT); }
3032            for j in 0..4
3033                { tmp.set_ubyte_(j, Self::SBOX[tmp.get_ubyte_(j) as usize]); }
3034            tmp.set(tmp.get() ^ Self::RC[round-1]);
3035            self.round_key[round][0] = tmp ^ self.round_key[round-1][0];
3036            for i in 1..NB
3037                { self.round_key[round][i] = self.round_key[round][i-1] ^ self.round_key[round-1][i]; }
3038        }
3039    }
3040
3041    fn make_round_keys_nk_greater_than_6_and_nk_equal_to_nb(&mut self)
3042    {
3043        self.set_zeroth_round_key();
3044        for round in 1..=ROUND
3045        {
3046            let mut tmp = self.round_key[round-1][NB-1];
3047            #[cfg(target_endian = "little")] { tmp = tmp.rotate_right(8 * ROT); }
3048            #[cfg(target_endian = "big")] { tmp = tmp.rotate_left(8 * ROT); }
3049            for j in 0..4
3050                { tmp.set_ubyte_(j, Self::SBOX[tmp.get_ubyte_(j) as usize]); }
3051            tmp.set(tmp.get() ^ Self::RC[round-1]);
3052            self.round_key[round][0] = tmp ^ self.round_key[round-1][0];
3053            for i in 1..3
3054                { self.round_key[round][0] = self.round_key[round][i-1] ^ self.round_key[round-1][i]; }
3055            tmp = self.round_key[round][3];
3056            for j in 0..4
3057                { tmp.set_ubyte_(j, Self::SBOX[tmp.get_ubyte_(j) as usize]); }
3058            self.round_key[round][4] = tmp ^ self.round_key[round-1][4];
3059            for i in 5..NB
3060                { self.round_key[round][i] = self.round_key[round][i-1] ^ self.round_key[round-1][i]; }
3061        }
3062    }
3063
3064    fn make_round_keys_nk_up_to_6_and_nk_diff_from_nb(&mut self)
3065    {
3066        self.set_zeroth_round_key();
3067        let mut round = NK / NB;
3068        let mut cc = NK % NB;
3069        let mut idx = NK;
3070        let mut rc_round = 0;
3071        while (round <= ROUND) && (rc_round < ROUND)
3072        {
3073            let mut tmp = if cc == 0 { self.round_key[round-1][NB-1] } else { self.round_key[round][cc-1] };
3074            if idx % NK == 0
3075            {
3076                #[cfg(target_endian = "little")] { tmp = tmp.rotate_right(8 * ROT); }
3077                #[cfg(target_endian = "big")] { tmp = tmp.rotate_left(8 * ROT); }
3078                for j in 0..4
3079                    { tmp.set_ubyte_(j, Self::SBOX[tmp.get_ubyte_(j) as usize]); }
3080                tmp.set(tmp.get() ^ Self::RC[rc_round]);
3081                rc_round += 1;
3082            }
3083            if cc < NK
3084            {
3085                let rrr = (idx - NK) / NB;
3086                let ccc = (idx - NK) % NB;
3087                self.round_key[round][cc] = tmp ^ self.round_key[rrr][ccc];
3088            }
3089            else
3090            {
3091                self.round_key[round][cc] = tmp ^ self.round_key[round][cc-NK];
3092            }
3093            if cc == NB - 1
3094            {
3095                cc = 0;
3096                round += 1;
3097            }
3098            else
3099            {
3100                cc += 1;
3101            }
3102            idx += 1;
3103        }
3104    }
3105
3106    fn make_round_keys_nk_greater_than_6_and_nk_diff_from_nb(&mut self)
3107    {
3108        self.set_zeroth_round_key();
3109        let mut round = NK / NB;
3110        let mut cc = NK % NB;
3111        let mut idx = NK;
3112        let mut rc_round = 0;
3113        while (round <= ROUND) && (rc_round < ROUND)
3114        {
3115            let mut tmp = if cc == 0 { self.round_key[round-1][NB-1] } else { self.round_key[round][cc-1] };
3116            if idx % NK == 0
3117            {
3118                #[cfg(target_endian = "little")] { tmp = tmp.rotate_right(8 * ROT); }
3119                #[cfg(target_endian = "big")] { tmp = tmp.rotate_left(8 * ROT); }
3120                for j in 0..4
3121                    { tmp.set_ubyte_(j, Self::SBOX[tmp.get_ubyte_(j) as usize]); }
3122                tmp.set(tmp.get() ^ Self::RC[rc_round]);
3123                rc_round += 1;
3124            }
3125            else if idx % NK == 4
3126            {
3127                let rrr = (idx - NK) / NB;
3128                let ccc = (idx - NK) % NB;
3129                for j in 0..4
3130                    { tmp.set_ubyte_(j, Self::SBOX[tmp.get_ubyte_(j) as usize]); }
3131                self.round_key[round][cc] = tmp ^ self.round_key[rrr][ccc];
3132            }
3133            if cc < NK
3134            {
3135                let rrr = (idx - NK) / NB;
3136                let ccc = (idx - NK) % NB;
3137                self.round_key[round][cc] = tmp ^ self.round_key[rrr][ccc];
3138            }
3139            else
3140            {
3141                self.round_key[round][cc] = tmp ^ self.round_key[round][cc-NK];
3142            }
3143            if cc < NB - 1
3144            {
3145                cc += 1;
3146            }
3147            else
3148            {
3149                cc = 0;
3150                round += 1;
3151            }
3152            idx += 1;
3153        }
3154    }
3155
3156    #[inline]
3157    fn set_zeroth_round_key(&mut self)
3158    {
3159        unsafe {
3160            copy_nonoverlapping(self.key.as_ptr() as *const u8,
3161                                self.round_key.as_mut_ptr() as *mut u8, NK * 4);
3162        }
3163    }
3164
3165    fn get_block(&self) -> [IntUnion; NB]
3166    {
3167        let mut block = [IntUnion::new(); NB];
3168        for j in 0..NB
3169        {
3170            for i in 0..4
3171            {
3172                block[j].set_ubyte_(i, self.block[i][j]);
3173            }
3174        }
3175        block
3176    }
3177
3178    fn get_block_u128(&self) -> u128
3179    {
3180        let nb = if 4 < NB {4} else {NB};
3181        let mut block = LongerUnion::new();
3182        let mut idx = 0;
3183        for j in 0..nb
3184        {
3185            for i in 0..4
3186            {
3187                block.set_ubyte_(idx, self.block[i][j]);
3188                idx += 1;
3189            }
3190        }
3191        block.get()
3192    }
3193
3194    fn get_block_u64(&self) -> u64
3195    {
3196        let nb = if 2 < NB {2} else {NB};
3197        let mut block = LongUnion::new();
3198        let mut idx = 0;
3199        for j in 0..nb
3200        {
3201            for i in 0..4
3202            {
3203                block.set_ubyte_(idx, self.block[i][j]);
3204                idx += 1;
3205            }
3206        }
3207        block.get()
3208    }
3209
3210    fn get_block_u32(&self) -> u32
3211    {
3212        let mut block = IntUnion::new();
3213        let mut idx = 0;
3214        for i in 0..4
3215        {
3216            block.set_ubyte_(idx, self.block[i][0]);
3217            idx += 1;
3218        }
3219        block.get()
3220    }
3221
3222    fn set_block(&mut self, block: &[IntUnion; NB])
3223    {
3224        for j in 0..NB
3225        {
3226            for i in 0..4
3227            {
3228                self.block[i][j] = block[j].get_ubyte_(i);
3229            }
3230        }
3231    }
3232
3233    fn set_block_u128(&mut self, block: u128)
3234    {
3235        let nb = if 4 < NB {4} else {NB};
3236        let block_union = LongerUnion::new_with(block);
3237        let mut idx = 0;
3238        for j in 0..nb
3239        {
3240            for i in 0..4
3241            {
3242                self.block[i][j] = block_union.get_ubyte_(idx);
3243                idx += 1;
3244            }
3245        }
3246    }
3247
3248    fn set_block_u64(&mut self, block: u64)
3249    {
3250        let nb = if 2 < NB {2} else {NB};
3251        let block_union = LongUnion::new_with(block);
3252        let mut idx = 0;
3253        for j in 0..nb
3254        {
3255            for i in 0..4
3256            {
3257                self.block[i][j] = block_union.get_ubyte_(idx);
3258                idx += 1;
3259            }
3260        }
3261    }
3262
3263    fn set_block_u32(&mut self, block: u32)
3264    {
3265        let block_union = IntUnion::new_with(block);
3266        let mut idx = 0;
3267        for i in 0..4
3268        {
3269            self.block[i][0] = block_union.get_ubyte_(idx);
3270            idx += 1;
3271        }
3272    }
3273
3274    // fn GF_mul(mut a: u8, mut b: u8, m: u8) -> u8
3275    // {
3276    //     let mut ret = 0_u8;
3277    //     while b != 0
3278    //     {
3279    //         if b & 1 == 1
3280    //             { ret ^= a; }
3281    //         if a & 0b1000_0000 != 0
3282    //             { a = (a << 1) ^ m; }
3283    //         else
3284    //             { a <<= 1; }
3285    //         b >>= 1;
3286    //     }
3287    //     ret
3288    // }
3289
3290
3291    /////// Testing Codes during Development //////
3292    // #[allow(non_snake_case)]
3293    // pub fn show_SBox()
3294    // {
3295    //     for i in 0..256
3296    //         { println!("{:02X} => {:02X}", i, Self::SBOX[i]); }
3297    // }
3298
3299    // #[allow(non_snake_case)]
3300    // pub fn show_InvSBox()
3301    // {
3302    //     for i in 0..256
3303    //         { println!("{:02X} => {:02X}", i, Self::INV_SBOX[i]); }
3304    // }
3305
3306    // #[allow(non_snake_case)]
3307    // pub fn show_MC()
3308    // {
3309    //     println!("MC is as follows:");
3310    //     for i in 0..4
3311    //     {
3312    //         for j in 0..4
3313    //             { print!("{:02x} ", Self::MC[i][j]); }
3314    //         println!();
3315    //     }
3316    // }
3317
3318    // #[allow(non_snake_case)]
3319    // pub fn show_InvMC()
3320    // {
3321    //     println!("Inverse MC is as follows:");
3322    //     for i in 0..4
3323    //     {
3324    //         for j in 0..4
3325    //             { print!("{:02x} ", Self::INV_MC[i][j]); }
3326    //         println!();
3327    //     }
3328    // }
3329
3330    // #[allow(non_snake_case)]
3331    // pub fn show_RC()
3332    // {
3333    //     for i in 0..ROUND
3334    //         { println!("{:02} => {:02X}", i, Self::RC[i]); }
3335    // }
3336}