Mirror

Bravion - Strong Encryption Algorithm (Views: 101)


Problem/Question/Abstract:

Is there more to encryption than XORing output from Random(256) with a chars from a string? Yes there's allot more to it.

Answer:

ABOUT

The name Bravion is pronnounced brave-ion. It is an alegory for molecules undergoing chemical reactions. A molecule is separeted into its ions, which then regroup with ions from a reactant to form new ions. In this algorithm, the ions change properties as well: protons, neutrons and electrons are reconfigured by the reactant and make the resulting molecules unpredictable without knowing the original reactant. Indeed it takes a brave ion to undergo such abuse :)

The routines here aren't very straight forward, even for one who has studied ciphers. I will try to keep it in lamens terms to the best of my ability. Bravion uses a 256bit key and a 128bit block size. It is an iterated (multiple rounds) substitution/permutation network. It is fast, but not nearly the fastest I've seen. I encrypt around 3MB/sec on my system.

GLOSSARY - read carefully

block size:
Size in bits of the data to encrypt (fixed in all block ciphers)

plaintext:
Data that has not yet been encrypted.

ciphertext:
Data that has been encrypted.

key:
Data used to modify plaintext into an incomprehensible sate.

entropy:
Unpredicatble data.

permutation:
Transformation of data by displacements (of individual or grouped bits) or transformation of data by mathematical    functions. Dependent permutations require another source of data, and once permutated, both data are required to    reverse the permutation.

dependency:
Data required to inverse a permutation.

key size:
Size in bits of the data used as a key (this can be  variable in *some* ciphers, but is limited to the dependency imposed by the block size)

xor:
Bitwise exclusive OR. xor has an important property:  if A xor B = C, then C xor A = B, C xor B = A  xor works wonders for permutations.

mul:
Multiplication modulo 2^32 where a factor of 0 is  interpreted as 2^32+1.

add:
Addition modulo 2^32.

sub:
Subtraction modulo 2^32.

shr:
Bit-shift to the right covering the ENTIRE block of data rather than individual integers.

shl:
Same as shr, but the bit shift is to the left.

substitution:
Exchanging one group of bits for another. The result of a substitution depends on the bits that are being substituted.  This process is always reversable, using irreversable substitution to change data is considered  (by myself) a  permutation.

S-BOX:
An array of values that are used to replace on block of  data for another such as SBOX:array[0..255]of byte would    be used to replace a byte for another:

B: byte;
B := SBOX[B];

To reverse the process S-BOXs can be structured such that  SBOX[SBOX[B]]=B or (preferably) a compliment of the X-BOX  can be created such that SBOX_1[SBOX_0[B]]=B  An S-BOX's array must be of suitable size to accept any  input data as an index (for a byte: 0..255, for a word:  0..65535). S-BOXs are very efficient substitution
mechanisms.

feistel network:
Data is divided into 2 halfs, one half is permutated  (and/or substituted) and the second half is a product  (usualy an xor) of the permuted first half and  itself. To reverse the process the inverse of the  product is obtained for to restore the second half  (in the case of an xor, another xor does the trick)  and the first half is then restored with the inserve    of the permutation applied to it.

round:
An intteration of a set of functions. Almost all ciphers  implement rounds. Some use as little as 8, others use as    many as 32. A general rule of thumb is the more rounds,  the harder it is to break the cipher (unless the rounds    are very simple). The number of rounds is usualy a little  bigger than the minimum needed to maintain a safe cihper.  It is a compromise between security and speed.

round keys:
Data that contains entropy from the key used in sequencial  order determined by the current round.

component:
A group of operations (permutations, substitutions etc..)

attacker:
Someone trying to decrypt ciphertext without the key.

satistical analysis:
Using probability theory to aid in *guessing* possible  plaintext from ciphertext.

brute force:
Decrypting ciphertext with every possible key until the  plaintext is found. If an attacker is unable to break a  cipher, the only option is brute force (holding a gun to  whomever knows the key's head is not considered brute  force, it's considered social engineering)

ALGORITHM

The encryption process can be broken down into 5 components.

BEFORE ITTERATING THROUGH THE ROUNDS

[1]

B[0] := B[0] xor RK[PK[16], 0]; //PK holds the path keys
B[1] := B[1] xor RK[PK[17], 1]; //that determine the round
B[2] := B[2] xor RK[PK[18], 2]; //keys to use
B[3] := B[3] xor RK[PK[19], 3];

A key-dependent permutation by XOR with round keys. Which round keys are used depends on the original key. A set of  path keys is extrapolated from the key. Which round keys  are used is unknown to an attacker. This is done so that   in the event that portions of the round keys have been  recovered by an attacker, knowledge of the original key   is inherently required. The original key cannot be found by solving all the round keys due to the initialization     mechanism (discussed later). This is done to the plaintext before entering the first round and after finishing the  last round. This dissolves linearity of repetited components (even though there should be none, I have taken no chances with Bravion. I have not seen this sort of  permutation in any other algorithm, but I am confident that this component seriously impairs an attacker's chances at successful statistical analysis.

ROUND DESCRIPTION

This part is repeated 16 times.

[2]

CarryBit := (B[0] and 2147483648) shr 31;
B[0] := (B[0] shl 1) or ((B[1] and 2147483648) shr 31);
B[1] := (B[1] shl 1) or ((B[2] and 2147483648) shr 31);
B[2] := (B[2] shl 1) or ((B[3] and 2147483648) shr 31);
B[3] := (B[3] shl 1) or CarryBit;

the data put through a shl and the last bit of the block is put into the first bit. In most ciphers data is only re-ordered in bytes, word, or longwords, and this leads to statistical analysis of these groups of bits. Since each bit is shifted 1 bit, every byte/word/longword recieves 1 bit from the previous. After itterating through 16 rounds, each byte has been permuted with each bit twice. Their order does not change however, so the same statistical analysis can be accomplished. The solution to this problem lies in [4]. The reverse is a shr and the first bit of the block is put into the last bit.

[3]

B[3] := B[3] xor (B[2] - RK[i, 3]);
B[2] := B[2] xor Mul(B[1], RK[i, 2]);
B[1] := B[1] xor (B[0] + RK[i, 1]);
B[0] := B[0] xor RK[i, 0];

Taking out all the components designed to reinforce Bravion except [5], the heart of Bravion lies here. The Theory employed here lies in 3 algebraic [is that how it's spelt?] groups, add, mul, xor each having an etropy the same size as its inputs (in this case 32bits). Using a fixed parameter (the round key) and going through each possible value with the second parameter will never result in the same output with any of these 3 groups. The second important property of this component is that all but one longword of the block are dependent of the others. To solve B[1] you must solve B[0], to solve B[2] you have to have solved B[2] with B[0] and so on. Only B[0] is independent of the other longwords of the block. xor is used, because of the inefficiency (in speed) of calculating the inverses of these algebraic groups.

[4]

for i := 0 to 15 do
  T[i] := B[P0[PK[i], 0]]
    Move(T, B, 16);
//T,B:array[0..15]of byte    

This is what I called a re-ordering matrix. Things get a little akward in this component. Have a look at the square     matrix below:

P0: array[0..15, 0..15] of longword = (
  ($A, $3, $B, $C, $5, $E, $9, $F, $0, $7, $4, $6, $1, $D, $2, $8),
  ($9, $5, $F, $3, $1, $0, $A, $4, $7, $B, $E, $8, $2, $6, $D, $C),
  ($6, $D, $A, $4, $3, $5, $2, $8, $B, $F, $9, $C, $0, $E, $7, $1),
  ($E, $7, $0, $D, $8, $B, $1, $3, $9, $6, $C, $4, $A, $2, $F, $5),
  ($C, $A, $2, $5, $F, $D, $7, $9, $4, $E, $6, $B, $8, $3, $1, $0),
  ($5, $9, $3, $8, $D, $6, $4, $C, $1, $0, $7, $2, $E, $B, $A, $F),
  ($0, $6, $4, $A, $7, $3, $B, $E, $2, $8, $5, $1, $D, $F, $C, $9),
  ($D, $F, $9, $0, $6, $2, $3, $1, $E, $C, $A, $5, $B, $8, $4, $7),
  ($1, $0, $C, $2, $9, $7, $6, $D, $3, $5, $8, $E, $F, $A, $B, $4),
  ($3, $8, $5, $7, $2, $C, $E, $B, $A, $9, $D, $F, $4, $1, $0, $6),
  ($F, $B, $D, $1, $C, $8, $0, $6, $5, $2, $3, $7, $9, $4, $E, $A),
  ($8, $E, $1, $9, $4, $F, $C, $5, $6, $D, $2, $A, $7, $0, $3, $B),
  ($4, $C, $7, $6, $E, $1, $5, $2, $F, $A, $B, $0, $3, $9, $8, $D),
  ($7, $2, $6, $B, $0, $4, $D, $A, $8, $1, $F, $3, $5, $C, $9, $E),
  ($2, $1, $8, $E, $B, $A, $F, $7, $D, $4, $0, $9, $C, $5, $6, $3),
  ($B, $4, $E, $F, $A, $9, $8, $0, $C, $3, $1, $D, $6, $7, $5, $2));

Pay attention to the values in each rown and each column. In every row, values from 0 to 15 are assigned once, and in every column, values from 0 to 15 are assigned once. Each row represents an order to put the bytes of the block in. To demonstrate I will use the following block of plaintext:

B = 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31

Using the first row for this demonstration value can be assigned to a temporary block through indexing:

T[0] := B[P0[0]]; //T[0]:=B[$A];
T[1] := B[P0[1]]; //T[1]:=B[$3];
T[2] := B[P0[2]]; //T[2]:=B[$B];
{...and so on... }
T[15] := B[P0[15]]; //T[15]:=B[$8];

T = 26, 19, 27, 28, 21, 30, 25, 31, 16, 23, 20, 22, 17, 29, 18, 24
    
T now contains all bytes of B, but in the new order. T is then copied into B and B has been re-ordered. There are 16  rows in all. A path key determines which row to use, hence which order to put B in. To reverse the permutation I have created a re-ordering matrix that is the inverse of this one such that T[0]=B[P0[0]], B[0]=T[P1[0]. There are 16! (=~2.09x10^13=~2^44) ways to re-order 16 bytes. This subsitution occurs 16 times, and since no 2 rows will put     any byte in the same position (look at the columns), the number of possible orders is increased by a factor of 16     each time, for a total of 16^16. This means that we cover all the possible orders 4.2 million times in excess! This is only the theoretical boundary, the true boundary is  still 16!, but we at least know that the resulting ciphertext could be in ANY of these 16! arrangements. The re-ordering matrix by itself helps, but does not do much against statistical analysis because the bits are still in 8bit groups. Combined with the re-ordering matrix, the 1bit shift, scatters bits independently from each-other in 16! orders. I have read papers stating that idealy, blocks should be permuted as one block and not sub-blocks, but  that because of the data size required to achieve such a large permutation would be beyond the reach of our technology. To put things into context, an S-BOX of 8bits in 8bits out is 255bytes, 16bits-in 16bits-out is 131072bytes, 128bits-in 128bits-out would be 5.4x10^39bytes! Unfortunatly, this structure only allows for 2^44 different block-sized permutations, but it's still a great advantage.

[5]

for i := 0 to 15 B[i] := S0[B[i], j];
//B:array[0..15]of byte

This component substitutes each byte in B for another. There are 16 of these S-BOXs and an inversed S-BOX for     each. One S-BOX is used for each round. I've added these S-BOXs as a precaution. I used my random number generator NoiseSpunge (article name "Cryptographic Random Numbers") to generate completly random S-BOXs. The result is the outputs are drastic permutations on 8bit groups.

INITIALIZATION

Initialization is done in 3 steps.

[1]

The key is divided into 32 bit groups. Each group serves as as seed to a pseudo random number generator (PRNG). This PRNG has a period of 2^32 implying that no 2 seeds will generate the same sequence and that it will no show signs of a pattern before ~4billion numbers have been output. Each of the 8 seeds are used to generate 256bits which are stored as the round keys.

[2]

Path keys are extrapolated directly from the key by means of this function:

for i := 0 to 15 do //SET 4BIT PATH KEYS
begin
  PK[i] := (Key[i] xor Key[i + 16]) and $F;
  j := 16 + (i mod 8);
  PK[j] := PK[j] xor (Key[i] xor Key[i + 16]) and $F0) shr 4;
end; //Key is interpreted as array[0..31]of byte

[3]

The key is encrypted with the current round keys and the resulting ciphertext is used to replace 2 sets of round     keys. This is repeated until each set of round keys has been overwritten 128 times. This may seem like obsessive     paranoya, but that would be incorrect. This is a precaution against brute force. If initialization requires encrypting     256 blocks, then for every key an attacker wants to test  will take the a little longer than it takes to decrypt 256     blocks! Of course to the end user this doesn't even put a dent in his processor usage, but to an attacker trying to     test 2^256 keys, it will lengthen his search by a factor of 256. This is like adding 8bits of key data to his search. I haven't seen this form of initialization used as a brute force deterent before, but I'm certain I'm not the first to think about it.

I strongly recomend you read this article "256bit keys for strong encryption" as well use the unit included to produce the 256bit keys.

Below is the entire unit. Credit is as always well appreciated!

//BRAVION (C)Copyright DrMungkee 2001

unit Bravion;
interface

type
  TBravionBlock8 = array[0..15] of byte;
  TBravionBlock32 = array[0..3] of longword;
  TBravionKey8 = array[0..31] of byte;
  TBravionKey32 = array[0..7] of longword;
  TBravionRoundKey32 = array[0..15] of TBravionBlock32;
  TBravionPathKey8 = array[0..23] of longword;

  TBravionContext = record
    RK: TBravionRoundKey32;
    PK: TBravionPathKey8;
  end;

procedure BravionInit(var Context: TBravionContext; var Key: TBravionKey32);
procedure BravionDecrypt(var Context: TBravionContext; var B: TBravionBlock32);
procedure BravionEncrypt(var Context: TBravionContext; var B: TBravionBlock32);

implementation
const
  //SUBSTITUTION BOXES FOR EACH ROUND
  S0: array[0..15, 0..255] of longword = ((
    $68, $9D, $A8, $7C, $0D, $E1, $C1, $21, $BC, $97, $84, $A2, $DE, $EE, $45, $BD,
    $17, $D8, $32, $D5, $A7, $1A, $64, $23, $1B, $B8, $07, $A1, $3B, $6E, $DF, $8D,
    $24, $50, $F4, $73, $C4, $59, $B7, $38, $D3, $47, $10, $E7, $93, $DD, $0A, $3C,
    $36, $AA, $9A, $B1, $75, $8E, $5B, $9B, $49, $33, $C8, $A4, $1C, $06, $20, $46,
    $88, $FA, $FC, $CC, $2E, $AD, $05, $1D, $86, $EF, $04, $3F, $6D, $0F, $D2, $5C,
    $DB, $5F, $0C, $71, $E3, $87, $A3, $8F, $AC, $9E, $0B, $AB, $EA, $5E, $AF, $16,
    $44, $E6, $39, $FB, $2A, $43, $3A, $F9, $48, $7E, $11, $08, $4C, $CB, $ED, $8B,
    $95, $C0, $01, $29, $4E, $B6, $63, $5D, $A9, $52, $56, $C5, $BB, $12, $81, $91,
    $F7, $7F, $4F, $3E, $2C, $F1, $EB, $54, $B5, $00, $6C, $8A, $26, $FF, $1E, $CA,
    $83, $9F, $D7, $EC, $77, $85, $B3, $F2, $CF, $28, $6B, $BF, $02, $96, $B0, $27,
    $F8, $F6, $DC, $D6, $7B, $65, $78, $60, $70, $82, $B9, $98, $BA, $62, $30, $61,
    $19, $B2, $09, $E9, $18, $79, $22, $14, $D9, $D1, $B4, $15, $E5, $F5, $92, $51,
    $80, $6A, $53, $89, $D4, $E0, $0E, $31, $76, $55, $4D, $9C, $94, $E4, $A0, $FE,
    $CD, $F3, $4A, $2F, $03, $1F, $69, $D0, $72, $F0, $AE, $8C, $E2, $41, $5A, $7D,
    $13, $74, $35, $42, $A6, $90, $25, $C7, $58, $2B, $6F, $C2, $66, $99, $E8, $3D,
    $C6, $C9, $57, $CE, $37, $67, $7A, $BE, $40, $2D, $34, $4B, $A5, $C3, $DA, $FD), (
    $78, $8D, $66, $CD, $1A, $9C, $0A, $FB, $D8, $3B, $9E, $6B, $73, $54, $45, $75,
    $15, $4C, $B5, $B1, $1B, $E0, $A3, $17, $2A, $57, $F0, $82, $07, $C5, $0C, $27,
    $88, $12, $A5, $1F, $8F, $D2, $18, $7B, $D3, $D9, $56, $F9, $05, $5C, $06, $68,
    $41, $6F, $94, $60, $C6, $C3, $6E, $E2, $D6, $11, $34, $19, $3D, $E5, $E1, $3E,
    $47, $B2, $DB, $F4, $B6, $CF, $F5, $10, $4B, $FA, $AB, $7F, $1C, $37, $46, $EE,
    $D7, $A6, $E9, $53, $FD, $CE, $EA, $8C, $84, $C7, $6C, $85, $9A, $D5, $28, $DC,
    $2B, $FF, $32, $EB, $77, $F2, $24, $4E, $9D, $03, $20, $81, $59, $DE, $C4, $6A,
    $A7, $89, $AE, $2E, $3A, $40, $86, $F8, $E4, $D1, $0B, $E8, $E7, $90, $D0, $08,
    $02, $B0, $4F, $B3, $C0, $92, $1D, $97, $7D, $E6, $99, $21, $9B, $83, $70, $AC,
    $C1, $80, $5E, $23, $5B, $4A, $65, $A8, $63, $61, $6D, $95, $16, $F1, $C2, $52,
    $96, $7C, $FE, $3F, $BD, $0D, $B4, $44, $ED, $42, $A0, $2C, $35, $22, $04, $0E,
    $D4, $51, $A2, $EC, $43, $AF, $B9, $EF, $39, $49, $2F, $69, $7E, $F3, $BF, $71,
    $67, $25, $8B, $8A, $01, $2D, $76, $79, $5F, $E3, $87, $3C, $31, $5A, $36, $1E,
    $9F, $98, $58, $CA, $A9, $BB, $DD, $AD, $A1, $50, $09, $33, $A4, $CB, $0F, $B8,
    $13, $14, $26, $29, $30, $38, $62, $FC, $72, $64, $DF, $00, $F7, $C8, $8E, $4D,
    $AA, $5D, $CC, $C9, $55, $74, $48, $DA, $91, $7A, $B7, $BC, $F6, $93, $BA, $BE), (
    $74, $8B, $4E, $20, $AC, $E8, $7A, $EF, $E2, $D6, $80, $BE, $A7, $05, $AA, $55,
    $C6, $DE, $1A, $5E, $1D, $30, $DA, $4B, $3D, $6D, $49, $4D, $5C, $9F, $77, $D1,
    $0E, $B3, $A5, $28, $0A, $F6, $E0, $83, $63, $7D, $3A, $E7, $E1, $C4, $7C, $27,
    $53, $54, $AD, $D3, $87, $F9, $FE, $A9, $1B, $F8, $99, $79, $43, $A1, $04, $46,
    $B2, $B4, $67, $CD, $F5, $14, $64, $BA, $16, $4F, $AE, $6A, $5B, $02, $DD, $32,
    $BF, $A4, $4C, $36, $2F, $10, $A6, $FA, $01, $8D, $ED, $FF, $7F, $93, $9A, $6F,
    $1C, $A3, $92, $B0, $97, $2B, $AF, $6B, $2D, $41, $FB, $EB, $78, $22, $C1, $91,
    $51, $15, $F1, $BC, $42, $6E, $70, $CB, $71, $C0, $25, $86, $8A, $18, $85, $98,
    $39, $F4, $E5, $00, $D5, $0F, $17, $45, $C3, $5F, $58, $2E, $C5, $7B, $B9, $40,
    $1F, $A0, $9C, $3E, $F2, $21, $31, $0B, $9B, $EA, $72, $5D, $76, $13, $3B, $52,
    $C8, $61, $09, $D2, $96, $75, $11, $94, $CF, $D0, $29, $06, $CC, $DF, $CE, $33,
    $62, $B5, $2C, $1E, $81, $88, $90, $A2, $26, $19, $84, $E3, $D8, $08, $3F, $F3,
    $8F, $AB, $B1, $BD, $50, $60, $23, $FC, $3C, $65, $EC, $07, $FD, $A8, $03, $E9,
    $DC, $95, $CA, $47, $35, $69, $0D, $38, $DB, $E4, $D4, $C9, $9D, $F0, $5A, $37,
    $B8, $6C, $C7, $4A, $68, $82, $66, $24, $7E, $89, $0C, $12, $2A, $34, $44, $48,
    $56, $57, $59, $73, $8C, $B6, $E6, $D7, $8E, $EE, $F7, $C2, $D9, $9E, $B7, $BB), (
    $DE, $9A, $C5, $FB, $93, $3E, $4E, $99, $68, $CC, $2E, $34, $07, $4F, $D1, $AB,
    $36, $50, $73, $19, $57, $F5, $16, $F8, $64, $D7, $37, $CA, $48, $62, $A9, $25,
    $3C, $3F, $0C, $C3, $A0, $DF, $D3, $C0, $3D, $66, $B2, $52, $94, $5E, $0E, $4D,
    $F0, $69, $8D, $AD, $EF, $4C, $29, $A1, $7C, $02, $23, $5D, $9E, $AC, $03, $97,
    $B5, $D6, $6B, $BA, $DC, $83, $C6, $AF, $F6, $9F, $F2, $09, $75, $76, $54, $15,
    $00, $DA, $8F, $71, $7B, $6F, $3A, $CE, $C1, $F1, $0F, $67, $B8, $C8, $ED, $45,
    $32, $1A, $2B, $6E, $B1, $BE, $85, $C7, $28, $BB, $C2, $82, $5F, $FD, $B0, $5B,
    $D5, $44, $61, $63, $7A, $0D, $1C, $E3, $F7, $A6, $8A, $98, $31, $7D, $11, $80,
    $A7, $EB, $A8, $22, $51, $E2, $F4, $47, $74, $A3, $14, $FF, $E6, $33, $42, $DD,
    $D8, $92, $01, $1D, $9C, $90, $EA, $BD, $8B, $B9, $E9, $24, $65, $7F, $D2, $6A,
    $81, $30, $9B, $B7, $E4, $60, $B3, $4A, $8C, $18, $B6, $53, $5A, $41, $B4, $3B,
    $D0, $F3, $2D, $87, $27, $26, $2A, $9D, $A4, $D4, $CF, $BC, $17, $72, $43, $46,
    $2F, $08, $91, $E0, $1F, $13, $88, $6C, $89, $8E, $38, $A2, $40, $C4, $AE, $FA,
    $FE, $E7, $EC, $78, $04, $84, $39, $E5, $77, $E8, $BF, $F9, $55, $59, $12, $21,
    $10, $86, $1B, $C9, $05, $A5, $FC, $49, $EE, $CB, $E1, $79, $DB, $96, $5C, $CD,
    $D9, $06, $0A, $0B, $1E, $20, $2C, $35, $4B, $56, $58, $6D, $70, $7E, $95, $AA), (
    $AE, $02, $85, $29, $A7, $FB, $64, $1C, $77, $78, $69, $F4, $D7, $27, $0F, $41,
    $54, $17, $A0, $03, $BB, $72, $E8, $3E, $C6, $3C, $65, $7D, $5E, $DD, $F7, $6B,
    $E1, $E9, $2A, $EC, $B0, $34, $35, $73, $BA, $6D, $32, $7A, $50, $2E, $8A, $3D,
    $12, $E6, $A6, $4A, $14, $8F, $31, $E2, $5D, $21, $CA, $8C, $48, $63, $8B, $92,
    $87, $BC, $16, $61, $E3, $5B, $08, $A5, $E7, $DA, $93, $3B, $94, $13, $0D, $9E,
    $07, $CE, $96, $38, $BE, $4F, $60, $66, $B3, $81, $F0, $B2, $36, $FE, $04, $FD,
    $C4, $0A, $75, $BF, $A4, $2C, $1D, $83, $42, $C1, $BD, $49, $C9, $B5, $9C, $79,
    $A1, $D8, $1B, $47, $D4, $74, $19, $24, $01, $51, $53, $EA, $ED, $1F, $67, $1E,
    $71, $D0, $6A, $2F, $62, $3A, $11, $AF, $B1, $57, $26, $43, $9A, $CB, $1A, $70,
    $C7, $7B, $39, $2B, $AB, $F2, $A9, $0B, $CC, $B9, $4B, $10, $DE, $E4, $FC, $D2,
    $AC, $CD, $EE, $00, $20, $AD, $68, $56, $D3, $AA, $6F, $15, $30, $7C, $28, $E5,
    $95, $25, $55, $5F, $0C, $D9, $C0, $A2, $59, $91, $C5, $82, $CF, $9B, $37, $A3,
    $F9, $F5, $C2, $22, $A8, $23, $4D, $B7, $FA, $40, $C3, $FF, $D5, $0E, $05, $97,
    $5C, $99, $18, $33, $D6, $F1, $B4, $DC, $B6, $D1, $09, $86, $8E, $F3, $52, $06,
    $2D, $7E, $EB, $C8, $7F, $3F, $44, $45, $46, $4C, $4E, $58, $88, $DF, $80, $84,
    $F8, $90, $9D, $9F, $F6, $8D, $B8, $89, $98, $EF, $5A, $DB, $E0, $6C, $6E, $76), (
    $5E, $63, $73, $A1, $FE, $6A, $8E, $C1, $5C, $D8, $1F, $D7, $B1, $97, $FB, $91,
    $78, $EB, $1C, $FA, $2C, $D5, $95, $B0, $40, $48, $89, $CE, $3C, $34, $43, $BF,
    $4A, $32, $9C, $5B, $71, $AF, $FD, $D2, $29, $18, $C0, $20, $72, $2B, $45, $0E,
    $C8, $55, $83, $15, $E5, $A7, $DB, $A5, $8D, $E7, $4F, $7D, $C3, $00, $D3, $85,
    $B5, $B4, $C2, $D9, $04, $88, $B8, $AE, $80, $C4, $99, $BB, $61, $13, $0C, $60,
    $6F, $9D, $AD, $56, $AA, $F1, $46, $8B, $F2, $8C, $F5, $F7, $51, $E4, $E6, $2F,
    $37, $12, $82, $67, $CA, $DF, $A6, $B3, $0F, $AB, $53, $44, $7F, $E9, $10, $1A,
    $7A, $9B, $92, $26, $81, $03, $DD, $C5, $11, $DA, $65, $BD, $4C, $42, $86, $E0,
    $31, $50, $84, $1D, $B2, $B6, $27, $14, $CF, $49, $D1, $30, $23, $52, $9E, $7C,
    $7E, $4B, $BA, $38, $BC, $3F, $EE, $6E, $02, $16, $74, $CB, $2A, $96, $E1, $E3,
    $35, $58, $06, $3D, $09, $3E, $E2, $93, $E8, $9A, $8F, $D4, $94, $F4, $47, $CD,
    $33, $3A, $A4, $05, $21, $66, $87, $22, $39, $70, $69, $1E, $F9, $75, $24, $79,
    $1B, $2E, $5A, $A2, $C6, $C7, $6B, $A8, $54, $D6, $5F, $F6, $EA, $08, $57, $FF,
    $28, $6D, $DC, $EF, $41, $BE, $0D, $FC, $7B, $DE, $76, $A9, $CC, $62, $01, $A3,
    $EC, $25, $59, $3B, $F8, $07, $0A, $0B, $17, $19, $2D, $36, $A0, $ED, $4E, $B7,
    $C9, $5D, $9F, $68, $AC, $64, $F3, $6C, $98, $4D, $D0, $8A, $77, $90, $F0, $B9), (
    $4D, $B2, $3C, $E6, $96, $B9, $9D, $C3, $A3, $9E, $FE, $1B, $76, $ED, $46, $31,
    $60, $C8, $3E, $98, $FF, $D0, $E2, $F8, $7D, $B8, $99, $FD, $64, $68, $BB, $40,
    $8B, $25, $2A, $DE, $4F, $E5, $88, $DB, $2B, $44, $32, $EB, $15, $C5, $5E, $F1,
    $3D, $01, $A4, $11, $BA, $5B, $8F, $0A, $37, $7F, $E0, $23, $7A, $2D, $EE, $1E,
    $A6, $29, $F7, $F0, $35, $4C, $63, $8A, $93, $92, $34, $B4, $4A, $89, $C4, $F6,
    $33, $9C, $FA, $0B, $38, $EA, $2F, $AD, $80, $E1, $1F, $BD, $91, $16, $5C, $9A,
    $12, $0D, $26, $82, $6C, $DF, $19, $1A, $54, $45, $F3, $D8, $A1, $3A, $65, $86,
    $77, $02, $B1, $74, $97, $BC, $6E, $CF, $F4, $7C, $B0, $8D, $50, $48, $FC, $41,
    $09, $81, $95, $6A, $D5, $59, $0E, $E3, $05, $C0, $78, $51, $A8, $87, $84, $D6,
    $C9, $E8, $C2, $14, $21, $49, $7E, $0C, $EC, $66, $13, $07, $C1, $10, $9B, $CD,
    $C7, $E9, $94, $5F, $B7, $B3, $AB, $3B, $FB, $06, $0F, $F9, $D1, $39, $53, $08,
    $6F, $CE, $D2, $61, $E7, $A0, $79, $55, $52, $30, $47, $B5, $04, $58, $75, $F5,
    $DD, $73, $71, $67, $BE, $43, $D4, $D9, $1D, $AC, $20, $DA, $A5, $70, $6B, $BF,
    $AF, $CC, $3F, $D3, $9F, $24, $DC, $28, $03, $17, $18, $1C, $22, $27, $85, $2E,
    $83, $56, $C6, $A9, $2C, $5A, $62, $72, $36, $00, $69, $8E, $CB, $42, $4E, $AE,
    $D7, $4B, $57, $A7, $A2, $EF, $E4, $CA, $5D, $6D, $F2, $7B, $8C, $90, $AA, $B6), (
    $0C, $56, $BF, $EE, $4F, $AB, $7D, $3E, $73, $98, $A8, $85, $05, $F4, $95, $3D,
    $C8, $D3, $67, $CA, $D2, $8C, $0D, $75, $47, $65, $CB, $63, $A2, $8F, $24, $C0,
    $18, $5A, $3B, $FA, $16, $77, $31, $A5, $71, $34, $E4, $66, $42, $FC, $EF, $E3,
    $DA, $D6, $92, $F1, $79, $EC, $C7, $4B, $99, $2D, $74, $12, $CD, $A9, $1B, $FF,
    $B2, $7F, $8A, $1F, $F3, $D0, $B1, $09, $8B, $59, $22, $DB, $D5, $84, $91, $57,
    $FE, $68, $C1, $C4, $6B, $87, $F0, $39, $17, $B7, $B0, $E8, $27, $1E, $9F, $2C,
    $BE, $1D, $E0, $7B, $E2, $94, $69, $20, $03, $64, $02, $4D, $ED, $7E, $AF, $19,
    $5D, $3C, $07, $6E, $36, $CC, $0E, $01, $51, $FD, $3F, $F5, $14, $DF, $0A, $93,
    $60, $40, $CF, $26, $53, $81, $2B, $B3, $43, $A6, $C6, $B4, $DD, $52, $A4, $61,
    $F6, $08, $28, $76, $7A, $46, $50, $7C, $C3, $A7, $9A, $13, $11, $4E, $04, $4A,
    $4C, $33, $6A, $A1, $2E, $83, $BA, $B8, $49, $44, $6F, $E1, $29, $C5, $88, $E9,
    $58, $90, $1A, $F7, $8D, $D8, $41, $15, $AC, $37, $F8, $E7, $89, $DC, $BC, $5B,
    $E6, $8E, $D7, $23, $1C, $9B, $48, $38, $97, $B6, $55, $2F, $E5, $5F, $B9, $80,
    $EA, $C9, $78, $6C, $30, $D1, $82, $AE, $D4, $9E, $00, $C2, $6D, $B5, $86, $DE,
    $9D, $45, $54, $AA, $D9, $BD, $5C, $96, $FB, $35, $0F, $CE, $9C, $10, $72, $0B,
    $70, $A3, $62, $A0, $25, $EB, $06, $21, $2A, $32, $3A, $5E, $AD, $BB, $F2, $F9), (
    $9F, $7E, $36, $84, $96, $8F, $B9, $F9, $32, $71, $93, $A7, $CB, $FA, $8E, $BA,
    $D3, $34, $7A, $6A, $E3, $B8, $90, $A5, $52, $A2, $48, $67, $CA, $02, $97, $E7,
    $F6, $40, $7C, $BF, $9A, $CD, $DB, $27, $5B, $1B, $63, $AC, $0A, $F3, $B6, $31,
    $C7, $80, $53, $4E, $ED, $C0, $CF, $19, $E1, $AA, $41, $E0, $07, $94, $57, $DD,
    $9E, $EF, $1E, $25, $74, $FF, $30, $33, $EB, $D5, $FD, $06, $99, $B4, $EE, $98,
    $1A, $47, $C1, $7D, $2C, $10, $51, $F0, $5D, $20, $38, $72, $EA, $43, $4D, $23,
    $FE, $87, $DA, $0E, $15, $14, $BB, $01, $6C, $8A, $85, $56, $82, $05, $BE, $16,
    $76, $2B, $EC, $D2, $44, $21, $61, $C8, $83, $49, $70, $F7, $F2, $AB, $37, $AF,
    $9C, $60, $E8, $E5, $7B, $4F, $AE, $39, $04, $CE, $3A, $03, $D1, $54, $7F, $50,
    $FB, $5E, $64, $24, $D7, $18, $86, $0D, $4B, $73, $A6, $3C, $69, $E6, $E4, $92,
    $E9, $AD, $F4, $28, $6F, $91, $0B, $D8, $2D, $9B, $62, $45, $2A, $6E, $6D, $8C,
    $59, $5C, $D9, $F8, $17, $66, $77, $A8, $8B, $DF, $78, $DE, $B3, $42, $79, $4C,
    $A3, $89, $D0, $55, $1F, $A4, $C6, $00, $75, $A9, $09, $0C, $81, $B5, $3D, $B7,
    $B2, $DC, $6B, $D6, $26, $9D, $3E, $95, $D4, $35, $3B, $E2, $65, $08, $4A, $13,
    $1C, $2E, $FC, $0F, $F5, $88, $C9, $BC, $12, $F1, $22, $3F, $B1, $68, $C5, $B0,
    $11, $1D, $29, $2F, $46, $58, $5A, $5F, $8D, $A0, $A1, $BD, $C3, $C4, $C2, $CC), (
    $EF, $8D, $10, $2A, $79, $42, $8C, $85, $D9, $83, $24, $12, $E9, $9F, $38, $67,
    $B2, $5C, $1A, $28, $36, $16, $B7, $11, $A5, $D2, $2E, $06, $1C, $FD, $E5, $41,
    $4F, $F4, $20, $AF, $3F, $3B, $05, $35, $9C, $A1, $DA, $3E, $7A, $CD, $F2, $B1,
    $FA, $7B, $E3, $F5, $5D, $FE, $ED, $1E, $26, $40, $F9, $BF, $46, $BE, $22, $4A,
    $EE, $5F, $6E, $77, $DE, $E8, $D0, $7D, $F6, $31, $2B, $B9, $99, $F3, $9D, $93,
    $A3, $A2, $7C, $68, $0A, $07, $6A, $C5, $03, $4C, $27, $C8, $3C, $0B, $4D, $56,
    $54, $CF, $73, $72, $49, $A8, $B5, $BC, $F1, $C4, $53, $69, $14, $9B, $47, $C0,
    $E0, $C2, $43, $13, $A6, $0C, $84, $E2, $29, $A7, $63, $D5, $2C, $74, $19, $0F,
    $CE, $1F, $0D, $DF, $C1, $97, $BB, $65, $C3, $61, $01, $7F, $6F, $3D, $5B, $FC,
    $87, $CA, $08, $B8, $09, $CC, $A9, $25, $86, $6D, $AE, $9A, $8A, $15, $66, $EA,
    $C7, $37, $58, $BD, $DD, $DC, $60, $91, $B3, $95, $B4, $33, $EC, $D7, $A0, $64,
    $2D, $98, $EB, $AD, $4B, $FB, $3A, $44, $71, $F8, $52, $A4, $9E, $E7, $89, $7E,
    $39, $B0, $D3, $94, $8F, $45, $E6, $B6, $CB, $0E, $92, $18, $5E, $30, $57, $AA,
    $02, $55, $D4, $48, $82, $6B, $E1, $D6, $8B, $21, $78, $75, $32, $90, $76, $70,
    $6C, $DB, $C6, $88, $04, $17, $1B, $1D, $23, $2F, $34, $4E, $50, $FF, $8E, $AB,
    $D8, $5A, $59, $AC, $00, $C9, $51, $BA, $F7, $D1, $62, $81, $80, $E4, $96, $F0), (
    $88, $DF, $B7, $A7, $8A, $CE, $44, $6C, $4F, $4D, $FD, $92, $4A, $56, $A4, $4B,
    $58, $D5, $FC, $E8, $F8, $F4, $3A, $43, $EF, $3E, $01, $AC, $36, $2E, $F2, $28,
    $09, $C3, $67, $D3, $A1, $29, $DE, $50, $79, $14, $78, $97, $26, $9C, $24, $AD,
    $15, $E9, $6B, $7B, $96, $87, $2D, $30, $9B, $8D, $89, $21, $4E, $20, $C8, $5A,
    $6E, $71, $06, $33, $74, $E2, $9F, $85, $BD, $EB, $34, $DB, $BE, $B1, $A0, $1B,
    $93, $CF, $1A, $E0, $5D, $59, $52, $46, $2C, $2B, $37, $CB, $FB, $38, $95, $9A,
    $BC, $32, $AF, $8B, $DA, $11, $68, $B2, $5E, $23, $D8, $22, $7C, $91, $E4, $C2,
    $41, $EE, $ED, $17, $05, $3D, $1C, $08, $83, $80, $4C, $D2, $5B, $9D, $3B, $02,
    $C4, $C1, $7E, $F3, $BA, $12, $51, $72, $FE, $E5, $62, $70, $60, $EA, $35, $99,
    $8C, $65, $BF, $45, $6D, $8E, $DD, $A9, $CA, $F0, $98, $53, $66, $D4, $AE, $B3,
    $10, $5C, $F7, $0E, $18, $A8, $0F, $B0, $EC, $76, $AA, $A6, $F5, $3F, $D6, $F6,
    $E7, $55, $82, $C9, $AB, $B6, $D0, $04, $C5, $7F, $86, $77, $07, $0C, $5F, $16,
    $81, $63, $C7, $40, $31, $54, $B5, $49, $90, $FF, $27, $75, $7A, $CD, $48, $13,
    $1D, $03, $D9, $D1, $E6, $0A, $84, $69, $C6, $B9, $B8, $C0, $A3, $B4, $94, $A2,
    $D7, $F9, $9E, $6A, $1F, $1E, $0D, $DC, $E3, $CC, $3C, $0B, $6F, $2A, $00, $7D,
    $39, $42, $BB, $19, $73, $61, $25, $2F, $47, $57, $64, $8F, $A5, $E1, $F1, $FA), (
    $61, $C1, $70, $D5, $26, $07, $09, $EB, $8B, $5F, $28, $E5, $64, $91, $46, $32,
    $E0, $72, $9A, $11, $C0, $45, $66, $99, $1D, $8D, $40, $62, $55, $EE, $BB, $5C,
    $94, $E6, $1F, $00, $A2, $76, $1B, $34, $78, $0F, $2C, $F6, $97, $4D, $3F, $21,
    $6E, $BA, $83, $8F, $B0, $9B, $9E, $2E, $F0, $C4, $FF, $71, $A4, $35, $D8, $69,
    $88, $4C, $DB, $1A, $BD, $30, $C7, $47, $80, $90, $17, $A5, $50, $0A, $C3, $57,
    $18, $03, $49, $37, $D4, $F8, $CE, $20, $CB, $65, $85, $02, $4A, $DA, $14, $24,
    $75, $7A, $48, $A1, $CC, $98, $73, $FD, $C2, $FA, $E7, $68, $AB, $B3, $0C, $D2,
    $FC, $53, $5A, $81, $2D, $63, $D3, $33, $DE, $95, $BC, $F2, $44, $4B, $B7, $5D,
    $AE, $EC, $B4, $1E, $9C, $DC, $7E, $9D, $8A, $25, $B1, $A8, $22, $D9, $B8, $D0,
    $82, $BF, $67, $6A, $01, $0D, $C9, $6B, $AA, $CA, $AC, $A9, $DD, $3C, $8E, $3B,
    $F5, $F9, $C8, $23, $C5, $6F, $3A, $08, $51, $E4, $C6, $D6, $84, $87, $A6, $0E,
    $FB, $A0, $0B, $E2, $8C, $1C, $15, $E1, $60, $B9, $10, $E8, $74, $5B, $9F, $ED,
    $2B, $B2, $29, $7F, $E9, $F7, $36, $F4, $3D, $A3, $D1, $58, $38, $93, $04, $6D,
    $B5, $AF, $05, $27, $31, $CF, $E3, $7B, $4F, $5E, $2F, $B6, $52, $7D, $42, $39,
    $06, $12, $13, $59, $D7, $16, $CD, $3E, $4E, $BE, $92, $A7, $F3, $77, $EA, $79,
    $89, $43, $AD, $86, $DF, $19, $41, $FE, $6C, $7C, $2A, $96, $54, $56, $EF, $F1), (
    $99, $09, $EE, $E3, $4B, $6E, $04, $D0, $F6, $76, $8F, $EA, $A7, $2F, $EB, $D8,
    $A9, $83, $96, $C8, $F7, $64, $B3, $54, $28, $9B, $B2, $9E, $41, $DF, $CD, $06,
    $33, $65, $1F, $80, $4C, $E0, $0C, $B6, $39, $90, $7C, $50, $3C, $B8, $73, $91,
    $92, $A2, $C5, $51, $C7, $1A, $4F, $21, $08, $A8, $36, $8B, $6A, $82, $86, $7E,
    $59, $95, $D6, $B5, $FC, $37, $02, $B1, $16, $6C, $B0, $C9, $55, $B9, $DE, $F5,
    $61, $98, $D4, $63, $C6, $FE, $BA, $C2, $24, $4A, $97, $5F, $67, $ED, $01, $2C,
    $46, $9F, $3D, $A0, $23, $58, $62, $13, $2B, $34, $D2, $8E, $D1, $00, $70, $68,
    $15, $2E, $31, $45, $A4, $EC, $81, $F4, $F3, $A3, $1C, $75, $07, $F0, $DA, $27,
    $CB, $CE, $0F, $1B, $BB, $5B, $F2, $CF, $77, $D9, $18, $7B, $29, $EF, $FB, $D5,
    $BE, $3F, $5E, $52, $8D, $26, $A1, $0E, $A5, $1D, $93, $43, $B7, $20, $F1, $38,
    $57, $5C, $94, $A6, $79, $E9, $7D, $40, $F9, $0B, $DC, $25, $FD, $BC, $49, $BD,
    $44, $AA, $6B, $12, $22, $4D, $0A, $53, $6D, $2D, $7A, $F8, $42, $C3, $4E, $7F,
    $60, $E8, $19, $AF, $D7, $71, $78, $1E, $AD, $CA, $6F, $AC, $11, $0D, $8C, $C1,
    $5A, $E7, $E2, $CC, $17, $30, $74, $3A, $BF, $3E, $88, $D3, $84, $66, $B4, $9A,
    $87, $03, $05, $10, $14, $2A, $32, $69, $9C, $5D, $9D, $85, $E6, $AB, $48, $E1,
    $FA, $3B, $72, $AE, $DD, $35, $89, $E5, $8A, $47, $C0, $56, $FF, $C4, $DB, $E4), (
    $81, $13, $59, $92, $52, $E4, $BF, $02, $B7, $19, $FD, $87, $53, $2E, $F2, $80,
    $CF, $12, $4F, $0A, $9B, $63, $9A, $E3, $68, $CB, $36, $EC, $C8, $2D, $34, $D3,
    $31, $56, $F4, $62, $A4, $D4, $71, $ED, $DB, $B0, $B3, $8C, $5A, $D8, $2C, $8D,
    $90, $B6, $91, $1C, $7D, $E7, $C5, $65, $F0, $21, $FA, $17, $57, $64, $B2, $75,
    $38, $6D, $10, $16, $C9, $E5, $A2, $6A, $0B, $09, $94, $54, $C0, $BE, $42, $95,
    $1A, $44, $66, $6B, $30, $73, $7C, $50, $99, $9D, $9E, $A9, $FB, $C4, $E2, $AD,
    $6E, $A3, $9C, $55, $EE, $72, $84, $8A, $46, $D2, $28, $A6, $6F, $AE, $74, $F3,
    $48, $BB, $35, $1F, $D7, $CC, $AC, $D1, $DD, $5D, $A7, $AA, $76, $3D, $8E, $D0,
    $24, $2F, $EB, $DC, $41, $8F, $97, $0F, $3A, $DF, $B9, $DE, $D9, $BD, $7E, $47,
    $5B, $14, $40, $FC, $4D, $58, $26, $C3, $29, $11, $4A, $43, $77, $EF, $33, $3B,
    $A5, $3E, $88, $1E, $B5, $7F, $4E, $E0, $61, $F8, $DA, $E6, $7A, $03, $A0, $C1,
    $BA, $78, $9F, $EA, $E8, $AB, $69, $07, $F9, $E9, $82, $93, $51, $D6, $F1, $FF,
    $39, $89, $E1, $1D, $A1, $C7, $F7, $37, $CD, $96, $6C, $67, $D5, $B4, $BC, $60,
    $B1, $70, $3F, $27, $85, $83, $7B, $C6, $20, $0C, $B8, $CE, $86, $F6, $0E, $AF,
    $5F, $01, $04, $15, $23, $0D, $32, $F5, $22, $00, $18, $4B, $A8, $98, $FE, $2B,
    $45, $8B, $5C, $5E, $79, $06, $25, $1B, $05, $CA, $49, $2A, $08, $3C, $C2, $4C), (
    $41, $EB, $7F, $0F, $02, $6F, $C4, $47, $D9, $04, $37, $4C, $EF, $A3, $BC, $B6,
    $17, $5B, $E4, $11, $1C, $18, $96, $6C, $AF, $58, $87, $50, $0A, $59, $E9, $3E,
    $49, $90, $DF, $07, $F1, $D7, $CD, $AE, $82, $2A, $34, $C8, $E0, $7C, $19, $C0,
    $9C, $D1, $BE, $31, $E7, $D6, $51, $AA, $EE, $F3, $28, $27, $8F, $A8, $05, $21,
    $B7, $78, $E8, $33, $A6, $4D, $DE, $7D, $16, $2B, $9F, $67, $CF, $65, $3B, $BB,
    $25, $C3, $6E, $72, $6A, $DD, $C2, $06, $C1, $10, $AD, $EC, $CE, $5F, $F6, $00,
    $03, $EA, $29, $FF, $83, $A9, $92, $A7, $53, $71, $7E, $61, $35, $43, $5D, $B8,
    $D4, $A4, $A2, $F2, $2D, $30, $DC, $1E, $5C, $88, $57, $24, $E2, $7A, $E1, $48,
    $4A, $98, $38, $CA, $5E, $13, $62, $A0, $D5, $F9, $C7, $8B, $54, $80, $BA, $81,
    $66, $A5, $F5, $1A, $CB, $6D, $D0, $E3, $F7, $C5, $09, $C6, $23, $20, $55, $94,
    $B5, $74, $2C, $26, $1B, $01, $BF, $14, $93, $56, $42, $40, $D3, $B9, $39, $FE,
    $8D, $E5, $12, $3A, $3F, $AB, $0B, $ED, $FC, $44, $85, $5A, $DB, $DA, $FB, $7B,
    $B1, $63, $9D, $0C, $B3, $8E, $46, $45, $F8, $68, $BD, $77, $FA, $9B, $69, $75,
    $76, $36, $99, $79, $FD, $91, $70, $3D, $08, $22, $95, $B0, $F4, $B4, $0E, $64,
    $89, $F0, $C9, $2F, $97, $52, $86, $D8, $CC, $4E, $60, $8A, $8C, $4F, $B2, $4B,
    $84, $2E, $AC, $A1, $32, $E6, $0D, $9A, $3C, $1D, $15, $1F, $6B, $73, $9E, $D2), (
    $BE, $B5, $90, $5C, $C9, $3A, $23, $DF, $78, $00, $F1, $E7, $B8, $ED, $FB, $B3,
    $1F, $F6, $6C, $12, $88, $32, $E8, $1C, $C8, $07, $5A, $C2, $25, $65, $B7, $CE,
    $47, $CD, $70, $4B, $FC, $53, $DB, $93, $EF, $AB, $6A, $92, $39, $02, $56, $81,
    $5E, $51, $1D, $30, $35, $7C, $5F, $A9, $BF, $29, $0A, $76, $DA, $DC, $67, $46,
    $96, $19, $10, $0C, $9F, $C1, $43, $3F, $57, $74, $F3, $44, $79, $F7, $BA, $E4,
    $6D, $F9, $4A, $34, $8D, $D5, $D8, $2A, $63, $05, $0B, $0E, $2D, $CC, $01, $18,
    $D4, $EA, $E9, $31, $94, $15, $AA, $F8, $E1, $C3, $E6, $59, $91, $69, $48, $6E,
    $20, $4D, $55, $45, $8A, $11, $66, $16, $F5, $1E, $03, $B1, $21, $9A, $38, $8B,
    $D6, $CB, $F2, $D2, $B4, $4E, $3E, $D3, $2E, $EE, $24, $FE, $C5, $77, $33, $E2,
    $54, $2C, $C6, $41, $BD, $17, $A0, $13, $D0, $40, $F0, $50, $A3, $EC, $CF, $FF,
    $99, $DD, $D1, $09, $61, $AD, $1A, $AF, $89, $CA, $EB, $A5, $84, $8E, $3C, $3B,
    $A4, $B0, $82, $8F, $83, $A1, $1B, $E5, $9C, $C0, $7A, $95, $3D, $52, $26, $9B,
    $C4, $42, $7F, $F4, $9E, $08, $AC, $72, $D9, $0D, $AE, $FD, $FA, $49, $A7, $D7,
    $B6, $62, $36, $68, $4F, $0F, $C7, $2F, $22, $BB, $9D, $04, $BC, $B2, $A8, $27,
    $E3, $14, $A6, $7B, $06, $64, $28, $6B, $80, $A2, $97, $87, $73, $7D, $75, $8C,
    $60, $85, $7E, $5D, $5B, $58, $37, $2B, $E0, $6F, $4C, $71, $86, $98, $B9, $DE));

  //SUBSTITUTION BOXES' INVERSE FOR EACH ROUND
  S1: array[0..15, 0..255] of longword = ((
    $89, $72, $9C, $D4, $4A, $46, $3D, $1A, $6B, $B2, $2E, $5A, $52, $04, $C6, $4D,
    $2A, $6A, $7D, $E0, $B7, $BB, $5F, $10, $B4, $B0, $15, $18, $3C, $47, $8E, $D5,
    $3E, $07, $B6, $17, $20, $E6, $8C, $9F, $99, $73, $64, $E9, $84, $F9, $44, $D3,
    $AE, $C7, $12, $39, $FA, $E2, $30, $F4, $27, $62, $66, $1C, $2F, $EF, $83, $4B,
    $F8, $DD, $E3, $65, $60, $0E, $3F, $29, $68, $38, $D2, $FB, $6C, $CA, $74, $82,
    $21, $BF, $79, $C2, $87, $C9, $7A, $F2, $E8, $25, $DE, $36, $4F, $77, $5D, $51,
    $A7, $AF, $AD, $76, $16, $A5, $EC, $F5, $00, $D6, $C1, $9A, $8A, $4C, $1D, $EA,
    $A8, $53, $D8, $23, $E1, $34, $C8, $94, $A6, $B5, $F6, $A4, $03, $DF, $69, $81,
    $C0, $7E, $A9, $90, $0A, $95, $48, $55, $40, $C3, $8B, $6F, $DB, $1F, $35, $57,
    $E5, $7F, $BE, $2C, $CC, $70, $9D, $09, $AB, $ED, $32, $37, $CB, $01, $59, $91,
    $CE, $1B, $0B, $56, $3B, $FC, $E4, $14, $02, $78, $31, $5B, $58, $45, $DA, $5E,
    $9E, $33, $B1, $96, $BA, $88, $75, $26, $19, $AA, $AC, $7C, $08, $0F, $F7, $9B,
    $71, $06, $EB, $FD, $24, $7B, $F0, $E7, $3A, $F1, $8F, $6D, $43, $D0, $F3, $98,
    $D7, $B9, $4E, $28, $C4, $13, $A3, $92, $11, $B8, $FE, $50, $A2, $2D, $0C, $1E,
    $C5, $05, $DC, $54, $CD, $BC, $61, $2B, $EE, $B3, $5C, $86, $93, $6E, $0D, $49,
    $D9, $85, $97, $D1, $22, $BD, $A1, $80, $A0, $67, $41, $63, $42, $FF, $CF, $8D), (
    $EB, $C4, $80, $69, $AE, $2C, $2E, $1C, $7F, $DA, $06, $7A, $1E, $A5, $AF, $DE,
    $47, $39, $21, $E0, $E1, $10, $9C, $17, $26, $3B, $04, $14, $4C, $86, $CF, $23,
    $6A, $8B, $AD, $93, $66, $C1, $E2, $1F, $5E, $E3, $18, $60, $AB, $C5, $73, $BA,
    $E4, $CC, $62, $DB, $3A, $AC, $CE, $4D, $E5, $B8, $74, $09, $CB, $3C, $3F, $A3,
    $75, $30, $A9, $B4, $A7, $0E, $4E, $40, $F6, $B9, $95, $48, $11, $EF, $67, $82,
    $D9, $B1, $9F, $53, $0D, $F4, $2A, $19, $D2, $6C, $CD, $94, $2D, $F1, $92, $C8,
    $33, $99, $E6, $98, $E9, $96, $02, $C0, $2F, $BB, $6F, $0B, $5A, $9A, $36, $31,
    $8E, $BF, $E8, $0C, $F5, $0F, $C6, $64, $00, $C7, $F9, $27, $A1, $88, $BC, $4B,
    $91, $6B, $1B, $8D, $58, $5B, $76, $CA, $20, $71, $C3, $C2, $57, $01, $EE, $24,
    $7D, $F8, $85, $FD, $32, $9B, $A0, $87, $D1, $8A, $5C, $8C, $05, $68, $0A, $D0,
    $AA, $D8, $B2, $16, $DC, $22, $51, $70, $97, $D4, $F0, $4A, $8F, $D7, $72, $B5,
    $81, $13, $41, $83, $A6, $12, $44, $FA, $DF, $B6, $FE, $D5, $FB, $A4, $FF, $BE,
    $84, $90, $9E, $35, $6E, $1D, $34, $59, $ED, $F3, $D3, $DD, $F2, $03, $55, $45,
    $7E, $79, $25, $28, $B0, $5D, $38, $50, $08, $29, $F7, $42, $5F, $D6, $6D, $EA,
    $15, $3E, $37, $C9, $78, $3D, $89, $7C, $7B, $52, $56, $63, $B3, $A8, $4F, $B7,
    $1A, $9D, $65, $BD, $43, $46, $FC, $EC, $77, $2B, $49, $07, $E7, $54, $A2, $61), (
    $83, $58, $4D, $CE, $3E, $0D, $AB, $CB, $BD, $A2, $24, $97, $EA, $D6, $20, $85,
    $55, $A6, $EB, $9D, $45, $71, $48, $86, $7D, $B9, $12, $38, $60, $14, $B3, $90,
    $03, $95, $6D, $C6, $E7, $7A, $B8, $2F, $23, $AA, $EC, $65, $B2, $68, $8B, $54,
    $15, $96, $4F, $AF, $ED, $D4, $53, $DF, $D7, $80, $2A, $9E, $C8, $18, $93, $BE,
    $8F, $69, $74, $3C, $EE, $87, $3F, $D3, $EF, $1A, $E3, $17, $52, $1B, $02, $49,
    $C4, $70, $9F, $30, $31, $0F, $F0, $F1, $8A, $F2, $DE, $4C, $1C, $9B, $13, $89,
    $C5, $A1, $B0, $28, $46, $C9, $E6, $42, $E4, $D5, $4B, $67, $E1, $19, $75, $5F,
    $76, $78, $9A, $F3, $00, $A5, $9C, $1E, $6C, $3B, $06, $8D, $2E, $29, $E8, $5C,
    $0A, $B4, $E5, $27, $BA, $7E, $7B, $34, $B5, $E9, $7C, $01, $F4, $59, $F8, $C0,
    $B6, $6F, $62, $5D, $A7, $D1, $A4, $64, $7F, $3A, $5E, $98, $92, $DC, $FD, $1D,
    $91, $3D, $B7, $61, $51, $22, $56, $0C, $CD, $37, $0E, $C1, $04, $32, $4A, $66,
    $63, $C2, $40, $21, $41, $B1, $F5, $FE, $E0, $8E, $47, $FF, $73, $C3, $0B, $50,
    $79, $6E, $FB, $88, $2D, $8C, $10, $E2, $A0, $DB, $D2, $77, $AC, $43, $AE, $A8,
    $A9, $1F, $A3, $33, $DA, $84, $09, $F7, $BC, $FC, $16, $D8, $D0, $4E, $11, $AD,
    $26, $2C, $08, $BB, $D9, $82, $F6, $2B, $05, $CF, $99, $6B, $CA, $5A, $F9, $07,
    $DD, $72, $94, $BF, $81, $44, $25, $FA, $39, $35, $57, $6A, $C7, $CC, $36, $5B), (
    $50, $92, $39, $3E, $D4, $E4, $F1, $0C, $C1, $4B, $F2, $F3, $22, $75, $2E, $5A,
    $E0, $7E, $DE, $C5, $8A, $4F, $16, $BC, $A9, $13, $61, $E2, $76, $93, $F4, $C4,
    $F5, $DF, $83, $3A, $9B, $1F, $B5, $B4, $68, $36, $B6, $62, $F6, $B2, $0A, $C0,
    $A1, $7C, $60, $8D, $0B, $F7, $10, $1A, $CA, $D6, $56, $AF, $20, $28, $05, $21,
    $CC, $AD, $8E, $BE, $71, $5F, $BF, $87, $1C, $E7, $A7, $F8, $35, $2F, $06, $0D,
    $11, $84, $2B, $AB, $4E, $DC, $F9, $14, $FA, $DD, $AC, $6F, $EE, $3B, $2D, $6C,
    $A5, $72, $1D, $73, $18, $9C, $29, $5B, $08, $31, $9F, $42, $C7, $FB, $63, $55,
    $FC, $53, $BD, $12, $88, $4C, $4D, $D8, $D3, $EB, $74, $54, $38, $7D, $FD, $9D,
    $7F, $A0, $6B, $45, $D5, $66, $E1, $B3, $C6, $C8, $7A, $98, $A8, $32, $C9, $52,
    $95, $C2, $91, $04, $2C, $FE, $ED, $3F, $7B, $07, $01, $A2, $94, $B7, $3C, $49,
    $24, $37, $CB, $89, $B8, $E5, $79, $80, $82, $1E, $FF, $0F, $3D, $33, $CE, $47,
    $6E, $64, $2A, $A6, $AE, $40, $AA, $A3, $5C, $99, $43, $69, $BB, $97, $65, $DA,
    $27, $58, $6A, $23, $CD, $02, $46, $67, $5D, $E3, $1B, $E9, $09, $EF, $57, $BA,
    $B0, $0E, $9E, $26, $B9, $70, $41, $19, $90, $F0, $51, $EC, $44, $8F, $00, $25,
    $C3, $EA, $85, $77, $A4, $D7, $8C, $D1, $D9, $9A, $96, $81, $D2, $5E, $E8, $34,
    $30, $59, $4A, $B1, $86, $15, $48, $78, $17, $DB, $CF, $03, $E6, $6D, $D0, $8B), (
    $A3, $78, $01, $13, $5E, $CE, $DF, $50, $46, $DA, $61, $97, $B4, $4E, $CD, $0E,
    $9B, $86, $30, $4D, $34, $AB, $42, $11, $D2, $76, $8E, $72, $07, $66, $7F, $7D,
    $A4, $39, $C3, $C5, $77, $B1, $8A, $0D, $AE, $03, $22, $93, $65, $E0, $2D, $83,
    $AC, $36, $2A, $D3, $25, $26, $5C, $BE, $53, $92, $85, $4B, $19, $2F, $17, $E5,
    $C9, $0F, $68, $8B, $E6, $E7, $E8, $73, $3C, $6B, $33, $9A, $E9, $C6, $EA, $55,
    $2C, $79, $DE, $7A, $10, $B2, $A7, $89, $EB, $B8, $FA, $45, $D0, $38, $1C, $B3,
    $56, $43, $84, $3D, $06, $1A, $57, $7E, $A6, $0A, $82, $1F, $FD, $29, $FE, $AA,
    $8F, $80, $15, $27, $75, $62, $FF, $08, $09, $6F, $2B, $91, $AD, $1B, $E1, $E4,
    $EE, $59, $BB, $67, $EF, $02, $DB, $40, $EC, $F7, $2E, $3E, $3B, $F5, $DC, $35,
    $F1, $B9, $3F, $4A, $4C, $B0, $52, $CF, $F8, $D1, $8C, $BD, $6E, $F2, $4F, $F3,
    $12, $70, $B7, $BF, $64, $47, $32, $04, $C4, $96, $A9, $94, $A0, $A5, $00, $87,
    $24, $88, $5B, $58, $D6, $6D, $D8, $C7, $F6, $99, $28, $14, $41, $6A, $54, $63,
    $B6, $69, $C2, $CA, $60, $BA, $18, $90, $E3, $6C, $3A, $8D, $98, $A1, $51, $BC,
    $81, $D9, $9F, $A8, $74, $CC, $D4, $0C, $71, $B5, $49, $FB, $D7, $1D, $9C, $ED,
    $FC, $20, $37, $44, $9D, $AF, $31, $48, $16, $21, $7B, $E2, $23, $7C, $A2, $F9,
    $5A, $D5, $95, $DD, $0B, $C1, $F4, $1E, $F0, $C0, $C8, $05, $9E, $5F, $5D, $CB), (
    $3D, $DE, $98, $75, $44, $B3, $A2, $E5, $CD, $A4, $E6, $E7, $4E, $D6, $2F, $68,
    $6E, $78, $61, $4D, $87, $33, $99, $E8, $29, $E9, $6F, $C0, $12, $83, $BB, $0A,
    $2B, $B4, $B7, $8C, $BE, $E1, $73, $86, $D0, $28, $9C, $2D, $14, $EA, $C1, $5F,
    $8B, $80, $21, $B0, $1D, $A0, $EB, $60, $93, $B8, $B1, $E3, $1C, $A3, $A5, $95,
    $18, $D4, $7D, $1E, $6B, $2E, $56, $AE, $19, $89, $20, $91, $7C, $F9, $EE, $3A,
    $81, $5C, $8D, $6A, $C8, $31, $53, $CE, $A1, $E2, $C2, $23, $08, $F1, $00, $CA,
    $4F, $4C, $DD, $01, $F5, $7A, $B5, $63, $F3, $BA, $05, $C6, $F7, $D1, $97, $50,
    $B9, $24, $2C, $02, $9A, $BD, $DA, $FC, $10, $BF, $70, $D8, $8F, $3B, $90, $6C,
    $48, $74, $62, $32, $82, $3F, $7E, $B6, $45, $1A, $FB, $57, $59, $38, $06, $AA,
    $FD, $0F, $72, $A7, $AC, $16, $9D, $0D, $F8, $4A, $A9, $71, $22, $51, $8E, $F2,
    $EC, $03, $C3, $DF, $B2, $37, $66, $35, $C7, $DB, $54, $69, $F4, $52, $47, $25,
    $17, $0C, $84, $67, $41, $40, $85, $EF, $46, $FF, $92, $4B, $94, $7B, $D5, $1F,
    $2A, $07, $42, $3C, $49, $77, $C4, $C5, $30, $F0, $64, $9B, $DC, $AF, $1B, $88,
    $FA, $8A, $27, $3E, $AB, $15, $C9, $0B, $09, $43, $79, $36, $D2, $76, $D9, $65,
    $7F, $9E, $A6, $9F, $5D, $34, $5E, $39, $A8, $6D, $CC, $11, $E0, $ED, $96, $D3,
    $FE, $55, $58, $F6, $AD, $5A, $CB, $5B, $E4, $BC, $13, $0E, $D7, $26, $04, $CF), (
    $E9, $31, $71, $D8, $BC, $88, $A9, $9B, $AF, $80, $37, $53, $97, $61, $86, $AA,
    $9D, $33, $60, $9A, $93, $2C, $5D, $D9, $DA, $66, $67, $0B, $DB, $C8, $3F, $5A,
    $CA, $94, $DC, $3B, $D5, $21, $62, $DD, $D7, $41, $22, $28, $E4, $3D, $DF, $56,
    $B9, $0F, $2A, $50, $4A, $44, $E8, $38, $54, $AD, $6D, $A7, $02, $30, $12, $D2,
    $1F, $7F, $ED, $C5, $29, $69, $0E, $BA, $7D, $95, $4C, $F1, $45, $00, $EE, $24,
    $7C, $8B, $B8, $AE, $68, $B7, $E1, $F2, $BD, $85, $E5, $35, $5E, $F8, $2E, $A3,
    $10, $B3, $E6, $46, $1C, $6E, $99, $C3, $1D, $EA, $83, $CE, $64, $F9, $76, $B0,
    $CD, $C2, $E7, $C1, $73, $BE, $0C, $70, $8A, $B6, $3C, $FB, $79, $18, $96, $39,
    $58, $81, $63, $E0, $8E, $DE, $6F, $8D, $26, $4D, $47, $20, $FC, $7B, $EB, $36,
    $FD, $5C, $49, $48, $A2, $82, $04, $74, $13, $1A, $5F, $9E, $51, $06, $09, $D4,
    $B5, $6C, $F4, $08, $32, $CC, $40, $F3, $8C, $E3, $FE, $A6, $C9, $57, $EF, $D0,
    $7A, $72, $01, $A5, $4B, $BB, $FF, $A4, $19, $05, $34, $1E, $75, $5B, $C4, $CF,
    $89, $9C, $92, $07, $4E, $2D, $E2, $A0, $11, $90, $F7, $EC, $D1, $9F, $B1, $77,
    $15, $AC, $B2, $D3, $C6, $84, $8F, $F0, $6B, $C7, $CB, $27, $D6, $C0, $23, $65,
    $3A, $59, $16, $87, $F6, $25, $03, $B4, $91, $A1, $55, $2B, $98, $0D, $3E, $F5,
    $43, $2F, $FA, $6A, $78, $BF, $4F, $42, $17, $AB, $52, $A8, $7E, $1B, $0A, $14), (
    $DA, $77, $6A, $68, $9E, $0C, $F6, $72, $91, $47, $7E, $EF, $00, $16, $76, $EA,
    $ED, $9C, $3B, $9B, $7C, $B7, $24, $58, $20, $6F, $B2, $3E, $C4, $61, $5D, $43,
    $67, $F7, $4A, $C3, $1E, $F4, $83, $5C, $92, $AC, $F8, $86, $5F, $39, $A4, $CB,
    $D4, $26, $F9, $A1, $29, $E9, $74, $B9, $C7, $57, $FA, $22, $71, $0F, $07, $7A,
    $81, $B6, $2C, $88, $A9, $E1, $95, $18, $C6, $A8, $9F, $37, $A0, $6B, $9D, $04,
    $96, $78, $8D, $84, $E2, $CA, $01, $4F, $B0, $49, $21, $BF, $E6, $70, $FB, $CD,
    $80, $8F, $F2, $1B, $69, $19, $2B, $12, $51, $66, $A2, $54, $D3, $DC, $73, $AA,
    $F0, $28, $EE, $08, $3A, $17, $93, $25, $D2, $34, $94, $63, $97, $06, $6D, $41,
    $CF, $85, $D6, $A5, $4D, $0B, $DE, $55, $AE, $BC, $42, $48, $15, $B4, $C1, $1D,
    $B1, $4E, $32, $7F, $65, $0E, $E7, $C8, $09, $38, $9A, $C5, $EC, $E0, $D9, $5E,
    $F3, $A3, $1C, $F1, $8E, $27, $89, $99, $0A, $3D, $E3, $05, $B8, $FC, $D7, $6E,
    $5A, $46, $40, $87, $8B, $DD, $C9, $59, $A7, $CE, $A6, $FD, $BE, $E5, $60, $02,
    $1F, $52, $DB, $98, $53, $AD, $8A, $36, $10, $D1, $13, $1A, $75, $3C, $EB, $82,
    $45, $D5, $14, $11, $D8, $4C, $31, $C2, $B5, $E4, $30, $4B, $BD, $8C, $DF, $7D,
    $62, $AB, $64, $2F, $2A, $CC, $C0, $BB, $5B, $AF, $D0, $F5, $35, $6C, $03, $2E,
    $56, $33, $FE, $44, $0D, $7B, $90, $B3, $BA, $FF, $23, $E8, $2D, $79, $50, $3F), (
    $C7, $67, $1D, $8B, $88, $6D, $4B, $3C, $DD, $CA, $2C, $A6, $CB, $97, $63, $E3,
    $55, $F0, $E8, $DF, $65, $64, $6F, $B4, $95, $37, $50, $29, $E0, $F1, $42, $C4,
    $59, $75, $EA, $5F, $93, $43, $D4, $27, $A3, $F2, $AC, $71, $54, $A8, $E1, $F3,
    $46, $2F, $08, $47, $11, $D9, $02, $7E, $5A, $87, $8A, $DA, $9B, $CE, $D6, $EB,
    $21, $3A, $BD, $5D, $74, $AB, $F4, $51, $1A, $79, $DE, $98, $BF, $5E, $33, $85,
    $8F, $56, $18, $32, $8D, $C3, $6B, $3E, $F5, $B0, $F6, $28, $B1, $58, $91, $F7,
    $81, $76, $AA, $2A, $92, $DC, $B5, $1B, $ED, $9C, $13, $D2, $68, $AE, $AD, $A4,
    $7A, $09, $5B, $99, $44, $C8, $70, $B6, $BA, $BE, $12, $84, $22, $53, $01, $8E,
    $31, $CC, $6C, $78, $03, $6A, $96, $61, $E5, $C1, $69, $B8, $AF, $F8, $0E, $05,
    $16, $A5, $9F, $0A, $3D, $D7, $04, $1E, $4F, $4C, $24, $A9, $80, $D5, $40, $00,
    $F9, $FA, $19, $C0, $C5, $17, $9A, $0B, $B7, $C9, $39, $7D, $2B, $A1, $86, $7F,
    $EF, $EC, $D0, $BC, $4D, $CD, $2E, $CF, $15, $06, $0F, $66, $E7, $FB, $6E, $23,
    $35, $52, $FE, $FC, $FD, $EE, $C6, $30, $77, $E6, $1C, $0C, $FF, $25, $89, $36,
    $C2, $8C, $73, $10, $D8, $49, $D3, $94, $A7, $B2, $62, $26, $D1, $3F, $BB, $B9,
    $3B, $38, $DB, $14, $9E, $83, $9D, $1F, $82, $A0, $5C, $48, $72, $34, $4E, $41,
    $57, $E9, $7C, $2D, $A2, $E4, $20, $7B, $B3, $07, $0D, $90, $E2, $4A, $60, $45), (
    $F4, $8A, $D0, $58, $E4, $26, $1B, $55, $92, $94, $54, $5D, $75, $82, $C9, $7F,
    $02, $17, $0B, $73, $6C, $9D, $15, $E5, $CB, $7E, $12, $E6, $1C, $E7, $37, $81,
    $22, $D9, $3E, $E8, $0A, $97, $38, $5A, $13, $78, $03, $4A, $7C, $B0, $1A, $E9,
    $CD, $49, $DC, $AB, $EA, $27, $14, $A1, $0E, $C0, $B6, $25, $5C, $8D, $2B, $24,
    $39, $1F, $05, $72, $B7, $C5, $3C, $6E, $D3, $64, $3F, $B4, $59, $5E, $EB, $20,
    $EC, $F6, $BA, $6A, $60, $D1, $5F, $CE, $A2, $F2, $F1, $8E, $11, $34, $CC, $41,
    $A6, $89, $FA, $7A, $AF, $87, $9E, $0F, $53, $6B, $56, $D5, $E0, $99, $42, $8C,
    $DF, $B8, $63, $62, $7D, $DB, $DE, $43, $DA, $04, $2C, $31, $52, $47, $BF, $8B,
    $FC, $FB, $D4, $09, $76, $07, $98, $90, $E3, $BE, $9C, $D8, $06, $01, $EE, $C4,
    $DD, $A7, $CA, $4F, $C3, $A9, $FE, $85, $B1, $4C, $9B, $6D, $28, $4E, $BC, $0D,
    $AE, $29, $51, $50, $BB, $18, $74, $79, $65, $96, $CF, $EF, $F3, $B3, $9A, $23,
    $C1, $2F, $10, $A8, $AA, $66, $C7, $16, $93, $4B, $F7, $86, $67, $A3, $3D, $3B,
    $6F, $84, $71, $88, $69, $57, $E2, $A0, $5B, $F5, $91, $C8, $95, $2D, $80, $61,
    $46, $F9, $19, $C2, $D2, $7B, $D7, $AD, $F0, $08, $2A, $E1, $A5, $A4, $44, $83,
    $70, $D6, $77, $32, $FD, $1E, $C6, $BD, $45, $0C, $9F, $B2, $AC, $36, $40, $00,
    $FF, $68, $2E, $4D, $21, $33, $48, $F8, $B9, $3A, $30, $B5, $8F, $1D, $35, $ED), (
    $EE, $1A, $7F, $D1, $B7, $74, $42, $BC, $77, $20, $D5, $EB, $BD, $E6, $A3, $A6,
    $A0, $65, $85, $CF, $29, $30, $BF, $73, $A4, $F3, $52, $4F, $76, $D0, $E5, $E4,
    $3D, $3B, $6B, $69, $2E, $F6, $2C, $CA, $1F, $25, $ED, $59, $58, $36, $1D, $F7,
    $37, $C4, $61, $43, $4A, $8E, $1C, $5A, $5D, $F0, $16, $7E, $EA, $75, $19, $AD,
    $C3, $70, $F1, $17, $06, $93, $57, $F8, $CE, $C7, $0C, $0F, $7A, $09, $3C, $08,
    $27, $86, $56, $9B, $C5, $B1, $0D, $F9, $10, $55, $3F, $7C, $A1, $54, $68, $BE,
    $8C, $F5, $8A, $C1, $FA, $91, $9C, $22, $66, $D7, $E3, $32, $07, $94, $40, $EC,
    $8B, $41, $87, $F4, $44, $CB, $A9, $BB, $2A, $28, $CC, $33, $6C, $EF, $82, $B9,
    $79, $C0, $B2, $78, $D6, $47, $BA, $35, $00, $3A, $04, $63, $90, $39, $95, $FB,
    $C8, $6D, $0B, $50, $DE, $5E, $34, $2B, $9A, $8F, $5F, $38, $2D, $7D, $E2, $46,
    $4E, $24, $DF, $DC, $0E, $FC, $AB, $03, $A5, $97, $AA, $B4, $1B, $2F, $9E, $62,
    $A7, $4D, $67, $9F, $DD, $C6, $B5, $02, $DA, $D9, $84, $F2, $60, $48, $4C, $92,
    $DB, $81, $6F, $21, $80, $B8, $D8, $C2, $3E, $B3, $98, $5B, $E9, $CD, $05, $51,
    $B6, $D3, $7B, $23, $9D, $11, $AE, $E0, $6A, $D2, $64, $4B, $E7, $96, $26, $01,
    $53, $FD, $45, $E8, $6E, $89, $D4, $B0, $13, $31, $8D, $49, $A8, $72, $71, $18,
    $99, $FE, $1E, $83, $15, $AC, $AF, $A2, $14, $E1, $FF, $5C, $12, $0A, $88, $C9), (
    $23, $94, $5B, $51, $CE, $D2, $E0, $05, $A7, $06, $4D, $B2, $6E, $95, $AF, $29,
    $BA, $13, $E1, $E2, $5E, $B6, $E5, $4A, $50, $F5, $43, $26, $B5, $18, $83, $22,
    $57, $2F, $8C, $A3, $5F, $89, $04, $D3, $0A, $C2, $FA, $C0, $2A, $74, $37, $DA,
    $45, $D4, $0F, $77, $27, $3D, $C6, $53, $CC, $DF, $A6, $9F, $9D, $C8, $E7, $2E,
    $1A, $F6, $DE, $F1, $7C, $15, $0E, $47, $62, $52, $5C, $7D, $41, $2D, $E8, $D8,
    $4C, $A8, $DC, $71, $FC, $1C, $FD, $4F, $CB, $E3, $72, $BD, $1F, $7F, $D9, $09,
    $B8, $00, $1B, $75, $0C, $59, $16, $92, $6B, $3F, $93, $97, $F8, $CF, $30, $A5,
    $02, $3B, $11, $66, $BC, $60, $25, $ED, $28, $EF, $61, $D7, $F9, $DD, $86, $C3,
    $48, $73, $90, $32, $AC, $5A, $F3, $AD, $40, $F0, $88, $08, $B4, $19, $9E, $33,
    $49, $0D, $EA, $CD, $20, $79, $FB, $2C, $65, $17, $12, $35, $84, $87, $36, $BE,
    $B1, $63, $24, $C9, $3C, $4B, $AE, $EB, $8B, $9B, $98, $6C, $9A, $F2, $80, $D1,
    $34, $8A, $C1, $6D, $82, $D0, $DB, $7E, $8E, $B9, $31, $1E, $7A, $44, $E9, $91,
    $14, $01, $68, $4E, $39, $A4, $AA, $46, $A2, $96, $99, $58, $64, $E6, $56, $D5,
    $8F, $CA, $6F, $76, $54, $03, $AB, $E4, $3E, $8D, $5D, $42, $85, $9C, $78, $F4,
    $10, $B7, $B3, $D6, $A9, $0B, $21, $6A, $BB, $C4, $EE, $07, $81, $BF, $1D, $FE,
    $38, $FF, $7B, $EC, $C7, $A0, $2B, $C5, $55, $A1, $69, $B0, $70, $67, $F7, $3A), (
    $6D, $5E, $46, $E1, $06, $E2, $1F, $7C, $38, $01, $B6, $A9, $26, $CD, $97, $82,
    $E3, $CC, $B3, $67, $E4, $70, $48, $D4, $8A, $C2, $35, $83, $7A, $99, $C7, $22,
    $9D, $37, $B4, $64, $58, $AB, $95, $7F, $18, $8C, $E5, $68, $5F, $B9, $71, $0D,
    $D5, $72, $E6, $20, $69, $F5, $3A, $45, $9F, $28, $D7, $F1, $2C, $62, $D9, $91,
    $A7, $1C, $BC, $9B, $B0, $73, $60, $F9, $EE, $AE, $59, $04, $24, $B5, $BE, $36,
    $2B, $33, $93, $B7, $17, $4C, $FB, $A0, $65, $40, $D0, $85, $A1, $E9, $92, $5B,
    $C0, $50, $66, $53, $15, $21, $DD, $5C, $6F, $E7, $3C, $B2, $49, $B8, $05, $CA,
    $6E, $C5, $F2, $2E, $D6, $7B, $09, $88, $C6, $A4, $BA, $8B, $2A, $A6, $3F, $BF,
    $23, $76, $3D, $11, $DC, $EB, $3E, $E0, $DA, $F6, $F8, $3B, $CE, $94, $6B, $0A,
    $29, $2F, $30, $9A, $A2, $41, $12, $5A, $51, $00, $DF, $19, $E8, $EA, $1B, $61,
    $63, $96, $31, $79, $74, $98, $A3, $0C, $39, $10, $B1, $ED, $CB, $C8, $F3, $C3,
    $4A, $47, $1A, $16, $DE, $43, $27, $9C, $2D, $4D, $56, $84, $AD, $AF, $90, $D8,
    $FA, $CF, $57, $BD, $FD, $32, $54, $34, $13, $4B, $C9, $80, $D3, $1E, $81, $87,
    $07, $6C, $6A, $DB, $52, $8F, $42, $C4, $0F, $89, $7E, $FE, $AA, $F4, $4E, $1D,
    $25, $EF, $D2, $03, $FF, $F7, $EC, $D1, $C1, $A5, $0B, $0E, $75, $5D, $02, $8D,
    $7D, $9E, $86, $78, $77, $4F, $08, $14, $BB, $A8, $F0, $8E, $44, $AC, $55, $FC), (
    $E9, $E1, $07, $AD, $E2, $F8, $F5, $B7, $FC, $49, $13, $48, $D9, $E5, $DE, $87,
    $42, $99, $11, $01, $91, $E3, $43, $3B, $EA, $09, $50, $F7, $33, $C3, $A3, $73,
    $D8, $39, $E8, $E4, $80, $F6, $96, $D3, $6A, $98, $FB, $EF, $2E, $1D, $0D, $81,
    $54, $20, $E6, $9E, $1E, $72, $1A, $C7, $40, $C0, $88, $9F, $FD, $7D, $A1, $D2,
    $92, $84, $4E, $9B, $51, $F0, $68, $8F, $70, $FA, $9A, $EB, $FF, $94, $A6, $12,
    $57, $BC, $04, $0C, $4B, $63, $21, $3C, $95, $02, $2C, $90, $F2, $79, $F3, $E0,
    $CF, $A8, $23, $15, $3D, $37, $52, $CB, $18, $B6, $47, $53, $CA, $41, $60, $6C,
    $D1, $26, $65, $55, $6E, $3F, $7C, $9C, $B1, $F4, $AC, $D6, $56, $34, $8E, $A5,
    $0F, $00, $BA, $D5, $66, $D4, $DC, $0B, $A2, $C1, $67, $F1, $2B, $2F, $7E, $85,
    $30, $32, $03, $BB, $4A, $4F, $C9, $86, $ED, $58, $16, $14, $62, $59, $5A, $B2,
    $AE, $C4, $46, $61, $24, $A0, $6B, $7A, $EC, $5B, $7B, $B5, $76, $5F, $6D, $DF,
    $29, $D0, $3E, $2A, $CD, $A4, $31, $08, $DA, $8A, $B0, $71, $CE, $8D, $4D, $06,
    $4C, $AF, $FE, $97, $5D, $36, $D7, $C5, $1C, $44, $F9, $19, $75, $C8, $DB, $10,
    $7F, $77, $69, $1F, $25, $CC, $BD, $74, $2D, $8C, $AA, $28, $83, $78, $8B, $89,
    $A7, $C2, $5E, $17, $05, $45, $AB, $35, $B4, $B9, $B3, $82, $1B, $27, $64, $9D,
    $38, $BE, $0E, $6F, $22, $E7, $DD, $C6, $A9, $B8, $3A, $5C, $93, $0A, $EE, $BF), (
    $5F, $A5, $04, $60, $09, $3E, $57, $23, $D8, $9A, $1C, $B6, $C3, $F6, $DE, $03,
    $59, $13, $B2, $85, $A7, $FA, $48, $10, $15, $2E, $93, $A4, $14, $F9, $77, $FB,
    $9D, $3F, $D9, $9C, $7B, $50, $A3, $3B, $3A, $62, $29, $49, $A2, $74, $F1, $E3,
    $75, $33, $F4, $43, $2A, $6C, $D1, $0A, $82, $AE, $B3, $4E, $F8, $D7, $1F, $B4,
    $AB, $00, $AA, $6D, $B9, $C7, $C6, $07, $7F, $20, $80, $EF, $0B, $45, $E9, $ED,
    $1B, $36, $E5, $68, $8C, $9E, $A9, $7A, $19, $1D, $BB, $11, $78, $6E, $84, $5D,
    $EA, $6B, $86, $C1, $DF, $4D, $90, $4B, $C9, $CE, $54, $FC, $17, $95, $52, $05,
    $D6, $69, $53, $FD, $A1, $CF, $D0, $CB, $41, $D3, $7D, $BF, $2D, $47, $6A, $02,
    $8D, $8F, $28, $64, $F0, $BA, $E6, $1A, $79, $E0, $EB, $8B, $EC, $B0, $C5, $3C,
    $21, $D5, $66, $A8, $9F, $DA, $16, $E4, $81, $D2, $F7, $CD, $30, $C2, $FE, $4A,
    $87, $F3, $72, $0D, $71, $91, $44, $67, $3D, $65, $37, $B5, $F2, $5A, $27, $18,
    $DB, $C0, $EE, $C4, $DD, $A0, $0F, $40, $6F, $AD, $8E, $4F, $0E, $CA, $32, $A6,
    $2F, $58, $56, $51, $06, $99, $9B, $8A, $2B, $E2, $83, $94, $E8, $26, $5C, $4C,
    $96, $31, $FF, $AC, $70, $88, $35, $25, $E7, $08, $BD, $BC, $76, $55, $46, $22,
    $2C, $7E, $7C, $97, $12, $B1, $F5, $34, $42, $1E, $61, $01, $5B, $B7, $38, $0C,
    $E1, $24, $73, $39, $DC, $92, $5E, $98, $C8, $89, $CC, $BE, $B8, $D4, $AF, $63), (
    $09, $5E, $2D, $7A, $DB, $59, $E4, $19, $C5, $A3, $3A, $5A, $43, $C9, $5B, $D5,
    $42, $75, $13, $97, $E1, $65, $77, $95, $5F, $41, $A6, $B6, $17, $32, $79, $10,
    $70, $7C, $D8, $06, $8A, $1C, $BE, $DF, $E6, $39, $57, $F7, $91, $5C, $88, $D7,
    $33, $63, $15, $8E, $53, $34, $D2, $F6, $7E, $2C, $05, $AF, $AE, $BC, $86, $47,
    $99, $93, $C1, $46, $4B, $73, $3F, $20, $6E, $CD, $52, $23, $FA, $71, $85, $D4,
    $9B, $31, $BD, $25, $90, $72, $2E, $48, $F5, $6B, $1A, $F4, $03, $F3, $30, $36,
    $F0, $A4, $D1, $58, $E5, $1D, $76, $3E, $D3, $6D, $2A, $E7, $12, $50, $6F, $F9,
    $22, $FB, $C7, $EC, $49, $EE, $3B, $8D, $08, $4C, $BA, $E3, $35, $ED, $F2, $C2,
    $E8, $2F, $B2, $B4, $AC, $F1, $FC, $EB, $14, $A8, $74, $7F, $EF, $54, $AD, $B3,
    $02, $6C, $2B, $27, $64, $BB, $40, $EA, $FD, $A0, $7D, $BF, $B8, $DA, $C4, $44,
    $96, $B5, $E9, $9C, $B0, $AB, $E2, $CE, $DE, $37, $66, $29, $C6, $A5, $CA, $A7,
    $B1, $7B, $DD, $0F, $84, $01, $D0, $1E, $0C, $FE, $4E, $D9, $DC, $94, $00, $38,
    $B9, $45, $1B, $69, $C0, $8C, $92, $D6, $18, $04, $A9, $81, $5D, $21, $1F, $9E,
    $98, $A2, $83, $87, $60, $55, $80, $CF, $56, $C8, $3C, $26, $3D, $A1, $FF, $07,
    $F8, $68, $8F, $E0, $4F, $B7, $6A, $0B, $16, $62, $61, $AA, $9D, $0D, $89, $28,
    $9A, $0A, $82, $4A, $C3, $78, $11, $4D, $67, $51, $CC, $0E, $24, $CB, $8B, $9F));

  //RE-ORDERING MATRIX
  P0: array[0..15, 0..15] of longword = (
    ($A, $3, $B, $C, $5, $E, $9, $F, $0, $7, $4, $6, $1, $D, $2, $8),
    ($9, $5, $F, $3, $1, $0, $A, $4, $7, $B, $E, $8, $2, $6, $D, $C),
    ($6, $D, $A, $4, $3, $5, $2, $8, $B, $F, $9, $C, $0, $E, $7, $1),
    ($E, $7, $0, $D, $8, $B, $1, $3, $9, $6, $C, $4, $A, $2, $F, $5),
    ($C, $A, $2, $5, $F, $D, $7, $9, $4, $E, $6, $B, $8, $3, $1, $0),
    ($5, $9, $3, $8, $D, $6, $4, $C, $1, $0, $7, $2, $E, $B, $A, $F),
    ($0, $6, $4, $A, $7, $3, $B, $E, $2, $8, $5, $1, $D, $F, $C, $9),
    ($D, $F, $9, $0, $6, $2, $3, $1, $E, $C, $A, $5, $B, $8, $4, $7),
    ($1, $0, $C, $2, $9, $7, $6, $D, $3, $5, $8, $E, $F, $A, $B, $4),
    ($3, $8, $5, $7, $2, $C, $E, $B, $A, $9, $D, $F, $4, $1, $0, $6),
    ($F, $B, $D, $1, $C, $8, $0, $6, $5, $2, $3, $7, $9, $4, $E, $A),
    ($8, $E, $1, $9, $4, $F, $C, $5, $6, $D, $2, $A, $7, $0, $3, $B),
    ($4, $C, $7, $6, $E, $1, $5, $2, $F, $A, $B, $0, $3, $9, $8, $D),
    ($7, $2, $6, $B, $0, $4, $D, $A, $8, $1, $F, $3, $5, $C, $9, $E),
    ($2, $1, $8, $E, $B, $A, $F, $7, $D, $4, $0, $9, $C, $5, $6, $3),
    ($B, $4, $E, $F, $A, $9, $8, $0, $C, $3, $1, $D, $6, $7, $5, $2));

  //RE-ORDERING MATRIX INVERSE
  P1: array[0..15, 0..15] of longword = (
    ($8, $C, $E, $1, $A, $4, $B, $9, $F, $6, $0, $2, $3, $D, $5, $7),
    ($5, $4, $C, $3, $7, $1, $D, $8, $B, $0, $6, $9, $F, $E, $A, $2),
    ($C, $F, $6, $4, $3, $5, $0, $E, $7, $A, $2, $8, $B, $1, $D, $9),
    ($2, $6, $D, $7, $B, $F, $9, $1, $4, $8, $C, $5, $A, $3, $0, $E),
    ($F, $E, $2, $D, $8, $3, $A, $6, $C, $7, $1, $B, $0, $5, $9, $4),
    ($9, $8, $B, $2, $6, $0, $5, $A, $3, $1, $E, $D, $7, $4, $C, $F),
    ($0, $B, $8, $5, $2, $A, $1, $4, $9, $F, $3, $6, $E, $C, $7, $D),
    ($3, $7, $5, $6, $E, $B, $4, $F, $D, $2, $A, $C, $9, $0, $8, $1),
    ($1, $0, $3, $8, $F, $9, $6, $5, $A, $4, $D, $E, $2, $7, $B, $C),
    ($E, $D, $4, $0, $C, $2, $F, $3, $1, $9, $8, $7, $5, $A, $6, $B),
    ($6, $3, $9, $A, $D, $8, $7, $B, $5, $C, $F, $1, $4, $2, $E, $0),
    ($D, $2, $A, $E, $4, $7, $8, $C, $0, $3, $B, $F, $6, $9, $1, $5),
    ($B, $5, $7, $C, $0, $6, $3, $2, $E, $D, $9, $A, $1, $F, $4, $8),
    ($4, $9, $1, $B, $5, $C, $2, $0, $8, $E, $7, $3, $D, $6, $F, $A),
    ($A, $1, $0, $F, $9, $D, $E, $7, $2, $B, $5, $4, $C, $8, $3, $6),
    ($7, $A, $F, $9, $1, $E, $C, $D, $6, $5, $4, $0, $8, $B, $2, $3));

function Mul(const Factor1, Factor2: longword): longword;
var
  Product: Int64;
  Lhalf, Rhalf: longword;
begin
  Product := Factor1 * Factor2;
  if Product = 0 then
    Result := 1 - Factor1 - Factor2
  else
  begin
    Lhalf := Product shr 32;
    Rhalf := Product and $FFFFFFFF;
    Result := Rhalf - Lhalf;
    if Rhalf < Lhalf then
      Inc(Result);
  end;
end;

procedure BravionEncrypt(var Context: TBravionContext; var B: TBravionBlock32);
var
  Temp: array[0..15] of longword;
  pB: ^TBravionBlock8;
  CarryBit: longword;
  i: integer;
begin
  pB := @B;
  with Context do
  begin
    //ALGORITHM PERMUTATION
    B[0] := B[0] xor RK[PK[16], 0];
    B[1] := B[1] xor RK[PK[17], 1];
    B[2] := B[2] xor RK[PK[18], 2];
    B[3] := B[3] xor RK[PK[19], 3];

    for i := 0 to 15 do //16 ROUNDS
    begin
      //IRRATIONALIZE 8BIT GROUPS
      CarryBit := (B[0] and 2147483648) shr 31;
      B[0] := (B[0] shl 1) or ((B[1] and 2147483648) shr 31);
      B[1] := (B[1] shl 1) or ((B[2] and 2147483648) shr 31);
      B[2] := (B[2] shl 1) or ((B[3] and 2147483648) shr 31);
      B[3] := (B[3] shl 1) or CarryBit;

      //PERMUTATION
      B[3] := B[3] xor (B[2] - RK[i, 3]);
      B[2] := B[2] xor Mul(B[1], RK[i, 2]);
      B[1] := B[1] xor (B[0] + RK[i, 1]);
      B[0] := B[0] xor RK[i, 0];

      //SUBSTITUTION
{if anyone can optimize the following 20 lines please post it as a comment.
Bellow may seem slow, but it's MUCH faster than using Temp as a byte array
and Move(Temp,B,16). This is probably because the compiler is optimized for 32bit integers. An assembly version would be VERY fast.}
      Temp[0] := S0[i, pB^[P0[PK[i], 0]]];
      Temp[1] := S0[i, pB^[P0[PK[i], 1]]];
      Temp[2] := S0[i, pB^[P0[PK[i], 2]]];
      Temp[3] := S0[i, pB^[P0[PK[i], 3]]];
      Temp[4] := S0[i, pB^[P0[PK[i], 4]]];
      Temp[5] := S0[i, pB^[P0[PK[i], 5]]];
      Temp[6] := S0[i, pB^[P0[PK[i], 6]]];
      Temp[7] := S0[i, pB^[P0[PK[i], 7]]];
      Temp[8] := S0[i, pB^[P0[PK[i], 8]]];
      Temp[9] := S0[i, pB^[P0[PK[i], 9]]];
      Temp[10] := S0[i, pB^[P0[PK[i], 10]]];
      Temp[11] := S0[i, pB^[P0[PK[i], 11]]];
      Temp[12] := S0[i, pB^[P0[PK[i], 12]]];
      Temp[13] := S0[i, pB^[P0[PK[i], 13]]];
      Temp[14] := S0[i, pB^[P0[PK[i], 14]]];
      Temp[15] := S0[i, pB^[P0[PK[i], 15]]];
      B[0] := (Temp[3] shl 24) or (Temp[2] shl 16) or (Temp[1] shl 8) or Temp[0];
      B[1] := (Temp[7] shl 24) or (Temp[6] shl 16) or (Temp[5] shl 8) or Temp[4];
      B[2] := (Temp[11] shl 24) or (Temp[10] shl 16) or (Temp[9] shl 8) or Temp[8];
      B[3] := (Temp[15] shl 24) or (Temp[14] shl 16) or (Temp[13] shl 8) or Temp[12];
    end;

    //ALGORITHM PERMUTATION
    B[0] := B[0] xor RK[PK[20], 0];
    B[1] := B[1] xor RK[PK[21], 1];
    B[2] := B[2] xor RK[PK[22], 2];
    B[3] := B[3] xor RK[PK[23], 3];
  end;
end;

procedure BravionDecrypt(var Context: TBravionContext; var B: TBravionBlock32);
var
  Temp: array[0..15] of longword;
  pB: ^TBravionBlock8;
  CarryBit: longword;
  i: integer;
begin
  pB := @B;
  with Context do
  begin
    B[3] := B[3] xor RK[PK[23], 3];
    B[2] := B[2] xor RK[PK[22], 2];
    B[1] := B[1] xor RK[PK[21], 1];
    B[0] := B[0] xor RK[PK[20], 0];

    for i := 15 downto 0 do
    begin
      Temp[0] := S1[i, pB^[P1[PK[i], 0]]];
      Temp[1] := S1[i, pB^[P1[PK[i], 1]]];
      Temp[2] := S1[i, pB^[P1[PK[i], 2]]];
      Temp[3] := S1[i, pB^[P1[PK[i], 3]]];
      Temp[4] := S1[i, pB^[P1[PK[i], 4]]];
      Temp[5] := S1[i, pB^[P1[PK[i], 5]]];
      Temp[6] := S1[i, pB^[P1[PK[i], 6]]];
      Temp[7] := S1[i, pB^[P1[PK[i], 7]]];
      Temp[8] := S1[i, pB^[P1[PK[i], 8]]];
      Temp[9] := S1[i, pB^[P1[PK[i], 9]]];
      Temp[10] := S1[i, pB^[P1[PK[i], 10]]];
      Temp[11] := S1[i, pB^[P1[PK[i], 11]]];
      Temp[12] := S1[i, pB^[P1[PK[i], 12]]];
      Temp[13] := S1[i, pB^[P1[PK[i], 13]]];
      Temp[14] := S1[i, pB^[P1[PK[i], 14]]];
      Temp[15] := S1[i, pB^[P1[PK[i], 15]]];
      B[0] := (Temp[3] shl 24) or (Temp[2] shl 16) or (Temp[1] shl 8) or Temp[0];
      B[1] := (Temp[7] shl 24) or (Temp[6] shl 16) or (Temp[5] shl 8) or Temp[4];
      B[2] := (Temp[11] shl 24) or (Temp[10] shl 16) or (Temp[9] shl 8) or Temp[8];
      B[3] := (Temp[15] shl 24) or (Temp[14] shl 16) or (Temp[13] shl 8) or Temp[12];

      B[0] := B[0] xor RK[i, 0];
      B[1] := B[1] xor (B[0] + RK[i, 1]);
      B[2] := B[2] xor Mul(B[1], RK[i, 2]);
      B[3] := B[3] xor (B[2] - RK[i, 3]);

      CarryBit := (B[3] and 1) shl 31;
      B[3] := (B[3] shr 1) or ((B[2] and 1) shl 31);
      B[2] := (B[2] shr 1) or ((B[1] and 1) shl 31);
      B[1] := (B[1] shr 1) or ((B[0] and 1) shl 31);
      B[0] := (B[0] shr 1) or CarryBit;
    end;

    B[3] := B[3] xor RK[PK[19], 3];
    B[2] := B[2] xor RK[PK[18], 2];
    B[1] := B[1] xor RK[PK[17], 1];
    B[0] := B[0] xor RK[PK[16], 0];
  end;
end;

procedure BravionInit(var Context: TBravionContext; var Key: TBravionKey32);
const
  M1 = longword(259200);
  M2 = longword(134456);
  M3 = longword(243000);
  I1 = longword(7141);
  I2 = longword(8121);
  I3 = longword(4561);
  C1 = longword(54773);
  C2 = longword(28411);
  C3 = longword(51349);

var
  X1, X2, X3: longword;
  R: array[1..97] of real;
  Temp: TBravionBlock32;
  i, j, k: integer;
begin
  with Context do
  begin
    FillChar(PK, Sizeof(TBravionPathKey8), 0);
    FillChar(RK, Sizeof(TBravionRoundKey32), 0);
    i := 0;
    repeat //KEY EXPANSION
      {I'm actualy using a PRNG with 2^32 period for the expansion}
      X1 := (Key[i] + C1) mod M1;
      X1 := (X1 * I1 + C1) mod M1;
      X2 := X1 mod M2;
      X1 := (X1 * I1 + C1) mod M1;
      X3 := X1 mod M3;
      for j := 1 to 97 do
      begin
        X1 := (X1 * I1 + C1) mod M1;
        X2 := (X2 * I2 + C2) mod M2;
        R[j] := (X1 + X2 / M2) / M1;
      end;

      for j := 0 to 3 do
      begin
        X1 := (X1 * I1 + C1) mod M1;
        X2 := (X2 * I2 + C2) mod M2;
        X3 := (X3 * I3 + C3) mod M3;
        k := 1 + (97 * X3) div M3;
        RK[i * 2, j] := trunc($FFFFFFFF * R[k]);
        R[k] := (X1 + X2 / M2) / M1;

        X1 := (X1 * I1 + C1) mod M1;
        X2 := (X2 * I2 + C2) mod M2;
        X3 := (X3 * I3 + C3) mod M3;
        k := 1 + (97 * X3) div M3;
        RK[(i * 2) + 1, j] := trunc($FFFFFFFF * r[k]);
        R[k] := (X1 + X2 / M2) / M1;
      end;
      Inc(i, 1);
    until i = 8;

    for i := 0 to 15 do //SET 4BIT PATH KEYS
    begin
      PK[i] := (TBravionKey8(Key)[i] xor TBravionKey8(Key)[i + 16]) and $F;
      j := 16 + (i and 7);
      PK[j] := PK[j] xor ((TBravionKey8(Key)[i] xor TBravionKey8(Key)[i + 16]) and $F0)
        shr 4;
    end;
  end;

  for i := 0 to 127 do //PERMUTE ROUND KEYS
  begin
    j := 0;
    repeat
      Move(Key[0], Temp, Sizeof(TBravionBlock32));
      BravionEncrypt(Context, Temp);
      Move(Temp, Context.RK[j], Sizeof(TBravionBlock32));

      Move(Key[4], Temp, Sizeof(TBravionBlock32));
      BravionEncrypt(Context, Temp);
      Move(Temp, Context.RK[j + 1], Sizeof(TBravionBlock32));
      Inc(j, 2);
    until j = 16;
  end;
end;

end.

Using the encryption is very simple:

procedure TForm1.Button1Click(Sender: TObject);
var
  k: TBravionKey32;
  b: TBravionBlock32;
  c: TBravionContext;
  s: string;
  i: longword;
begin
  randomize;
  for i := 0 to 7 do
    k[i] := Random(MaxInt);
  for i := 0 to 3 do
    b[i] := Random(MaxInt);
  BravionInit(c, k);

  s := 'Key: {';
  for i := 0 to 15 do
    s := s + inttohex(TBravionKey8(k)[i], 2);
  memo1.lines.add(s + ',');

  s := '         ';
  for i := 16 to 31 do
    s := s + inttohex(TBravionKey8(k)[i], 2);
  memo1.lines.add(s + '}');

  s := 'Plaintext:    {';
  for i := 0 to 15 do
    s := s + inttohex(TBravionBlock8(b)[i], 2);
  memo1.lines.add(s + '}');

  BravionEncrypt(c, b);
  s := 'Ciphertext: {';
  for i := 0 to 15 do
    s := s + inttohex(TBravionBlock8(b)[i], 2);
  memo1.lines.add(s + '}');

  BravionDecrypt(c, b);
  s := 'Plaintext:    {';
  for i := 0 to 15 do
    s := s + inttohex(TBravionBlock8(b)[i], 2);
  memo1.lines.add(s + '}');
  memo1.lines.add('');
end;

this example requires a form, button and memo. it's pretty self explanatory.

<< Back to main page