xtool/contrib/CoreCipher/Source/CoreCipher.pas

10206 lines
394 KiB
ObjectPascal

{ ****************************************************************************** }
{ * Core cipher Library ,writen by QQ 600585@qq.com * }
{ * https://zpascal.net * }
{ * https://github.com/PassByYou888/zAI * }
{ * https://github.com/PassByYou888/ZServer4D * }
{ * https://github.com/PassByYou888/PascalString * }
{ * https://github.com/PassByYou888/zRasterization * }
{ * https://github.com/PassByYou888/CoreCipher * }
{ * https://github.com/PassByYou888/zSound * }
{ * https://github.com/PassByYou888/zChinese * }
{ * https://github.com/PassByYou888/zExpression * }
{ * https://github.com/PassByYou888/zGameWare * }
{ * https://github.com/PassByYou888/zAnalysis * }
{ * https://github.com/PassByYou888/FFMPEG-Header * }
{ * https://github.com/PassByYou888/zTranslate * }
{ * https://github.com/PassByYou888/InfiniteIoT * }
{ * https://github.com/PassByYou888/FastMD5 * }
{ ****************************************************************************** }
(*
update history
2017-11-26
fixed fastMD5,THashMD5 calculate x64 and x86,ARM platform more than 4G memory Support QQ600585
change name TMD5Class as THashMD5
Added global DefaultParallelDepth
2017-12-6
added supported hash elf64
2017-12-7
added System default key
2018-5-16
remove pasmp
2018-9
fixed rc6 with arm Linux
*)
unit CoreCipher;
{ core cipher engine. create by qq600585 }
{$INCLUDE zDefine.inc}
// debug used
// {$UNDEF RangeCheck}
// {$UNDEF OverflowCheck}
{$O+}
interface
uses
Types, SysUtils, Math, TypInfo,
{$IFDEF FastMD5}
Fast_MD5,
{$ENDIF}
CoreClasses, UnicodeMixedLib, MemoryStream64, PascalStrings, ListEngine;
{$REGION 'BaseDefine'}
const
{ largest structure that can be created }
MaxStructSize = MaxInt; { 2G }
cIntSize = 4;
cKeyDWORDSize = 4;
cKey2DWORDSize = 8;
cKey64Size = 8;
cKey128Size = 16;
cKey192Size = 24;
cKey256Size = 32;
type
PDWORD = ^DWORD;
{ general structures }
PDWordArray = ^TDWordArray;
TDWordArray = array [0 .. MaxStructSize div SizeOf(DWORD) - 1] of DWORD;
TCCByteArray = array [0 .. MaxStructSize div SizeOf(Byte) - 1] of Byte;
PCCByteArray = ^TCCByteArray;
TInt32 = packed record
case Byte of
1: (Lo: Word;
Hi: Word);
2: (LoLo: Byte;
LoHi: Byte;
HiLo: Byte;
HiHi: Byte);
3: (i: Integer);
4: (u: DWORD);
end;
TInt64 = packed record
case Byte of
0: (Lo: Integer;
Hi: Integer);
1: (LoLo: Word;
LoHi: Word;
HiLo: Word;
HiHi: Word);
2: (LoLoLo: Byte;
LoLoHi: Byte;
LoHiLo: Byte;
LoHiHi: Byte;
HiLoLo: Byte;
HiLoHi: Byte;
HiHiLo: Byte;
HiHiHi: Byte);
3: (i: Int64);
4: (u: UInt64);
end;
{ encryption key types }
type
PKey64 = ^TKey64; { !!.03 }
TKey64 = array [0 .. 7] of Byte;
PKey128 = ^TKey128; { !!.03 }
TKey128 = array [0 .. 15] of Byte;
PKey256 = ^TKey256; { !!.03 }
TKey256 = array [0 .. 31] of Byte;
{ encryption block types }
PLBCBlock = ^TLBCBlock;
TLBCBlock = array [0 .. 3] of DWORD; { LBC block }
PDESBlock = ^TDESBlock;
TDESBlock = array [0 .. 7] of Byte; { DES block }
PLQCBlock = ^TLQCBlock;
TLQCBlock = array [0 .. 1] of DWORD; { Quick Cipher,no LBC key generate }
PBFBlock = ^TBFBlock;
TBFBlock = array [0 .. 1] of DWORD; { BlowFish }
PXXTEABlock = ^TXXTEABlock;
TXXTEABlock = array [0 .. 63] of Byte; { XXTEA }
TDesConverter = packed record
case Byte of
0: (Bytes: array [0 .. 7] of Byte);
1: (DWords: array [0 .. 1] of DWORD)
end;
P128Bit = ^T128Bit;
T128Bit = array [0 .. 3] of DWORD;
P256Bit = ^T256Bit;
T256Bit = array [0 .. 7] of DWORD;
TTransformOutput = array [0 .. 3] of DWORD;
PTransformInput = ^TTransformInput;
TTransformInput = array [0 .. 15] of DWORD;
{ context type constants }
const
BFRounds = 16; { 16 blowfish rounds }
{ block cipher context types }
type
{ Blowfish }
PBFContext = ^TBFContext;
TBFContext = packed record
PBox: array [0 .. (BFRounds + 1)] of DWORD;
SBox: array [0 .. 3, 0 .. 255] of DWORD;
end;
{ DES }
PDESContext = ^TDESContext;
TDESContext = packed record
TransformedKey: array [0 .. 31] of DWORD;
Encrypt: Boolean;
end;
{ 3 DES }
PTripleDESContext = ^TTripleDESContext;
TTripleDESContext = array [0 .. 1] of TDESContext;
PTripleDESContext3Key = ^TTripleDESContext3Key;
TTripleDESContext3Key = array [0 .. 2] of TDESContext; { !!.01 }
{ LBC Cipher context }
PLBCContext = ^TLBCContext;
TLBCContext = packed record
Encrypt: Boolean;
Dummy: array [0 .. 2] of Byte; { filler }
Rounds: Integer;
case Byte of
0: (SubKeys64: array [0 .. 15] of TKey64);
1: (SubKeysInts: array [0 .. 3, 0 .. 7] of DWORD);
end;
{ LSC stream cipher }
PLSCContext = ^TLSCContext;
TLSCContext = packed record
index: Integer;
Accumulator: Integer;
SBox: array [0 .. 255] of Byte;
end;
{ random number stream ciphers }
PRNG32Context = ^TRNG32Context;
TRNG32Context = array [0 .. 3] of Byte;
PRNG64Context = ^TRNG64Context;
TRNG64Context = array [0 .. 7] of Byte;
{ message digest blocks }
PMD5Digest = ^TMD5Digest;
TMD5Digest = TMD5; { 128 bits - MD5 }
TMD5Key = TMD5Digest;
PSHA1Digest = ^TSHA1Digest;
TSHA1Digest = array [0 .. 19] of Byte; { 160 bits - SHA-1 }
TSHA1Key = TSHA1Digest;
PSHA256Digest = ^TSHA256Digest;
TSHA256Digest = array [0 .. 31] of Byte; { 256 bits - SHA-256 }
TSHA256Key = TSHA256Digest;
PSHA512Digest = ^TSHA512Digest;
TSHA512Digest = array [0 .. 63] of Byte; { 512 bits - SHA-512 }
TSHA512Key = TSHA512Digest;
PSHA3_224_Digest = ^TSHA3_224_Digest;
PSHA3_256_Digest = ^TSHA3_256_Digest;
PSHA3_384_Digest = ^TSHA3_384_Digest;
PSHA3_512_Digest = ^TSHA3_512_Digest;
TSHA3_224_Digest = array [0 .. 224 div 8 - 1] of Byte;
TSHA3_256_Digest = array [0 .. 256 div 8 - 1] of Byte;
TSHA3_384_Digest = array [0 .. 384 div 8 - 1] of Byte;
TSHA3_512_Digest = array [0 .. 512 div 8 - 1] of Byte;
{ message digest context types }
TLMDContext = packed record
DigestIndex: Integer;
Digest: array [0 .. 255] of Byte;
KeyIndex: Integer;
case Byte of
0: (KeyInts: array [0 .. 3] of DWORD);
1: (key: TKey128);
end;
PMD5Context = ^TMD5Context;
TMD5Context = packed record { MD5 }
Count: array [0 .. 1] of DWORD; { number of bits handled mod 2^64 }
State: TTransformOutput; { scratch buffer }
Buf: array [0 .. 63] of Byte; { input buffer }
end;
TSHA1Context = packed record { SHA-1 }
sdHi: DWORD;
sdLo: DWORD;
sdIndex: nativeUInt;
sdHash: array [0 .. 4] of DWORD;
sdBuf: array [0 .. 63] of Byte;
end;
{$ENDREGION 'BaseDefine'}
type
{ key style and auto Encrypt }
TCipherSecurity = (csNone,
csDES64, csDES128, csDES192,
csBlowfish, csLBC, csLQC, csRNG32, csRNG64, csLSC,
// mini cipher
csXXTea512,
// NIST cipher
csRC6, csSerpent, csMars, csRijndael, csTwoFish);
TCipherSecuritys = set of TCipherSecurity;
TCipherSecurityArray = array of TCipherSecurity;
TCipherKeyStyle = (cksNone, cksKey64, cks3Key64, cksKey128, cksKey256, cks2IntKey, cksIntKey, ckyDynamicKey);
PCipherKeyBuffer = ^TCipherKeyBuffer;
TCipherKeyBuffer = TBytes;
THashSecurity = (
hsNone,
hsFastMD5, hsMD5, hsSHA1, hsSHA256, hsSHA512,
hsSHA3_224, hsSHA3_256, hsSHA3_384, hsSHA3_512,
hs256, hs128, hs64, hs32, hs16, hsELF, hsELF64, hsMix128, hsCRC16, hsCRC32);
THashSecuritys = set of THashSecurity;
TCipher = class(TCoreClassObject)
public const
CAllHash: THashSecuritys = [
hsNone,
hsFastMD5, hsMD5, hsSHA1, hsSHA256, hsSHA512,
hsSHA3_224, hsSHA3_256, hsSHA3_384, hsSHA3_512,
hs256, hs128, hs64, hs32, hs16, hsELF, hsELF64, hsMix128, hsCRC16, hsCRC32];
CHashName: array [THashSecurity] of SystemString = (
'None',
'FastMD5', 'MD5', 'SHA1', 'SHA256', 'SHA512',
'SHA3_224', 'SHA3_256', 'SHA3_384', 'SHA3_512',
'256', '128', '64', '32', '16', 'ELF', 'ELF64', 'Mix128', 'CRC16', 'CRC32');
CCipherSecurityName: array [TCipherSecurity] of SystemString =
('None',
'DES64', 'DES128', 'DES192',
'Blowfish', 'LBC', 'LQC', 'RNG32', 'RNG64', 'LSC',
'XXTea512',
'RC6', 'Serpent', 'Mars', 'Rijndael', 'TwoFish');
cCipherKeyStyle: array [TCipherSecurity] of TCipherKeyStyle =
(
cksNone, // csNone
cksKey64, // csDES64
cksKey128, // csDES128
cks3Key64, // csDES192
cksKey128, // csBlowfish
cksKey128, // csLBC
cksKey128, // csLQC
cksIntKey, // csRNG32
cks2IntKey, // csRNG64
ckyDynamicKey, // csLSC
cksKey128, // csXXTea512
ckyDynamicKey, // csRC6
ckyDynamicKey, // csSerpent
ckyDynamicKey, // csMars
ckyDynamicKey, // csRijndael
ckyDynamicKey // csTwoFish
);
public
class function AllCipher: TCipherSecurityArray;
class function NameToHashSecurity(n: SystemString; var hash: THashSecurity): Boolean;
class function BuffToString(buff: Pointer; Size: NativeInt): TPascalString; overload;
class function StringToBuff(const Hex: TPascalString; var Buf; BufSize: Cardinal): Boolean; overload;
class procedure HashToString(hash: Pointer; Size: NativeInt; var output: TPascalString); overload;
class procedure HashToString(hash: TSHA3_224_Digest; var output: TPascalString); overload;
class procedure HashToString(hash: TSHA3_256_Digest; var output: TPascalString); overload;
class procedure HashToString(hash: TSHA3_384_Digest; var output: TPascalString); overload;
class procedure HashToString(hash: TSHA3_512_Digest; var output: TPascalString); overload;
class procedure HashToString(hash: TSHA512Digest; var output: TPascalString); overload;
class procedure HashToString(hash: TSHA256Digest; var output: TPascalString); overload;
class procedure HashToString(hash: TSHA1Digest; var output: TPascalString); overload;
class procedure HashToString(hash: TMD5Digest; var output: TPascalString); overload;
class procedure HashToString(hash: TBytes; var output: TPascalString); overload;
class procedure HashToString(hash: TBytes; var output: SystemString); overload;
class function CompareHash(h1, h2: TSHA3_224_Digest): Boolean; overload;
class function CompareHash(h1, h2: TSHA3_256_Digest): Boolean; overload;
class function CompareHash(h1, h2: TSHA3_384_Digest): Boolean; overload;
class function CompareHash(h1, h2: TSHA3_512_Digest): Boolean; overload;
class function CompareHash(h1, h2: TSHA512Digest): Boolean; overload;
class function CompareHash(h1, h2: TSHA256Digest): Boolean; overload;
class function CompareHash(h1, h2: TSHA1Digest): Boolean; overload;
class function CompareHash(h1, h2: TMD5Digest): Boolean; overload;
class function CompareHash(h1, h2: Pointer; Size: NativeInt): Boolean; overload;
class function CompareHash(h1, h2: TBytes): Boolean; overload;
class function CompareKey(k1, k2: TCipherKeyBuffer): Boolean; overload;
class function GenerateSHA3_224Hash(sour: Pointer; Size: NativeInt): TSHA3_224_Digest;
class function GenerateSHA3_256Hash(sour: Pointer; Size: NativeInt): TSHA3_256_Digest;
class function GenerateSHA3_384Hash(sour: Pointer; Size: NativeInt): TSHA3_384_Digest;
class function GenerateSHA3_512Hash(sour: Pointer; Size: NativeInt): TSHA3_512_Digest;
class function GenerateSHA512Hash(sour: Pointer; Size: NativeInt): TSHA512Digest;
class function GenerateSHA256Hash(sour: Pointer; Size: NativeInt): TSHA256Digest;
class function GenerateSHA1Hash(sour: Pointer; Size: NativeInt): TSHA1Digest;
class function GenerateMD5Hash(sour: Pointer; Size: NativeInt): TMD5Digest;
class procedure GenerateMDHash(sour: Pointer; Size: NativeInt; OutHash: Pointer; HashSize: NativeInt);
class procedure GenerateHashByte(hs: THashSecurity; sour: Pointer; Size: NativeInt; var output: TBytes);
class function GenerateHashString(hs: THashSecurity; sour: Pointer; Size: NativeInt): TPascalString;
class function BufferToHex(const Buf; BufSize: Cardinal): TPascalString;
class function HexToBuffer(const Hex: TPascalString; var Buf; BufSize: Cardinal): Boolean;
class function CopyKey(const k: TCipherKeyBuffer): TCipherKeyBuffer;
class procedure GenerateNoneKey(var output: TCipherKeyBuffer);
class procedure GenerateKey64(const s: TPascalString; var output: TCipherKeyBuffer); overload;
class procedure GenerateKey64(sour: Pointer; Size: NativeInt; var output: TCipherKeyBuffer); overload;
class procedure GenerateKey128(const s: TPascalString; var output: TCipherKeyBuffer); overload;
class procedure GenerateKey128(sour: Pointer; Size: NativeInt; var output: TCipherKeyBuffer); overload;
class procedure GenerateKey256(const s: TPascalString; var output: TCipherKeyBuffer); overload;
class procedure GenerateKey256(sour: Pointer; Size: NativeInt; var output: TCipherKeyBuffer); overload;
class procedure Generate3Key64(const s: TPascalString; var output: TCipherKeyBuffer); overload;
class procedure Generate3Key64(sour: Pointer; Size: NativeInt; var output: TCipherKeyBuffer); overload;
class procedure Generate2IntKey(const s: TPascalString; var output: TCipherKeyBuffer); overload;
class procedure Generate2IntKey(sour: Pointer; Size: NativeInt; var output: TCipherKeyBuffer); overload;
class procedure GenerateIntKey(const s: TPascalString; var output: TCipherKeyBuffer); overload;
class procedure GenerateIntKey(sour: Pointer; Size: NativeInt; var output: TCipherKeyBuffer); overload;
class procedure GenerateBytesKey(const s: TPascalString; KeySize: DWORD; var output: TCipherKeyBuffer); overload;
class procedure GenerateBytesKey(sour: Pointer; Size, KeySize: DWORD; var output: TCipherKeyBuffer); overload;
class procedure GenerateKey64(const k: TKey64; var output: TCipherKeyBuffer); overload;
class procedure GenerateKey128(const k1, k2: TKey64; var output: TCipherKeyBuffer); overload;
class procedure GenerateKey(const k: TKey64; var output: TCipherKeyBuffer); overload;
class procedure GenerateKey(const k1, k2, k3: TKey64; var output: TCipherKeyBuffer); overload;
class procedure GenerateKey(const k: TKey128; var output: TCipherKeyBuffer); overload;
class procedure GenerateKey(const k: TKey256; var output: TCipherKeyBuffer); overload;
class procedure GenerateKey(const k1, k2: DWORD; var output: TCipherKeyBuffer); overload;
class procedure GenerateKey(const k: DWORD; var output: TCipherKeyBuffer); overload;
class procedure GenerateKey(const key: PByte; Size: DWORD; var output: TCipherKeyBuffer); overload;
class procedure GenerateKey(cs: TCipherSecurity; buffPtr: Pointer; Size: NativeInt; var output: TCipherKeyBuffer); overload;
class procedure GenerateKey(cs: TCipherSecurity; s: TPascalString; var output: TCipherKeyBuffer); overload;
class function GetKeyStyle(const p: PCipherKeyBuffer): TCipherKeyStyle; overload;
class function GetKey(const KeyBuffPtr: PCipherKeyBuffer; var k: TKey64): Boolean; overload;
class function GetKey(const KeyBuffPtr: PCipherKeyBuffer; var k1, k2, k3: TKey64): Boolean; overload;
class function GetKey(const KeyBuffPtr: PCipherKeyBuffer; var k: TKey128): Boolean; overload;
class function GetKey(const KeyBuffPtr: PCipherKeyBuffer; var k: TKey256): Boolean; overload;
class function GetKey(const KeyBuffPtr: PCipherKeyBuffer; var k1, k2: DWORD): Boolean; overload;
class function GetKey(const KeyBuffPtr: PCipherKeyBuffer; var k: DWORD): Boolean; overload;
class function GetKey(const KeyBuffPtr: PCipherKeyBuffer; var key: TBytes): Boolean; overload;
class procedure EncryptTail(TailPtr: Pointer; TailSize: NativeInt);
class function DES64(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
class function DES128(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
class function DES192(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
class function Blowfish(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
class function LBC(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
class function LQC(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
class function RNG32(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer): Boolean;
class function RNG64(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer): Boolean;
class function LSC(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer): Boolean;
class function TwoFish(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
class function XXTea512(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
class function RC6(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
class function Serpent(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
class function Mars(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
class function Rijndael(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
class procedure BlockCBC(sour: Pointer; Size: NativeInt; boxBuff: Pointer; boxSiz: NativeInt);
class function EncryptBuffer(cs: TCipherSecurity; sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
class function EncryptBufferCBC(cs: TCipherSecurity; sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
end;
{$IFDEF Parallel}
TParallelCipher = class(TCoreClassObject)
private type
TParallelCipherFunc = procedure(Job, buff, key: Pointer; Size: NativeInt) of object;
PParallelCipherJobData = ^TParallelCipherJobData;
TParallelCipherJobData = packed record
cipherFunc: TParallelCipherFunc;
KeyBuffer: Pointer;
OriginBuffer: Pointer;
BlockLen: NativeInt;
TotalBlock: NativeInt;
CompletedBlock: NativeInt;
Encrypt: Boolean;
end;
protected
procedure DES64_Parallel(Job, buff, key: Pointer; Size: NativeInt);
procedure DES128_Parallel(Job, buff, key: Pointer; Size: NativeInt);
procedure DES192_Parallel(Job, buff, key: Pointer; Size: NativeInt);
procedure Blowfish_Parallel(Job, buff, key: Pointer; Size: NativeInt);
procedure LBC_Parallel(Job, buff, key: Pointer; Size: NativeInt);
procedure LQC_Parallel(Job, buff, key: Pointer; Size: NativeInt);
procedure TwoFish_Parallel(Job, buff, key: Pointer; Size: NativeInt);
procedure XXTea512_Parallel(Job, buff, key: Pointer; Size: NativeInt);
procedure RC6_Parallel(Job, buff, key: Pointer; Size: NativeInt);
procedure Serpent_Parallel(Job, buff, key: Pointer; Size: NativeInt);
procedure Mars_Parallel(Job, buff, key: Pointer; Size: NativeInt);
procedure Rijndael_Parallel(Job, buff, key: Pointer; Size: NativeInt);
procedure BlockCBC_Parallel(Job, buff, key: Pointer; Size: NativeInt);
procedure ParallelCipherCall(const JobData: PParallelCipherJobData; const FromIndex, ToIndex: Integer);
procedure RunParallel(const JobData: PParallelCipherJobData; const Total, Depth: Integer);
public
BlockDepth: Integer;
constructor Create;
destructor Destroy; override;
function DES64(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
function DES128(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
function DES192(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
function Blowfish(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
function LBC(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
function LQC(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
function TwoFish(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
function XXTea512(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
function RC6(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
function Serpent(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
function Mars(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
function Rijndael(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
procedure BlockCBC(sour: Pointer; Size: NativeInt; boxBuff: Pointer; boxSiz: NativeInt);
function EncryptBuffer(cs: TCipherSecurity; sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
function EncryptBufferCBC(cs: TCipherSecurity; sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
end;
{$ENDIF}
var
{ system default cbc refrence }
SystemCBC: TBytes;
{$IFDEF Parallel}
{ system default Parallel depth }
DefaultParallelDepth: Integer; // default cpucount * 2
ParallelTriggerCondition: Integer; // default 1024
{$ENDIF}
procedure InitSysCBCAndDefaultKey(rand: Int64);
function SequEncryptWithDirect(const cs: TCipherSecurity; sour: Pointer; Size: NativeInt; const key: TCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean; overload;
function SequEncryptWithDirect(const ca: TCipherSecurityArray; sour: Pointer; Size: NativeInt; const key: TCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean; overload;
{$IFDEF Parallel}
function SequEncryptWithParallel(const cs: TCipherSecurity; sour: Pointer; Size: NativeInt; const key: TCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean; overload;
function SequEncryptWithParallel(const ca: TCipherSecurityArray; sour: Pointer; Size: NativeInt; const key: TCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean; overload;
{$ENDIF}
function SequEncrypt(const ca: TCipherSecurityArray; sour: Pointer; Size: NativeInt; const key: TCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean; overload;
function SequEncrypt(const cs: TCipherSecurity; sour: Pointer; Size: NativeInt; const key: TCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean; overload;
function SequEncryptCBCWithDirect(const cs: TCipherSecurity; sour: Pointer; Size: NativeInt; const key: TCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean; overload;
function SequEncryptCBCWithDirect(const ca: TCipherSecurityArray; sour: Pointer; Size: NativeInt; const key: TCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean; overload;
{$IFDEF Parallel}
function SequEncryptCBCWithParallel(const cs: TCipherSecurity; sour: Pointer; Size: NativeInt; const key: TCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean; overload;
function SequEncryptCBCWithParallel(const ca: TCipherSecurityArray; sour: Pointer; Size: NativeInt; const key: TCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean; overload;
{$ENDIF}
function SequEncryptCBC(const ca: TCipherSecurityArray; sour: Pointer; Size: NativeInt; const key: TCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean; overload;
function SequEncryptCBC(const cs: TCipherSecurity; sour: Pointer; Size: NativeInt; const key: TCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean; overload;
function GenerateSequHash(hssArry: THashSecuritys; sour: Pointer; Size: NativeInt): TPascalString; overload;
procedure GenerateSequHash(hssArry: THashSecuritys; sour: Pointer; Size: NativeInt; output: TListPascalString); overload;
procedure GenerateSequHash(hssArry: THashSecuritys; sour: Pointer; Size: NativeInt; output: TCoreClassStream); overload;
function CompareSequHash(HashVL: THashStringList; sour: Pointer; Size: NativeInt): Boolean; overload;
function CompareSequHash(hashData: TPascalString; sour: Pointer; Size: NativeInt): Boolean; overload;
function CompareSequHash(hashData: TListPascalString; sour: Pointer; Size: NativeInt): Boolean; overload;
function CompareSequHash(hashData: TCoreClassStream; sour: Pointer; Size: NativeInt): Boolean; overload;
function GenerateMemoryHash(hssArry: THashSecuritys; sour: Pointer; Size: NativeInt): TPascalString;
function CompareMemoryHash(sour: Pointer; Size: NativeInt; const hashBuff: TPascalString): Boolean;
function GeneratePasswordHash(hssArry: THashSecuritys; const passwd: TPascalString): TPascalString;
function ComparePasswordHash(const passwd, hashBuff: TPascalString): Boolean;
function GeneratePassword(const ca: TCipherSecurityArray; const passwd: TPascalString): TPascalString; overload;
function ComparePassword(const ca: TCipherSecurityArray; const passwd, passwdDataSource: TPascalString): Boolean; overload;
function GeneratePassword(const cs: TCipherSecurity; const passwd: TPascalString): TPascalString; overload;
function ComparePassword(const cs: TCipherSecurity; const passwd, passwdDataSource: TPascalString): Boolean; overload;
{
QuantumCryptographyPassword: used sha-3 shake256 cryptography as 512 bits password
SHA-3 (Secure Hash Algorithm 3) is the latest member of the Secure Hash Algorithm family of standards,
released by NIST on August 5, 2015.[4][5] Although part of the same series of standards,
SHA-3 is internally quite different from the MD5-like structure of SHA-1 and SHA-2.
Keccak is based on a novel approach called sponge construction.
Sponge construction is based on a wide random function or random permutation, and allows inputting ("absorbing" in sponge terminology) any amount of data,
and outputting ("squeezing") any amount of data,
while acting as a pseudorandom function with regard to all previous inputs. This leads to great flexibility.
NIST does not currently plan to withdraw SHA-2 or remove it from the revised Secure Hash Standard.
The purpose of SHA-3 is that it can be directly substituted for SHA-2 in current applications if necessary,
and to significantly improve the robustness of NIST's overall hash algorithm toolkit
ref wiki
https://en.wikipedia.org/wiki/SHA-3
}
function GenerateQuantumCryptographyPassword(const passwd: TPascalString): TPascalString;
function CompareQuantumCryptographyPassword(const passwd, passwdDataSource: TPascalString): Boolean;
// QuantumCryptography for Stream support: used sha-3-512 cryptography as 512 bits password
procedure QuantumEncrypt(input, output: TCoreClassStream; SecurityLevel: Integer; key: TCipherKeyBuffer);
function QuantumDecrypt(input, output: TCoreClassStream; key: TCipherKeyBuffer): Boolean;
procedure TestCoreCipher;
{$REGION 'cryptAndHash'}
type
{ Blowfish Cipher }
TBlowfish = class(TCoreClassObject)
public
class procedure EncryptBF(const Context: TBFContext; var Block: TBFBlock; Encrypt: Boolean);
class procedure InitEncryptBF(key: TKey128; var Context: TBFContext);
end;
{ DES Cipher }
TDES = class(TCoreClassObject)
strict private
class procedure JoinBlock(const l, r: DWORD; var Block: TDESBlock);
class procedure SplitBlock(const Block: TDESBlock; var l, r: DWORD);
private
public
class procedure EncryptDES(const Context: TDESContext; var Block: TDESBlock);
class procedure EncryptTripleDES(const Context: TTripleDESContext; var Block: TDESBlock);
class procedure EncryptTripleDES3Key(const Context: TTripleDESContext3Key; var Block: TDESBlock);
class procedure InitEncryptDES(const key: TKey64; var Context: TDESContext; Encrypt: Boolean);
class procedure InitEncryptTripleDES(const key: TKey128; var Context: TTripleDESContext; Encrypt: Boolean);
class procedure InitEncryptTripleDES3Key(const Key1, Key2, Key3: TKey64; var Context: TTripleDESContext3Key; Encrypt: Boolean);
class procedure ShrinkDESKey(var key: TKey64);
end;
{ SHA1 }
TSHA1 = class(TCoreClassObject)
strict private
class procedure SHA1Clear(var Context: TSHA1Context);
class procedure SHA1Hash(var Context: TSHA1Context);
class function SHA1SwapByteOrder(n: DWORD): DWORD;
class procedure SHA1UpdateLen(var Context: TSHA1Context; Len: DWORD);
public
class procedure FinalizeSHA1(var Context: TSHA1Context; var Digest: TSHA1Digest);
class procedure SHA1(var Digest: TSHA1Digest; const Buf; BufSize: nativeUInt);
class procedure InitSHA1(var Context: TSHA1Context);
class procedure ByteBuffSHA1(var Digest: TSHA1Digest; const ABytes: TBytes);
class procedure UpdateSHA1(var Context: TSHA1Context; const Buf; BufSize: nativeUInt);
end;
{ SHA-2-SHA256 }
TSHA256 = class(TCoreClassObject)
private
class procedure SwapDWORD(var a: DWORD);
class procedure Compute(var Digest: TSHA256Digest; const buff: Pointer);
public
class procedure SHA256(var Digest: TSHA256Digest; const Buf; BufSize: nativeUInt);
end;
{ SHA-2-SHA512 }
TSHA512 = class(TCoreClassObject)
private
class procedure SwapQWORD(var a: UInt64);
class procedure Compute(var Digest: TSHA512Digest; const buff: Pointer);
public
class procedure SHA512(var Digest: TSHA512Digest; const Buf; BufSize: UInt64);
end;
{ SHA-3:SHA224,SHA256,SHA384,SHA512,SHAKE128,SHAKE256 }
TSHA3 = class(TCoreClassObject)
private type
TSHA3Context = record
HashLength: DWORD;
BlockLen: DWORD;
Buffer: array of Byte;
BufSize: DWORD;
a, b: array [0 .. 24] of UInt64;
c, d: array [0 .. 4] of UInt64;
end;
private const
// Round constants
RC: array [0 .. 23] of UInt64 = (
$0000000000000001, $0000000000008082, $800000000000808A, $8000000080008000,
$000000000000808B, $0000000080000001, $8000000080008081, $8000000000008009,
$000000000000008A, $0000000000000088, $0000000080008009, $000000008000000A,
$000000008000808B, $800000000000008B, $8000000000008089, $8000000000008003,
$8000000000008002, $8000000000000080, $000000000000800A, $800000008000000A,
$8000000080008081, $8000000000008080, $0000000080000001, $8000000080008008);
// Rotation offsets
RO: array [0 .. 24] of Integer = (0, 1, 62, 28, 27, 36, 44, 6, 55, 20, 3, 10, 43, 25, 39, 41, 45, 15, 21, 8, 18, 2, 61, 56, 14);
private
class function ComputeX(const x: Integer): Integer; inline;
class function ComputeXY(const x, y: Integer): Integer; inline;
class procedure BlockSHA3(var Context: TSHA3Context);
class procedure InitializeSHA3(var Context: TSHA3Context; HashLength: Integer);
class procedure SHA3(var Context: TSHA3Context; Chunk: PByte; Size: NativeInt);
class procedure FinalizeSHA3(var Context: TSHA3Context; const output: PCCByteArray);
class procedure FinalizeSHAKE(var Context: TSHA3Context; Limit: Integer; const output: PCCByteArray);
public
class procedure SHA224(var Digest: TSHA3_224_Digest; Buf: PByte; BufSize: NativeInt);
class procedure SHA256(var Digest: TSHA3_256_Digest; Buf: PByte; BufSize: NativeInt);
class procedure SHA384(var Digest: TSHA3_384_Digest; Buf: PByte; BufSize: NativeInt);
class procedure SHA512(var Digest: TSHA3_512_Digest; Buf: PByte; BufSize: NativeInt);
class procedure SHAKE128(const Digest: PCCByteArray; Buf: PByte; BufSize: NativeInt; Limit: Integer);
class procedure SHAKE256(const Digest: PCCByteArray; Buf: PByte; BufSize: NativeInt; Limit: Integer);
end;
{ LBC Cipher }
TLBC = class(TCoreClassObject)
public
class procedure EncryptLBC(const Context: TLBCContext; var Block: TLBCBlock);
class procedure EncryptLQC(const key: TKey128; var Block: TLQCBlock; Encrypt: Boolean);
class procedure InitEncryptLBC(const key: TKey128; var Context: TLBCContext; Rounds: Integer; Encrypt: Boolean);
end;
{ MD5 }
THashMD5 = class(TCoreClassObject)
public
class procedure FinalizeMD5(var Context: TMD5Context; var Digest: TMD5Digest);
class procedure GenerateMD5Key(var key: TKey128; const ABytes: TBytes);
class procedure HashMD5(var Digest: TMD5Digest; const Buf; BufSize: NativeInt);
class procedure InitMD5(var Context: TMD5Context);
class procedure ByteBuffHashMD5(var Digest: TMD5Digest; const ABytes: TBytes);
class procedure UpdateMD5(var Context: TMD5Context; const Buf; BufSize: NativeInt);
end;
{ message digest }
THashMD = class(TCoreClassObject)
public
class procedure FinalizeLMD(var Context: TLMDContext; var Digest; DigestSize: Integer);
class procedure GenerateLMDKey(var key; KeySize: Integer; const ABytes: TBytes);
class procedure HashLMD(var Digest; DigestSize: Integer; const Buf; BufSize: NativeInt);
class procedure InitLMD(var Context: TLMDContext);
class procedure ByteBuffHashLMD(var Digest; DigestSize: Integer; const ABytes: TBytes);
class procedure UpdateLMD(var Context: TLMDContext; const Buf; BufSize: NativeInt);
end;
{ Random Number Cipher }
TRNG = class(TCoreClassObject)
public
class procedure EncryptRNG32(var Context: TRNG32Context; var Buf; BufSize: Integer);
class procedure EncryptRNG64(var Context: TRNG64Context; var Buf; BufSize: Integer);
class procedure InitEncryptRNG32(key: DWORD; var Context: TRNG32Context);
class procedure InitEncryptRNG64(KeyHi, KeyLo: DWORD; var Context: TRNG64Context);
end;
{ LSC Stream Cipher }
TLSC = class(TCoreClassObject)
public
class procedure EncryptLSC(var Context: TLSCContext; var Buf; BufSize: Integer);
class procedure InitEncryptLSC(const key; KeySize: Integer; var Context: TLSCContext);
end;
{ Miscellaneous algorithms }
{ Misc public utilities }
TMISC = class(TCoreClassObject)
public
class procedure Mix128(var x: T128Bit); static;
class function Ran0Prim(var Seed: Integer; IA, IQ, IR: Integer): Integer; static;
class function Random64(var Seed: TInt64): Integer; static;
class procedure Transform(var OutputBuffer: TTransformOutput; var InBuf: TTransformInput); static;
class procedure GenerateRandomKey(var key; KeySize: Integer); static;
class procedure HashELF(var Digest: DWORD; const Buf; BufSize: nativeUInt); static;
class procedure HashELF64(var Digest: Int64; const Buf; BufSize: nativeUInt); static;
class procedure HashMix128(var Digest: DWORD; const Buf; BufSize: NativeInt); static;
class function Ran01(var Seed: Integer): Integer; static;
class function Ran02(var Seed: Integer): Integer; static;
class function Ran03(var Seed: Integer): Integer; static;
class function Random32Byte(var Seed: Integer): Byte; static;
class function Random64Byte(var Seed: TInt64): Byte; static;
class function RolX(i, c: DWORD): DWORD; static;
class procedure ByteBuffHashELF(var Digest: DWORD; const ABytes: TBytes); static;
class procedure ByteBuffHashMix128(var Digest: DWORD; const ABytes: TBytes); static;
class procedure XorMem(var Mem1; const Mem2; Count: NativeInt); static;
end;
{ TEA }
procedure XXTEAEncrypt(var key: TKey128; var Block: TXXTEABlock);
procedure XXTEADecrypt(var key: TKey128; var Block: TXXTEABlock);
const
{ RC6 }
cRC6_NumRounds = 20; { number of rounds must be between 16-24 }
type
PRC6Key = ^TRC6Key;
TRC6Key = array [0 .. ((cRC6_NumRounds * 2) + 3)] of DWORD;
PRC6Block = ^TRC6Block;
TRC6Block = array [0 .. 15] of Byte;
TRC6 = class(TCoreClassObject)
public
class function LRot32(x, c: DWORD): DWORD;
class function RRot32(x, c: DWORD): DWORD;
class procedure InitKey(buff: Pointer; Size: Integer; var KeyContext: TRC6Key);
class procedure Encrypt(var KeyContext: TRC6Key; var Data: TRC6Block);
class procedure Decrypt(var KeyContext: TRC6Key; var Data: TRC6Block);
end;
type
{ Serpent }
PSerpentkey = ^TSerpentkey;
TSerpentkey = array [0 .. 131] of DWORD;
PSerpentBlock = ^TSerpentBlock;
TSerpentBlock = array [0 .. 15] of Byte;
TSerpent = class(TCoreClassObject)
public
class procedure InitKey(buff: Pointer; Size: Integer; var KeyContext: TSerpentkey);
class procedure Encrypt(var KeyContext: TSerpentkey; var Data: TSerpentBlock);
class procedure Decrypt(var KeyContext: TSerpentkey; var Data: TSerpentBlock);
end;
type
{ Mars }
PMarskey = ^TMarskey;
TMarskey = array [0 .. 39] of DWORD;
PMarsBlock = ^TMarsBlock;
TMarsBlock = array [0 .. 15] of Byte;
TMars = class(TCoreClassObject)
public
class procedure gen_mask(var x, m: DWORD);
class procedure InitKey(buff: Pointer; Size: Integer; var KeyContext: TMarskey);
class procedure Encrypt(var KeyContext: TMarskey; var Data: TMarsBlock);
class procedure Decrypt(var KeyContext: TMarskey; var Data: TMarsBlock);
end;
type
{ Rijndael }
PRijndaelkey = ^TRijndaelkey;
TRijndaelkey = packed record
NumRounds: DWORD;
rk, drk: array [0 .. 14, 0 .. 7] of DWORD;
end;
PRijndaelBlock = ^TRijndaelBlock;
TRijndaelBlock = array [0 .. 15] of Byte;
TRijndael = class(TCoreClassObject)
private const
{$REGION 'RijndaelDefine'}
T1: array [0 .. 255, 0 .. 3] of Byte = (
($C6, $63, $63, $A5), ($F8, $7C, $7C, $84), ($EE, $77, $77, $99), ($F6, $7B, $7B, $8D),
($FF, $F2, $F2, $0D), ($D6, $6B, $6B, $BD), ($DE, $6F, $6F, $B1), ($91, $C5, $C5, $54),
($60, $30, $30, $50), ($02, $01, $01, $03), ($CE, $67, $67, $A9), ($56, $2B, $2B, $7D),
($E7, $FE, $FE, $19), ($B5, $D7, $D7, $62), ($4D, $AB, $AB, $E6), ($EC, $76, $76, $9A),
($8F, $CA, $CA, $45), ($1F, $82, $82, $9D), ($89, $C9, $C9, $40), ($FA, $7D, $7D, $87),
($EF, $FA, $FA, $15), ($B2, $59, $59, $EB), ($8E, $47, $47, $C9), ($FB, $F0, $F0, $0B),
($41, $AD, $AD, $EC), ($B3, $D4, $D4, $67), ($5F, $A2, $A2, $FD), ($45, $AF, $AF, $EA),
($23, $9C, $9C, $BF), ($53, $A4, $A4, $F7), ($E4, $72, $72, $96), ($9B, $C0, $C0, $5B),
($75, $B7, $B7, $C2), ($E1, $FD, $FD, $1C), ($3D, $93, $93, $AE), ($4C, $26, $26, $6A),
($6C, $36, $36, $5A), ($7E, $3F, $3F, $41), ($F5, $F7, $F7, $02), ($83, $CC, $CC, $4F),
($68, $34, $34, $5C), ($51, $A5, $A5, $F4), ($D1, $E5, $E5, $34), ($F9, $F1, $F1, $08),
($E2, $71, $71, $93), ($AB, $D8, $D8, $73), ($62, $31, $31, $53), ($2A, $15, $15, $3F),
($08, $04, $04, $0C), ($95, $C7, $C7, $52), ($46, $23, $23, $65), ($9D, $C3, $C3, $5E),
($30, $18, $18, $28), ($37, $96, $96, $A1), ($0A, $05, $05, $0F), ($2F, $9A, $9A, $B5),
($0E, $07, $07, $09), ($24, $12, $12, $36), ($1B, $80, $80, $9B), ($DF, $E2, $E2, $3D),
($CD, $EB, $EB, $26), ($4E, $27, $27, $69), ($7F, $B2, $B2, $CD), ($EA, $75, $75, $9F),
($12, $09, $09, $1B), ($1D, $83, $83, $9E), ($58, $2C, $2C, $74), ($34, $1A, $1A, $2E),
($36, $1B, $1B, $2D), ($DC, $6E, $6E, $B2), ($B4, $5A, $5A, $EE), ($5B, $A0, $A0, $FB),
($A4, $52, $52, $F6), ($76, $3B, $3B, $4D), ($B7, $D6, $D6, $61), ($7D, $B3, $B3, $CE),
($52, $29, $29, $7B), ($DD, $E3, $E3, $3E), ($5E, $2F, $2F, $71), ($13, $84, $84, $97),
($A6, $53, $53, $F5), ($B9, $D1, $D1, $68), ($00, $00, $00, $00), ($C1, $ED, $ED, $2C),
($40, $20, $20, $60), ($E3, $FC, $FC, $1F), ($79, $B1, $B1, $C8), ($B6, $5B, $5B, $ED),
($D4, $6A, $6A, $BE), ($8D, $CB, $CB, $46), ($67, $BE, $BE, $D9), ($72, $39, $39, $4B),
($94, $4A, $4A, $DE), ($98, $4C, $4C, $D4), ($B0, $58, $58, $E8), ($85, $CF, $CF, $4A),
($BB, $D0, $D0, $6B), ($C5, $EF, $EF, $2A), ($4F, $AA, $AA, $E5), ($ED, $FB, $FB, $16),
($86, $43, $43, $C5), ($9A, $4D, $4D, $D7), ($66, $33, $33, $55), ($11, $85, $85, $94),
($8A, $45, $45, $CF), ($E9, $F9, $F9, $10), ($04, $02, $02, $06), ($FE, $7F, $7F, $81),
($A0, $50, $50, $F0), ($78, $3C, $3C, $44), ($25, $9F, $9F, $BA), ($4B, $A8, $A8, $E3),
($A2, $51, $51, $F3), ($5D, $A3, $A3, $FE), ($80, $40, $40, $C0), ($05, $8F, $8F, $8A),
($3F, $92, $92, $AD), ($21, $9D, $9D, $BC), ($70, $38, $38, $48), ($F1, $F5, $F5, $04),
($63, $BC, $BC, $DF), ($77, $B6, $B6, $C1), ($AF, $DA, $DA, $75), ($42, $21, $21, $63),
($20, $10, $10, $30), ($E5, $FF, $FF, $1A), ($FD, $F3, $F3, $0E), ($BF, $D2, $D2, $6D),
($81, $CD, $CD, $4C), ($18, $0C, $0C, $14), ($26, $13, $13, $35), ($C3, $EC, $EC, $2F),
($BE, $5F, $5F, $E1), ($35, $97, $97, $A2), ($88, $44, $44, $CC), ($2E, $17, $17, $39),
($93, $C4, $C4, $57), ($55, $A7, $A7, $F2), ($FC, $7E, $7E, $82), ($7A, $3D, $3D, $47),
($C8, $64, $64, $AC), ($BA, $5D, $5D, $E7), ($32, $19, $19, $2B), ($E6, $73, $73, $95),
($C0, $60, $60, $A0), ($19, $81, $81, $98), ($9E, $4F, $4F, $D1), ($A3, $DC, $DC, $7F),
($44, $22, $22, $66), ($54, $2A, $2A, $7E), ($3B, $90, $90, $AB), ($0B, $88, $88, $83),
($8C, $46, $46, $CA), ($C7, $EE, $EE, $29), ($6B, $B8, $B8, $D3), ($28, $14, $14, $3C),
($A7, $DE, $DE, $79), ($BC, $5E, $5E, $E2), ($16, $0B, $0B, $1D), ($AD, $DB, $DB, $76),
($DB, $E0, $E0, $3B), ($64, $32, $32, $56), ($74, $3A, $3A, $4E), ($14, $0A, $0A, $1E),
($92, $49, $49, $DB), ($0C, $06, $06, $0A), ($48, $24, $24, $6C), ($B8, $5C, $5C, $E4),
($9F, $C2, $C2, $5D), ($BD, $D3, $D3, $6E), ($43, $AC, $AC, $EF), ($C4, $62, $62, $A6),
($39, $91, $91, $A8), ($31, $95, $95, $A4), ($D3, $E4, $E4, $37), ($F2, $79, $79, $8B),
($D5, $E7, $E7, $32), ($8B, $C8, $C8, $43), ($6E, $37, $37, $59), ($DA, $6D, $6D, $B7),
($01, $8D, $8D, $8C), ($B1, $D5, $D5, $64), ($9C, $4E, $4E, $D2), ($49, $A9, $A9, $E0),
($D8, $6C, $6C, $B4), ($AC, $56, $56, $FA), ($F3, $F4, $F4, $07), ($CF, $EA, $EA, $25),
($CA, $65, $65, $AF), ($F4, $7A, $7A, $8E), ($47, $AE, $AE, $E9), ($10, $08, $08, $18),
($6F, $BA, $BA, $D5), ($F0, $78, $78, $88), ($4A, $25, $25, $6F), ($5C, $2E, $2E, $72),
($38, $1C, $1C, $24), ($57, $A6, $A6, $F1), ($73, $B4, $B4, $C7), ($97, $C6, $C6, $51),
($CB, $E8, $E8, $23), ($A1, $DD, $DD, $7C), ($E8, $74, $74, $9C), ($3E, $1F, $1F, $21),
($96, $4B, $4B, $DD), ($61, $BD, $BD, $DC), ($0D, $8B, $8B, $86), ($0F, $8A, $8A, $85),
($E0, $70, $70, $90), ($7C, $3E, $3E, $42), ($71, $B5, $B5, $C4), ($CC, $66, $66, $AA),
($90, $48, $48, $D8), ($06, $03, $03, $05), ($F7, $F6, $F6, $01), ($1C, $0E, $0E, $12),
($C2, $61, $61, $A3), ($6A, $35, $35, $5F), ($AE, $57, $57, $F9), ($69, $B9, $B9, $D0),
($17, $86, $86, $91), ($99, $C1, $C1, $58), ($3A, $1D, $1D, $27), ($27, $9E, $9E, $B9),
($D9, $E1, $E1, $38), ($EB, $F8, $F8, $13), ($2B, $98, $98, $B3), ($22, $11, $11, $33),
($D2, $69, $69, $BB), ($A9, $D9, $D9, $70), ($07, $8E, $8E, $89), ($33, $94, $94, $A7),
($2D, $9B, $9B, $B6), ($3C, $1E, $1E, $22), ($15, $87, $87, $92), ($C9, $E9, $E9, $20),
($87, $CE, $CE, $49), ($AA, $55, $55, $FF), ($50, $28, $28, $78), ($A5, $DF, $DF, $7A),
($03, $8C, $8C, $8F), ($59, $A1, $A1, $F8), ($09, $89, $89, $80), ($1A, $0D, $0D, $17),
($65, $BF, $BF, $DA), ($D7, $E6, $E6, $31), ($84, $42, $42, $C6), ($D0, $68, $68, $B8),
($82, $41, $41, $C3), ($29, $99, $99, $B0), ($5A, $2D, $2D, $77), ($1E, $0F, $0F, $11),
($7B, $B0, $B0, $CB), ($A8, $54, $54, $FC), ($6D, $BB, $BB, $D6), ($2C, $16, $16, $3A));
T2: array [0 .. 255, 0 .. 3] of Byte = (
($A5, $C6, $63, $63), ($84, $F8, $7C, $7C), ($99, $EE, $77, $77), ($8D, $F6, $7B, $7B),
($0D, $FF, $F2, $F2), ($BD, $D6, $6B, $6B), ($B1, $DE, $6F, $6F), ($54, $91, $C5, $C5),
($50, $60, $30, $30), ($03, $02, $01, $01), ($A9, $CE, $67, $67), ($7D, $56, $2B, $2B),
($19, $E7, $FE, $FE), ($62, $B5, $D7, $D7), ($E6, $4D, $AB, $AB), ($9A, $EC, $76, $76),
($45, $8F, $CA, $CA), ($9D, $1F, $82, $82), ($40, $89, $C9, $C9), ($87, $FA, $7D, $7D),
($15, $EF, $FA, $FA), ($EB, $B2, $59, $59), ($C9, $8E, $47, $47), ($0B, $FB, $F0, $F0),
($EC, $41, $AD, $AD), ($67, $B3, $D4, $D4), ($FD, $5F, $A2, $A2), ($EA, $45, $AF, $AF),
($BF, $23, $9C, $9C), ($F7, $53, $A4, $A4), ($96, $E4, $72, $72), ($5B, $9B, $C0, $C0),
($C2, $75, $B7, $B7), ($1C, $E1, $FD, $FD), ($AE, $3D, $93, $93), ($6A, $4C, $26, $26),
($5A, $6C, $36, $36), ($41, $7E, $3F, $3F), ($02, $F5, $F7, $F7), ($4F, $83, $CC, $CC),
($5C, $68, $34, $34), ($F4, $51, $A5, $A5), ($34, $D1, $E5, $E5), ($08, $F9, $F1, $F1),
($93, $E2, $71, $71), ($73, $AB, $D8, $D8), ($53, $62, $31, $31), ($3F, $2A, $15, $15),
($0C, $08, $04, $04), ($52, $95, $C7, $C7), ($65, $46, $23, $23), ($5E, $9D, $C3, $C3),
($28, $30, $18, $18), ($A1, $37, $96, $96), ($0F, $0A, $05, $05), ($B5, $2F, $9A, $9A),
($09, $0E, $07, $07), ($36, $24, $12, $12), ($9B, $1B, $80, $80), ($3D, $DF, $E2, $E2),
($26, $CD, $EB, $EB), ($69, $4E, $27, $27), ($CD, $7F, $B2, $B2), ($9F, $EA, $75, $75),
($1B, $12, $09, $09), ($9E, $1D, $83, $83), ($74, $58, $2C, $2C), ($2E, $34, $1A, $1A),
($2D, $36, $1B, $1B), ($B2, $DC, $6E, $6E), ($EE, $B4, $5A, $5A), ($FB, $5B, $A0, $A0),
($F6, $A4, $52, $52), ($4D, $76, $3B, $3B), ($61, $B7, $D6, $D6), ($CE, $7D, $B3, $B3),
($7B, $52, $29, $29), ($3E, $DD, $E3, $E3), ($71, $5E, $2F, $2F), ($97, $13, $84, $84),
($F5, $A6, $53, $53), ($68, $B9, $D1, $D1), ($00, $00, $00, $00), ($2C, $C1, $ED, $ED),
($60, $40, $20, $20), ($1F, $E3, $FC, $FC), ($C8, $79, $B1, $B1), ($ED, $B6, $5B, $5B),
($BE, $D4, $6A, $6A), ($46, $8D, $CB, $CB), ($D9, $67, $BE, $BE), ($4B, $72, $39, $39),
($DE, $94, $4A, $4A), ($D4, $98, $4C, $4C), ($E8, $B0, $58, $58), ($4A, $85, $CF, $CF),
($6B, $BB, $D0, $D0), ($2A, $C5, $EF, $EF), ($E5, $4F, $AA, $AA), ($16, $ED, $FB, $FB),
($C5, $86, $43, $43), ($D7, $9A, $4D, $4D), ($55, $66, $33, $33), ($94, $11, $85, $85),
($CF, $8A, $45, $45), ($10, $E9, $F9, $F9), ($06, $04, $02, $02), ($81, $FE, $7F, $7F),
($F0, $A0, $50, $50), ($44, $78, $3C, $3C), ($BA, $25, $9F, $9F), ($E3, $4B, $A8, $A8),
($F3, $A2, $51, $51), ($FE, $5D, $A3, $A3), ($C0, $80, $40, $40), ($8A, $05, $8F, $8F),
($AD, $3F, $92, $92), ($BC, $21, $9D, $9D), ($48, $70, $38, $38), ($04, $F1, $F5, $F5),
($DF, $63, $BC, $BC), ($C1, $77, $B6, $B6), ($75, $AF, $DA, $DA), ($63, $42, $21, $21),
($30, $20, $10, $10), ($1A, $E5, $FF, $FF), ($0E, $FD, $F3, $F3), ($6D, $BF, $D2, $D2),
($4C, $81, $CD, $CD), ($14, $18, $0C, $0C), ($35, $26, $13, $13), ($2F, $C3, $EC, $EC),
($E1, $BE, $5F, $5F), ($A2, $35, $97, $97), ($CC, $88, $44, $44), ($39, $2E, $17, $17),
($57, $93, $C4, $C4), ($F2, $55, $A7, $A7), ($82, $FC, $7E, $7E), ($47, $7A, $3D, $3D),
($AC, $C8, $64, $64), ($E7, $BA, $5D, $5D), ($2B, $32, $19, $19), ($95, $E6, $73, $73),
($A0, $C0, $60, $60), ($98, $19, $81, $81), ($D1, $9E, $4F, $4F), ($7F, $A3, $DC, $DC),
($66, $44, $22, $22), ($7E, $54, $2A, $2A), ($AB, $3B, $90, $90), ($83, $0B, $88, $88),
($CA, $8C, $46, $46), ($29, $C7, $EE, $EE), ($D3, $6B, $B8, $B8), ($3C, $28, $14, $14),
($79, $A7, $DE, $DE), ($E2, $BC, $5E, $5E), ($1D, $16, $0B, $0B), ($76, $AD, $DB, $DB),
($3B, $DB, $E0, $E0), ($56, $64, $32, $32), ($4E, $74, $3A, $3A), ($1E, $14, $0A, $0A),
($DB, $92, $49, $49), ($0A, $0C, $06, $06), ($6C, $48, $24, $24), ($E4, $B8, $5C, $5C),
($5D, $9F, $C2, $C2), ($6E, $BD, $D3, $D3), ($EF, $43, $AC, $AC), ($A6, $C4, $62, $62),
($A8, $39, $91, $91), ($A4, $31, $95, $95), ($37, $D3, $E4, $E4), ($8B, $F2, $79, $79),
($32, $D5, $E7, $E7), ($43, $8B, $C8, $C8), ($59, $6E, $37, $37), ($B7, $DA, $6D, $6D),
($8C, $01, $8D, $8D), ($64, $B1, $D5, $D5), ($D2, $9C, $4E, $4E), ($E0, $49, $A9, $A9),
($B4, $D8, $6C, $6C), ($FA, $AC, $56, $56), ($07, $F3, $F4, $F4), ($25, $CF, $EA, $EA),
($AF, $CA, $65, $65), ($8E, $F4, $7A, $7A), ($E9, $47, $AE, $AE), ($18, $10, $08, $08),
($D5, $6F, $BA, $BA), ($88, $F0, $78, $78), ($6F, $4A, $25, $25), ($72, $5C, $2E, $2E),
($24, $38, $1C, $1C), ($F1, $57, $A6, $A6), ($C7, $73, $B4, $B4), ($51, $97, $C6, $C6),
($23, $CB, $E8, $E8), ($7C, $A1, $DD, $DD), ($9C, $E8, $74, $74), ($21, $3E, $1F, $1F),
($DD, $96, $4B, $4B), ($DC, $61, $BD, $BD), ($86, $0D, $8B, $8B), ($85, $0F, $8A, $8A),
($90, $E0, $70, $70), ($42, $7C, $3E, $3E), ($C4, $71, $B5, $B5), ($AA, $CC, $66, $66),
($D8, $90, $48, $48), ($05, $06, $03, $03), ($01, $F7, $F6, $F6), ($12, $1C, $0E, $0E),
($A3, $C2, $61, $61), ($5F, $6A, $35, $35), ($F9, $AE, $57, $57), ($D0, $69, $B9, $B9),
($91, $17, $86, $86), ($58, $99, $C1, $C1), ($27, $3A, $1D, $1D), ($B9, $27, $9E, $9E),
($38, $D9, $E1, $E1), ($13, $EB, $F8, $F8), ($B3, $2B, $98, $98), ($33, $22, $11, $11),
($BB, $D2, $69, $69), ($70, $A9, $D9, $D9), ($89, $07, $8E, $8E), ($A7, $33, $94, $94),
($B6, $2D, $9B, $9B), ($22, $3C, $1E, $1E), ($92, $15, $87, $87), ($20, $C9, $E9, $E9),
($49, $87, $CE, $CE), ($FF, $AA, $55, $55), ($78, $50, $28, $28), ($7A, $A5, $DF, $DF),
($8F, $03, $8C, $8C), ($F8, $59, $A1, $A1), ($80, $09, $89, $89), ($17, $1A, $0D, $0D),
($DA, $65, $BF, $BF), ($31, $D7, $E6, $E6), ($C6, $84, $42, $42), ($B8, $D0, $68, $68),
($C3, $82, $41, $41), ($B0, $29, $99, $99), ($77, $5A, $2D, $2D), ($11, $1E, $0F, $0F),
($CB, $7B, $B0, $B0), ($FC, $A8, $54, $54), ($D6, $6D, $BB, $BB), ($3A, $2C, $16, $16));
T3: array [0 .. 255, 0 .. 3] of Byte = (
($63, $A5, $C6, $63), ($7C, $84, $F8, $7C), ($77, $99, $EE, $77), ($7B, $8D, $F6, $7B),
($F2, $0D, $FF, $F2), ($6B, $BD, $D6, $6B), ($6F, $B1, $DE, $6F), ($C5, $54, $91, $C5),
($30, $50, $60, $30), ($01, $03, $02, $01), ($67, $A9, $CE, $67), ($2B, $7D, $56, $2B),
($FE, $19, $E7, $FE), ($D7, $62, $B5, $D7), ($AB, $E6, $4D, $AB), ($76, $9A, $EC, $76),
($CA, $45, $8F, $CA), ($82, $9D, $1F, $82), ($C9, $40, $89, $C9), ($7D, $87, $FA, $7D),
($FA, $15, $EF, $FA), ($59, $EB, $B2, $59), ($47, $C9, $8E, $47), ($F0, $0B, $FB, $F0),
($AD, $EC, $41, $AD), ($D4, $67, $B3, $D4), ($A2, $FD, $5F, $A2), ($AF, $EA, $45, $AF),
($9C, $BF, $23, $9C), ($A4, $F7, $53, $A4), ($72, $96, $E4, $72), ($C0, $5B, $9B, $C0),
($B7, $C2, $75, $B7), ($FD, $1C, $E1, $FD), ($93, $AE, $3D, $93), ($26, $6A, $4C, $26),
($36, $5A, $6C, $36), ($3F, $41, $7E, $3F), ($F7, $02, $F5, $F7), ($CC, $4F, $83, $CC),
($34, $5C, $68, $34), ($A5, $F4, $51, $A5), ($E5, $34, $D1, $E5), ($F1, $08, $F9, $F1),
($71, $93, $E2, $71), ($D8, $73, $AB, $D8), ($31, $53, $62, $31), ($15, $3F, $2A, $15),
($04, $0C, $08, $04), ($C7, $52, $95, $C7), ($23, $65, $46, $23), ($C3, $5E, $9D, $C3),
($18, $28, $30, $18), ($96, $A1, $37, $96), ($05, $0F, $0A, $05), ($9A, $B5, $2F, $9A),
($07, $09, $0E, $07), ($12, $36, $24, $12), ($80, $9B, $1B, $80), ($E2, $3D, $DF, $E2),
($EB, $26, $CD, $EB), ($27, $69, $4E, $27), ($B2, $CD, $7F, $B2), ($75, $9F, $EA, $75),
($09, $1B, $12, $09), ($83, $9E, $1D, $83), ($2C, $74, $58, $2C), ($1A, $2E, $34, $1A),
($1B, $2D, $36, $1B), ($6E, $B2, $DC, $6E), ($5A, $EE, $B4, $5A), ($A0, $FB, $5B, $A0),
($52, $F6, $A4, $52), ($3B, $4D, $76, $3B), ($D6, $61, $B7, $D6), ($B3, $CE, $7D, $B3),
($29, $7B, $52, $29), ($E3, $3E, $DD, $E3), ($2F, $71, $5E, $2F), ($84, $97, $13, $84),
($53, $F5, $A6, $53), ($D1, $68, $B9, $D1), ($00, $00, $00, $00), ($ED, $2C, $C1, $ED),
($20, $60, $40, $20), ($FC, $1F, $E3, $FC), ($B1, $C8, $79, $B1), ($5B, $ED, $B6, $5B),
($6A, $BE, $D4, $6A), ($CB, $46, $8D, $CB), ($BE, $D9, $67, $BE), ($39, $4B, $72, $39),
($4A, $DE, $94, $4A), ($4C, $D4, $98, $4C), ($58, $E8, $B0, $58), ($CF, $4A, $85, $CF),
($D0, $6B, $BB, $D0), ($EF, $2A, $C5, $EF), ($AA, $E5, $4F, $AA), ($FB, $16, $ED, $FB),
($43, $C5, $86, $43), ($4D, $D7, $9A, $4D), ($33, $55, $66, $33), ($85, $94, $11, $85),
($45, $CF, $8A, $45), ($F9, $10, $E9, $F9), ($02, $06, $04, $02), ($7F, $81, $FE, $7F),
($50, $F0, $A0, $50), ($3C, $44, $78, $3C), ($9F, $BA, $25, $9F), ($A8, $E3, $4B, $A8),
($51, $F3, $A2, $51), ($A3, $FE, $5D, $A3), ($40, $C0, $80, $40), ($8F, $8A, $05, $8F),
($92, $AD, $3F, $92), ($9D, $BC, $21, $9D), ($38, $48, $70, $38), ($F5, $04, $F1, $F5),
($BC, $DF, $63, $BC), ($B6, $C1, $77, $B6), ($DA, $75, $AF, $DA), ($21, $63, $42, $21),
($10, $30, $20, $10), ($FF, $1A, $E5, $FF), ($F3, $0E, $FD, $F3), ($D2, $6D, $BF, $D2),
($CD, $4C, $81, $CD), ($0C, $14, $18, $0C), ($13, $35, $26, $13), ($EC, $2F, $C3, $EC),
($5F, $E1, $BE, $5F), ($97, $A2, $35, $97), ($44, $CC, $88, $44), ($17, $39, $2E, $17),
($C4, $57, $93, $C4), ($A7, $F2, $55, $A7), ($7E, $82, $FC, $7E), ($3D, $47, $7A, $3D),
($64, $AC, $C8, $64), ($5D, $E7, $BA, $5D), ($19, $2B, $32, $19), ($73, $95, $E6, $73),
($60, $A0, $C0, $60), ($81, $98, $19, $81), ($4F, $D1, $9E, $4F), ($DC, $7F, $A3, $DC),
($22, $66, $44, $22), ($2A, $7E, $54, $2A), ($90, $AB, $3B, $90), ($88, $83, $0B, $88),
($46, $CA, $8C, $46), ($EE, $29, $C7, $EE), ($B8, $D3, $6B, $B8), ($14, $3C, $28, $14),
($DE, $79, $A7, $DE), ($5E, $E2, $BC, $5E), ($0B, $1D, $16, $0B), ($DB, $76, $AD, $DB),
($E0, $3B, $DB, $E0), ($32, $56, $64, $32), ($3A, $4E, $74, $3A), ($0A, $1E, $14, $0A),
($49, $DB, $92, $49), ($06, $0A, $0C, $06), ($24, $6C, $48, $24), ($5C, $E4, $B8, $5C),
($C2, $5D, $9F, $C2), ($D3, $6E, $BD, $D3), ($AC, $EF, $43, $AC), ($62, $A6, $C4, $62),
($91, $A8, $39, $91), ($95, $A4, $31, $95), ($E4, $37, $D3, $E4), ($79, $8B, $F2, $79),
($E7, $32, $D5, $E7), ($C8, $43, $8B, $C8), ($37, $59, $6E, $37), ($6D, $B7, $DA, $6D),
($8D, $8C, $01, $8D), ($D5, $64, $B1, $D5), ($4E, $D2, $9C, $4E), ($A9, $E0, $49, $A9),
($6C, $B4, $D8, $6C), ($56, $FA, $AC, $56), ($F4, $07, $F3, $F4), ($EA, $25, $CF, $EA),
($65, $AF, $CA, $65), ($7A, $8E, $F4, $7A), ($AE, $E9, $47, $AE), ($08, $18, $10, $08),
($BA, $D5, $6F, $BA), ($78, $88, $F0, $78), ($25, $6F, $4A, $25), ($2E, $72, $5C, $2E),
($1C, $24, $38, $1C), ($A6, $F1, $57, $A6), ($B4, $C7, $73, $B4), ($C6, $51, $97, $C6),
($E8, $23, $CB, $E8), ($DD, $7C, $A1, $DD), ($74, $9C, $E8, $74), ($1F, $21, $3E, $1F),
($4B, $DD, $96, $4B), ($BD, $DC, $61, $BD), ($8B, $86, $0D, $8B), ($8A, $85, $0F, $8A),
($70, $90, $E0, $70), ($3E, $42, $7C, $3E), ($B5, $C4, $71, $B5), ($66, $AA, $CC, $66),
($48, $D8, $90, $48), ($03, $05, $06, $03), ($F6, $01, $F7, $F6), ($0E, $12, $1C, $0E),
($61, $A3, $C2, $61), ($35, $5F, $6A, $35), ($57, $F9, $AE, $57), ($B9, $D0, $69, $B9),
($86, $91, $17, $86), ($C1, $58, $99, $C1), ($1D, $27, $3A, $1D), ($9E, $B9, $27, $9E),
($E1, $38, $D9, $E1), ($F8, $13, $EB, $F8), ($98, $B3, $2B, $98), ($11, $33, $22, $11),
($69, $BB, $D2, $69), ($D9, $70, $A9, $D9), ($8E, $89, $07, $8E), ($94, $A7, $33, $94),
($9B, $B6, $2D, $9B), ($1E, $22, $3C, $1E), ($87, $92, $15, $87), ($E9, $20, $C9, $E9),
($CE, $49, $87, $CE), ($55, $FF, $AA, $55), ($28, $78, $50, $28), ($DF, $7A, $A5, $DF),
($8C, $8F, $03, $8C), ($A1, $F8, $59, $A1), ($89, $80, $09, $89), ($0D, $17, $1A, $0D),
($BF, $DA, $65, $BF), ($E6, $31, $D7, $E6), ($42, $C6, $84, $42), ($68, $B8, $D0, $68),
($41, $C3, $82, $41), ($99, $B0, $29, $99), ($2D, $77, $5A, $2D), ($0F, $11, $1E, $0F),
($B0, $CB, $7B, $B0), ($54, $FC, $A8, $54), ($BB, $D6, $6D, $BB), ($16, $3A, $2C, $16));
T4: array [0 .. 255, 0 .. 3] of Byte = (
($63, $63, $A5, $C6), ($7C, $7C, $84, $F8), ($77, $77, $99, $EE), ($7B, $7B, $8D, $F6),
($F2, $F2, $0D, $FF), ($6B, $6B, $BD, $D6), ($6F, $6F, $B1, $DE), ($C5, $C5, $54, $91),
($30, $30, $50, $60), ($01, $01, $03, $02), ($67, $67, $A9, $CE), ($2B, $2B, $7D, $56),
($FE, $FE, $19, $E7), ($D7, $D7, $62, $B5), ($AB, $AB, $E6, $4D), ($76, $76, $9A, $EC),
($CA, $CA, $45, $8F), ($82, $82, $9D, $1F), ($C9, $C9, $40, $89), ($7D, $7D, $87, $FA),
($FA, $FA, $15, $EF), ($59, $59, $EB, $B2), ($47, $47, $C9, $8E), ($F0, $F0, $0B, $FB),
($AD, $AD, $EC, $41), ($D4, $D4, $67, $B3), ($A2, $A2, $FD, $5F), ($AF, $AF, $EA, $45),
($9C, $9C, $BF, $23), ($A4, $A4, $F7, $53), ($72, $72, $96, $E4), ($C0, $C0, $5B, $9B),
($B7, $B7, $C2, $75), ($FD, $FD, $1C, $E1), ($93, $93, $AE, $3D), ($26, $26, $6A, $4C),
($36, $36, $5A, $6C), ($3F, $3F, $41, $7E), ($F7, $F7, $02, $F5), ($CC, $CC, $4F, $83),
($34, $34, $5C, $68), ($A5, $A5, $F4, $51), ($E5, $E5, $34, $D1), ($F1, $F1, $08, $F9),
($71, $71, $93, $E2), ($D8, $D8, $73, $AB), ($31, $31, $53, $62), ($15, $15, $3F, $2A),
($04, $04, $0C, $08), ($C7, $C7, $52, $95), ($23, $23, $65, $46), ($C3, $C3, $5E, $9D),
($18, $18, $28, $30), ($96, $96, $A1, $37), ($05, $05, $0F, $0A), ($9A, $9A, $B5, $2F),
($07, $07, $09, $0E), ($12, $12, $36, $24), ($80, $80, $9B, $1B), ($E2, $E2, $3D, $DF),
($EB, $EB, $26, $CD), ($27, $27, $69, $4E), ($B2, $B2, $CD, $7F), ($75, $75, $9F, $EA),
($09, $09, $1B, $12), ($83, $83, $9E, $1D), ($2C, $2C, $74, $58), ($1A, $1A, $2E, $34),
($1B, $1B, $2D, $36), ($6E, $6E, $B2, $DC), ($5A, $5A, $EE, $B4), ($A0, $A0, $FB, $5B),
($52, $52, $F6, $A4), ($3B, $3B, $4D, $76), ($D6, $D6, $61, $B7), ($B3, $B3, $CE, $7D),
($29, $29, $7B, $52), ($E3, $E3, $3E, $DD), ($2F, $2F, $71, $5E), ($84, $84, $97, $13),
($53, $53, $F5, $A6), ($D1, $D1, $68, $B9), ($00, $00, $00, $00), ($ED, $ED, $2C, $C1),
($20, $20, $60, $40), ($FC, $FC, $1F, $E3), ($B1, $B1, $C8, $79), ($5B, $5B, $ED, $B6),
($6A, $6A, $BE, $D4), ($CB, $CB, $46, $8D), ($BE, $BE, $D9, $67), ($39, $39, $4B, $72),
($4A, $4A, $DE, $94), ($4C, $4C, $D4, $98), ($58, $58, $E8, $B0), ($CF, $CF, $4A, $85),
($D0, $D0, $6B, $BB), ($EF, $EF, $2A, $C5), ($AA, $AA, $E5, $4F), ($FB, $FB, $16, $ED),
($43, $43, $C5, $86), ($4D, $4D, $D7, $9A), ($33, $33, $55, $66), ($85, $85, $94, $11),
($45, $45, $CF, $8A), ($F9, $F9, $10, $E9), ($02, $02, $06, $04), ($7F, $7F, $81, $FE),
($50, $50, $F0, $A0), ($3C, $3C, $44, $78), ($9F, $9F, $BA, $25), ($A8, $A8, $E3, $4B),
($51, $51, $F3, $A2), ($A3, $A3, $FE, $5D), ($40, $40, $C0, $80), ($8F, $8F, $8A, $05),
($92, $92, $AD, $3F), ($9D, $9D, $BC, $21), ($38, $38, $48, $70), ($F5, $F5, $04, $F1),
($BC, $BC, $DF, $63), ($B6, $B6, $C1, $77), ($DA, $DA, $75, $AF), ($21, $21, $63, $42),
($10, $10, $30, $20), ($FF, $FF, $1A, $E5), ($F3, $F3, $0E, $FD), ($D2, $D2, $6D, $BF),
($CD, $CD, $4C, $81), ($0C, $0C, $14, $18), ($13, $13, $35, $26), ($EC, $EC, $2F, $C3),
($5F, $5F, $E1, $BE), ($97, $97, $A2, $35), ($44, $44, $CC, $88), ($17, $17, $39, $2E),
($C4, $C4, $57, $93), ($A7, $A7, $F2, $55), ($7E, $7E, $82, $FC), ($3D, $3D, $47, $7A),
($64, $64, $AC, $C8), ($5D, $5D, $E7, $BA), ($19, $19, $2B, $32), ($73, $73, $95, $E6),
($60, $60, $A0, $C0), ($81, $81, $98, $19), ($4F, $4F, $D1, $9E), ($DC, $DC, $7F, $A3),
($22, $22, $66, $44), ($2A, $2A, $7E, $54), ($90, $90, $AB, $3B), ($88, $88, $83, $0B),
($46, $46, $CA, $8C), ($EE, $EE, $29, $C7), ($B8, $B8, $D3, $6B), ($14, $14, $3C, $28),
($DE, $DE, $79, $A7), ($5E, $5E, $E2, $BC), ($0B, $0B, $1D, $16), ($DB, $DB, $76, $AD),
($E0, $E0, $3B, $DB), ($32, $32, $56, $64), ($3A, $3A, $4E, $74), ($0A, $0A, $1E, $14),
($49, $49, $DB, $92), ($06, $06, $0A, $0C), ($24, $24, $6C, $48), ($5C, $5C, $E4, $B8),
($C2, $C2, $5D, $9F), ($D3, $D3, $6E, $BD), ($AC, $AC, $EF, $43), ($62, $62, $A6, $C4),
($91, $91, $A8, $39), ($95, $95, $A4, $31), ($E4, $E4, $37, $D3), ($79, $79, $8B, $F2),
($E7, $E7, $32, $D5), ($C8, $C8, $43, $8B), ($37, $37, $59, $6E), ($6D, $6D, $B7, $DA),
($8D, $8D, $8C, $01), ($D5, $D5, $64, $B1), ($4E, $4E, $D2, $9C), ($A9, $A9, $E0, $49),
($6C, $6C, $B4, $D8), ($56, $56, $FA, $AC), ($F4, $F4, $07, $F3), ($EA, $EA, $25, $CF),
($65, $65, $AF, $CA), ($7A, $7A, $8E, $F4), ($AE, $AE, $E9, $47), ($08, $08, $18, $10),
($BA, $BA, $D5, $6F), ($78, $78, $88, $F0), ($25, $25, $6F, $4A), ($2E, $2E, $72, $5C),
($1C, $1C, $24, $38), ($A6, $A6, $F1, $57), ($B4, $B4, $C7, $73), ($C6, $C6, $51, $97),
($E8, $E8, $23, $CB), ($DD, $DD, $7C, $A1), ($74, $74, $9C, $E8), ($1F, $1F, $21, $3E),
($4B, $4B, $DD, $96), ($BD, $BD, $DC, $61), ($8B, $8B, $86, $0D), ($8A, $8A, $85, $0F),
($70, $70, $90, $E0), ($3E, $3E, $42, $7C), ($B5, $B5, $C4, $71), ($66, $66, $AA, $CC),
($48, $48, $D8, $90), ($03, $03, $05, $06), ($F6, $F6, $01, $F7), ($0E, $0E, $12, $1C),
($61, $61, $A3, $C2), ($35, $35, $5F, $6A), ($57, $57, $F9, $AE), ($B9, $B9, $D0, $69),
($86, $86, $91, $17), ($C1, $C1, $58, $99), ($1D, $1D, $27, $3A), ($9E, $9E, $B9, $27),
($E1, $E1, $38, $D9), ($F8, $F8, $13, $EB), ($98, $98, $B3, $2B), ($11, $11, $33, $22),
($69, $69, $BB, $D2), ($D9, $D9, $70, $A9), ($8E, $8E, $89, $07), ($94, $94, $A7, $33),
($9B, $9B, $B6, $2D), ($1E, $1E, $22, $3C), ($87, $87, $92, $15), ($E9, $E9, $20, $C9),
($CE, $CE, $49, $87), ($55, $55, $FF, $AA), ($28, $28, $78, $50), ($DF, $DF, $7A, $A5),
($8C, $8C, $8F, $03), ($A1, $A1, $F8, $59), ($89, $89, $80, $09), ($0D, $0D, $17, $1A),
($BF, $BF, $DA, $65), ($E6, $E6, $31, $D7), ($42, $42, $C6, $84), ($68, $68, $B8, $D0),
($41, $41, $C3, $82), ($99, $99, $B0, $29), ($2D, $2D, $77, $5A), ($0F, $0F, $11, $1E),
($B0, $B0, $CB, $7B), ($54, $54, $FC, $A8), ($BB, $BB, $D6, $6D), ($16, $16, $3A, $2C));
T5: array [0 .. 255, 0 .. 3] of Byte = (
($51, $F4, $A7, $50), ($7E, $41, $65, $53), ($1A, $17, $A4, $C3), ($3A, $27, $5E, $96),
($3B, $AB, $6B, $CB), ($1F, $9D, $45, $F1), ($AC, $FA, $58, $AB), ($4B, $E3, $03, $93),
($20, $30, $FA, $55), ($AD, $76, $6D, $F6), ($88, $CC, $76, $91), ($F5, $02, $4C, $25),
($4F, $E5, $D7, $FC), ($C5, $2A, $CB, $D7), ($26, $35, $44, $80), ($B5, $62, $A3, $8F),
($DE, $B1, $5A, $49), ($25, $BA, $1B, $67), ($45, $EA, $0E, $98), ($5D, $FE, $C0, $E1),
($C3, $2F, $75, $02), ($81, $4C, $F0, $12), ($8D, $46, $97, $A3), ($6B, $D3, $F9, $C6),
($03, $8F, $5F, $E7), ($15, $92, $9C, $95), ($BF, $6D, $7A, $EB), ($95, $52, $59, $DA),
($D4, $BE, $83, $2D), ($58, $74, $21, $D3), ($49, $E0, $69, $29), ($8E, $C9, $C8, $44),
($75, $C2, $89, $6A), ($F4, $8E, $79, $78), ($99, $58, $3E, $6B), ($27, $B9, $71, $DD),
($BE, $E1, $4F, $B6), ($F0, $88, $AD, $17), ($C9, $20, $AC, $66), ($7D, $CE, $3A, $B4),
($63, $DF, $4A, $18), ($E5, $1A, $31, $82), ($97, $51, $33, $60), ($62, $53, $7F, $45),
($B1, $64, $77, $E0), ($BB, $6B, $AE, $84), ($FE, $81, $A0, $1C), ($F9, $08, $2B, $94),
($70, $48, $68, $58), ($8F, $45, $FD, $19), ($94, $DE, $6C, $87), ($52, $7B, $F8, $B7),
($AB, $73, $D3, $23), ($72, $4B, $02, $E2), ($E3, $1F, $8F, $57), ($66, $55, $AB, $2A),
($B2, $EB, $28, $07), ($2F, $B5, $C2, $03), ($86, $C5, $7B, $9A), ($D3, $37, $08, $A5),
($30, $28, $87, $F2), ($23, $BF, $A5, $B2), ($02, $03, $6A, $BA), ($ED, $16, $82, $5C),
($8A, $CF, $1C, $2B), ($A7, $79, $B4, $92), ($F3, $07, $F2, $F0), ($4E, $69, $E2, $A1),
($65, $DA, $F4, $CD), ($06, $05, $BE, $D5), ($D1, $34, $62, $1F), ($C4, $A6, $FE, $8A),
($34, $2E, $53, $9D), ($A2, $F3, $55, $A0), ($05, $8A, $E1, $32), ($A4, $F6, $EB, $75),
($0B, $83, $EC, $39), ($40, $60, $EF, $AA), ($5E, $71, $9F, $06), ($BD, $6E, $10, $51),
($3E, $21, $8A, $F9), ($96, $DD, $06, $3D), ($DD, $3E, $05, $AE), ($4D, $E6, $BD, $46),
($91, $54, $8D, $B5), ($71, $C4, $5D, $05), ($04, $06, $D4, $6F), ($60, $50, $15, $FF),
($19, $98, $FB, $24), ($D6, $BD, $E9, $97), ($89, $40, $43, $CC), ($67, $D9, $9E, $77),
($B0, $E8, $42, $BD), ($07, $89, $8B, $88), ($E7, $19, $5B, $38), ($79, $C8, $EE, $DB),
($A1, $7C, $0A, $47), ($7C, $42, $0F, $E9), ($F8, $84, $1E, $C9), ($00, $00, $00, $00),
($09, $80, $86, $83), ($32, $2B, $ED, $48), ($1E, $11, $70, $AC), ($6C, $5A, $72, $4E),
($FD, $0E, $FF, $FB), ($0F, $85, $38, $56), ($3D, $AE, $D5, $1E), ($36, $2D, $39, $27),
($0A, $0F, $D9, $64), ($68, $5C, $A6, $21), ($9B, $5B, $54, $D1), ($24, $36, $2E, $3A),
($0C, $0A, $67, $B1), ($93, $57, $E7, $0F), ($B4, $EE, $96, $D2), ($1B, $9B, $91, $9E),
($80, $C0, $C5, $4F), ($61, $DC, $20, $A2), ($5A, $77, $4B, $69), ($1C, $12, $1A, $16),
($E2, $93, $BA, $0A), ($C0, $A0, $2A, $E5), ($3C, $22, $E0, $43), ($12, $1B, $17, $1D),
($0E, $09, $0D, $0B), ($F2, $8B, $C7, $AD), ($2D, $B6, $A8, $B9), ($14, $1E, $A9, $C8),
($57, $F1, $19, $85), ($AF, $75, $07, $4C), ($EE, $99, $DD, $BB), ($A3, $7F, $60, $FD),
($F7, $01, $26, $9F), ($5C, $72, $F5, $BC), ($44, $66, $3B, $C5), ($5B, $FB, $7E, $34),
($8B, $43, $29, $76), ($CB, $23, $C6, $DC), ($B6, $ED, $FC, $68), ($B8, $E4, $F1, $63),
($D7, $31, $DC, $CA), ($42, $63, $85, $10), ($13, $97, $22, $40), ($84, $C6, $11, $20),
($85, $4A, $24, $7D), ($D2, $BB, $3D, $F8), ($AE, $F9, $32, $11), ($C7, $29, $A1, $6D),
($1D, $9E, $2F, $4B), ($DC, $B2, $30, $F3), ($0D, $86, $52, $EC), ($77, $C1, $E3, $D0),
($2B, $B3, $16, $6C), ($A9, $70, $B9, $99), ($11, $94, $48, $FA), ($47, $E9, $64, $22),
($A8, $FC, $8C, $C4), ($A0, $F0, $3F, $1A), ($56, $7D, $2C, $D8), ($22, $33, $90, $EF),
($87, $49, $4E, $C7), ($D9, $38, $D1, $C1), ($8C, $CA, $A2, $FE), ($98, $D4, $0B, $36),
($A6, $F5, $81, $CF), ($A5, $7A, $DE, $28), ($DA, $B7, $8E, $26), ($3F, $AD, $BF, $A4),
($2C, $3A, $9D, $E4), ($50, $78, $92, $0D), ($6A, $5F, $CC, $9B), ($54, $7E, $46, $62),
($F6, $8D, $13, $C2), ($90, $D8, $B8, $E8), ($2E, $39, $F7, $5E), ($82, $C3, $AF, $F5),
($9F, $5D, $80, $BE), ($69, $D0, $93, $7C), ($6F, $D5, $2D, $A9), ($CF, $25, $12, $B3),
($C8, $AC, $99, $3B), ($10, $18, $7D, $A7), ($E8, $9C, $63, $6E), ($DB, $3B, $BB, $7B),
($CD, $26, $78, $09), ($6E, $59, $18, $F4), ($EC, $9A, $B7, $01), ($83, $4F, $9A, $A8),
($E6, $95, $6E, $65), ($AA, $FF, $E6, $7E), ($21, $BC, $CF, $08), ($EF, $15, $E8, $E6),
($BA, $E7, $9B, $D9), ($4A, $6F, $36, $CE), ($EA, $9F, $09, $D4), ($29, $B0, $7C, $D6),
($31, $A4, $B2, $AF), ($2A, $3F, $23, $31), ($C6, $A5, $94, $30), ($35, $A2, $66, $C0),
($74, $4E, $BC, $37), ($FC, $82, $CA, $A6), ($E0, $90, $D0, $B0), ($33, $A7, $D8, $15),
($F1, $04, $98, $4A), ($41, $EC, $DA, $F7), ($7F, $CD, $50, $0E), ($17, $91, $F6, $2F),
($76, $4D, $D6, $8D), ($43, $EF, $B0, $4D), ($CC, $AA, $4D, $54), ($E4, $96, $04, $DF),
($9E, $D1, $B5, $E3), ($4C, $6A, $88, $1B), ($C1, $2C, $1F, $B8), ($46, $65, $51, $7F),
($9D, $5E, $EA, $04), ($01, $8C, $35, $5D), ($FA, $87, $74, $73), ($FB, $0B, $41, $2E),
($B3, $67, $1D, $5A), ($92, $DB, $D2, $52), ($E9, $10, $56, $33), ($6D, $D6, $47, $13),
($9A, $D7, $61, $8C), ($37, $A1, $0C, $7A), ($59, $F8, $14, $8E), ($EB, $13, $3C, $89),
($CE, $A9, $27, $EE), ($B7, $61, $C9, $35), ($E1, $1C, $E5, $ED), ($7A, $47, $B1, $3C),
($9C, $D2, $DF, $59), ($55, $F2, $73, $3F), ($18, $14, $CE, $79), ($73, $C7, $37, $BF),
($53, $F7, $CD, $EA), ($5F, $FD, $AA, $5B), ($DF, $3D, $6F, $14), ($78, $44, $DB, $86),
($CA, $AF, $F3, $81), ($B9, $68, $C4, $3E), ($38, $24, $34, $2C), ($C2, $A3, $40, $5F),
($16, $1D, $C3, $72), ($BC, $E2, $25, $0C), ($28, $3C, $49, $8B), ($FF, $0D, $95, $41),
($39, $A8, $01, $71), ($08, $0C, $B3, $DE), ($D8, $B4, $E4, $9C), ($64, $56, $C1, $90),
($7B, $CB, $84, $61), ($D5, $32, $B6, $70), ($48, $6C, $5C, $74), ($D0, $B8, $57, $42));
T6: array [0 .. 255, 0 .. 3] of Byte = (
($50, $51, $F4, $A7), ($53, $7E, $41, $65), ($C3, $1A, $17, $A4), ($96, $3A, $27, $5E),
($CB, $3B, $AB, $6B), ($F1, $1F, $9D, $45), ($AB, $AC, $FA, $58), ($93, $4B, $E3, $03),
($55, $20, $30, $FA), ($F6, $AD, $76, $6D), ($91, $88, $CC, $76), ($25, $F5, $02, $4C),
($FC, $4F, $E5, $D7), ($D7, $C5, $2A, $CB), ($80, $26, $35, $44), ($8F, $B5, $62, $A3),
($49, $DE, $B1, $5A), ($67, $25, $BA, $1B), ($98, $45, $EA, $0E), ($E1, $5D, $FE, $C0),
($02, $C3, $2F, $75), ($12, $81, $4C, $F0), ($A3, $8D, $46, $97), ($C6, $6B, $D3, $F9),
($E7, $03, $8F, $5F), ($95, $15, $92, $9C), ($EB, $BF, $6D, $7A), ($DA, $95, $52, $59),
($2D, $D4, $BE, $83), ($D3, $58, $74, $21), ($29, $49, $E0, $69), ($44, $8E, $C9, $C8),
($6A, $75, $C2, $89), ($78, $F4, $8E, $79), ($6B, $99, $58, $3E), ($DD, $27, $B9, $71),
($B6, $BE, $E1, $4F), ($17, $F0, $88, $AD), ($66, $C9, $20, $AC), ($B4, $7D, $CE, $3A),
($18, $63, $DF, $4A), ($82, $E5, $1A, $31), ($60, $97, $51, $33), ($45, $62, $53, $7F),
($E0, $B1, $64, $77), ($84, $BB, $6B, $AE), ($1C, $FE, $81, $A0), ($94, $F9, $08, $2B),
($58, $70, $48, $68), ($19, $8F, $45, $FD), ($87, $94, $DE, $6C), ($B7, $52, $7B, $F8),
($23, $AB, $73, $D3), ($E2, $72, $4B, $02), ($57, $E3, $1F, $8F), ($2A, $66, $55, $AB),
($07, $B2, $EB, $28), ($03, $2F, $B5, $C2), ($9A, $86, $C5, $7B), ($A5, $D3, $37, $08),
($F2, $30, $28, $87), ($B2, $23, $BF, $A5), ($BA, $02, $03, $6A), ($5C, $ED, $16, $82),
($2B, $8A, $CF, $1C), ($92, $A7, $79, $B4), ($F0, $F3, $07, $F2), ($A1, $4E, $69, $E2),
($CD, $65, $DA, $F4), ($D5, $06, $05, $BE), ($1F, $D1, $34, $62), ($8A, $C4, $A6, $FE),
($9D, $34, $2E, $53), ($A0, $A2, $F3, $55), ($32, $05, $8A, $E1), ($75, $A4, $F6, $EB),
($39, $0B, $83, $EC), ($AA, $40, $60, $EF), ($06, $5E, $71, $9F), ($51, $BD, $6E, $10),
($F9, $3E, $21, $8A), ($3D, $96, $DD, $06), ($AE, $DD, $3E, $05), ($46, $4D, $E6, $BD),
($B5, $91, $54, $8D), ($05, $71, $C4, $5D), ($6F, $04, $06, $D4), ($FF, $60, $50, $15),
($24, $19, $98, $FB), ($97, $D6, $BD, $E9), ($CC, $89, $40, $43), ($77, $67, $D9, $9E),
($BD, $B0, $E8, $42), ($88, $07, $89, $8B), ($38, $E7, $19, $5B), ($DB, $79, $C8, $EE),
($47, $A1, $7C, $0A), ($E9, $7C, $42, $0F), ($C9, $F8, $84, $1E), ($00, $00, $00, $00),
($83, $09, $80, $86), ($48, $32, $2B, $ED), ($AC, $1E, $11, $70), ($4E, $6C, $5A, $72),
($FB, $FD, $0E, $FF), ($56, $0F, $85, $38), ($1E, $3D, $AE, $D5), ($27, $36, $2D, $39),
($64, $0A, $0F, $D9), ($21, $68, $5C, $A6), ($D1, $9B, $5B, $54), ($3A, $24, $36, $2E),
($B1, $0C, $0A, $67), ($0F, $93, $57, $E7), ($D2, $B4, $EE, $96), ($9E, $1B, $9B, $91),
($4F, $80, $C0, $C5), ($A2, $61, $DC, $20), ($69, $5A, $77, $4B), ($16, $1C, $12, $1A),
($0A, $E2, $93, $BA), ($E5, $C0, $A0, $2A), ($43, $3C, $22, $E0), ($1D, $12, $1B, $17),
($0B, $0E, $09, $0D), ($AD, $F2, $8B, $C7), ($B9, $2D, $B6, $A8), ($C8, $14, $1E, $A9),
($85, $57, $F1, $19), ($4C, $AF, $75, $07), ($BB, $EE, $99, $DD), ($FD, $A3, $7F, $60),
($9F, $F7, $01, $26), ($BC, $5C, $72, $F5), ($C5, $44, $66, $3B), ($34, $5B, $FB, $7E),
($76, $8B, $43, $29), ($DC, $CB, $23, $C6), ($68, $B6, $ED, $FC), ($63, $B8, $E4, $F1),
($CA, $D7, $31, $DC), ($10, $42, $63, $85), ($40, $13, $97, $22), ($20, $84, $C6, $11),
($7D, $85, $4A, $24), ($F8, $D2, $BB, $3D), ($11, $AE, $F9, $32), ($6D, $C7, $29, $A1),
($4B, $1D, $9E, $2F), ($F3, $DC, $B2, $30), ($EC, $0D, $86, $52), ($D0, $77, $C1, $E3),
($6C, $2B, $B3, $16), ($99, $A9, $70, $B9), ($FA, $11, $94, $48), ($22, $47, $E9, $64),
($C4, $A8, $FC, $8C), ($1A, $A0, $F0, $3F), ($D8, $56, $7D, $2C), ($EF, $22, $33, $90),
($C7, $87, $49, $4E), ($C1, $D9, $38, $D1), ($FE, $8C, $CA, $A2), ($36, $98, $D4, $0B),
($CF, $A6, $F5, $81), ($28, $A5, $7A, $DE), ($26, $DA, $B7, $8E), ($A4, $3F, $AD, $BF),
($E4, $2C, $3A, $9D), ($0D, $50, $78, $92), ($9B, $6A, $5F, $CC), ($62, $54, $7E, $46),
($C2, $F6, $8D, $13), ($E8, $90, $D8, $B8), ($5E, $2E, $39, $F7), ($F5, $82, $C3, $AF),
($BE, $9F, $5D, $80), ($7C, $69, $D0, $93), ($A9, $6F, $D5, $2D), ($B3, $CF, $25, $12),
($3B, $C8, $AC, $99), ($A7, $10, $18, $7D), ($6E, $E8, $9C, $63), ($7B, $DB, $3B, $BB),
($09, $CD, $26, $78), ($F4, $6E, $59, $18), ($01, $EC, $9A, $B7), ($A8, $83, $4F, $9A),
($65, $E6, $95, $6E), ($7E, $AA, $FF, $E6), ($08, $21, $BC, $CF), ($E6, $EF, $15, $E8),
($D9, $BA, $E7, $9B), ($CE, $4A, $6F, $36), ($D4, $EA, $9F, $09), ($D6, $29, $B0, $7C),
($AF, $31, $A4, $B2), ($31, $2A, $3F, $23), ($30, $C6, $A5, $94), ($C0, $35, $A2, $66),
($37, $74, $4E, $BC), ($A6, $FC, $82, $CA), ($B0, $E0, $90, $D0), ($15, $33, $A7, $D8),
($4A, $F1, $04, $98), ($F7, $41, $EC, $DA), ($0E, $7F, $CD, $50), ($2F, $17, $91, $F6),
($8D, $76, $4D, $D6), ($4D, $43, $EF, $B0), ($54, $CC, $AA, $4D), ($DF, $E4, $96, $04),
($E3, $9E, $D1, $B5), ($1B, $4C, $6A, $88), ($B8, $C1, $2C, $1F), ($7F, $46, $65, $51),
($04, $9D, $5E, $EA), ($5D, $01, $8C, $35), ($73, $FA, $87, $74), ($2E, $FB, $0B, $41),
($5A, $B3, $67, $1D), ($52, $92, $DB, $D2), ($33, $E9, $10, $56), ($13, $6D, $D6, $47),
($8C, $9A, $D7, $61), ($7A, $37, $A1, $0C), ($8E, $59, $F8, $14), ($89, $EB, $13, $3C),
($EE, $CE, $A9, $27), ($35, $B7, $61, $C9), ($ED, $E1, $1C, $E5), ($3C, $7A, $47, $B1),
($59, $9C, $D2, $DF), ($3F, $55, $F2, $73), ($79, $18, $14, $CE), ($BF, $73, $C7, $37),
($EA, $53, $F7, $CD), ($5B, $5F, $FD, $AA), ($14, $DF, $3D, $6F), ($86, $78, $44, $DB),
($81, $CA, $AF, $F3), ($3E, $B9, $68, $C4), ($2C, $38, $24, $34), ($5F, $C2, $A3, $40),
($72, $16, $1D, $C3), ($0C, $BC, $E2, $25), ($8B, $28, $3C, $49), ($41, $FF, $0D, $95),
($71, $39, $A8, $01), ($DE, $08, $0C, $B3), ($9C, $D8, $B4, $E4), ($90, $64, $56, $C1),
($61, $7B, $CB, $84), ($70, $D5, $32, $B6), ($74, $48, $6C, $5C), ($42, $D0, $B8, $57));
T7: array [0 .. 255, 0 .. 3] of Byte = (
($A7, $50, $51, $F4), ($65, $53, $7E, $41), ($A4, $C3, $1A, $17), ($5E, $96, $3A, $27),
($6B, $CB, $3B, $AB), ($45, $F1, $1F, $9D), ($58, $AB, $AC, $FA), ($03, $93, $4B, $E3),
($FA, $55, $20, $30), ($6D, $F6, $AD, $76), ($76, $91, $88, $CC), ($4C, $25, $F5, $02),
($D7, $FC, $4F, $E5), ($CB, $D7, $C5, $2A), ($44, $80, $26, $35), ($A3, $8F, $B5, $62),
($5A, $49, $DE, $B1), ($1B, $67, $25, $BA), ($0E, $98, $45, $EA), ($C0, $E1, $5D, $FE),
($75, $02, $C3, $2F), ($F0, $12, $81, $4C), ($97, $A3, $8D, $46), ($F9, $C6, $6B, $D3),
($5F, $E7, $03, $8F), ($9C, $95, $15, $92), ($7A, $EB, $BF, $6D), ($59, $DA, $95, $52),
($83, $2D, $D4, $BE), ($21, $D3, $58, $74), ($69, $29, $49, $E0), ($C8, $44, $8E, $C9),
($89, $6A, $75, $C2), ($79, $78, $F4, $8E), ($3E, $6B, $99, $58), ($71, $DD, $27, $B9),
($4F, $B6, $BE, $E1), ($AD, $17, $F0, $88), ($AC, $66, $C9, $20), ($3A, $B4, $7D, $CE),
($4A, $18, $63, $DF), ($31, $82, $E5, $1A), ($33, $60, $97, $51), ($7F, $45, $62, $53),
($77, $E0, $B1, $64), ($AE, $84, $BB, $6B), ($A0, $1C, $FE, $81), ($2B, $94, $F9, $08),
($68, $58, $70, $48), ($FD, $19, $8F, $45), ($6C, $87, $94, $DE), ($F8, $B7, $52, $7B),
($D3, $23, $AB, $73), ($02, $E2, $72, $4B), ($8F, $57, $E3, $1F), ($AB, $2A, $66, $55),
($28, $07, $B2, $EB), ($C2, $03, $2F, $B5), ($7B, $9A, $86, $C5), ($08, $A5, $D3, $37),
($87, $F2, $30, $28), ($A5, $B2, $23, $BF), ($6A, $BA, $02, $03), ($82, $5C, $ED, $16),
($1C, $2B, $8A, $CF), ($B4, $92, $A7, $79), ($F2, $F0, $F3, $07), ($E2, $A1, $4E, $69),
($F4, $CD, $65, $DA), ($BE, $D5, $06, $05), ($62, $1F, $D1, $34), ($FE, $8A, $C4, $A6),
($53, $9D, $34, $2E), ($55, $A0, $A2, $F3), ($E1, $32, $05, $8A), ($EB, $75, $A4, $F6),
($EC, $39, $0B, $83), ($EF, $AA, $40, $60), ($9F, $06, $5E, $71), ($10, $51, $BD, $6E),
($8A, $F9, $3E, $21), ($06, $3D, $96, $DD), ($05, $AE, $DD, $3E), ($BD, $46, $4D, $E6),
($8D, $B5, $91, $54), ($5D, $05, $71, $C4), ($D4, $6F, $04, $06), ($15, $FF, $60, $50),
($FB, $24, $19, $98), ($E9, $97, $D6, $BD), ($43, $CC, $89, $40), ($9E, $77, $67, $D9),
($42, $BD, $B0, $E8), ($8B, $88, $07, $89), ($5B, $38, $E7, $19), ($EE, $DB, $79, $C8),
($0A, $47, $A1, $7C), ($0F, $E9, $7C, $42), ($1E, $C9, $F8, $84), ($00, $00, $00, $00),
($86, $83, $09, $80), ($ED, $48, $32, $2B), ($70, $AC, $1E, $11), ($72, $4E, $6C, $5A),
($FF, $FB, $FD, $0E), ($38, $56, $0F, $85), ($D5, $1E, $3D, $AE), ($39, $27, $36, $2D),
($D9, $64, $0A, $0F), ($A6, $21, $68, $5C), ($54, $D1, $9B, $5B), ($2E, $3A, $24, $36),
($67, $B1, $0C, $0A), ($E7, $0F, $93, $57), ($96, $D2, $B4, $EE), ($91, $9E, $1B, $9B),
($C5, $4F, $80, $C0), ($20, $A2, $61, $DC), ($4B, $69, $5A, $77), ($1A, $16, $1C, $12),
($BA, $0A, $E2, $93), ($2A, $E5, $C0, $A0), ($E0, $43, $3C, $22), ($17, $1D, $12, $1B),
($0D, $0B, $0E, $09), ($C7, $AD, $F2, $8B), ($A8, $B9, $2D, $B6), ($A9, $C8, $14, $1E),
($19, $85, $57, $F1), ($07, $4C, $AF, $75), ($DD, $BB, $EE, $99), ($60, $FD, $A3, $7F),
($26, $9F, $F7, $01), ($F5, $BC, $5C, $72), ($3B, $C5, $44, $66), ($7E, $34, $5B, $FB),
($29, $76, $8B, $43), ($C6, $DC, $CB, $23), ($FC, $68, $B6, $ED), ($F1, $63, $B8, $E4),
($DC, $CA, $D7, $31), ($85, $10, $42, $63), ($22, $40, $13, $97), ($11, $20, $84, $C6),
($24, $7D, $85, $4A), ($3D, $F8, $D2, $BB), ($32, $11, $AE, $F9), ($A1, $6D, $C7, $29),
($2F, $4B, $1D, $9E), ($30, $F3, $DC, $B2), ($52, $EC, $0D, $86), ($E3, $D0, $77, $C1),
($16, $6C, $2B, $B3), ($B9, $99, $A9, $70), ($48, $FA, $11, $94), ($64, $22, $47, $E9),
($8C, $C4, $A8, $FC), ($3F, $1A, $A0, $F0), ($2C, $D8, $56, $7D), ($90, $EF, $22, $33),
($4E, $C7, $87, $49), ($D1, $C1, $D9, $38), ($A2, $FE, $8C, $CA), ($0B, $36, $98, $D4),
($81, $CF, $A6, $F5), ($DE, $28, $A5, $7A), ($8E, $26, $DA, $B7), ($BF, $A4, $3F, $AD),
($9D, $E4, $2C, $3A), ($92, $0D, $50, $78), ($CC, $9B, $6A, $5F), ($46, $62, $54, $7E),
($13, $C2, $F6, $8D), ($B8, $E8, $90, $D8), ($F7, $5E, $2E, $39), ($AF, $F5, $82, $C3),
($80, $BE, $9F, $5D), ($93, $7C, $69, $D0), ($2D, $A9, $6F, $D5), ($12, $B3, $CF, $25),
($99, $3B, $C8, $AC), ($7D, $A7, $10, $18), ($63, $6E, $E8, $9C), ($BB, $7B, $DB, $3B),
($78, $09, $CD, $26), ($18, $F4, $6E, $59), ($B7, $01, $EC, $9A), ($9A, $A8, $83, $4F),
($6E, $65, $E6, $95), ($E6, $7E, $AA, $FF), ($CF, $08, $21, $BC), ($E8, $E6, $EF, $15),
($9B, $D9, $BA, $E7), ($36, $CE, $4A, $6F), ($09, $D4, $EA, $9F), ($7C, $D6, $29, $B0),
($B2, $AF, $31, $A4), ($23, $31, $2A, $3F), ($94, $30, $C6, $A5), ($66, $C0, $35, $A2),
($BC, $37, $74, $4E), ($CA, $A6, $FC, $82), ($D0, $B0, $E0, $90), ($D8, $15, $33, $A7),
($98, $4A, $F1, $04), ($DA, $F7, $41, $EC), ($50, $0E, $7F, $CD), ($F6, $2F, $17, $91),
($D6, $8D, $76, $4D), ($B0, $4D, $43, $EF), ($4D, $54, $CC, $AA), ($04, $DF, $E4, $96),
($B5, $E3, $9E, $D1), ($88, $1B, $4C, $6A), ($1F, $B8, $C1, $2C), ($51, $7F, $46, $65),
($EA, $04, $9D, $5E), ($35, $5D, $01, $8C), ($74, $73, $FA, $87), ($41, $2E, $FB, $0B),
($1D, $5A, $B3, $67), ($D2, $52, $92, $DB), ($56, $33, $E9, $10), ($47, $13, $6D, $D6),
($61, $8C, $9A, $D7), ($0C, $7A, $37, $A1), ($14, $8E, $59, $F8), ($3C, $89, $EB, $13),
($27, $EE, $CE, $A9), ($C9, $35, $B7, $61), ($E5, $ED, $E1, $1C), ($B1, $3C, $7A, $47),
($DF, $59, $9C, $D2), ($73, $3F, $55, $F2), ($CE, $79, $18, $14), ($37, $BF, $73, $C7),
($CD, $EA, $53, $F7), ($AA, $5B, $5F, $FD), ($6F, $14, $DF, $3D), ($DB, $86, $78, $44),
($F3, $81, $CA, $AF), ($C4, $3E, $B9, $68), ($34, $2C, $38, $24), ($40, $5F, $C2, $A3),
($C3, $72, $16, $1D), ($25, $0C, $BC, $E2), ($49, $8B, $28, $3C), ($95, $41, $FF, $0D),
($01, $71, $39, $A8), ($B3, $DE, $08, $0C), ($E4, $9C, $D8, $B4), ($C1, $90, $64, $56),
($84, $61, $7B, $CB), ($B6, $70, $D5, $32), ($5C, $74, $48, $6C), ($57, $42, $D0, $B8));
T8: array [0 .. 255, 0 .. 3] of Byte = (
($F4, $A7, $50, $51), ($41, $65, $53, $7E), ($17, $A4, $C3, $1A), ($27, $5E, $96, $3A),
($AB, $6B, $CB, $3B), ($9D, $45, $F1, $1F), ($FA, $58, $AB, $AC), ($E3, $03, $93, $4B),
($30, $FA, $55, $20), ($76, $6D, $F6, $AD), ($CC, $76, $91, $88), ($02, $4C, $25, $F5),
($E5, $D7, $FC, $4F), ($2A, $CB, $D7, $C5), ($35, $44, $80, $26), ($62, $A3, $8F, $B5),
($B1, $5A, $49, $DE), ($BA, $1B, $67, $25), ($EA, $0E, $98, $45), ($FE, $C0, $E1, $5D),
($2F, $75, $02, $C3), ($4C, $F0, $12, $81), ($46, $97, $A3, $8D), ($D3, $F9, $C6, $6B),
($8F, $5F, $E7, $03), ($92, $9C, $95, $15), ($6D, $7A, $EB, $BF), ($52, $59, $DA, $95),
($BE, $83, $2D, $D4), ($74, $21, $D3, $58), ($E0, $69, $29, $49), ($C9, $C8, $44, $8E),
($C2, $89, $6A, $75), ($8E, $79, $78, $F4), ($58, $3E, $6B, $99), ($B9, $71, $DD, $27),
($E1, $4F, $B6, $BE), ($88, $AD, $17, $F0), ($20, $AC, $66, $C9), ($CE, $3A, $B4, $7D),
($DF, $4A, $18, $63), ($1A, $31, $82, $E5), ($51, $33, $60, $97), ($53, $7F, $45, $62),
($64, $77, $E0, $B1), ($6B, $AE, $84, $BB), ($81, $A0, $1C, $FE), ($08, $2B, $94, $F9),
($48, $68, $58, $70), ($45, $FD, $19, $8F), ($DE, $6C, $87, $94), ($7B, $F8, $B7, $52),
($73, $D3, $23, $AB), ($4B, $02, $E2, $72), ($1F, $8F, $57, $E3), ($55, $AB, $2A, $66),
($EB, $28, $07, $B2), ($B5, $C2, $03, $2F), ($C5, $7B, $9A, $86), ($37, $08, $A5, $D3),
($28, $87, $F2, $30), ($BF, $A5, $B2, $23), ($03, $6A, $BA, $02), ($16, $82, $5C, $ED),
($CF, $1C, $2B, $8A), ($79, $B4, $92, $A7), ($07, $F2, $F0, $F3), ($69, $E2, $A1, $4E),
($DA, $F4, $CD, $65), ($05, $BE, $D5, $06), ($34, $62, $1F, $D1), ($A6, $FE, $8A, $C4),
($2E, $53, $9D, $34), ($F3, $55, $A0, $A2), ($8A, $E1, $32, $05), ($F6, $EB, $75, $A4),
($83, $EC, $39, $0B), ($60, $EF, $AA, $40), ($71, $9F, $06, $5E), ($6E, $10, $51, $BD),
($21, $8A, $F9, $3E), ($DD, $06, $3D, $96), ($3E, $05, $AE, $DD), ($E6, $BD, $46, $4D),
($54, $8D, $B5, $91), ($C4, $5D, $05, $71), ($06, $D4, $6F, $04), ($50, $15, $FF, $60),
($98, $FB, $24, $19), ($BD, $E9, $97, $D6), ($40, $43, $CC, $89), ($D9, $9E, $77, $67),
($E8, $42, $BD, $B0), ($89, $8B, $88, $07), ($19, $5B, $38, $E7), ($C8, $EE, $DB, $79),
($7C, $0A, $47, $A1), ($42, $0F, $E9, $7C), ($84, $1E, $C9, $F8), ($00, $00, $00, $00),
($80, $86, $83, $09), ($2B, $ED, $48, $32), ($11, $70, $AC, $1E), ($5A, $72, $4E, $6C),
($0E, $FF, $FB, $FD), ($85, $38, $56, $0F), ($AE, $D5, $1E, $3D), ($2D, $39, $27, $36),
($0F, $D9, $64, $0A), ($5C, $A6, $21, $68), ($5B, $54, $D1, $9B), ($36, $2E, $3A, $24),
($0A, $67, $B1, $0C), ($57, $E7, $0F, $93), ($EE, $96, $D2, $B4), ($9B, $91, $9E, $1B),
($C0, $C5, $4F, $80), ($DC, $20, $A2, $61), ($77, $4B, $69, $5A), ($12, $1A, $16, $1C),
($93, $BA, $0A, $E2), ($A0, $2A, $E5, $C0), ($22, $E0, $43, $3C), ($1B, $17, $1D, $12),
($09, $0D, $0B, $0E), ($8B, $C7, $AD, $F2), ($B6, $A8, $B9, $2D), ($1E, $A9, $C8, $14),
($F1, $19, $85, $57), ($75, $07, $4C, $AF), ($99, $DD, $BB, $EE), ($7F, $60, $FD, $A3),
($01, $26, $9F, $F7), ($72, $F5, $BC, $5C), ($66, $3B, $C5, $44), ($FB, $7E, $34, $5B),
($43, $29, $76, $8B), ($23, $C6, $DC, $CB), ($ED, $FC, $68, $B6), ($E4, $F1, $63, $B8),
($31, $DC, $CA, $D7), ($63, $85, $10, $42), ($97, $22, $40, $13), ($C6, $11, $20, $84),
($4A, $24, $7D, $85), ($BB, $3D, $F8, $D2), ($F9, $32, $11, $AE), ($29, $A1, $6D, $C7),
($9E, $2F, $4B, $1D), ($B2, $30, $F3, $DC), ($86, $52, $EC, $0D), ($C1, $E3, $D0, $77),
($B3, $16, $6C, $2B), ($70, $B9, $99, $A9), ($94, $48, $FA, $11), ($E9, $64, $22, $47),
($FC, $8C, $C4, $A8), ($F0, $3F, $1A, $A0), ($7D, $2C, $D8, $56), ($33, $90, $EF, $22),
($49, $4E, $C7, $87), ($38, $D1, $C1, $D9), ($CA, $A2, $FE, $8C), ($D4, $0B, $36, $98),
($F5, $81, $CF, $A6), ($7A, $DE, $28, $A5), ($B7, $8E, $26, $DA), ($AD, $BF, $A4, $3F),
($3A, $9D, $E4, $2C), ($78, $92, $0D, $50), ($5F, $CC, $9B, $6A), ($7E, $46, $62, $54),
($8D, $13, $C2, $F6), ($D8, $B8, $E8, $90), ($39, $F7, $5E, $2E), ($C3, $AF, $F5, $82),
($5D, $80, $BE, $9F), ($D0, $93, $7C, $69), ($D5, $2D, $A9, $6F), ($25, $12, $B3, $CF),
($AC, $99, $3B, $C8), ($18, $7D, $A7, $10), ($9C, $63, $6E, $E8), ($3B, $BB, $7B, $DB),
($26, $78, $09, $CD), ($59, $18, $F4, $6E), ($9A, $B7, $01, $EC), ($4F, $9A, $A8, $83),
($95, $6E, $65, $E6), ($FF, $E6, $7E, $AA), ($BC, $CF, $08, $21), ($15, $E8, $E6, $EF),
($E7, $9B, $D9, $BA), ($6F, $36, $CE, $4A), ($9F, $09, $D4, $EA), ($B0, $7C, $D6, $29),
($A4, $B2, $AF, $31), ($3F, $23, $31, $2A), ($A5, $94, $30, $C6), ($A2, $66, $C0, $35),
($4E, $BC, $37, $74), ($82, $CA, $A6, $FC), ($90, $D0, $B0, $E0), ($A7, $D8, $15, $33),
($04, $98, $4A, $F1), ($EC, $DA, $F7, $41), ($CD, $50, $0E, $7F), ($91, $F6, $2F, $17),
($4D, $D6, $8D, $76), ($EF, $B0, $4D, $43), ($AA, $4D, $54, $CC), ($96, $04, $DF, $E4),
($D1, $B5, $E3, $9E), ($6A, $88, $1B, $4C), ($2C, $1F, $B8, $C1), ($65, $51, $7F, $46),
($5E, $EA, $04, $9D), ($8C, $35, $5D, $01), ($87, $74, $73, $FA), ($0B, $41, $2E, $FB),
($67, $1D, $5A, $B3), ($DB, $D2, $52, $92), ($10, $56, $33, $E9), ($D6, $47, $13, $6D),
($D7, $61, $8C, $9A), ($A1, $0C, $7A, $37), ($F8, $14, $8E, $59), ($13, $3C, $89, $EB),
($A9, $27, $EE, $CE), ($61, $C9, $35, $B7), ($1C, $E5, $ED, $E1), ($47, $B1, $3C, $7A),
($D2, $DF, $59, $9C), ($F2, $73, $3F, $55), ($14, $CE, $79, $18), ($C7, $37, $BF, $73),
($F7, $CD, $EA, $53), ($FD, $AA, $5B, $5F), ($3D, $6F, $14, $DF), ($44, $DB, $86, $78),
($AF, $F3, $81, $CA), ($68, $C4, $3E, $B9), ($24, $34, $2C, $38), ($A3, $40, $5F, $C2),
($1D, $C3, $72, $16), ($E2, $25, $0C, $BC), ($3C, $49, $8B, $28), ($0D, $95, $41, $FF),
($A8, $01, $71, $39), ($0C, $B3, $DE, $08), ($B4, $E4, $9C, $D8), ($56, $C1, $90, $64),
($CB, $84, $61, $7B), ($32, $B6, $70, $D5), ($6C, $5C, $74, $48), ($B8, $57, $42, $D0));
S5: array [0 .. 255] of Byte = (
$52, $09, $6A, $D5, $30, $36, $A5, $38, $BF, $40, $A3, $9E, $81, $F3, $D7, $FB, $7C, $E3, $39, $82,
$9B, $2F, $FF, $87, $34, $8E, $43, $44, $C4, $DE, $E9, $CB, $54, $7B, $94, $32, $A6, $C2, $23, $3D,
$EE, $4C, $95, $0B, $42, $FA, $C3, $4E, $08, $2E, $A1, $66, $28, $D9, $24, $B2, $76, $5B, $A2, $49,
$6D, $8B, $D1, $25, $72, $F8, $F6, $64, $86, $68, $98, $16, $D4, $A4, $5C, $CC, $5D, $65, $B6, $92,
$6C, $70, $48, $50, $FD, $ED, $B9, $DA, $5E, $15, $46, $57, $A7, $8D, $9D, $84, $90, $D8, $AB, $00,
$8C, $BC, $D3, $0A, $F7, $E4, $58, $05, $B8, $B3, $45, $06, $D0, $2C, $1E, $8F, $CA, $3F, $0F, $02,
$C1, $AF, $BD, $03, $01, $13, $8A, $6B, $3A, $91, $11, $41, $4F, $67, $DC, $EA, $97, $F2, $CF, $CE,
$F0, $B4, $E6, $73, $96, $AC, $74, $22, $E7, $AD, $35, $85, $E2, $F9, $37, $E8, $1C, $75, $DF, $6E,
$47, $F1, $1A, $71, $1D, $29, $C5, $89, $6F, $B7, $62, $0E, $AA, $18, $BE, $1B, $FC, $56, $3E, $4B,
$C6, $D2, $79, $20, $9A, $DB, $C0, $FE, $78, $CD, $5A, $F4, $1F, $DD, $A8, $33, $88, $07, $C7, $31,
$B1, $12, $10, $59, $27, $80, $EC, $5F, $60, $51, $7F, $A9, $19, $B5, $4A, $0D, $2D, $E5, $7A, $9F,
$93, $C9, $9C, $EF, $A0, $E0, $3B, $4D, $AE, $2A, $F5, $B0, $C8, $EB, $BB, $3C, $83, $53, $99, $61,
$17, $2B, $04, $7E, $BA, $77, $D6, $26, $E1, $69, $14, $63, $55, $21, $0C, $7D);
U1: array [0 .. 255, 0 .. 3] of Byte = (
($00, $00, $00, $00), ($0E, $09, $0D, $0B), ($1C, $12, $1A, $16), ($12, $1B, $17, $1D),
($38, $24, $34, $2C), ($36, $2D, $39, $27), ($24, $36, $2E, $3A), ($2A, $3F, $23, $31),
($70, $48, $68, $58), ($7E, $41, $65, $53), ($6C, $5A, $72, $4E), ($62, $53, $7F, $45),
($48, $6C, $5C, $74), ($46, $65, $51, $7F), ($54, $7E, $46, $62), ($5A, $77, $4B, $69),
($E0, $90, $D0, $B0), ($EE, $99, $DD, $BB), ($FC, $82, $CA, $A6), ($F2, $8B, $C7, $AD),
($D8, $B4, $E4, $9C), ($D6, $BD, $E9, $97), ($C4, $A6, $FE, $8A), ($CA, $AF, $F3, $81),
($90, $D8, $B8, $E8), ($9E, $D1, $B5, $E3), ($8C, $CA, $A2, $FE), ($82, $C3, $AF, $F5),
($A8, $FC, $8C, $C4), ($A6, $F5, $81, $CF), ($B4, $EE, $96, $D2), ($BA, $E7, $9B, $D9),
($DB, $3B, $BB, $7B), ($D5, $32, $B6, $70), ($C7, $29, $A1, $6D), ($C9, $20, $AC, $66),
($E3, $1F, $8F, $57), ($ED, $16, $82, $5C), ($FF, $0D, $95, $41), ($F1, $04, $98, $4A),
($AB, $73, $D3, $23), ($A5, $7A, $DE, $28), ($B7, $61, $C9, $35), ($B9, $68, $C4, $3E),
($93, $57, $E7, $0F), ($9D, $5E, $EA, $04), ($8F, $45, $FD, $19), ($81, $4C, $F0, $12),
($3B, $AB, $6B, $CB), ($35, $A2, $66, $C0), ($27, $B9, $71, $DD), ($29, $B0, $7C, $D6),
($03, $8F, $5F, $E7), ($0D, $86, $52, $EC), ($1F, $9D, $45, $F1), ($11, $94, $48, $FA),
($4B, $E3, $03, $93), ($45, $EA, $0E, $98), ($57, $F1, $19, $85), ($59, $F8, $14, $8E),
($73, $C7, $37, $BF), ($7D, $CE, $3A, $B4), ($6F, $D5, $2D, $A9), ($61, $DC, $20, $A2),
($AD, $76, $6D, $F6), ($A3, $7F, $60, $FD), ($B1, $64, $77, $E0), ($BF, $6D, $7A, $EB),
($95, $52, $59, $DA), ($9B, $5B, $54, $D1), ($89, $40, $43, $CC), ($87, $49, $4E, $C7),
($DD, $3E, $05, $AE), ($D3, $37, $08, $A5), ($C1, $2C, $1F, $B8), ($CF, $25, $12, $B3),
($E5, $1A, $31, $82), ($EB, $13, $3C, $89), ($F9, $08, $2B, $94), ($F7, $01, $26, $9F),
($4D, $E6, $BD, $46), ($43, $EF, $B0, $4D), ($51, $F4, $A7, $50), ($5F, $FD, $AA, $5B),
($75, $C2, $89, $6A), ($7B, $CB, $84, $61), ($69, $D0, $93, $7C), ($67, $D9, $9E, $77),
($3D, $AE, $D5, $1E), ($33, $A7, $D8, $15), ($21, $BC, $CF, $08), ($2F, $B5, $C2, $03),
($05, $8A, $E1, $32), ($0B, $83, $EC, $39), ($19, $98, $FB, $24), ($17, $91, $F6, $2F),
($76, $4D, $D6, $8D), ($78, $44, $DB, $86), ($6A, $5F, $CC, $9B), ($64, $56, $C1, $90),
($4E, $69, $E2, $A1), ($40, $60, $EF, $AA), ($52, $7B, $F8, $B7), ($5C, $72, $F5, $BC),
($06, $05, $BE, $D5), ($08, $0C, $B3, $DE), ($1A, $17, $A4, $C3), ($14, $1E, $A9, $C8),
($3E, $21, $8A, $F9), ($30, $28, $87, $F2), ($22, $33, $90, $EF), ($2C, $3A, $9D, $E4),
($96, $DD, $06, $3D), ($98, $D4, $0B, $36), ($8A, $CF, $1C, $2B), ($84, $C6, $11, $20),
($AE, $F9, $32, $11), ($A0, $F0, $3F, $1A), ($B2, $EB, $28, $07), ($BC, $E2, $25, $0C),
($E6, $95, $6E, $65), ($E8, $9C, $63, $6E), ($FA, $87, $74, $73), ($F4, $8E, $79, $78),
($DE, $B1, $5A, $49), ($D0, $B8, $57, $42), ($C2, $A3, $40, $5F), ($CC, $AA, $4D, $54),
($41, $EC, $DA, $F7), ($4F, $E5, $D7, $FC), ($5D, $FE, $C0, $E1), ($53, $F7, $CD, $EA),
($79, $C8, $EE, $DB), ($77, $C1, $E3, $D0), ($65, $DA, $F4, $CD), ($6B, $D3, $F9, $C6),
($31, $A4, $B2, $AF), ($3F, $AD, $BF, $A4), ($2D, $B6, $A8, $B9), ($23, $BF, $A5, $B2),
($09, $80, $86, $83), ($07, $89, $8B, $88), ($15, $92, $9C, $95), ($1B, $9B, $91, $9E),
($A1, $7C, $0A, $47), ($AF, $75, $07, $4C), ($BD, $6E, $10, $51), ($B3, $67, $1D, $5A),
($99, $58, $3E, $6B), ($97, $51, $33, $60), ($85, $4A, $24, $7D), ($8B, $43, $29, $76),
($D1, $34, $62, $1F), ($DF, $3D, $6F, $14), ($CD, $26, $78, $09), ($C3, $2F, $75, $02),
($E9, $10, $56, $33), ($E7, $19, $5B, $38), ($F5, $02, $4C, $25), ($FB, $0B, $41, $2E),
($9A, $D7, $61, $8C), ($94, $DE, $6C, $87), ($86, $C5, $7B, $9A), ($88, $CC, $76, $91),
($A2, $F3, $55, $A0), ($AC, $FA, $58, $AB), ($BE, $E1, $4F, $B6), ($B0, $E8, $42, $BD),
($EA, $9F, $09, $D4), ($E4, $96, $04, $DF), ($F6, $8D, $13, $C2), ($F8, $84, $1E, $C9),
($D2, $BB, $3D, $F8), ($DC, $B2, $30, $F3), ($CE, $A9, $27, $EE), ($C0, $A0, $2A, $E5),
($7A, $47, $B1, $3C), ($74, $4E, $BC, $37), ($66, $55, $AB, $2A), ($68, $5C, $A6, $21),
($42, $63, $85, $10), ($4C, $6A, $88, $1B), ($5E, $71, $9F, $06), ($50, $78, $92, $0D),
($0A, $0F, $D9, $64), ($04, $06, $D4, $6F), ($16, $1D, $C3, $72), ($18, $14, $CE, $79),
($32, $2B, $ED, $48), ($3C, $22, $E0, $43), ($2E, $39, $F7, $5E), ($20, $30, $FA, $55),
($EC, $9A, $B7, $01), ($E2, $93, $BA, $0A), ($F0, $88, $AD, $17), ($FE, $81, $A0, $1C),
($D4, $BE, $83, $2D), ($DA, $B7, $8E, $26), ($C8, $AC, $99, $3B), ($C6, $A5, $94, $30),
($9C, $D2, $DF, $59), ($92, $DB, $D2, $52), ($80, $C0, $C5, $4F), ($8E, $C9, $C8, $44),
($A4, $F6, $EB, $75), ($AA, $FF, $E6, $7E), ($B8, $E4, $F1, $63), ($B6, $ED, $FC, $68),
($0C, $0A, $67, $B1), ($02, $03, $6A, $BA), ($10, $18, $7D, $A7), ($1E, $11, $70, $AC),
($34, $2E, $53, $9D), ($3A, $27, $5E, $96), ($28, $3C, $49, $8B), ($26, $35, $44, $80),
($7C, $42, $0F, $E9), ($72, $4B, $02, $E2), ($60, $50, $15, $FF), ($6E, $59, $18, $F4),
($44, $66, $3B, $C5), ($4A, $6F, $36, $CE), ($58, $74, $21, $D3), ($56, $7D, $2C, $D8),
($37, $A1, $0C, $7A), ($39, $A8, $01, $71), ($2B, $B3, $16, $6C), ($25, $BA, $1B, $67),
($0F, $85, $38, $56), ($01, $8C, $35, $5D), ($13, $97, $22, $40), ($1D, $9E, $2F, $4B),
($47, $E9, $64, $22), ($49, $E0, $69, $29), ($5B, $FB, $7E, $34), ($55, $F2, $73, $3F),
($7F, $CD, $50, $0E), ($71, $C4, $5D, $05), ($63, $DF, $4A, $18), ($6D, $D6, $47, $13),
($D7, $31, $DC, $CA), ($D9, $38, $D1, $C1), ($CB, $23, $C6, $DC), ($C5, $2A, $CB, $D7),
($EF, $15, $E8, $E6), ($E1, $1C, $E5, $ED), ($F3, $07, $F2, $F0), ($FD, $0E, $FF, $FB),
($A7, $79, $B4, $92), ($A9, $70, $B9, $99), ($BB, $6B, $AE, $84), ($B5, $62, $A3, $8F),
($9F, $5D, $80, $BE), ($91, $54, $8D, $B5), ($83, $4F, $9A, $A8), ($8D, $46, $97, $A3));
U2: array [0 .. 255, 0 .. 3] of Byte = (
($00, $00, $00, $00), ($0B, $0E, $09, $0D), ($16, $1C, $12, $1A), ($1D, $12, $1B, $17),
($2C, $38, $24, $34), ($27, $36, $2D, $39), ($3A, $24, $36, $2E), ($31, $2A, $3F, $23),
($58, $70, $48, $68), ($53, $7E, $41, $65), ($4E, $6C, $5A, $72), ($45, $62, $53, $7F),
($74, $48, $6C, $5C), ($7F, $46, $65, $51), ($62, $54, $7E, $46), ($69, $5A, $77, $4B),
($B0, $E0, $90, $D0), ($BB, $EE, $99, $DD), ($A6, $FC, $82, $CA), ($AD, $F2, $8B, $C7),
($9C, $D8, $B4, $E4), ($97, $D6, $BD, $E9), ($8A, $C4, $A6, $FE), ($81, $CA, $AF, $F3),
($E8, $90, $D8, $B8), ($E3, $9E, $D1, $B5), ($FE, $8C, $CA, $A2), ($F5, $82, $C3, $AF),
($C4, $A8, $FC, $8C), ($CF, $A6, $F5, $81), ($D2, $B4, $EE, $96), ($D9, $BA, $E7, $9B),
($7B, $DB, $3B, $BB), ($70, $D5, $32, $B6), ($6D, $C7, $29, $A1), ($66, $C9, $20, $AC),
($57, $E3, $1F, $8F), ($5C, $ED, $16, $82), ($41, $FF, $0D, $95), ($4A, $F1, $04, $98),
($23, $AB, $73, $D3), ($28, $A5, $7A, $DE), ($35, $B7, $61, $C9), ($3E, $B9, $68, $C4),
($0F, $93, $57, $E7), ($04, $9D, $5E, $EA), ($19, $8F, $45, $FD), ($12, $81, $4C, $F0),
($CB, $3B, $AB, $6B), ($C0, $35, $A2, $66), ($DD, $27, $B9, $71), ($D6, $29, $B0, $7C),
($E7, $03, $8F, $5F), ($EC, $0D, $86, $52), ($F1, $1F, $9D, $45), ($FA, $11, $94, $48),
($93, $4B, $E3, $03), ($98, $45, $EA, $0E), ($85, $57, $F1, $19), ($8E, $59, $F8, $14),
($BF, $73, $C7, $37), ($B4, $7D, $CE, $3A), ($A9, $6F, $D5, $2D), ($A2, $61, $DC, $20),
($F6, $AD, $76, $6D), ($FD, $A3, $7F, $60), ($E0, $B1, $64, $77), ($EB, $BF, $6D, $7A),
($DA, $95, $52, $59), ($D1, $9B, $5B, $54), ($CC, $89, $40, $43), ($C7, $87, $49, $4E),
($AE, $DD, $3E, $05), ($A5, $D3, $37, $08), ($B8, $C1, $2C, $1F), ($B3, $CF, $25, $12),
($82, $E5, $1A, $31), ($89, $EB, $13, $3C), ($94, $F9, $08, $2B), ($9F, $F7, $01, $26),
($46, $4D, $E6, $BD), ($4D, $43, $EF, $B0), ($50, $51, $F4, $A7), ($5B, $5F, $FD, $AA),
($6A, $75, $C2, $89), ($61, $7B, $CB, $84), ($7C, $69, $D0, $93), ($77, $67, $D9, $9E),
($1E, $3D, $AE, $D5), ($15, $33, $A7, $D8), ($08, $21, $BC, $CF), ($03, $2F, $B5, $C2),
($32, $05, $8A, $E1), ($39, $0B, $83, $EC), ($24, $19, $98, $FB), ($2F, $17, $91, $F6),
($8D, $76, $4D, $D6), ($86, $78, $44, $DB), ($9B, $6A, $5F, $CC), ($90, $64, $56, $C1),
($A1, $4E, $69, $E2), ($AA, $40, $60, $EF), ($B7, $52, $7B, $F8), ($BC, $5C, $72, $F5),
($D5, $06, $05, $BE), ($DE, $08, $0C, $B3), ($C3, $1A, $17, $A4), ($C8, $14, $1E, $A9),
($F9, $3E, $21, $8A), ($F2, $30, $28, $87), ($EF, $22, $33, $90), ($E4, $2C, $3A, $9D),
($3D, $96, $DD, $06), ($36, $98, $D4, $0B), ($2B, $8A, $CF, $1C), ($20, $84, $C6, $11),
($11, $AE, $F9, $32), ($1A, $A0, $F0, $3F), ($07, $B2, $EB, $28), ($0C, $BC, $E2, $25),
($65, $E6, $95, $6E), ($6E, $E8, $9C, $63), ($73, $FA, $87, $74), ($78, $F4, $8E, $79),
($49, $DE, $B1, $5A), ($42, $D0, $B8, $57), ($5F, $C2, $A3, $40), ($54, $CC, $AA, $4D),
($F7, $41, $EC, $DA), ($FC, $4F, $E5, $D7), ($E1, $5D, $FE, $C0), ($EA, $53, $F7, $CD),
($DB, $79, $C8, $EE), ($D0, $77, $C1, $E3), ($CD, $65, $DA, $F4), ($C6, $6B, $D3, $F9),
($AF, $31, $A4, $B2), ($A4, $3F, $AD, $BF), ($B9, $2D, $B6, $A8), ($B2, $23, $BF, $A5),
($83, $09, $80, $86), ($88, $07, $89, $8B), ($95, $15, $92, $9C), ($9E, $1B, $9B, $91),
($47, $A1, $7C, $0A), ($4C, $AF, $75, $07), ($51, $BD, $6E, $10), ($5A, $B3, $67, $1D),
($6B, $99, $58, $3E), ($60, $97, $51, $33), ($7D, $85, $4A, $24), ($76, $8B, $43, $29),
($1F, $D1, $34, $62), ($14, $DF, $3D, $6F), ($09, $CD, $26, $78), ($02, $C3, $2F, $75),
($33, $E9, $10, $56), ($38, $E7, $19, $5B), ($25, $F5, $02, $4C), ($2E, $FB, $0B, $41),
($8C, $9A, $D7, $61), ($87, $94, $DE, $6C), ($9A, $86, $C5, $7B), ($91, $88, $CC, $76),
($A0, $A2, $F3, $55), ($AB, $AC, $FA, $58), ($B6, $BE, $E1, $4F), ($BD, $B0, $E8, $42),
($D4, $EA, $9F, $09), ($DF, $E4, $96, $04), ($C2, $F6, $8D, $13), ($C9, $F8, $84, $1E),
($F8, $D2, $BB, $3D), ($F3, $DC, $B2, $30), ($EE, $CE, $A9, $27), ($E5, $C0, $A0, $2A),
($3C, $7A, $47, $B1), ($37, $74, $4E, $BC), ($2A, $66, $55, $AB), ($21, $68, $5C, $A6),
($10, $42, $63, $85), ($1B, $4C, $6A, $88), ($06, $5E, $71, $9F), ($0D, $50, $78, $92),
($64, $0A, $0F, $D9), ($6F, $04, $06, $D4), ($72, $16, $1D, $C3), ($79, $18, $14, $CE),
($48, $32, $2B, $ED), ($43, $3C, $22, $E0), ($5E, $2E, $39, $F7), ($55, $20, $30, $FA),
($01, $EC, $9A, $B7), ($0A, $E2, $93, $BA), ($17, $F0, $88, $AD), ($1C, $FE, $81, $A0),
($2D, $D4, $BE, $83), ($26, $DA, $B7, $8E), ($3B, $C8, $AC, $99), ($30, $C6, $A5, $94),
($59, $9C, $D2, $DF), ($52, $92, $DB, $D2), ($4F, $80, $C0, $C5), ($44, $8E, $C9, $C8),
($75, $A4, $F6, $EB), ($7E, $AA, $FF, $E6), ($63, $B8, $E4, $F1), ($68, $B6, $ED, $FC),
($B1, $0C, $0A, $67), ($BA, $02, $03, $6A), ($A7, $10, $18, $7D), ($AC, $1E, $11, $70),
($9D, $34, $2E, $53), ($96, $3A, $27, $5E), ($8B, $28, $3C, $49), ($80, $26, $35, $44),
($E9, $7C, $42, $0F), ($E2, $72, $4B, $02), ($FF, $60, $50, $15), ($F4, $6E, $59, $18),
($C5, $44, $66, $3B), ($CE, $4A, $6F, $36), ($D3, $58, $74, $21), ($D8, $56, $7D, $2C),
($7A, $37, $A1, $0C), ($71, $39, $A8, $01), ($6C, $2B, $B3, $16), ($67, $25, $BA, $1B),
($56, $0F, $85, $38), ($5D, $01, $8C, $35), ($40, $13, $97, $22), ($4B, $1D, $9E, $2F),
($22, $47, $E9, $64), ($29, $49, $E0, $69), ($34, $5B, $FB, $7E), ($3F, $55, $F2, $73),
($0E, $7F, $CD, $50), ($05, $71, $C4, $5D), ($18, $63, $DF, $4A), ($13, $6D, $D6, $47),
($CA, $D7, $31, $DC), ($C1, $D9, $38, $D1), ($DC, $CB, $23, $C6), ($D7, $C5, $2A, $CB),
($E6, $EF, $15, $E8), ($ED, $E1, $1C, $E5), ($F0, $F3, $07, $F2), ($FB, $FD, $0E, $FF),
($92, $A7, $79, $B4), ($99, $A9, $70, $B9), ($84, $BB, $6B, $AE), ($8F, $B5, $62, $A3),
($BE, $9F, $5D, $80), ($B5, $91, $54, $8D), ($A8, $83, $4F, $9A), ($A3, $8D, $46, $97));
U3: array [0 .. 255, 0 .. 3] of Byte = (
($00, $00, $00, $00), ($0D, $0B, $0E, $09), ($1A, $16, $1C, $12), ($17, $1D, $12, $1B),
($34, $2C, $38, $24), ($39, $27, $36, $2D), ($2E, $3A, $24, $36), ($23, $31, $2A, $3F),
($68, $58, $70, $48), ($65, $53, $7E, $41), ($72, $4E, $6C, $5A), ($7F, $45, $62, $53),
($5C, $74, $48, $6C), ($51, $7F, $46, $65), ($46, $62, $54, $7E), ($4B, $69, $5A, $77),
($D0, $B0, $E0, $90), ($DD, $BB, $EE, $99), ($CA, $A6, $FC, $82), ($C7, $AD, $F2, $8B),
($E4, $9C, $D8, $B4), ($E9, $97, $D6, $BD), ($FE, $8A, $C4, $A6), ($F3, $81, $CA, $AF),
($B8, $E8, $90, $D8), ($B5, $E3, $9E, $D1), ($A2, $FE, $8C, $CA), ($AF, $F5, $82, $C3),
($8C, $C4, $A8, $FC), ($81, $CF, $A6, $F5), ($96, $D2, $B4, $EE), ($9B, $D9, $BA, $E7),
($BB, $7B, $DB, $3B), ($B6, $70, $D5, $32), ($A1, $6D, $C7, $29), ($AC, $66, $C9, $20),
($8F, $57, $E3, $1F), ($82, $5C, $ED, $16), ($95, $41, $FF, $0D), ($98, $4A, $F1, $04),
($D3, $23, $AB, $73), ($DE, $28, $A5, $7A), ($C9, $35, $B7, $61), ($C4, $3E, $B9, $68),
($E7, $0F, $93, $57), ($EA, $04, $9D, $5E), ($FD, $19, $8F, $45), ($F0, $12, $81, $4C),
($6B, $CB, $3B, $AB), ($66, $C0, $35, $A2), ($71, $DD, $27, $B9), ($7C, $D6, $29, $B0),
($5F, $E7, $03, $8F), ($52, $EC, $0D, $86), ($45, $F1, $1F, $9D), ($48, $FA, $11, $94),
($03, $93, $4B, $E3), ($0E, $98, $45, $EA), ($19, $85, $57, $F1), ($14, $8E, $59, $F8),
($37, $BF, $73, $C7), ($3A, $B4, $7D, $CE), ($2D, $A9, $6F, $D5), ($20, $A2, $61, $DC),
($6D, $F6, $AD, $76), ($60, $FD, $A3, $7F), ($77, $E0, $B1, $64), ($7A, $EB, $BF, $6D),
($59, $DA, $95, $52), ($54, $D1, $9B, $5B), ($43, $CC, $89, $40), ($4E, $C7, $87, $49),
($05, $AE, $DD, $3E), ($08, $A5, $D3, $37), ($1F, $B8, $C1, $2C), ($12, $B3, $CF, $25),
($31, $82, $E5, $1A), ($3C, $89, $EB, $13), ($2B, $94, $F9, $08), ($26, $9F, $F7, $01),
($BD, $46, $4D, $E6), ($B0, $4D, $43, $EF), ($A7, $50, $51, $F4), ($AA, $5B, $5F, $FD),
($89, $6A, $75, $C2), ($84, $61, $7B, $CB), ($93, $7C, $69, $D0), ($9E, $77, $67, $D9),
($D5, $1E, $3D, $AE), ($D8, $15, $33, $A7), ($CF, $08, $21, $BC), ($C2, $03, $2F, $B5),
($E1, $32, $05, $8A), ($EC, $39, $0B, $83), ($FB, $24, $19, $98), ($F6, $2F, $17, $91),
($D6, $8D, $76, $4D), ($DB, $86, $78, $44), ($CC, $9B, $6A, $5F), ($C1, $90, $64, $56),
($E2, $A1, $4E, $69), ($EF, $AA, $40, $60), ($F8, $B7, $52, $7B), ($F5, $BC, $5C, $72),
($BE, $D5, $06, $05), ($B3, $DE, $08, $0C), ($A4, $C3, $1A, $17), ($A9, $C8, $14, $1E),
($8A, $F9, $3E, $21), ($87, $F2, $30, $28), ($90, $EF, $22, $33), ($9D, $E4, $2C, $3A),
($06, $3D, $96, $DD), ($0B, $36, $98, $D4), ($1C, $2B, $8A, $CF), ($11, $20, $84, $C6),
($32, $11, $AE, $F9), ($3F, $1A, $A0, $F0), ($28, $07, $B2, $EB), ($25, $0C, $BC, $E2),
($6E, $65, $E6, $95), ($63, $6E, $E8, $9C), ($74, $73, $FA, $87), ($79, $78, $F4, $8E),
($5A, $49, $DE, $B1), ($57, $42, $D0, $B8), ($40, $5F, $C2, $A3), ($4D, $54, $CC, $AA),
($DA, $F7, $41, $EC), ($D7, $FC, $4F, $E5), ($C0, $E1, $5D, $FE), ($CD, $EA, $53, $F7),
($EE, $DB, $79, $C8), ($E3, $D0, $77, $C1), ($F4, $CD, $65, $DA), ($F9, $C6, $6B, $D3),
($B2, $AF, $31, $A4), ($BF, $A4, $3F, $AD), ($A8, $B9, $2D, $B6), ($A5, $B2, $23, $BF),
($86, $83, $09, $80), ($8B, $88, $07, $89), ($9C, $95, $15, $92), ($91, $9E, $1B, $9B),
($0A, $47, $A1, $7C), ($07, $4C, $AF, $75), ($10, $51, $BD, $6E), ($1D, $5A, $B3, $67),
($3E, $6B, $99, $58), ($33, $60, $97, $51), ($24, $7D, $85, $4A), ($29, $76, $8B, $43),
($62, $1F, $D1, $34), ($6F, $14, $DF, $3D), ($78, $09, $CD, $26), ($75, $02, $C3, $2F),
($56, $33, $E9, $10), ($5B, $38, $E7, $19), ($4C, $25, $F5, $02), ($41, $2E, $FB, $0B),
($61, $8C, $9A, $D7), ($6C, $87, $94, $DE), ($7B, $9A, $86, $C5), ($76, $91, $88, $CC),
($55, $A0, $A2, $F3), ($58, $AB, $AC, $FA), ($4F, $B6, $BE, $E1), ($42, $BD, $B0, $E8),
($09, $D4, $EA, $9F), ($04, $DF, $E4, $96), ($13, $C2, $F6, $8D), ($1E, $C9, $F8, $84),
($3D, $F8, $D2, $BB), ($30, $F3, $DC, $B2), ($27, $EE, $CE, $A9), ($2A, $E5, $C0, $A0),
($B1, $3C, $7A, $47), ($BC, $37, $74, $4E), ($AB, $2A, $66, $55), ($A6, $21, $68, $5C),
($85, $10, $42, $63), ($88, $1B, $4C, $6A), ($9F, $06, $5E, $71), ($92, $0D, $50, $78),
($D9, $64, $0A, $0F), ($D4, $6F, $04, $06), ($C3, $72, $16, $1D), ($CE, $79, $18, $14),
($ED, $48, $32, $2B), ($E0, $43, $3C, $22), ($F7, $5E, $2E, $39), ($FA, $55, $20, $30),
($B7, $01, $EC, $9A), ($BA, $0A, $E2, $93), ($AD, $17, $F0, $88), ($A0, $1C, $FE, $81),
($83, $2D, $D4, $BE), ($8E, $26, $DA, $B7), ($99, $3B, $C8, $AC), ($94, $30, $C6, $A5),
($DF, $59, $9C, $D2), ($D2, $52, $92, $DB), ($C5, $4F, $80, $C0), ($C8, $44, $8E, $C9),
($EB, $75, $A4, $F6), ($E6, $7E, $AA, $FF), ($F1, $63, $B8, $E4), ($FC, $68, $B6, $ED),
($67, $B1, $0C, $0A), ($6A, $BA, $02, $03), ($7D, $A7, $10, $18), ($70, $AC, $1E, $11),
($53, $9D, $34, $2E), ($5E, $96, $3A, $27), ($49, $8B, $28, $3C), ($44, $80, $26, $35),
($0F, $E9, $7C, $42), ($02, $E2, $72, $4B), ($15, $FF, $60, $50), ($18, $F4, $6E, $59),
($3B, $C5, $44, $66), ($36, $CE, $4A, $6F), ($21, $D3, $58, $74), ($2C, $D8, $56, $7D),
($0C, $7A, $37, $A1), ($01, $71, $39, $A8), ($16, $6C, $2B, $B3), ($1B, $67, $25, $BA),
($38, $56, $0F, $85), ($35, $5D, $01, $8C), ($22, $40, $13, $97), ($2F, $4B, $1D, $9E),
($64, $22, $47, $E9), ($69, $29, $49, $E0), ($7E, $34, $5B, $FB), ($73, $3F, $55, $F2),
($50, $0E, $7F, $CD), ($5D, $05, $71, $C4), ($4A, $18, $63, $DF), ($47, $13, $6D, $D6),
($DC, $CA, $D7, $31), ($D1, $C1, $D9, $38), ($C6, $DC, $CB, $23), ($CB, $D7, $C5, $2A),
($E8, $E6, $EF, $15), ($E5, $ED, $E1, $1C), ($F2, $F0, $F3, $07), ($FF, $FB, $FD, $0E),
($B4, $92, $A7, $79), ($B9, $99, $A9, $70), ($AE, $84, $BB, $6B), ($A3, $8F, $B5, $62),
($80, $BE, $9F, $5D), ($8D, $B5, $91, $54), ($9A, $A8, $83, $4F), ($97, $A3, $8D, $46));
U4: array [0 .. 255, 0 .. 3] of Byte = (
($00, $00, $00, $00), ($09, $0D, $0B, $0E), ($12, $1A, $16, $1C), ($1B, $17, $1D, $12),
($24, $34, $2C, $38), ($2D, $39, $27, $36), ($36, $2E, $3A, $24), ($3F, $23, $31, $2A),
($48, $68, $58, $70), ($41, $65, $53, $7E), ($5A, $72, $4E, $6C), ($53, $7F, $45, $62),
($6C, $5C, $74, $48), ($65, $51, $7F, $46), ($7E, $46, $62, $54), ($77, $4B, $69, $5A),
($90, $D0, $B0, $E0), ($99, $DD, $BB, $EE), ($82, $CA, $A6, $FC), ($8B, $C7, $AD, $F2),
($B4, $E4, $9C, $D8), ($BD, $E9, $97, $D6), ($A6, $FE, $8A, $C4), ($AF, $F3, $81, $CA),
($D8, $B8, $E8, $90), ($D1, $B5, $E3, $9E), ($CA, $A2, $FE, $8C), ($C3, $AF, $F5, $82),
($FC, $8C, $C4, $A8), ($F5, $81, $CF, $A6), ($EE, $96, $D2, $B4), ($E7, $9B, $D9, $BA),
($3B, $BB, $7B, $DB), ($32, $B6, $70, $D5), ($29, $A1, $6D, $C7), ($20, $AC, $66, $C9),
($1F, $8F, $57, $E3), ($16, $82, $5C, $ED), ($0D, $95, $41, $FF), ($04, $98, $4A, $F1),
($73, $D3, $23, $AB), ($7A, $DE, $28, $A5), ($61, $C9, $35, $B7), ($68, $C4, $3E, $B9),
($57, $E7, $0F, $93), ($5E, $EA, $04, $9D), ($45, $FD, $19, $8F), ($4C, $F0, $12, $81),
($AB, $6B, $CB, $3B), ($A2, $66, $C0, $35), ($B9, $71, $DD, $27), ($B0, $7C, $D6, $29),
($8F, $5F, $E7, $03), ($86, $52, $EC, $0D), ($9D, $45, $F1, $1F), ($94, $48, $FA, $11),
($E3, $03, $93, $4B), ($EA, $0E, $98, $45), ($F1, $19, $85, $57), ($F8, $14, $8E, $59),
($C7, $37, $BF, $73), ($CE, $3A, $B4, $7D), ($D5, $2D, $A9, $6F), ($DC, $20, $A2, $61),
($76, $6D, $F6, $AD), ($7F, $60, $FD, $A3), ($64, $77, $E0, $B1), ($6D, $7A, $EB, $BF),
($52, $59, $DA, $95), ($5B, $54, $D1, $9B), ($40, $43, $CC, $89), ($49, $4E, $C7, $87),
($3E, $05, $AE, $DD), ($37, $08, $A5, $D3), ($2C, $1F, $B8, $C1), ($25, $12, $B3, $CF),
($1A, $31, $82, $E5), ($13, $3C, $89, $EB), ($08, $2B, $94, $F9), ($01, $26, $9F, $F7),
($E6, $BD, $46, $4D), ($EF, $B0, $4D, $43), ($F4, $A7, $50, $51), ($FD, $AA, $5B, $5F),
($C2, $89, $6A, $75), ($CB, $84, $61, $7B), ($D0, $93, $7C, $69), ($D9, $9E, $77, $67),
($AE, $D5, $1E, $3D), ($A7, $D8, $15, $33), ($BC, $CF, $08, $21), ($B5, $C2, $03, $2F),
($8A, $E1, $32, $05), ($83, $EC, $39, $0B), ($98, $FB, $24, $19), ($91, $F6, $2F, $17),
($4D, $D6, $8D, $76), ($44, $DB, $86, $78), ($5F, $CC, $9B, $6A), ($56, $C1, $90, $64),
($69, $E2, $A1, $4E), ($60, $EF, $AA, $40), ($7B, $F8, $B7, $52), ($72, $F5, $BC, $5C),
($05, $BE, $D5, $06), ($0C, $B3, $DE, $08), ($17, $A4, $C3, $1A), ($1E, $A9, $C8, $14),
($21, $8A, $F9, $3E), ($28, $87, $F2, $30), ($33, $90, $EF, $22), ($3A, $9D, $E4, $2C),
($DD, $06, $3D, $96), ($D4, $0B, $36, $98), ($CF, $1C, $2B, $8A), ($C6, $11, $20, $84),
($F9, $32, $11, $AE), ($F0, $3F, $1A, $A0), ($EB, $28, $07, $B2), ($E2, $25, $0C, $BC),
($95, $6E, $65, $E6), ($9C, $63, $6E, $E8), ($87, $74, $73, $FA), ($8E, $79, $78, $F4),
($B1, $5A, $49, $DE), ($B8, $57, $42, $D0), ($A3, $40, $5F, $C2), ($AA, $4D, $54, $CC),
($EC, $DA, $F7, $41), ($E5, $D7, $FC, $4F), ($FE, $C0, $E1, $5D), ($F7, $CD, $EA, $53),
($C8, $EE, $DB, $79), ($C1, $E3, $D0, $77), ($DA, $F4, $CD, $65), ($D3, $F9, $C6, $6B),
($A4, $B2, $AF, $31), ($AD, $BF, $A4, $3F), ($B6, $A8, $B9, $2D), ($BF, $A5, $B2, $23),
($80, $86, $83, $09), ($89, $8B, $88, $07), ($92, $9C, $95, $15), ($9B, $91, $9E, $1B),
($7C, $0A, $47, $A1), ($75, $07, $4C, $AF), ($6E, $10, $51, $BD), ($67, $1D, $5A, $B3),
($58, $3E, $6B, $99), ($51, $33, $60, $97), ($4A, $24, $7D, $85), ($43, $29, $76, $8B),
($34, $62, $1F, $D1), ($3D, $6F, $14, $DF), ($26, $78, $09, $CD), ($2F, $75, $02, $C3),
($10, $56, $33, $E9), ($19, $5B, $38, $E7), ($02, $4C, $25, $F5), ($0B, $41, $2E, $FB),
($D7, $61, $8C, $9A), ($DE, $6C, $87, $94), ($C5, $7B, $9A, $86), ($CC, $76, $91, $88),
($F3, $55, $A0, $A2), ($FA, $58, $AB, $AC), ($E1, $4F, $B6, $BE), ($E8, $42, $BD, $B0),
($9F, $09, $D4, $EA), ($96, $04, $DF, $E4), ($8D, $13, $C2, $F6), ($84, $1E, $C9, $F8),
($BB, $3D, $F8, $D2), ($B2, $30, $F3, $DC), ($A9, $27, $EE, $CE), ($A0, $2A, $E5, $C0),
($47, $B1, $3C, $7A), ($4E, $BC, $37, $74), ($55, $AB, $2A, $66), ($5C, $A6, $21, $68),
($63, $85, $10, $42), ($6A, $88, $1B, $4C), ($71, $9F, $06, $5E), ($78, $92, $0D, $50),
($0F, $D9, $64, $0A), ($06, $D4, $6F, $04), ($1D, $C3, $72, $16), ($14, $CE, $79, $18),
($2B, $ED, $48, $32), ($22, $E0, $43, $3C), ($39, $F7, $5E, $2E), ($30, $FA, $55, $20),
($9A, $B7, $01, $EC), ($93, $BA, $0A, $E2), ($88, $AD, $17, $F0), ($81, $A0, $1C, $FE),
($BE, $83, $2D, $D4), ($B7, $8E, $26, $DA), ($AC, $99, $3B, $C8), ($A5, $94, $30, $C6),
($D2, $DF, $59, $9C), ($DB, $D2, $52, $92), ($C0, $C5, $4F, $80), ($C9, $C8, $44, $8E),
($F6, $EB, $75, $A4), ($FF, $E6, $7E, $AA), ($E4, $F1, $63, $B8), ($ED, $FC, $68, $B6),
($0A, $67, $B1, $0C), ($03, $6A, $BA, $02), ($18, $7D, $A7, $10), ($11, $70, $AC, $1E),
($2E, $53, $9D, $34), ($27, $5E, $96, $3A), ($3C, $49, $8B, $28), ($35, $44, $80, $26),
($42, $0F, $E9, $7C), ($4B, $02, $E2, $72), ($50, $15, $FF, $60), ($59, $18, $F4, $6E),
($66, $3B, $C5, $44), ($6F, $36, $CE, $4A), ($74, $21, $D3, $58), ($7D, $2C, $D8, $56),
($A1, $0C, $7A, $37), ($A8, $01, $71, $39), ($B3, $16, $6C, $2B), ($BA, $1B, $67, $25),
($85, $38, $56, $0F), ($8C, $35, $5D, $01), ($97, $22, $40, $13), ($9E, $2F, $4B, $1D),
($E9, $64, $22, $47), ($E0, $69, $29, $49), ($FB, $7E, $34, $5B), ($F2, $73, $3F, $55),
($CD, $50, $0E, $7F), ($C4, $5D, $05, $71), ($DF, $4A, $18, $63), ($D6, $47, $13, $6D),
($31, $DC, $CA, $D7), ($38, $D1, $C1, $D9), ($23, $C6, $DC, $CB), ($2A, $CB, $D7, $C5),
($15, $E8, $E6, $EF), ($1C, $E5, $ED, $E1), ($07, $F2, $F0, $F3), ($0E, $FF, $FB, $FD),
($79, $B4, $92, $A7), ($70, $B9, $99, $A9), ($6B, $AE, $84, $BB), ($62, $A3, $8F, $B5),
($5D, $80, $BE, $9F), ($54, $8D, $B5, $91), ($4F, $9A, $A8, $83), ($46, $97, $A3, $8D));
rcon: array [0 .. 29] of Cardinal = (
$01, $02, $04, $08, $10, $20, $40, $80, $1B, $36, $6C, $D8, $AB, $4D, $9A,
$2F, $5E, $BC, $63, $C6, $97, $35, $6A, $D4, $B3, $7D, $FA, $EF, $C5, $91);
{$ENDREGION 'RijndaelDefine'}
class procedure InvMixColumn(const a: PByteArray; const BC: Byte);
public
class procedure InitKey(buff: Pointer; Size: Integer; var KeyContext: TRijndaelkey);
class procedure Encrypt(var KeyContext: TRijndaelkey; var Data: TRijndaelBlock); overload;
class procedure Encrypt(var KeyContext: TRijndaelkey; var B1, B2, B3, B4: DWORD); overload;
class procedure Decrypt(var KeyContext: TRijndaelkey; var Data: TRijndaelBlock); overload;
class procedure Decrypt(var KeyContext: TRijndaelkey; var B1, B2, B3, B4: DWORD); overload;
end;
type
{ twofish }
PTwofishKey = ^TTwofishKey;
TTwofishKey = record
ExpandedKey: array [0 .. 39] of DWORD;
SBoxKey: array [0 .. 3] of DWORD;
SBox0: array [0 .. 255] of Byte;
SBox1: array [0 .. 255] of Byte;
SBox2: array [0 .. 255] of Byte;
SBox3: array [0 .. 255] of Byte;
KeyLen: Integer;
end;
PTwofishBlock = ^TTwofishBlock;
TTwofishBlock = array [0 .. 15] of Byte;
TTwofish = class(TCoreClassObject)
private const
{$REGION 'TwofishDefine'}
P8x8: array [0 .. 1, 0 .. 255] of Byte =
(($A9, $67, $B3, $E8, $04, $FD, $A3, $76,
$9A, $92, $80, $78, $E4, $DD, $D1, $38,
$0D, $C6, $35, $98, $18, $F7, $EC, $6C,
$43, $75, $37, $26, $FA, $13, $94, $48,
$F2, $D0, $8B, $30, $84, $54, $DF, $23,
$19, $5B, $3D, $59, $F3, $AE, $A2, $82,
$63, $01, $83, $2E, $D9, $51, $9B, $7C,
$A6, $EB, $A5, $BE, $16, $0C, $E3, $61,
$C0, $8C, $3A, $F5, $73, $2C, $25, $0B,
$BB, $4E, $89, $6B, $53, $6A, $B4, $F1,
$E1, $E6, $BD, $45, $E2, $F4, $B6, $66,
$CC, $95, $03, $56, $D4, $1C, $1E, $D7,
$FB, $C3, $8E, $B5, $E9, $CF, $BF, $BA,
$EA, $77, $39, $AF, $33, $C9, $62, $71,
$81, $79, $09, $AD, $24, $CD, $F9, $D8,
$E5, $C5, $B9, $4D, $44, $08, $86, $E7,
$A1, $1D, $AA, $ED, $06, $70, $B2, $D2,
$41, $7B, $A0, $11, $31, $C2, $27, $90,
$20, $F6, $60, $FF, $96, $5C, $B1, $AB,
$9E, $9C, $52, $1B, $5F, $93, $0A, $EF,
$91, $85, $49, $EE, $2D, $4F, $8F, $3B,
$47, $87, $6D, $46, $D6, $3E, $69, $64,
$2A, $CE, $CB, $2F, $FC, $97, $05, $7A,
$AC, $7F, $D5, $1A, $4B, $0E, $A7, $5A,
$28, $14, $3F, $29, $88, $3C, $4C, $02,
$B8, $DA, $B0, $17, $55, $1F, $8A, $7D,
$57, $C7, $8D, $74, $B7, $C4, $9F, $72,
$7E, $15, $22, $12, $58, $07, $99, $34,
$6E, $50, $DE, $68, $65, $BC, $DB, $F8,
$C8, $A8, $2B, $40, $DC, $FE, $32, $A4,
$CA, $10, $21, $F0, $D3, $5D, $0F, $00,
$6F, $9D, $36, $42, $4A, $5E, $C1, $E0),
($75, $F3, $C6, $F4, $DB, $7B, $FB, $C8,
$4A, $D3, $E6, $6B, $45, $7D, $E8, $4B,
$D6, $32, $D8, $FD, $37, $71, $F1, $E1,
$30, $0F, $F8, $1B, $87, $FA, $06, $3F,
$5E, $BA, $AE, $5B, $8A, $00, $BC, $9D,
$6D, $C1, $B1, $0E, $80, $5D, $D2, $D5,
$A0, $84, $07, $14, $B5, $90, $2C, $A3,
$B2, $73, $4C, $54, $92, $74, $36, $51,
$38, $B0, $BD, $5A, $FC, $60, $62, $96,
$6C, $42, $F7, $10, $7C, $28, $27, $8C,
$13, $95, $9C, $C7, $24, $46, $3B, $70,
$CA, $E3, $85, $CB, $11, $D0, $93, $B8,
$A6, $83, $20, $FF, $9F, $77, $C3, $CC,
$03, $6F, $08, $BF, $40, $E7, $2B, $E2,
$79, $0C, $AA, $82, $41, $3A, $EA, $B9,
$E4, $9A, $A4, $97, $7E, $DA, $7A, $17,
$66, $94, $A1, $1D, $3D, $F0, $DE, $B3,
$0B, $72, $A7, $1C, $EF, $D1, $53, $3E,
$8F, $33, $26, $5F, $EC, $76, $2A, $49,
$81, $88, $EE, $21, $C4, $1A, $EB, $D9,
$C5, $39, $99, $CD, $AD, $31, $8B, $01,
$18, $23, $DD, $1F, $4E, $2D, $F9, $48,
$4F, $F2, $65, $8E, $78, $5C, $58, $19,
$8D, $E5, $98, $57, $67, $7F, $05, $64,
$AF, $63, $B6, $FE, $F5, $B7, $3C, $A5,
$CE, $E9, $68, $44, $E0, $4D, $43, $69,
$29, $2E, $AC, $15, $59, $A8, $0A, $9E,
$6E, $47, $DF, $34, $35, $6A, $CF, $DC,
$22, $C9, $C0, $9B, $89, $D4, $ED, $AB,
$12, $A2, $0D, $52, $BB, $02, $2F, $A9,
$D7, $61, $1E, $B4, $50, $04, $F6, $C2,
$16, $25, $86, $56, $55, $09, $BE, $91));
MDS: array [0 .. 3, 0 .. 7] of Byte = (($01, $A4, $55, $87, $5A, $58, $DB, $9E),
($A4, $56, $82, $F3, $1E, $C6, $68, $E5),
($02, $A1, $FC, $C1, $47, $AE, $3D, $19),
($A4, $55, $87, $5A, $58, $DB, $9E, $03));
Arr5B: array [0 .. 255] of DWORD = (
$00, $5B, $B6, $ED, $05, $5E, $B3, $E8, $0A, $51, $BC, $E7, $0F, $54, $B9, $E2,
$14, $4F, $A2, $F9, $11, $4A, $A7, $FC, $1E, $45, $A8, $F3, $1B, $40, $AD, $F6,
$28, $73, $9E, $C5, $2D, $76, $9B, $C0, $22, $79, $94, $CF, $27, $7C, $91, $CA,
$3C, $67, $8A, $D1, $39, $62, $8F, $D4, $36, $6D, $80, $DB, $33, $68, $85, $DE,
$50, $0B, $E6, $BD, $55, $0E, $E3, $B8, $5A, $01, $EC, $B7, $5F, $04, $E9, $B2,
$44, $1F, $F2, $A9, $41, $1A, $F7, $AC, $4E, $15, $F8, $A3, $4B, $10, $FD, $A6,
$78, $23, $CE, $95, $7D, $26, $CB, $90, $72, $29, $C4, $9F, $77, $2C, $C1, $9A,
$6C, $37, $DA, $81, $69, $32, $DF, $84, $66, $3D, $D0, $8B, $63, $38, $D5, $8E,
$A0, $FB, $16, $4D, $A5, $FE, $13, $48, $AA, $F1, $1C, $47, $AF, $F4, $19, $42,
$B4, $EF, $02, $59, $B1, $EA, $07, $5C, $BE, $E5, $08, $53, $BB, $E0, $0D, $56,
$88, $D3, $3E, $65, $8D, $D6, $3B, $60, $82, $D9, $34, $6F, $87, $DC, $31, $6A,
$9C, $C7, $2A, $71, $99, $C2, $2F, $74, $96, $CD, $20, $7B, $93, $C8, $25, $7E,
$F0, $AB, $46, $1D, $F5, $AE, $43, $18, $FA, $A1, $4C, $17, $FF, $A4, $49, $12,
$E4, $BF, $52, $09, $E1, $BA, $57, $0C, $EE, $B5, $58, $03, $EB, $B0, $5D, $06,
$D8, $83, $6E, $35, $DD, $86, $6B, $30, $D2, $89, $64, $3F, $D7, $8C, $61, $3A,
$CC, $97, $7A, $21, $C9, $92, $7F, $24, $C6, $9D, $70, $2B, $C3, $98, $75, $2E);
ArrEF: array [0 .. 255] of Byte = (
$00, $EF, $B7, $58, $07, $E8, $B0, $5F, $0E, $E1, $B9, $56, $09, $E6, $BE, $51,
$1C, $F3, $AB, $44, $1B, $F4, $AC, $43, $12, $FD, $A5, $4A, $15, $FA, $A2, $4D,
$38, $D7, $8F, $60, $3F, $D0, $88, $67, $36, $D9, $81, $6E, $31, $DE, $86, $69,
$24, $CB, $93, $7C, $23, $CC, $94, $7B, $2A, $C5, $9D, $72, $2D, $C2, $9A, $75,
$70, $9F, $C7, $28, $77, $98, $C0, $2F, $7E, $91, $C9, $26, $79, $96, $CE, $21,
$6C, $83, $DB, $34, $6B, $84, $DC, $33, $62, $8D, $D5, $3A, $65, $8A, $D2, $3D,
$48, $A7, $FF, $10, $4F, $A0, $F8, $17, $46, $A9, $F1, $1E, $41, $AE, $F6, $19,
$54, $BB, $E3, $0C, $53, $BC, $E4, $0B, $5A, $B5, $ED, $02, $5D, $B2, $EA, $05,
$E0, $0F, $57, $B8, $E7, $08, $50, $BF, $EE, $01, $59, $B6, $E9, $06, $5E, $B1,
$FC, $13, $4B, $A4, $FB, $14, $4C, $A3, $F2, $1D, $45, $AA, $F5, $1A, $42, $AD,
$D8, $37, $6F, $80, $DF, $30, $68, $87, $D6, $39, $61, $8E, $D1, $3E, $66, $89,
$C4, $2B, $73, $9C, $C3, $2C, $74, $9B, $CA, $25, $7D, $92, $CD, $22, $7A, $95,
$90, $7F, $27, $C8, $97, $78, $20, $CF, $9E, $71, $29, $C6, $99, $76, $2E, $C1,
$8C, $63, $3B, $D4, $8B, $64, $3C, $D3, $82, $6D, $35, $DA, $85, $6A, $32, $DD,
$A8, $47, $1F, $F0, $AF, $40, $18, $F7, $A6, $49, $11, $FE, $A1, $4E, $16, $F9,
$B4, $5B, $03, $EC, $B3, $5C, $04, $EB, $BA, $55, $0D, $E2, $BD, $52, $0A, $E5);
{$ENDREGION 'TwofishDefine'}
class function TwofishCalculateSBoxes(x: DWORD; l: Pointer; KeySize: DWORD): DWORD;
class function TwofishH(x: DWORD; l: Pointer; KeySize: DWORD): DWORD; overload;
class function TwofishH(const x: DWORD; const key: TTwofishKey): DWORD; overload;
class function RSMDSMul(const x, y: Byte): Byte;
class function MultiplyMDS(const E, O: DWORD): DWORD;
public
class procedure InitKey(buff: PCCByteArray; Size: Integer; var KeyContext: TTwofishKey);
class procedure Encrypt(var KeyContext: TTwofishKey; var Data: TTwofishBlock);
class procedure Decrypt(var KeyContext: TTwofishKey; var Data: TTwofishBlock);
end;
{$ENDREGION 'cryptAndHash'}
implementation
uses DoStatusIO;
const
{ Blowfish lookup tables }
bf_P: array [0 .. (BFRounds + 1)] of DWORD = (
$243F6A88, $85A308D3, $13198A2E, $03707344,
$A4093822, $299F31D0, $082EFA98, $EC4E6C89,
$452821E6, $38D01377, $BE5466CF, $34E90C6C,
$C0AC29B7, $C97C50DD, $3F84D5B5, $B5470917,
$9216D5D9, $8979FB1B);
bf_S: array [0 .. 3, 0 .. 255] of DWORD =
(
($D1310BA6, $98DFB5AC, $2FFD72DB, $D01ADFB7,
$B8E1AFED, $6A267E96, $BA7C9045, $F12C7F99,
$24A19947, $B3916CF7, $0801F2E2, $858EFC16,
$636920D8, $71574E69, $A458FEA3, $F4933D7E,
$0D95748F, $728EB658, $718BCD58, $82154AEE,
$7B54A41D, $C25A59B5, $9C30D539, $2AF26013,
$C5D1B023, $286085F0, $CA417918, $B8DB38EF,
$8E79DCB0, $603A180E, $6C9E0E8B, $B01E8A3E,
$D71577C1, $BD314B27, $78AF2FDA, $55605C60,
$E65525F3, $AA55AB94, $57489862, $63E81440,
$55CA396A, $2AAB10B6, $B4CC5C34, $1141E8CE,
$A15486AF, $7C72E993, $B3EE1411, $636FBC2A,
$2BA9C55D, $741831F6, $CE5C3E16, $9B87931E,
$AFD6BA33, $6C24CF5C, $7A325381, $28958677,
$3B8F4898, $6B4BB9AF, $C4BFE81B, $66282193,
$61D809CC, $FB21A991, $487CAC60, $5DEC8032,
$EF845D5D, $E98575B1, $DC262302, $EB651B88,
$23893E81, $D396ACC5, $0F6D6FF3, $83F44239,
$2E0B4482, $A4842004, $69C8F04A, $9E1F9B5E,
$21C66842, $F6E96C9A, $670C9C61, $ABD388F0,
$6A51A0D2, $D8542F68, $960FA728, $AB5133A3,
$6EEF0B6C, $137A3BE4, $BA3BF050, $7EFB2A98,
$A1F1651D, $39AF0176, $66CA593E, $82430E88,
$8CEE8619, $456F9FB4, $7D84A5C3, $3B8B5EBE,
$E06F75D8, $85C12073, $401A449F, $56C16AA6,
$4ED3AA62, $363F7706, $1BFEDF72, $429B023D,
$37D0D724, $D00A1248, $DB0FEAD3, $49F1C09B,
$075372C9, $80991B7B, $25D479D8, $F6E8DEF7,
$E3FE501A, $B6794C3B, $976CE0BD, $04C006BA,
$C1A94FB6, $409F60C4, $5E5C9EC2, $196A2463,
$68FB6FAF, $3E6C53B5, $1339B2EB, $3B52EC6F,
$6DFC511F, $9B30952C, $CC814544, $AF5EBD09,
$BEE3D004, $DE334AFD, $660F2807, $192E4BB3,
$C0CBA857, $45C8740F, $D20B5F39, $B9D3FBDB,
$5579C0BD, $1A60320A, $D6A100C6, $402C7279,
$679F25FE, $FB1FA3CC, $8EA5E9F8, $DB3222F8,
$3C7516DF, $FD616B15, $2F501EC8, $AD0552AB,
$323DB5FA, $FD238760, $53317B48, $3E00DF82,
$9E5C57BB, $CA6F8CA0, $1A87562E, $DF1769DB,
$D542A8F6, $287EFFC3, $AC6732C6, $8C4F5573,
$695B27B0, $BBCA58C8, $E1FFA35D, $B8F011A0,
$10FA3D98, $FD2183B8, $4AFCB56C, $2DD1D35B,
$9A53E479, $B6F84565, $D28E49BC, $4BFB9790,
$E1DDF2DA, $A4CB7E33, $62FB1341, $CEE4C6E8,
$EF20CADA, $36774C01, $D07E9EFE, $2BF11FB4,
$95DBDA4D, $AE909198, $EAAD8E71, $6B93D5A0,
$D08ED1D0, $AFC725E0, $8E3C5B2F, $8E7594B7,
$8FF6E2FB, $F2122B64, $8888B812, $900DF01C,
$4FAD5EA0, $688FC31C, $D1CFF191, $B3A8C1AD,
$2F2F2218, $BE0E1777, $EA752DFE, $8B021FA1,
$E5A0CC0F, $B56F74E8, $18ACF3D6, $CE89E299,
$B4A84FE0, $FD13E0B7, $7CC43B81, $D2ADA8D9,
$165FA266, $80957705, $93CC7314, $211A1477,
$E6AD2065, $77B5FA86, $C75442F5, $FB9D35CF,
$EBCDAF0C, $7B3E89A0, $D6411BD3, $AE1E7E49,
$00250E2D, $2071B35E, $226800BB, $57B8E0AF,
$2464369B, $F009B91E, $5563911D, $59DFA6AA,
$78C14389, $D95A537F, $207D5BA2, $02E5B9C5,
$83260376, $6295CFA9, $11C81968, $4E734A41,
$B3472DCA, $7B14A94A, $1B510052, $9A532915,
$D60F573F, $BC9BC6E4, $2B60A476, $81E67400,
$08BA6FB5, $571BE91F, $F296EC6B, $2A0DD915,
$B6636521, $E7B9F9B6, $FF34052E, $C5855664,
$53B02D5D, $A99F8FA1, $08BA4799, $6E85076A),
{ SECOND 256 }
($4B7A70E9, $B5B32944, $DB75092E, $C4192623,
$AD6EA6B0, $49A7DF7D, $9CEE60B8, $8FEDB266,
$ECAA8C71, $699A17FF, $5664526C, $C2B19EE1,
$193602A5, $75094C29, $A0591340, $E4183A3E,
$3F54989A, $5B429D65, $6B8FE4D6, $99F73FD6,
$A1D29C07, $EFE830F5, $4D2D38E6, $F0255DC1,
$4CDD2086, $8470EB26, $6382E9C6, $021ECC5E,
$09686B3F, $3EBAEFC9, $3C971814, $6B6A70A1,
$687F3584, $52A0E286, $B79C5305, $AA500737,
$3E07841C, $7FDEAE5C, $8E7D44EC, $5716F2B8,
$B03ADA37, $F0500C0D, $F01C1F04, $0200B3FF,
$AE0CF51A, $3CB574B2, $25837A58, $DC0921BD,
$D19113F9, $7CA92FF6, $94324773, $22F54701,
$3AE5E581, $37C2DADC, $C8B57634, $9AF3DDA7,
$A9446146, $0FD0030E, $ECC8C73E, $A4751E41,
$E238CD99, $3BEA0E2F, $3280BBA1, $183EB331,
$4E548B38, $4F6DB908, $6F420D03, $F60A04BF,
$2CB81290, $24977C79, $5679B072, $BCAF89AF,
$DE9A771F, $D9930810, $B38BAE12, $DCCF3F2E,
$5512721F, $2E6B7124, $501ADDE6, $9F84CD87,
$7A584718, $7408DA17, $BC9F9ABC, $E94B7D8C,
$EC7AEC3A, $DB851DFA, $63094366, $C464C3D2,
$EF1C1847, $3215D908, $DD433B37, $24C2BA16,
$12A14D43, $2A65C451, $50940002, $133AE4DD,
$71DFF89E, $10314E55, $81AC77D6, $5F11199B,
$043556F1, $D7A3C76B, $3C11183B, $5924A509,
$F28FE6ED, $97F1FBFA, $9EBABF2C, $1E153C6E,
$86E34570, $EAE96FB1, $860E5E0A, $5A3E2AB3,
$771FE71C, $4E3D06FA, $2965DCB9, $99E71D0F,
$803E89D6, $5266C825, $2E4CC978, $9C10B36A,
$C6150EBA, $94E2EA78, $A5FC3C53, $1E0A2DF4,
$F2F74EA7, $361D2B3D, $1939260F, $19C27960,
$5223A708, $F71312B6, $EBADFE6E, $EAC31F66,
$E3BC4595, $A67BC883, $B17F37D1, $018CFF28,
$C332DDEF, $BE6C5AA5, $65582185, $68AB9802,
$EECEA50F, $DB2F953B, $2AEF7DAD, $5B6E2F84,
$1521B628, $29076170, $ECDD4775, $619F1510,
$13CCA830, $EB61BD96, $0334FE1E, $AA0363CF,
$B5735C90, $4C70A239, $D59E9E0B, $CBAADE14,
$EECC86BC, $60622CA7, $9CAB5CAB, $B2F3846E,
$648B1EAF, $19BDF0CA, $A02369B9, $655ABB50,
$40685A32, $3C2AB4B3, $319EE9D5, $C021B8F7,
$9B540B19, $875FA099, $95F7997E, $623D7DA8,
$F837889A, $97E32D77, $11ED935F, $16681281,
$0E358829, $C7E61FD6, $96DEDFA1, $7858BA99,
$57F584A5, $1B227263, $9B83C3FF, $1AC24696,
$CDB30AEB, $532E3054, $8FD948E4, $6DBC3128,
$58EBF2EF, $34C6FFEA, $FE28ED61, $EE7C3C73,
$5D4A14D9, $E864B7E3, $42105D14, $203E13E0,
$45EEE2B6, $A3AAABEA, $DB6C4F15, $FACB4FD0,
$C742F442, $EF6ABBB5, $654F3B1D, $41CD2105,
$D81E799E, $86854DC7, $E44B476A, $3D816250,
$CF62A1F2, $5B8D2646, $FC8883A0, $C1C7B6A3,
$7F1524C3, $69CB7492, $47848A0B, $5692B285,
$095BBF00, $AD19489D, $1462B174, $23820E00,
$58428D2A, $0C55F5EA, $1DADF43E, $233F7061,
$3372F092, $8D937E41, $D65FECF1, $6C223BDB,
$7CDE3759, $CBEE7460, $4085F2A7, $CE77326E,
$A6078084, $19F8509E, $E8EFD855, $61D99735,
$A969A7AA, $C50C06C2, $5A04ABFC, $800BCADC,
$9E447A2E, $C3453484, $FDD56705, $0E1E9EC9,
$DB73DBD3, $105588CD, $675FDA79, $E3674340,
$C5C43465, $713E38D8, $3D28F89E, $F16DFF20,
$153E21E7, $8FB03D4A, $E6E39F2B, $DB83ADF7),
{ THIRD 256 }
($E93D5A68, $948140F7, $F64C261C, $94692934,
$411520F7, $7602D4F7, $BCF46B2E, $D4A20068,
$D4082471, $3320F46A, $43B7D4B7, $500061AF,
$1E39F62E, $97244546, $14214F74, $BF8B8840,
$4D95FC1D, $96B591AF, $70F4DDD3, $66A02F45,
$BFBC09EC, $03BD9785, $7FAC6DD0, $31CB8504,
$96EB27B3, $55FD3941, $DA2547E6, $ABCA0A9A,
$28507825, $530429F4, $0A2C86DA, $E9B66DFB,
$68DC1462, $D7486900, $680EC0A4, $27A18DEE,
$4F3FFEA2, $E887AD8C, $B58CE006, $7AF4D6B6,
$AACE1E7C, $D3375FEC, $CE78A399, $406B2A42,
$20FE9E35, $D9F385B9, $EE39D7AB, $3B124E8B,
$1DC9FAF7, $4B6D1856, $26A36631, $EAE397B2,
$3A6EFA74, $DD5B4332, $6841E7F7, $CA7820FB,
$FB0AF54E, $D8FEB397, $454056AC, $BA489527,
$55533A3A, $20838D87, $FE6BA9B7, $D096954B,
$55A867BC, $A1159A58, $CCA92963, $99E1DB33,
$A62A4A56, $3F3125F9, $5EF47E1C, $9029317C,
$FDF8E802, $04272F70, $80BB155C, $05282CE3,
$95C11548, $E4C66D22, $48C1133F, $C70F86DC,
$07F9C9EE, $41041F0F, $404779A4, $5D886E17,
$325F51EB, $D59BC0D1, $F2BCC18F, $41113564,
$257B7834, $602A9C60, $DFF8E8A3, $1F636C1B,
$0E12B4C2, $02E1329E, $AF664FD1, $CAD18115,
$6B2395E0, $333E92E1, $3B240B62, $EEBEB922,
$85B2A20E, $E6BA0D99, $DE720C8C, $2DA2F728,
$D0127845, $95B794FD, $647D0862, $E7CCF5F0,
$5449A36F, $877D48FA, $C39DFD27, $F33E8D1E,
$0A476341, $992EFF74, $3A6F6EAB, $F4F8FD37,
$A812DC60, $A1EBDDF8, $991BE14C, $DB6E6B0D,
$C67B5510, $6D672C37, $2765D43B, $DCD0E804,
$F1290DC7, $CC00FFA3, $B5390F92, $690FED0B,
$667B9FFB, $CEDB7D9C, $A091CF0B, $D9155EA3,
$BB132F88, $515BAD24, $7B9479BF, $763BD6EB,
$37392EB3, $CC115979, $8026E297, $F42E312D,
$6842ADA7, $C66A2B3B, $12754CCC, $782EF11C,
$6A124237, $B79251E7, $06A1BBE6, $4BFB6350,
$1A6B1018, $11CAEDFA, $3D25BDD8, $E2E1C3C9,
$44421659, $0A121386, $D90CEC6E, $D5ABEA2A,
$64AF674E, $DA86A85F, $BEBFE988, $64E4C3FE,
$9DBC8057, $F0F7C086, $60787BF8, $6003604D,
$D1FD8346, $F6381FB0, $7745AE04, $D736FCCC,
$83426B33, $F01EAB71, $B0804187, $3C005E5F,
$77A057BE, $BDE8AE24, $55464299, $BF582E61,
$4E58F48F, $F2DDFDA2, $F474EF38, $8789BDC2,
$5366F9C3, $C8B38E74, $B475F255, $46FCD9B9,
$7AEB2661, $8B1DDF84, $846A0E79, $915F95E2,
$466E598E, $20B45770, $8CD55591, $C902DE4C,
$B90BACE1, $BB8205D0, $11A86248, $7574A99E,
$B77F19B6, $E0A9DC09, $662D09A1, $C4324633,
$E85A1F02, $09F0BE8C, $4A99A025, $1D6EFE10,
$1AB93D1D, $0BA5A4DF, $A186F20F, $2868F169,
$DCB7DA83, $573906FE, $A1E2CE9B, $4FCD7F52,
$50115E01, $A70683FA, $A002B5C4, $0DE6D027,
$9AF88C27, $773F8641, $C3604C06, $61A806B5,
$F0177A28, $C0F586E0, $006058AA, $30DC7D62,
$11E69ED7, $2338EA63, $53C2DD94, $C2C21634,
$BBCBEE56, $90BCB6DE, $EBFC7DA1, $CE591D76,
$6F05E409, $4B7C0188, $39720A3D, $7C927C24,
$86E3725F, $724D9DB9, $1AC15BB4, $D39EB8FC,
$ED545578, $08FCA5B5, $D83D7CD3, $4DAD0FC4,
$1E50EF5E, $B161E6F8, $A28514D9, $6C51133C,
$6FD5C7E7, $56E14EC4, $362ABFCE, $DDC6C837,
$D79A3234, $92638212, $670EFA8E, $406000E0),
{ FOURTH 256 }
($3A39CE37, $D3FAF5CF, $ABC27737, $5AC52D1B,
$5CB0679E, $4FA33742, $D3822740, $99BC9BBE,
$D5118E9D, $BF0F7315, $D62D1C7E, $C700C47B,
$B78C1B6B, $21A19045, $B26EB1BE, $6A366EB4,
$5748AB2F, $BC946E79, $C6A376D2, $6549C2C8,
$530FF8EE, $468DDE7D, $D5730A1D, $4CD04DC6,
$2939BBDB, $A9BA4650, $AC9526E8, $BE5EE304,
$A1FAD5F0, $6A2D519A, $63EF8CE2, $9A86EE22,
$C089C2B8, $43242EF6, $A51E03AA, $9CF2D0A4,
$83C061BA, $9BE96A4D, $8FE51550, $BA645BD6,
$2826A2F9, $A73A3AE1, $4BA99586, $EF5562E9,
$C72FEFD3, $F752F7DA, $3F046F69, $77FA0A59,
$80E4A915, $87B08601, $9B09E6AD, $3B3EE593,
$E990FD5A, $9E34D797, $2CF0B7D9, $022B8B51,
$96D5AC3A, $017DA67D, $D1CF3ED6, $7C7D2D28,
$1F9F25CF, $ADF2B89B, $5AD6B472, $5A88F54C,
$E029AC71, $E019A5E6, $47B0ACFD, $ED93FA9B,
$E8D3C48D, $283B57CC, $F8D56629, $79132E28,
$785F0191, $ED756055, $F7960E44, $E3D35E8C,
$15056DD4, $88F46DBA, $03A16125, $0564F0BD,
$C3EB9E15, $3C9057A2, $97271AEC, $A93A072A,
$1B3F6D9B, $1E6321F5, $F59C66FB, $26DCF319,
$7533D928, $B155FDF5, $03563482, $8ABA3CBB,
$28517711, $C20AD9F8, $ABCC5167, $CCAD925F,
$4DE81751, $3830DC8E, $379D5862, $9320F991,
$EA7A90C2, $FB3E7BCE, $5121CE64, $774FBE32,
$A8B6E37E, $C3293D46, $48DE5369, $6413E680,
$A2AE0810, $DD6DB224, $69852DFD, $09072166,
$B39A460A, $6445C0DD, $586CDECF, $1C20C8AE,
$5BBEF7DD, $1B588D40, $CCD2017F, $6BB4E3BB,
$DDA26A7E, $3A59FF45, $3E350A44, $BCB4CDD5,
$72EACEA8, $FA6484BB, $8D6612AE, $BF3C6F47,
$D29BE463, $542F5D9E, $AEC2771B, $F64E6370,
$740E0D8D, $E75B1357, $F8721671, $AF537D5D,
$4040CB08, $4EB4E2CC, $34D2466A, $0115AF84,
$E1B00428, $95983A1D, $06B89FB4, $CE6EA048,
$6F3F3B82, $3520AB82, $011A1D4B, $277227F8,
$611560B1, $E7933FDC, $BB3A792B, $344525BD,
$A08839E1, $51CE794B, $2F32C9B7, $A01FBAC9,
$E01CC87E, $BCC7D1F6, $CF0111C3, $A1E8AAC7,
$1A908749, $D44FBD9A, $D0DADECB, $D50ADA38,
$0339C32A, $C6913667, $8DF9317C, $E0B12B4F,
$F79E59B7, $43F5BB3A, $F2D519FF, $27D9459C,
$BF97222C, $15E6FC2A, $0F91FC71, $9B941525,
$FAE59361, $CEB69CEB, $C2A86459, $12BAA8D1,
$B6C1075E, $E3056A0C, $10D25065, $CB03A442,
$E0EC6E0E, $1698DB3B, $4C98A0BE, $3278E964,
$9F1F9532, $E0D392DF, $D3A0342B, $8971F21E,
$1B0A7441, $4BA3348C, $C5BE7120, $C37632D8,
$DF359F8D, $9B992F2E, $E60B6F47, $0FE3F11D,
$E54CDA54, $1EDAD891, $CE6279CF, $CD3E7E6F,
$1618B166, $FD2C1D05, $848FD2C5, $F6FB2299,
$F523F357, $A6327623, $93A83531, $56CCCD02,
$ACF08162, $5A75EBB5, $6E163697, $88D273CC,
$DE966292, $81B949D0, $4C50901B, $71C65614,
$E6C6C7BD, $327A140A, $45E1D006, $C3F27B9A,
$C9AA53FD, $62A80F00, $BB25BFE2, $35BDD2F6,
$71126905, $B2040222, $B6CBCF7C, $CD769C2B,
$53113EC0, $1640E3D3, $38ABBD60, $2547ADF0,
$BA38209C, $F746CE76, $77AFA1C5, $20756060,
$85CBFE4E, $8AE88DD8, $7AAAF9B0, $4CF9AA7E,
$1948C25C, $02FB8A8C, $01C36AE4, $D6EBE1F9,
$90D4F869, $A65CDEA0, $3F09252D, $C208E69F,
$B74E6132, $CE77E25B, $578FDFE3, $3AC372E6)
);
{ first 2048 bits of Pi in hexadecimal, low to high, without the leading "3" }
Pi2048: array [0 .. 255] of Byte = (
$24, $3F, $6A, $88, $85, $A3, $08, $D3, $13, $19, $8A, $2E, $03, $70, $73, $44,
$A4, $09, $38, $22, $29, $9F, $31, $D0, $08, $2E, $FA, $98, $EC, $4E, $6C, $89,
$45, $28, $21, $E6, $38, $D0, $13, $77, $BE, $54, $66, $CF, $34, $E9, $0C, $6C,
$C0, $AC, $29, $B7, $C9, $7C, $50, $DD, $3F, $84, $D5, $B5, $B5, $47, $09, $17,
$92, $16, $D5, $D9, $89, $79, $FB, $1B, $D1, $31, $0B, $A6, $98, $DF, $B5, $AC,
$2F, $FD, $72, $DB, $D0, $1A, $DF, $B7, $B8, $E1, $AF, $ED, $6A, $26, $7E, $96,
$BA, $7C, $90, $45, $F1, $2C, $7F, $99, $24, $A1, $99, $47, $B3, $91, $6C, $F7,
$08, $01, $F2, $E2, $85, $8E, $FC, $16, $63, $69, $20, $D8, $71, $57, $4E, $69,
$A4, $58, $FE, $A3, $F4, $93, $3D, $7E, $0D, $95, $74, $8F, $72, $8E, $B6, $58,
$71, $8B, $CD, $58, $82, $15, $4A, $EE, $7B, $54, $A4, $1D, $C2, $5A, $59, $B5,
$9C, $30, $D5, $39, $2A, $F2, $60, $13, $C5, $D1, $B0, $23, $28, $60, $85, $F0,
$CA, $41, $79, $18, $B8, $DB, $38, $EF, $8E, $79, $DC, $B0, $60, $3A, $18, $0E,
$6C, $9E, $0E, $8B, $B0, $1E, $8A, $3E, $D7, $15, $77, $C1, $BD, $31, $4B, $27,
$78, $AF, $2F, $DA, $55, $60, $5C, $60, $E6, $55, $25, $F3, $AA, $55, $AB, $94,
$57, $48, $98, $62, $63, $E8, $14, $40, $55, $CA, $39, $6A, $2A, $AB, $10, $B6,
$B4, $CC, $5C, $34, $11, $41, $E8, $CE, $A1, $54, $86, $AF, $7C, $72, $E9, $93);
BCSalts: array [0 .. 3] of DWORD =
($55555555, $AAAAAAAA, $33333333, $CCCCCCCC);
{ SHA-1 constants }
{ 5 magic numbers }
SHA1_A = DWORD($67452301);
SHA1_B = DWORD($EFCDAB89);
SHA1_C = DWORD($98BADCFE);
SHA1_D = DWORD($10325476);
SHA1_E = DWORD($C3D2E1F0);
{ four rounds consts }
SHA1_K1 = DWORD($5A827999);
SHA1_K2 = DWORD($6ED9EBA1);
SHA1_K3 = DWORD($8F1BBCDC);
SHA1_K4 = DWORD($CA62C1D6);
{ Maskes used in byte swap }
LBMASK_HI = DWORD($FF0000);
LBMASK_LO = DWORD($FF00);
INPUTWHITEN = 0;
RS_GF_FDBK = $14D;
MDS_GF_FDBK = $169;
SK_STEP = $02020202;
SK_BUMP = $01010101;
SK_ROTL = 9;
Mars_SBox: array [0 .. 511] of DWORD = (
$09D0C479, $28C8FFE0, $84AA6C39, $9DAD7287,
$7DFF9BE3, $D4268361, $C96DA1D4, $7974CC93,
$85D0582E, $2A4B5705, $1CA16A62, $C3BD279D,
$0F1F25E5, $5160372F, $C695C1FB, $4D7FF1E4,
$AE5F6BF4, $0D72EE46, $FF23DE8A, $B1CF8E83,
$F14902E2, $3E981E42, $8BF53EB6, $7F4BF8AC,
$83631F83, $25970205, $76AFE784, $3A7931D4,
$4F846450, $5C64C3F6, $210A5F18, $C6986A26,
$28F4E826, $3A60A81C, $D340A664, $7EA820C4,
$526687C5, $7EDDD12B, $32A11D1D, $9C9EF086,
$80F6E831, $AB6F04AD, $56FB9B53, $8B2E095C,
$B68556AE, $D2250B0D, $294A7721, $E21FB253,
$AE136749, $E82AAE86, $93365104, $99404A66,
$78A784DC, $B69BA84B, $04046793, $23DB5C1E,
$46CAE1D6, $2FE28134, $5A223942, $1863CD5B,
$C190C6E3, $07DFB846, $6EB88816, $2D0DCC4A,
$A4CCAE59, $3798670D, $CBFA9493, $4F481D45,
$EAFC8CA8, $DB1129D6, $B0449E20, $0F5407FB,
$6167D9A8, $D1F45763, $4DAA96C3, $3BEC5958,
$ABABA014, $B6CCD201, $38D6279F, $02682215,
$8F376CD5, $092C237E, $BFC56593, $32889D2C,
$854B3E95, $05BB9B43, $7DCD5DCD, $A02E926C,
$FAE527E5, $36A1C330, $3412E1AE, $F257F462,
$3C4F1D71, $30A2E809, $68E5F551, $9C61BA44,
$5DED0AB8, $75CE09C8, $9654F93E, $698C0CCA,
$243CB3E4, $2B062B97, $0F3B8D9E, $00E050DF,
$FC5D6166, $E35F9288, $C079550D, $0591AEE8,
$8E531E74, $75FE3578, $2F6D829A, $F60B21AE,
$95E8EB8D, $6699486B, $901D7D9B, $FD6D6E31,
$1090ACEF, $E0670DD8, $DAB2E692, $CD6D4365,
$E5393514, $3AF345F0, $6241FC4D, $460DA3A3,
$7BCF3729, $8BF1D1E0, $14AAC070, $1587ED55,
$3AFD7D3E, $D2F29E01, $29A9D1F6, $EFB10C53,
$CF3B870F, $B414935C, $664465ED, $024ACAC7,
$59A744C1, $1D2936A7, $DC580AA6, $CF574CA8,
$040A7A10, $6CD81807, $8A98BE4C, $ACCEA063,
$C33E92B5, $D1E0E03D, $B322517E, $2092BD13,
$386B2C4A, $52E8DD58, $58656DFB, $50820371,
$41811896, $E337EF7E, $D39FB119, $C97F0DF6,
$68FEA01B, $A150A6E5, $55258962, $EB6FF41B,
$D7C9CD7A, $A619CD9E, $BCF09576, $2672C073,
$F003FB3C, $4AB7A50B, $1484126A, $487BA9B1,
$A64FC9C6, $F6957D49, $38B06A75, $DD805FCD,
$63D094CF, $F51C999E, $1AA4D343, $B8495294,
$CE9F8E99, $BFFCD770, $C7C275CC, $378453A7,
$7B21BE33, $397F41BD, $4E94D131, $92CC1F98,
$5915EA51, $99F861B7, $C9980A88, $1D74FD5F,
$B0A495F8, $614DEED0, $B5778EEA, $5941792D,
$FA90C1F8, $33F824B4, $C4965372, $3FF6D550,
$4CA5FEC0, $8630E964, $5B3FBBD6, $7DA26A48,
$B203231A, $04297514, $2D639306, $2EB13149,
$16A45272, $532459A0, $8E5F4872, $F966C7D9,
$07128DC0, $0D44DB62, $AFC8D52D, $06316131,
$D838E7CE, $1BC41D00, $3A2E8C0F, $EA83837E,
$B984737D, $13BA4891, $C4F8B949, $A6D6ACB3,
$A215CDCE, $8359838B, $6BD1AA31, $F579DD52,
$21B93F93, $F5176781, $187DFDDE, $E94AEB76,
$2B38FD54, $431DE1DA, $AB394825, $9AD3048F,
$DFEA32AA, $659473E3, $623F7863, $F3346C59,
$AB3AB685, $3346A90B, $6B56443E, $C6DE01F8,
$8D421FC0, $9B0ED10C, $88F1A1E9, $54C1F029,
$7DEAD57B, $8D7BA426, $4CF5178A, $551A7CCA,
$1A9A5F08, $FCD651B9, $25605182, $E11FC6C3,
$B6FD9676, $337B3027, $B7C8EB14, $9E5FD030,
$6B57E354, $AD913CF7, $7E16688D, $58872A69,
$2C2FC7DF, $E389CCC6, $30738DF1, $0824A734,
$E1797A8B, $A4A8D57B, $5B5D193B, $C8A8309B,
$73F9A978, $73398D32, $0F59573E, $E9DF2B03,
$E8A5B6C8, $848D0704, $98DF93C2, $720A1DC3,
$684F259A, $943BA848, $A6370152, $863B5EA3,
$D17B978B, $6D9B58EF, $0A700DD4, $A73D36BF,
$8E6A0829, $8695BC14, $E35B3447, $933AC568,
$8894B022, $2F511C27, $DDFBCC3C, $006662B6,
$117C83FE, $4E12B414, $C2BCA766, $3A2FEC10,
$F4562420, $55792E2A, $46F5D857, $CEDA25CE,
$C3601D3B, $6C00AB46, $EFAC9C28, $B3C35047,
$611DFEE3, $257C3207, $FDD58482, $3B14D84F,
$23BECB64, $A075F3A3, $088F8EAD, $07ADF158,
$7796943C, $FACABF3D, $C09730CD, $F7679969,
$DA44E9ED, $2C854C12, $35935FA3, $2F057D9F,
$690624F8, $1CB0BAFD, $7B0DBDC6, $810F23BB,
$FA929A1A, $6D969A17, $6742979B, $74AC7D05,
$010E65C4, $86A3D963, $F907B5A0, $D0042BD3,
$158D7D03, $287A8255, $BBA8366F, $096EDC33,
$21916A7B, $77B56B86, $951622F9, $A6C5E650,
$8CEA17D1, $CD8C62BC, $A3D63433, $358A68FD,
$0F9B9D3C, $D6AA295B, $FE33384A, $C000738E,
$CD67EB2F, $E2EB6DC2, $97338B02, $06C9F246,
$419CF1AD, $2B83C045, $3723F18A, $CB5B3089,
$160BEAD7, $5D494656, $35F8A74B, $1E4E6C9E,
$000399BD, $67466880, $B4174831, $ACF423B2,
$CA815AB3, $5A6395E7, $302A67C5, $8BDB446B,
$108F8FA4, $10223EDA, $92B8B48B, $7F38D0EE,
$AB2701D4, $0262D415, $AF224A30, $B3D88ABA,
$F8B2C3AF, $DAF7EF70, $CC97D3B7, $E9614B6C,
$2BAEBFF4, $70F687CF, $386C9156, $CE092EE5,
$01E87DA6, $6CE91E6A, $BB7BCC84, $C7922C20,
$9D3B71FD, $060E41C6, $D7590F15, $4E03BB47,
$183C198E, $63EEB240, $2DDBF49A, $6D5CBA54,
$923750AF, $F9E14236, $7838162B, $59726C72,
$81B66760, $BB2926C1, $48A0CE0D, $A6C0496D,
$AD43507B, $718D496A, $9DF057AF, $44B1BDE6,
$054356DC, $DE7CED35, $D51A138B, $62088CC9,
$35830311, $C96EFCA2, $686F86EC, $8E77CB68,
$63E1D6B8, $C80F9778, $79C491FD, $1B4C67F2,
$72698D7D, $5E368C31, $F7D95E2E, $A1D3493F,
$DCD9433E, $896F1552, $4BC4CA7A, $A6D1BAF4,
$A5A96DCC, $0BEF8B46, $A169FDA7, $74DF40B7,
$4E208804, $9A756607, $038E87C8, $20211E44,
$8B7AD4BF, $C6403F35, $1848E36D, $80BDB038,
$1E62891C, $643D2107, $BF04D6F8, $21092C8C,
$F644F389, $0778404E, $7B78ADB8, $A2C52D53,
$42157ABE, $A2253E2E, $7BF3F4AE, $80F594F9,
$953194E7, $77EB92ED, $B3816930, $DA8D9336,
$BF447469, $F26D9483, $EE6FAED5, $71371235,
$DE425F73, $B4E59F43, $7DBE2D4E, $2D37B185,
$49DC9A63, $98C39D98, $1301C9A2, $389B1BBF,
$0C18588D, $A421C1BA, $7AA3865C, $71E08558,
$3C5CFCAA, $7D239CA4, $0297D9DD, $D7DC2830,
$4B37802B, $7428AB54, $AEEE0347, $4B3FBB85,
$692F2F08, $134E578E, $36D9E0BF, $AE8B5FCF,
$EDB93ECF, $2B27248E, $170EB1EF, $7DC57FD6,
$1E760F16, $B1136601, $864E1B9B, $D7EA7319,
$3AB871BD, $CFA4D76F, $E31BD782, $0DBEB469,
$ABB96061, $5370F85D, $FFB07E37, $DA30D0FB,
$EBC977B6, $0B98B40F, $3A4D0FE6, $DF4FC26B,
$159CF22A, $C298D6E2, $2B78EF6A, $61A94AC0,
$AB561187, $14EEA0F0, $DF0D4164, $19AF70EE);
type
TBlock2048 = array [0 .. 255] of Byte;
TBCHalfBlock = array [0 .. 1] of Integer;
TBFBlockEx = packed record
Xl: array [0 .. 3] of Byte;
Xr: array [0 .. 3] of Byte;
end;
class function TCipher.AllCipher: TCipherSecurityArray;
var
cs: TCipherSecurity;
begin
SetLength(Result, Integer(high(TCipherSecurity)) + 1);
for cs := low(TCipherSecurity) to high(TCipherSecurity) do
Result[Integer(cs)] := cs;
end;
class function TCipher.NameToHashSecurity(n: SystemString; var hash: THashSecurity): Boolean;
var
h: THashSecurity;
begin
Result := False;
for h := low(THashSecurity) to high(THashSecurity) do
if SameText(CHashName[h], n) then
begin
hash := h;
Result := True;
Exit;
end;
end;
class function TCipher.BuffToString(buff: Pointer; Size: NativeInt): TPascalString;
begin
HashToString(buff, Size, Result);
end;
class function TCipher.StringToBuff(const Hex: TPascalString; var Buf; BufSize: Cardinal): Boolean;
begin
Result := HexToBuffer(Hex, Buf, BufSize);
end;
class procedure TCipher.HashToString(hash: Pointer; Size: NativeInt; var output: TPascalString);
const
HexArr: array [0 .. 15] of U_Char = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f');
var
i: Integer;
begin
output.Len := Size * 2;
for i := 0 to Size - 1 do
begin
output.buff[i * 2] := HexArr[(PByte(nativeUInt(hash) + i)^ shr 4) and $0F];
output.buff[i * 2 + 1] := HexArr[PByte(nativeUInt(hash) + i)^ and $0F];
end;
end;
class procedure TCipher.HashToString(hash: TSHA3_224_Digest; var output: TPascalString);
begin
HashToString(@hash[0], SizeOf(hash), output);
end;
class procedure TCipher.HashToString(hash: TSHA3_256_Digest; var output: TPascalString);
begin
HashToString(@hash[0], SizeOf(hash), output);
end;
class procedure TCipher.HashToString(hash: TSHA3_384_Digest; var output: TPascalString);
begin
HashToString(@hash[0], SizeOf(hash), output);
end;
class procedure TCipher.HashToString(hash: TSHA3_512_Digest; var output: TPascalString);
begin
HashToString(@hash[0], SizeOf(hash), output);
end;
class procedure TCipher.HashToString(hash: TSHA512Digest; var output: TPascalString);
begin
HashToString(@hash[0], SizeOf(hash), output);
end;
class procedure TCipher.HashToString(hash: TSHA256Digest; var output: TPascalString);
begin
HashToString(@hash[0], SizeOf(hash), output);
end;
class procedure TCipher.HashToString(hash: TSHA1Digest; var output: TPascalString);
begin
HashToString(@hash[0], SizeOf(hash), output);
end;
class procedure TCipher.HashToString(hash: TMD5Digest; var output: TPascalString);
begin
HashToString(@hash[0], SizeOf(hash), output);
end;
class procedure TCipher.HashToString(hash: TBytes; var output: TPascalString);
begin
HashToString(@hash[0], length(hash), output);
end;
class procedure TCipher.HashToString(hash: TBytes; var output: SystemString);
var
s: TPascalString;
begin
if length(hash) > 0 then
begin
HashToString(@hash[0], length(hash), s);
output := s.Text;
end
else
output := '';
end;
class function TCipher.CompareHash(h1, h2: TSHA3_224_Digest): Boolean;
begin
Result := CompareMemory(@h1[0], @h2[0], SizeOf(h1));
end;
class function TCipher.CompareHash(h1, h2: TSHA3_256_Digest): Boolean;
begin
Result := CompareMemory(@h1[0], @h2[0], SizeOf(h1));
end;
class function TCipher.CompareHash(h1, h2: TSHA3_384_Digest): Boolean;
begin
Result := CompareMemory(@h1[0], @h2[0], SizeOf(h1));
end;
class function TCipher.CompareHash(h1, h2: TSHA3_512_Digest): Boolean;
begin
Result := CompareMemory(@h1[0], @h2[0], SizeOf(h1));
end;
class function TCipher.CompareHash(h1, h2: TSHA512Digest): Boolean;
begin
Result := CompareMemory(@h1[0], @h2[0], SizeOf(h1));
end;
class function TCipher.CompareHash(h1, h2: TSHA256Digest): Boolean;
begin
Result := CompareMemory(@h1[0], @h2[0], SizeOf(h1));
end;
class function TCipher.CompareHash(h1, h2: TSHA1Digest): Boolean;
begin
Result := CompareMemory(@h1[0], @h2[0], SizeOf(h1));
end;
class function TCipher.CompareHash(h1, h2: TMD5Digest): Boolean;
begin
Result := CompareMemory(@h1[0], @h2[0], SizeOf(h1));
end;
class function TCipher.CompareHash(h1, h2: Pointer; Size: NativeInt): Boolean;
begin
Result := CompareMemory(h1, h2, Size);
end;
class function TCipher.CompareHash(h1, h2: TBytes): Boolean;
begin
if length(h1) = 0 then
Result := length(h2) = 0
else
Result := (length(h1) = length(h2)) and (CompareMemory(@h1[0], @h2[0], length(h1)));
end;
class function TCipher.CompareKey(k1, k2: TCipherKeyBuffer): Boolean;
begin
if length(k1) = 0 then
Result := length(k2) = 0
else
Result := (length(k1) = length(k2)) and (CompareMemory(@k1[0], @k2[0], length(k1)));
end;
class function TCipher.GenerateSHA3_224Hash(sour: Pointer; Size: NativeInt): TSHA3_224_Digest;
begin
TSHA3.SHA224(Result, sour, Size);
end;
class function TCipher.GenerateSHA3_256Hash(sour: Pointer; Size: NativeInt): TSHA3_256_Digest;
begin
TSHA3.SHA256(Result, sour, Size);
end;
class function TCipher.GenerateSHA3_384Hash(sour: Pointer; Size: NativeInt): TSHA3_384_Digest;
begin
TSHA3.SHA384(Result, sour, Size);
end;
class function TCipher.GenerateSHA3_512Hash(sour: Pointer; Size: NativeInt): TSHA3_512_Digest;
begin
TSHA3.SHA512(Result, sour, Size);
end;
class function TCipher.GenerateSHA512Hash(sour: Pointer; Size: NativeInt): TSHA512Digest;
begin
TSHA512.SHA512(Result, sour^, Size);
end;
class function TCipher.GenerateSHA256Hash(sour: Pointer; Size: NativeInt): TSHA256Digest;
begin
TSHA256.SHA256(Result, sour^, Size);
end;
class function TCipher.GenerateSHA1Hash(sour: Pointer; Size: NativeInt): TSHA1Digest;
begin
TSHA1.SHA1(Result, sour^, Size);
end;
class function TCipher.GenerateMD5Hash(sour: Pointer; Size: NativeInt): TMD5Digest;
begin
{$IF Defined(FastMD5) and (Defined(WIN32) or Defined(WIN64))}
Result := FastMD5(sour, Size);
{$ELSE}
THashMD5.HashMD5(Result, sour^, Size);
{$IFEND}
end;
class procedure TCipher.GenerateMDHash(sour: Pointer; Size: NativeInt; OutHash: Pointer; HashSize: NativeInt);
begin
THashMD.HashLMD(OutHash^, HashSize, sour^, Size);
end;
class procedure TCipher.GenerateHashByte(hs: THashSecurity; sour: Pointer; Size: NativeInt; var output: TBytes);
var
swBuff: TBytes;
begin
if Size <= 0 then
begin
SetLength(output, 0);
Exit;
end;
if Size < 6 then
begin
SetLength(output, 16);
PMD5(@output[0])^ := umlMD5(PByte(sour), Size);
Exit;
end;
case hs of
hsNone:
begin
SetLength(output, 0);
end;
hsFastMD5:
begin
SetLength(output, 16);
PMD5(@output[0])^ := umlMD5(PByte(sour), DWORD(Size));
end;
hsMD5:
begin
SetLength(output, 16);
THashMD5.HashMD5(PMD5Digest(@output[0])^, sour^, Size);
end;
hsSHA1:
begin
SetLength(output, 20);
TSHA1.SHA1(PSHA1Digest(@output[0])^, sour^, Size);
end;
hsSHA256:
begin
SetLength(output, 32);
TSHA256.SHA256(PSHA256Digest(@output[0])^, sour^, Size);
end;
hsSHA512:
begin
SetLength(output, 64);
TSHA512.SHA512(PSHA512Digest(@output[0])^, sour^, Size);
end;
hsSHA3_224:
begin
SetLength(output, SizeOf(TSHA3_224_Digest));
TSHA3.SHA224(PSHA3_224_Digest(@output[0])^, sour, Size);
end;
hsSHA3_256:
begin
SetLength(output, SizeOf(TSHA3_256_Digest));
TSHA3.SHA256(PSHA3_256_Digest(@output[0])^, sour, Size);
end;
hsSHA3_384:
begin
SetLength(output, SizeOf(TSHA3_384_Digest));
TSHA3.SHA384(PSHA3_384_Digest(@output[0])^, sour, Size);
end;
hsSHA3_512:
begin
SetLength(output, SizeOf(TSHA3_512_Digest));
TSHA3.SHA512(PSHA3_512_Digest(@output[0])^, sour, Size);
end;
hs256:
begin
SetLength(output, 256);
THashMD.HashLMD((@output[0])^, 256, sour^, Size);
end;
hs128:
begin
SetLength(output, 128);
THashMD.HashLMD((@output[0])^, 128, sour^, Size);
end;
hs64:
begin
SetLength(output, 64);
THashMD.HashLMD((@output[0])^, 64, sour^, Size);
end;
hs32:
begin
SetLength(output, 32);
THashMD.HashLMD((@output[0])^, 32, sour^, Size);
end;
hs16:
begin
SetLength(output, 16);
THashMD.HashLMD((@output[0])^, 16, sour^, Size);
end;
hsELF:
begin
SetLength(output, 4);
TMISC.HashELF(PDWORD(@output[0])^, sour^, Size);
end;
hsELF64:
begin
SetLength(output, 8);
TMISC.HashELF64(PInt64(@output[0])^, sour^, Size);
end;
hsMix128:
begin
SetLength(output, 4);
if Size < 16 then
begin
SetLength(swBuff, 16);
THashMD.HashLMD(swBuff[0], 16, sour^, Size);
TMISC.HashMix128(PDWORD(@output[0])^, swBuff[0], 16);
end
else
TMISC.HashMix128(PDWORD(@output[0])^, sour^, Size);
end;
hsCRC16:
begin
SetLength(output, 2);
PWORD(@output[0])^ := umlCRC16(PByte(sour), Size);
end;
hsCRC32:
begin
SetLength(output, 4);
PCardinal(@output[0])^ := umlCRC32(PByte(sour), Size);
end;
end;
end;
class function TCipher.GenerateHashString(hs: THashSecurity; sour: Pointer; Size: NativeInt): TPascalString;
var
h: TBytes;
begin
GenerateHashByte(hs, sour, Size, h);
HashToString(h, Result);
SetLength(h, 0);
end;
class function TCipher.BufferToHex(const Buf; BufSize: Cardinal): TPascalString;
begin
Result := BuffToString(@Buf, BufSize);
end;
class function TCipher.HexToBuffer(const Hex: TPascalString; var Buf; BufSize: Cardinal): Boolean;
var
i, c: Integer;
filStr: TPascalString;
Count: Integer;
cChar: Char;
begin
Result := False;
filStr.Text := '';
for cChar in Hex.buff do
if CharIn(cChar, [c0to9, cLoAtoF, cHiAtoF]) then
filStr.Append(cChar);
FillPtrByte(@Buf, BufSize, 0);
Count := Min(filStr.Len div 2, BufSize);
for i := 0 to Count - 1 do
begin
val('$' + filStr[i * 2 + 1] + filStr[i * 2 + 2], TCCByteArray(Buf)[i], c);
if c <> 0 then
Exit;
end;
Result := True;
end;
class function TCipher.CopyKey(const k: TCipherKeyBuffer): TCipherKeyBuffer;
begin
SetLength(Result, length(k));
CopyPtr(@k[0], @Result[0], length(k));
end;
class procedure TCipher.GenerateNoneKey(var output: TCipherKeyBuffer);
begin
SetLength(output, C_Byte_Size);
output[0] := Byte(TCipherKeyStyle.cksNone);
end;
class procedure TCipher.GenerateKey64(const s: TPascalString; var output: TCipherKeyBuffer);
begin
SetLength(output, C_Byte_Size + cKey64Size);
output[0] := Byte(TCipherKeyStyle.cksKey64);
THashMD.GenerateLMDKey((@output[1])^, cKey64Size, s.Bytes);
end;
class procedure TCipher.GenerateKey64(sour: Pointer; Size: NativeInt; var output: TCipherKeyBuffer);
begin
SetLength(output, C_Byte_Size + cKey64Size);
output[0] := Byte(TCipherKeyStyle.cksKey64);
THashMD.HashLMD((@output[1])^, cKey64Size, sour^, Size);
end;
class procedure TCipher.GenerateKey128(const s: TPascalString; var output: TCipherKeyBuffer);
begin
SetLength(output, C_Byte_Size + cKey128Size);
output[0] := Byte(TCipherKeyStyle.cksKey128);
THashMD.GenerateLMDKey((@output[1])^, cKey128Size, s.Bytes);
end;
class procedure TCipher.GenerateKey128(sour: Pointer; Size: NativeInt; var output: TCipherKeyBuffer);
begin
SetLength(output, C_Byte_Size + cKey128Size);
output[0] := Byte(TCipherKeyStyle.cksKey128);
THashMD.HashLMD((@output[1])^, cKey128Size, sour^, Size);
end;
class procedure TCipher.GenerateKey256(const s: TPascalString; var output: TCipherKeyBuffer);
begin
SetLength(output, C_Byte_Size + cKey256Size);
output[0] := Byte(TCipherKeyStyle.cksKey256);
THashMD.GenerateLMDKey((@output[1])^, cKey256Size, s.Bytes);
end;
class procedure TCipher.GenerateKey256(sour: Pointer; Size: NativeInt; var output: TCipherKeyBuffer);
begin
SetLength(output, C_Byte_Size + cKey256Size);
output[0] := Byte(TCipherKeyStyle.cksKey256);
THashMD.HashLMD((@output[1])^, cKey256Size, sour^, Size);
end;
class procedure TCipher.Generate3Key64(const s: TPascalString; var output: TCipherKeyBuffer);
begin
SetLength(output, C_Byte_Size + cKey192Size);
output[0] := Byte(TCipherKeyStyle.cks3Key64);
THashMD.GenerateLMDKey((@output[1])^, cKey192Size, s.Bytes);
end;
class procedure TCipher.Generate3Key64(sour: Pointer; Size: NativeInt; var output: TCipherKeyBuffer);
begin
SetLength(output, C_Byte_Size + cKey192Size);
output[0] := Byte(TCipherKeyStyle.cks3Key64);
THashMD.HashLMD((@output[1])^, cKey192Size, sour^, Size);
end;
class procedure TCipher.Generate2IntKey(const s: TPascalString; var output: TCipherKeyBuffer);
begin
SetLength(output, C_Byte_Size + cKey2DWORDSize);
output[0] := Byte(TCipherKeyStyle.cks2IntKey);
THashMD.GenerateLMDKey((@output[1])^, cKey2DWORDSize, s.Bytes);
end;
class procedure TCipher.Generate2IntKey(sour: Pointer; Size: NativeInt; var output: TCipherKeyBuffer);
begin
SetLength(output, C_Byte_Size + cKey2DWORDSize);
output[0] := Byte(TCipherKeyStyle.cks2IntKey);
THashMD.HashLMD((@output[1])^, cKey2DWORDSize, sour^, Size);
end;
class procedure TCipher.GenerateIntKey(const s: TPascalString; var output: TCipherKeyBuffer);
begin
SetLength(output, C_Byte_Size + cKeyDWORDSize);
output[0] := Byte(TCipherKeyStyle.cksIntKey);
THashMD.GenerateLMDKey((@output[1])^, cKeyDWORDSize, s.Bytes);
end;
class procedure TCipher.GenerateIntKey(sour: Pointer; Size: NativeInt; var output: TCipherKeyBuffer);
begin
SetLength(output, C_Byte_Size + cKeyDWORDSize);
output[0] := Byte(TCipherKeyStyle.cksIntKey);
THashMD.HashLMD((@output[1])^, cKeyDWORDSize, sour^, Size);
end;
class procedure TCipher.GenerateBytesKey(const s: TPascalString; KeySize: DWORD; var output: TCipherKeyBuffer);
begin
SetLength(output, C_Byte_Size + cIntSize + KeySize);
output[0] := Byte(TCipherKeyStyle.ckyDynamicKey);
PDWORD(@output[1])^ := KeySize;
THashMD.GenerateLMDKey((@output[1 + cIntSize])^, KeySize, s.Bytes);
end;
class procedure TCipher.GenerateBytesKey(sour: Pointer; Size, KeySize: DWORD; var output: TCipherKeyBuffer);
begin
SetLength(output, C_Byte_Size + cIntSize + KeySize);
output[0] := Byte(TCipherKeyStyle.ckyDynamicKey);
PDWORD(@output[1])^ := KeySize;
THashMD.HashLMD((@output[1 + cIntSize])^, KeySize, sour^, Size);
end;
class procedure TCipher.GenerateKey64(const k: TKey64; var output: TCipherKeyBuffer);
begin
GenerateKey(k, output);
end;
class procedure TCipher.GenerateKey128(const k1, k2: TKey64; var output: TCipherKeyBuffer);
begin
SetLength(output, C_Byte_Size + cKey128Size);
output[0] := Byte(TCipherKeyStyle.cksKey128);
PKey64(@output[1])^ := k1;
PKey64(@output[1 + cKey64Size])^ := k2;
end;
class procedure TCipher.GenerateKey(const k: TKey64; var output: TCipherKeyBuffer);
begin
SetLength(output, C_Byte_Size + cKey64Size);
output[0] := Byte(TCipherKeyStyle.cksKey64);
PKey64(@output[1])^ := k;
end;
class procedure TCipher.GenerateKey(const k1, k2, k3: TKey64; var output: TCipherKeyBuffer);
begin
SetLength(output, C_Byte_Size + cKey192Size);
output[0] := Byte(TCipherKeyStyle.cks3Key64);
PKey64(@output[1])^ := k1;
PKey64(@output[1 + cKey64Size])^ := k2;
PKey64(@output[1 + cKey64Size + cKey64Size])^ := k3;
end;
class procedure TCipher.GenerateKey(const k: TKey128; var output: TCipherKeyBuffer);
begin
SetLength(output, C_Byte_Size + cKey128Size);
output[0] := Byte(TCipherKeyStyle.cksKey128);
PKey128(@output[1])^ := k;
end;
class procedure TCipher.GenerateKey(const k: TKey256; var output: TCipherKeyBuffer);
begin
SetLength(output, C_Byte_Size + cKey256Size);
output[0] := Byte(TCipherKeyStyle.cksKey256);
PKey256(@output[1])^ := k;
end;
class procedure TCipher.GenerateKey(const k1, k2: DWORD; var output: TCipherKeyBuffer);
begin
SetLength(output, C_Byte_Size + cKey2DWORDSize);
output[0] := Byte(TCipherKeyStyle.cks2IntKey);
PInteger(@output[1])^ := k1;
PInteger(@output[1 + cKeyDWORDSize])^ := k2;
end;
class procedure TCipher.GenerateKey(const k: DWORD; var output: TCipherKeyBuffer);
begin
SetLength(output, C_Byte_Size + cKeyDWORDSize);
output[0] := Byte(TCipherKeyStyle.cksIntKey);
PInteger(@output[1])^ := k;
end;
class procedure TCipher.GenerateKey(const key: PByte; Size: DWORD; var output: TCipherKeyBuffer);
begin
SetLength(output, C_Byte_Size + cIntSize + Size);
output[0] := Byte(TCipherKeyStyle.ckyDynamicKey);
PInteger(@output[1])^ := Size;
CopyPtr(key, @output[1 + cIntSize], Size);
end;
class procedure TCipher.GenerateKey(cs: TCipherSecurity; buffPtr: Pointer; Size: NativeInt; var output: TCipherKeyBuffer);
begin
case cCipherKeyStyle[cs] of
cksNone: GenerateNoneKey(output);
cksKey64: GenerateKey64(buffPtr, Size, output);
cks3Key64: Generate3Key64(buffPtr, Size, output);
cksKey128: GenerateKey128(buffPtr, Size, output);
cksKey256: GenerateKey256(buffPtr, Size, output);
cks2IntKey: Generate2IntKey(buffPtr, Size, output);
cksIntKey: GenerateIntKey(buffPtr, Size, output);
ckyDynamicKey: GenerateBytesKey(buffPtr, Size, 32, output);
end;
end;
class procedure TCipher.GenerateKey(cs: TCipherSecurity; s: TPascalString; var output: TCipherKeyBuffer);
var
buff: TBytes;
key: TBytes;
begin
buff := s.Bytes;
SetLength(key, 128);
TCipher.GenerateMDHash(@buff[0], SizeOf(buff), @key[0], 128);
GenerateKey(cs, @key[0], 128, output);
end;
class function TCipher.GetKeyStyle(const p: PCipherKeyBuffer): TCipherKeyStyle;
begin
Result := TCipherKeyStyle(p^[0]);
end;
class function TCipher.GetKey(const KeyBuffPtr: PCipherKeyBuffer; var k: TKey64): Boolean;
begin
Result := GetKeyStyle(KeyBuffPtr) = TCipherKeyStyle.cksKey64;
if not Result then
Exit;
k := PKey64(@KeyBuffPtr^[1])^
end;
class function TCipher.GetKey(const KeyBuffPtr: PCipherKeyBuffer; var k1, k2, k3: TKey64): Boolean;
begin
Result := GetKeyStyle(KeyBuffPtr) = TCipherKeyStyle.cks3Key64;
if not Result then
Exit;
k1 := PKey64(@KeyBuffPtr^[1])^;
k2 := PKey64(@KeyBuffPtr^[1 + cKey64Size])^;
k3 := PKey64(@KeyBuffPtr^[1 + cKey64Size + cKey64Size])^;
end;
class function TCipher.GetKey(const KeyBuffPtr: PCipherKeyBuffer; var k: TKey128): Boolean;
begin
Result := GetKeyStyle(KeyBuffPtr) = TCipherKeyStyle.cksKey128;
if not Result then
Exit;
k := PKey128(@KeyBuffPtr^[1])^
end;
class function TCipher.GetKey(const KeyBuffPtr: PCipherKeyBuffer; var k: TKey256): Boolean;
begin
Result := GetKeyStyle(KeyBuffPtr) = TCipherKeyStyle.cksKey256;
if not Result then
Exit;
k := PKey256(@KeyBuffPtr^[1])^
end;
class function TCipher.GetKey(const KeyBuffPtr: PCipherKeyBuffer; var k1, k2: DWORD): Boolean;
begin
Result := GetKeyStyle(KeyBuffPtr) = TCipherKeyStyle.cks2IntKey;
if not Result then
Exit;
k1 := PDWORD(@KeyBuffPtr^[1])^;
k2 := PDWORD(@KeyBuffPtr^[1 + cKeyDWORDSize])^;
end;
class function TCipher.GetKey(const KeyBuffPtr: PCipherKeyBuffer; var k: DWORD): Boolean;
begin
Result := GetKeyStyle(KeyBuffPtr) = TCipherKeyStyle.cksIntKey;
if not Result then
Exit;
k := PDWORD(@KeyBuffPtr^[1])^;
end;
class function TCipher.GetKey(const KeyBuffPtr: PCipherKeyBuffer; var key: TBytes): Boolean;
var
siz: Integer;
begin
Result := GetKeyStyle(KeyBuffPtr) = TCipherKeyStyle.ckyDynamicKey;
if not Result then
Exit;
siz := PInteger(@KeyBuffPtr^[1])^;
SetLength(key, siz);
CopyPtr(@KeyBuffPtr^[1 + cIntSize], @key[0], siz);
end;
class procedure TCipher.EncryptTail(TailPtr: Pointer; TailSize: NativeInt);
begin
BlockCBC(TailPtr, TailSize, @SystemCBC[0], length(SystemCBC));
end;
class function TCipher.DES64(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
k: TKey64;
d: TDESContext;
p: nativeUInt;
begin
Result := False;
if Size <= 0 then
Exit;
if Size >= 8 then
begin
if not GetKey(KeyBuff, k) then
Exit;
TDES.InitEncryptDES(k, d, Encrypt);
p := 0;
repeat
TDES.EncryptDES(d, PDESBlock(nativeUInt(sour) + p)^);
p := p + 8;
until p + 8 > Size;
end
else
p := 0;
if (ProcessTail) and (Size - p > 0) then
EncryptTail(Pointer(nativeUInt(sour) + p), Size - p);
Result := True;
end;
class function TCipher.DES128(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
k: TKey128;
d: TTripleDESContext;
p: nativeUInt;
begin
Result := False;
if Size <= 0 then
Exit;
if Size >= 8 then
begin
if not GetKey(KeyBuff, k) then
Exit;
TDES.InitEncryptTripleDES(k, d, Encrypt);
p := 0;
repeat
TDES.EncryptTripleDES(d, PDESBlock(nativeUInt(sour) + p)^);
p := p + 8;
until p + 8 > Size;
end
else
p := 0;
if (ProcessTail) and (Size - p > 0) then
EncryptTail(Pointer(nativeUInt(sour) + p), Size - p);
Result := True;
end;
class function TCipher.DES192(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
k1, k2, k3: TKey64;
d: TTripleDESContext3Key;
p: nativeUInt;
begin
Result := False;
if Size <= 0 then
Exit;
if Size >= 8 then
begin
if not GetKey(KeyBuff, k1, k2, k3) then
Exit;
TDES.InitEncryptTripleDES3Key(k1, k2, k3, d, Encrypt);
p := 0;
repeat
TDES.EncryptTripleDES3Key(d, PDESBlock(nativeUInt(sour) + p)^);
p := p + 8;
until p + 8 > Size;
end
else
p := 0;
if (ProcessTail) and (Size - p > 0) then
EncryptTail(Pointer(nativeUInt(sour) + p), Size - p);
Result := True;
end;
class function TCipher.Blowfish(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
k: TKey128;
d: TBFContext;
p: nativeUInt;
begin
Result := False;
if Size <= 0 then
Exit;
if Size >= 8 then
begin
if not GetKey(KeyBuff, k) then
Exit;
TBlowfish.InitEncryptBF(k, d);
p := 0;
repeat
TBlowfish.EncryptBF(d, PBFBlock(nativeUInt(sour) + p)^, Encrypt);
p := p + 8;
until p + 8 > Size;
end
else
p := 0;
if (ProcessTail) and (Size - p > 0) then
EncryptTail(Pointer(nativeUInt(sour) + p), Size - p);
Result := True;
end;
class function TCipher.LBC(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
k: TKey128;
d: TLBCContext;
p: nativeUInt;
begin
Result := False;
if Size <= 0 then
Exit;
if Size >= 16 then
begin
if not GetKey(KeyBuff, k) then
Exit;
TLBC.InitEncryptLBC(k, d, 16, Encrypt);
p := 0;
repeat
TLBC.EncryptLBC(d, PLBCBlock(nativeUInt(sour) + p)^);
p := p + 16;
until p + 16 > Size;
end
else
p := 0;
if (ProcessTail) and (Size - p > 0) then
EncryptTail(Pointer(nativeUInt(sour) + p), Size - p);
Result := True;
end;
class function TCipher.LQC(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
k: TKey128;
p: nativeUInt;
begin
Result := False;
if Size <= 0 then
Exit;
if Size >= 8 then
begin
if not GetKey(KeyBuff, k) then
Exit;
p := 0;
repeat
TLBC.EncryptLQC(k, PLQCBlock(nativeUInt(sour) + p)^, Encrypt);
p := p + 8;
until p + 8 > Size;
end
else
p := 0;
if (ProcessTail) and (Size - p > 0) then
EncryptTail(Pointer(nativeUInt(sour) + p), Size - p);
Result := True;
end;
class function TCipher.RNG32(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer): Boolean;
var
k: DWORD;
d: TRNG32Context;
begin
Result := False;
if Size <= 0 then
Exit;
if not GetKey(KeyBuff, k) then
Exit;
TRNG.InitEncryptRNG32(k, d);
TRNG.EncryptRNG32(d, sour^, Size);
Result := True;
end;
class function TCipher.RNG64(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer): Boolean;
var
k1, k2: DWORD;
d: TRNG64Context;
begin
Result := False;
if Size <= 0 then
Exit;
if not GetKey(KeyBuff, k1, k2) then
Exit;
TRNG.InitEncryptRNG64(k1, k2, d);
TRNG.EncryptRNG64(d, sour^, Size);
Result := True;
end;
class function TCipher.LSC(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer): Boolean;
var
k: TBytes;
k255: TBytes;
d: TLSCContext;
begin
Result := False;
if Size <= 0 then
Exit;
if not GetKey(KeyBuff, k) then
Exit;
if length(k) > 255 then
begin
SetLength(k255, 255);
THashMD.GenerateLMDKey((@k255[0])^, 255, k);
end
else
k255 := k;
TLSC.InitEncryptLSC((@k255[0])^, length(k255), d);
TLSC.EncryptLSC(d, sour^, Size);
Result := True;
end;
class function TCipher.TwoFish(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
k, k256: TBytes;
d: TTwofishKey;
p: nativeUInt;
begin
Result := False;
if Size <= 0 then
Exit;
if Size >= 16 then
begin
if not GetKey(KeyBuff, k) then
Exit;
SetLength(k256, 32);
THashMD.GenerateLMDKey((@k256[0])^, 32, k);
TTwofish.InitKey(@k256[0], 32, d);
if Encrypt then
begin
p := 0;
repeat
TTwofish.Encrypt(d, PTwofishBlock(nativeUInt(sour) + p)^);
p := p + 16;
until p + 16 > Size;
end
else
begin
p := 0;
repeat
TTwofish.Decrypt(d, PTwofishBlock(nativeUInt(sour) + p)^);
p := p + 16;
until p + 16 > Size;
end;
end
else
p := 0;
if (ProcessTail) and (Size - p > 0) then
EncryptTail(Pointer(nativeUInt(sour) + p), Size - p);
Result := True;
end;
class function TCipher.XXTea512(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
k: TKey128;
p: nativeUInt;
begin
Result := False;
if Size <= 0 then
Exit;
if Size >= 64 then
begin
if not GetKey(KeyBuff, k) then
Exit;
if Encrypt then
begin
p := 0;
repeat
XXTEAEncrypt(k, PXXTEABlock(nativeUInt(sour) + p)^);
p := p + 64;
until p + 64 > Size;
end
else
begin
p := 0;
repeat
XXTEADecrypt(k, PXXTEABlock(nativeUInt(sour) + p)^);
p := p + 64;
until p + 64 > Size;
end;
end
else
p := 0;
if (ProcessTail) and (Size - p > 0) then
EncryptTail(Pointer(nativeUInt(sour) + p), Size - p);
Result := True;
end;
class function TCipher.RC6(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
k, k256: TBytes;
d: TRC6Key;
p: nativeUInt;
begin
Result := False;
if Size <= 0 then
Exit;
if Size >= 16 then
begin
if not GetKey(KeyBuff, k) then
Exit;
SetLength(k256, 32);
THashMD.GenerateLMDKey((@k256[0])^, 32, k);
TRC6.InitKey(@k256[0], 32, d);
if Encrypt then
begin
p := 0;
repeat
TRC6.Encrypt(d, PRC6Block(nativeUInt(sour) + p)^);
p := p + 16;
until p + 16 > Size;
end
else
begin
p := 0;
repeat
TRC6.Decrypt(d, PRC6Block(nativeUInt(sour) + p)^);
p := p + 16;
until p + 16 > Size;
end;
end
else
p := 0;
if (ProcessTail) and (Size - p > 0) then
EncryptTail(Pointer(nativeUInt(sour) + p), Size - p);
Result := True;
end;
class function TCipher.Serpent(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
k, k256: TBytes;
d: TSerpentkey;
p: nativeUInt;
begin
Result := False;
if Size <= 0 then
Exit;
if Size >= 16 then
begin
if not GetKey(KeyBuff, k) then
Exit;
SetLength(k256, 32);
THashMD.GenerateLMDKey((@k256[0])^, 32, k);
TSerpent.InitKey(@k256[0], 32, d);
if Encrypt then
begin
p := 0;
repeat
TSerpent.Encrypt(d, PSerpentBlock(nativeUInt(sour) + p)^);
p := p + 16;
until p + 16 > Size;
end
else
begin
p := 0;
repeat
TSerpent.Decrypt(d, PSerpentBlock(nativeUInt(sour) + p)^);
p := p + 16;
until p + 16 > Size;
end;
end
else
p := 0;
if (ProcessTail) and (Size - p > 0) then
EncryptTail(Pointer(nativeUInt(sour) + p), Size - p);
Result := True;
end;
class function TCipher.Mars(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
k, k256: TBytes;
d: TMarskey;
p: nativeUInt;
begin
Result := False;
if Size <= 0 then
Exit;
if Size >= 16 then
begin
if not GetKey(KeyBuff, k) then
Exit;
SetLength(k256, 32);
THashMD.GenerateLMDKey((@k256[0])^, 32, k);
TMars.InitKey(@k256[0], 32, d);
if Encrypt then
begin
p := 0;
repeat
TMars.Encrypt(d, PMarsBlock(nativeUInt(sour) + p)^);
p := p + 16;
until p + 16 > Size;
end
else
begin
p := 0;
repeat
TMars.Decrypt(d, PMarsBlock(nativeUInt(sour) + p)^);
p := p + 16;
until p + 16 > Size;
end;
end
else
p := 0;
if (ProcessTail) and (Size - p > 0) then
EncryptTail(Pointer(nativeUInt(sour) + p), Size - p);
Result := True;
end;
class function TCipher.Rijndael(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
k, k256: TBytes;
d: TRijndaelkey;
p: nativeUInt;
begin
Result := False;
if Size <= 0 then
Exit;
if Size >= 16 then
begin
if not GetKey(KeyBuff, k) then
Exit;
SetLength(k256, 32);
THashMD.GenerateLMDKey((@k256[0])^, 32, k);
TRijndael.InitKey(@k256[0], 32, d);
if Encrypt then
begin
p := 0;
repeat
TRijndael.Encrypt(d, PRijndaelBlock(nativeUInt(sour) + p)^);
p := p + 16;
until p + 16 > Size;
end
else
begin
p := 0;
repeat
TRijndael.Decrypt(d, PRijndaelBlock(nativeUInt(sour) + p)^);
p := p + 16;
until p + 16 > Size;
end;
end
else
p := 0;
if (ProcessTail) and (Size - p > 0) then
EncryptTail(Pointer(nativeUInt(sour) + p), Size - p);
Result := True;
end;
class procedure TCipher.BlockCBC(sour: Pointer; Size: NativeInt; boxBuff: Pointer; boxSiz: NativeInt);
var
p: nativeUInt;
begin
if Size = 0 then
Exit;
if boxSiz >= Size then
begin
TMISC.XorMem(sour^, boxBuff^, Size);
end
else
begin
p := 0;
repeat
TMISC.XorMem(Pointer(nativeUInt(sour) + p)^, boxBuff^, boxSiz);
p := p + boxSiz;
until p + boxSiz > Size;
BlockCBC(Pointer(nativeUInt(sour) + p), Size - p, boxBuff, boxSiz);
end;
end;
class function TCipher.EncryptBuffer(cs: TCipherSecurity; sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
begin
Result := False;
case cs of
csNone: Result := True;
csDES64: Result := DES64(sour, Size, KeyBuff, Encrypt, ProcessTail);
csDES128: Result := DES128(sour, Size, KeyBuff, Encrypt, ProcessTail);
csDES192: Result := DES192(sour, Size, KeyBuff, Encrypt, ProcessTail);
csBlowfish: Result := Blowfish(sour, Size, KeyBuff, Encrypt, ProcessTail);
csLBC: Result := LBC(sour, Size, KeyBuff, Encrypt, ProcessTail);
csLQC: Result := LQC(sour, Size, KeyBuff, Encrypt, ProcessTail);
csRNG32: Result := RNG32(sour, Size, KeyBuff);
csRNG64: Result := RNG64(sour, Size, KeyBuff);
csLSC: Result := LSC(sour, Size, KeyBuff);
csTwoFish: Result := TwoFish(sour, Size, KeyBuff, Encrypt, ProcessTail);
csXXTea512: Result := XXTea512(sour, Size, KeyBuff, Encrypt, ProcessTail);
csRC6: Result := RC6(sour, Size, KeyBuff, Encrypt, ProcessTail);
csSerpent: Result := Serpent(sour, Size, KeyBuff, Encrypt, ProcessTail);
csMars: Result := Mars(sour, Size, KeyBuff, Encrypt, ProcessTail);
csRijndael: Result := Rijndael(sour, Size, KeyBuff, Encrypt, ProcessTail);
end;
end;
class function TCipher.EncryptBufferCBC(cs: TCipherSecurity; sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
begin
if cs = TCipherSecurity.csNone then
begin
Result := True;
Exit;
end;
if Encrypt then
begin
Result := EncryptBuffer(cs, sour, Size, KeyBuff, Encrypt, ProcessTail);
if Result then
BlockCBC(sour, Size, @SystemCBC[0], length(SystemCBC));
end
else
begin
BlockCBC(sour, Size, @SystemCBC[0], length(SystemCBC));
Result := EncryptBuffer(cs, sour, Size, KeyBuff, Encrypt, ProcessTail);
end;
end;
{$IFDEF Parallel}
procedure TParallelCipher.DES64_Parallel(Job, buff, key: Pointer; Size: NativeInt);
var
p: nativeUInt;
begin
p := 0;
repeat
TDES.EncryptDES(PDESContext(key)^, PDESBlock(nativeUInt(buff) + p)^);
p := p + PParallelCipherJobData(Job)^.BlockLen;
until p + PParallelCipherJobData(Job)^.BlockLen > Size;
end;
procedure TParallelCipher.DES128_Parallel(Job, buff, key: Pointer; Size: NativeInt);
var
p: nativeUInt;
begin
p := 0;
repeat
TDES.EncryptTripleDES(PTripleDESContext(key)^, PDESBlock(nativeUInt(buff) + p)^);
p := p + PParallelCipherJobData(Job)^.BlockLen;
until p + PParallelCipherJobData(Job)^.BlockLen > Size;
end;
procedure TParallelCipher.DES192_Parallel(Job, buff, key: Pointer; Size: NativeInt);
var
p: nativeUInt;
begin
p := 0;
repeat
TDES.EncryptTripleDES3Key(PTripleDESContext3Key(key)^, PDESBlock(nativeUInt(buff) + p)^);
p := p + PParallelCipherJobData(Job)^.BlockLen;
until p + PParallelCipherJobData(Job)^.BlockLen > Size;
end;
procedure TParallelCipher.Blowfish_Parallel(Job, buff, key: Pointer; Size: NativeInt);
var
p: nativeUInt;
begin
p := 0;
repeat
TBlowfish.EncryptBF(PBFContext(key)^, PBFBlock(nativeUInt(buff) + p)^, PParallelCipherJobData(Job)^.Encrypt);
p := p + PParallelCipherJobData(Job)^.BlockLen;
until p + PParallelCipherJobData(Job)^.BlockLen > Size;
end;
procedure TParallelCipher.LBC_Parallel(Job, buff, key: Pointer; Size: NativeInt);
var
p: nativeUInt;
begin
p := 0;
repeat
TLBC.EncryptLBC(PLBCContext(key)^, PLBCBlock(nativeUInt(buff) + p)^);
p := p + PParallelCipherJobData(Job)^.BlockLen;
until p + PParallelCipherJobData(Job)^.BlockLen > Size;
end;
procedure TParallelCipher.LQC_Parallel(Job, buff, key: Pointer; Size: NativeInt);
var
p: nativeUInt;
begin
p := 0;
repeat
TLBC.EncryptLQC(PKey128(key)^, PLQCBlock(nativeUInt(buff) + p)^, PParallelCipherJobData(Job)^.Encrypt);
p := p + PParallelCipherJobData(Job)^.BlockLen;
until p + PParallelCipherJobData(Job)^.BlockLen > Size;
end;
procedure TParallelCipher.TwoFish_Parallel(Job, buff, key: Pointer; Size: NativeInt);
var
p: nativeUInt;
begin
if PParallelCipherJobData(Job)^.Encrypt then
begin
p := 0;
repeat
TTwofish.Encrypt(PTwofishKey(key)^, PTwofishBlock(nativeUInt(buff) + p)^);
p := p + PParallelCipherJobData(Job)^.BlockLen;
until p + PParallelCipherJobData(Job)^.BlockLen > Size;
end
else
begin
p := 0;
repeat
TTwofish.Decrypt(PTwofishKey(key)^, PTwofishBlock(nativeUInt(buff) + p)^);
p := p + PParallelCipherJobData(Job)^.BlockLen;
until p + PParallelCipherJobData(Job)^.BlockLen > Size;
end;
end;
procedure TParallelCipher.XXTea512_Parallel(Job, buff, key: Pointer; Size: NativeInt);
var
p: nativeUInt;
begin
if PParallelCipherJobData(Job)^.Encrypt then
begin
p := 0;
repeat
XXTEAEncrypt(PKey128(key)^, PXXTEABlock(nativeUInt(buff) + p)^);
p := p + PParallelCipherJobData(Job)^.BlockLen;
until p + PParallelCipherJobData(Job)^.BlockLen > Size;
end
else
begin
p := 0;
repeat
XXTEADecrypt(PKey128(key)^, PXXTEABlock(nativeUInt(buff) + p)^);
p := p + PParallelCipherJobData(Job)^.BlockLen;
until p + PParallelCipherJobData(Job)^.BlockLen > Size;
end;
end;
procedure TParallelCipher.RC6_Parallel(Job, buff, key: Pointer; Size: NativeInt);
var
p: nativeUInt;
begin
if PParallelCipherJobData(Job)^.Encrypt then
begin
p := 0;
repeat
TRC6.Encrypt(PRC6Key(key)^, PRC6Block(nativeUInt(buff) + p)^);
p := p + PParallelCipherJobData(Job)^.BlockLen;
until p + PParallelCipherJobData(Job)^.BlockLen > Size;
end
else
begin
p := 0;
repeat
TRC6.Decrypt(PRC6Key(key)^, PRC6Block(nativeUInt(buff) + p)^);
p := p + PParallelCipherJobData(Job)^.BlockLen;
until p + PParallelCipherJobData(Job)^.BlockLen > Size;
end;
end;
procedure TParallelCipher.Serpent_Parallel(Job, buff, key: Pointer; Size: NativeInt);
var
p: nativeUInt;
begin
if PParallelCipherJobData(Job)^.Encrypt then
begin
p := 0;
repeat
TSerpent.Encrypt(PSerpentkey(key)^, PSerpentBlock(nativeUInt(buff) + p)^);
p := p + PParallelCipherJobData(Job)^.BlockLen;
until p + PParallelCipherJobData(Job)^.BlockLen > Size;
end
else
begin
p := 0;
repeat
TSerpent.Decrypt(PSerpentkey(key)^, PSerpentBlock(nativeUInt(buff) + p)^);
p := p + PParallelCipherJobData(Job)^.BlockLen;
until p + PParallelCipherJobData(Job)^.BlockLen > Size;
end;
end;
procedure TParallelCipher.Mars_Parallel(Job, buff, key: Pointer; Size: NativeInt);
var
p: nativeUInt;
begin
if PParallelCipherJobData(Job)^.Encrypt then
begin
p := 0;
repeat
TMars.Encrypt(PMarskey(key)^, PMarsBlock(nativeUInt(buff) + p)^);
p := p + PParallelCipherJobData(Job)^.BlockLen;
until p + PParallelCipherJobData(Job)^.BlockLen > Size;
end
else
begin
p := 0;
repeat
TMars.Decrypt(PMarskey(key)^, PMarsBlock(nativeUInt(buff) + p)^);
p := p + PParallelCipherJobData(Job)^.BlockLen;
until p + PParallelCipherJobData(Job)^.BlockLen > Size;
end;
end;
procedure TParallelCipher.Rijndael_Parallel(Job, buff, key: Pointer; Size: NativeInt);
var
p: nativeUInt;
begin
if PParallelCipherJobData(Job)^.Encrypt then
begin
p := 0;
repeat
TRijndael.Encrypt(PRijndaelkey(key)^, PRijndaelBlock(nativeUInt(buff) + p)^);
p := p + PParallelCipherJobData(Job)^.BlockLen;
until p + PParallelCipherJobData(Job)^.BlockLen > Size;
end
else
begin
p := 0;
repeat
TRijndael.Decrypt(PRijndaelkey(key)^, PRijndaelBlock(nativeUInt(buff) + p)^);
p := p + PParallelCipherJobData(Job)^.BlockLen;
until p + PParallelCipherJobData(Job)^.BlockLen > Size;
end;
end;
procedure TParallelCipher.BlockCBC_Parallel(Job, buff, key: Pointer; Size: NativeInt);
begin
TCipher.BlockCBC(buff, Size, key, PParallelCipherJobData(Job)^.BlockLen);
end;
procedure TParallelCipher.ParallelCipherCall(const JobData: PParallelCipherJobData; const FromIndex, ToIndex: Integer);
var
newBuffPtr: Pointer;
newBuffSiz: nativeUInt;
begin
newBuffPtr := Pointer(nativeUInt(JobData^.OriginBuffer) + (FromIndex * JobData^.BlockLen));
newBuffSiz := (ToIndex - FromIndex) * JobData^.BlockLen;
try
JobData^.cipherFunc(JobData, newBuffPtr, JobData^.KeyBuffer, newBuffSiz);
except
end;
inc(JobData^.CompletedBlock, (ToIndex - FromIndex));
end;
procedure TParallelCipher.RunParallel(const JobData: PParallelCipherJobData; const Total, Depth: Integer);
var
StepTotal, stepW: Integer;
{$IFDEF FPC}
procedure Nested_ParallelFor(pass: Integer);
var
w: Integer;
begin
w := stepW * pass;
if w + stepW <= Total then
ParallelCipherCall(JobData, w, w + stepW)
else
ParallelCipherCall(JobData, w, Total);
end;
{$ENDIF FPC}
begin
if Total <= 0 then
Exit;
if (Depth <= 0) or (Total < Depth) then
begin
ParallelCipherCall(JobData, 0, Total);
Exit;
end;
stepW := Total div Depth;
StepTotal := Total div stepW;
if Total mod stepW > 0 then
inc(StepTotal);
{$IFDEF FPC}
FPCParallelFor(@Nested_ParallelFor, 0, StepTotal - 1);
{$ELSE FPC}
DelphiParallelFor(0, StepTotal - 1, procedure(pass: Integer)
var
w: Integer;
begin
w := stepW * pass;
if w + stepW <= Total then
ParallelCipherCall(JobData, w, w + stepW)
else
ParallelCipherCall(JobData, w, Total);
end);
{$ENDIF FPC}
end;
constructor TParallelCipher.Create;
begin
inherited Create;
BlockDepth := DefaultParallelDepth;
end;
destructor TParallelCipher.Destroy;
begin
inherited Destroy;
end;
function TParallelCipher.DES64(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
JobData: TParallelCipherJobData;
k: TKey64;
Context: TDESContext;
tailSiz: NativeInt;
begin
Result := False;
if Size <= 0 then
Exit;
if Size >= 8 then
begin
if not TCipher.GetKey(KeyBuff, k) then
Exit;
TDES.InitEncryptDES(k, Context, Encrypt);
JobData.cipherFunc := {$IFDEF FPC}@{$ENDIF FPC}DES64_Parallel;
JobData.KeyBuffer := @Context;
JobData.OriginBuffer := sour;
JobData.BlockLen := 8;
JobData.TotalBlock := Size div JobData.BlockLen;
JobData.CompletedBlock := 0;
JobData.Encrypt := Encrypt;
RunParallel(@JobData, JobData.TotalBlock, BlockDepth);
end;
if ProcessTail then
begin
tailSiz := Size mod JobData.BlockLen;
if tailSiz > 0 then
TCipher.EncryptTail(Pointer(nativeUInt(sour) + Size - tailSiz), tailSiz);
end;
Result := True;
end;
function TParallelCipher.DES128(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
JobData: TParallelCipherJobData;
k: TKey128;
Context: TTripleDESContext;
tailSiz: NativeInt;
begin
Result := False;
if Size <= 0 then
Exit;
if Size >= 8 then
begin
if not TCipher.GetKey(KeyBuff, k) then
Exit;
TDES.InitEncryptTripleDES(k, Context, Encrypt);
JobData.cipherFunc := {$IFDEF FPC}@{$ENDIF FPC}DES128_Parallel;
JobData.KeyBuffer := @Context;
JobData.OriginBuffer := sour;
JobData.BlockLen := 8;
JobData.TotalBlock := Size div JobData.BlockLen;
JobData.CompletedBlock := 0;
JobData.Encrypt := Encrypt;
RunParallel(@JobData, JobData.TotalBlock, BlockDepth);
end;
if ProcessTail then
begin
tailSiz := Size mod JobData.BlockLen;
if tailSiz > 0 then
TCipher.EncryptTail(Pointer(nativeUInt(sour) + Size - tailSiz), tailSiz);
end;
Result := True;
end;
function TParallelCipher.DES192(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
JobData: TParallelCipherJobData;
k1, k2, k3: TKey64;
Context: TTripleDESContext3Key;
tailSiz: NativeInt;
begin
Result := False;
if Size <= 0 then
Exit;
if Size >= 8 then
begin
if not TCipher.GetKey(KeyBuff, k1, k2, k3) then
Exit;
TDES.InitEncryptTripleDES3Key(k1, k2, k3, Context, Encrypt);
JobData.cipherFunc := {$IFDEF FPC}@{$ENDIF FPC}DES192_Parallel;
JobData.KeyBuffer := @Context;
JobData.OriginBuffer := sour;
JobData.BlockLen := 8;
JobData.TotalBlock := Size div JobData.BlockLen;
JobData.CompletedBlock := 0;
JobData.Encrypt := Encrypt;
RunParallel(@JobData, JobData.TotalBlock, BlockDepth);
end;
if ProcessTail then
begin
tailSiz := Size mod JobData.BlockLen;
if tailSiz > 0 then
TCipher.EncryptTail(Pointer(nativeUInt(sour) + Size - tailSiz), tailSiz);
end;
Result := True;
end;
function TParallelCipher.Blowfish(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
JobData: TParallelCipherJobData;
k: TKey128;
Context: TBFContext;
tailSiz: NativeInt;
begin
Result := False;
if Size <= 0 then
Exit;
if Size >= 8 then
begin
if not TCipher.GetKey(KeyBuff, k) then
Exit;
TBlowfish.InitEncryptBF(k, Context);
JobData.cipherFunc := {$IFDEF FPC}@{$ENDIF FPC}Blowfish_Parallel;
JobData.KeyBuffer := @Context;
JobData.OriginBuffer := sour;
JobData.BlockLen := 8;
JobData.TotalBlock := Size div JobData.BlockLen;
JobData.CompletedBlock := 0;
JobData.Encrypt := Encrypt;
RunParallel(@JobData, JobData.TotalBlock, BlockDepth);
end;
if ProcessTail then
begin
tailSiz := Size mod JobData.BlockLen;
if tailSiz > 0 then
TCipher.EncryptTail(Pointer(nativeUInt(sour) + Size - tailSiz), tailSiz);
end;
Result := True;
end;
function TParallelCipher.LBC(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
JobData: TParallelCipherJobData;
k: TKey128;
Context: TLBCContext;
tailSiz: NativeInt;
begin
Result := False;
if Size <= 0 then
Exit;
if Size >= 16 then
begin
if not TCipher.GetKey(KeyBuff, k) then
Exit;
TLBC.InitEncryptLBC(k, Context, 16, Encrypt);
JobData.cipherFunc := {$IFDEF FPC}@{$ENDIF FPC}LBC_Parallel;
JobData.KeyBuffer := @Context;
JobData.OriginBuffer := sour;
JobData.BlockLen := 16;
JobData.TotalBlock := Size div JobData.BlockLen;
JobData.CompletedBlock := 0;
JobData.Encrypt := Encrypt;
RunParallel(@JobData, JobData.TotalBlock, BlockDepth);
end;
if ProcessTail then
begin
tailSiz := Size mod JobData.BlockLen;
if tailSiz > 0 then
TCipher.EncryptTail(Pointer(nativeUInt(sour) + Size - tailSiz), tailSiz);
end;
Result := True;
end;
function TParallelCipher.LQC(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
JobData: TParallelCipherJobData;
k: TKey128;
tailSiz: NativeInt;
begin
Result := False;
if Size <= 0 then
Exit;
if Size >= 8 then
begin
if not TCipher.GetKey(KeyBuff, k) then
Exit;
JobData.cipherFunc := {$IFDEF FPC}@{$ENDIF FPC}LQC_Parallel;
JobData.KeyBuffer := @k;
JobData.OriginBuffer := sour;
JobData.BlockLen := 8;
JobData.TotalBlock := Size div JobData.BlockLen;
JobData.CompletedBlock := 0;
JobData.Encrypt := Encrypt;
RunParallel(@JobData, JobData.TotalBlock, BlockDepth);
end;
if ProcessTail then
begin
tailSiz := Size mod JobData.BlockLen;
if tailSiz > 0 then
TCipher.EncryptTail(Pointer(nativeUInt(sour) + Size - tailSiz), tailSiz);
end;
Result := True;
end;
function TParallelCipher.TwoFish(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
JobData: TParallelCipherJobData;
k, k256: TBytes;
Context: TTwofishKey;
tailSiz: NativeInt;
begin
Result := False;
if Size <= 0 then
Exit;
if Size >= 16 then
begin
if not TCipher.GetKey(KeyBuff, k) then
Exit;
SetLength(k256, 32);
THashMD.GenerateLMDKey((@k256[0])^, 32, k);
TTwofish.InitKey(@k256[0], 32, Context);
JobData.cipherFunc := {$IFDEF FPC}@{$ENDIF FPC}TwoFish_Parallel;
JobData.KeyBuffer := @Context;
JobData.OriginBuffer := sour;
JobData.BlockLen := 16;
JobData.TotalBlock := Size div JobData.BlockLen;
JobData.CompletedBlock := 0;
JobData.Encrypt := Encrypt;
RunParallel(@JobData, JobData.TotalBlock, BlockDepth);
end;
if ProcessTail then
begin
tailSiz := Size mod JobData.BlockLen;
if tailSiz > 0 then
TCipher.EncryptTail(Pointer(nativeUInt(sour) + Size - tailSiz), tailSiz);
end;
Result := True;
end;
function TParallelCipher.XXTea512(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
JobData: TParallelCipherJobData;
k: TKey128;
tailSiz: NativeInt;
begin
Result := False;
if Size <= 0 then
Exit;
if Size >= 64 then
begin
if not TCipher.GetKey(KeyBuff, k) then
Exit;
JobData.cipherFunc := {$IFDEF FPC}@{$ENDIF FPC}XXTea512_Parallel;
JobData.KeyBuffer := @k;
JobData.OriginBuffer := sour;
JobData.BlockLen := 64;
JobData.TotalBlock := Size div JobData.BlockLen;
JobData.CompletedBlock := 0;
JobData.Encrypt := Encrypt;
RunParallel(@JobData, JobData.TotalBlock, BlockDepth);
end;
if ProcessTail then
begin
tailSiz := Size mod JobData.BlockLen;
if tailSiz > 0 then
TCipher.EncryptTail(Pointer(nativeUInt(sour) + Size - tailSiz), tailSiz);
end;
Result := True;
end;
function TParallelCipher.RC6(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
JobData: TParallelCipherJobData;
k, k256: TBytes;
Context: TRC6Key;
tailSiz: NativeInt;
begin
Result := False;
if Size <= 0 then
Exit;
if Size >= 16 then
begin
if not TCipher.GetKey(KeyBuff, k) then
Exit;
SetLength(k256, 32);
THashMD.GenerateLMDKey((@k256[0])^, 32, k);
TRC6.InitKey(@k256[0], 32, Context);
JobData.cipherFunc := {$IFDEF FPC}@{$ENDIF FPC}RC6_Parallel;
JobData.KeyBuffer := @Context;
JobData.OriginBuffer := sour;
JobData.BlockLen := 16;
JobData.TotalBlock := Size div JobData.BlockLen;
JobData.CompletedBlock := 0;
JobData.Encrypt := Encrypt;
RunParallel(@JobData, JobData.TotalBlock, BlockDepth);
end;
if ProcessTail then
begin
tailSiz := Size mod JobData.BlockLen;
if tailSiz > 0 then
TCipher.EncryptTail(Pointer(nativeUInt(sour) + Size - tailSiz), tailSiz);
end;
Result := True;
end;
function TParallelCipher.Serpent(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
JobData: TParallelCipherJobData;
k, k256: TBytes;
Context: TSerpentkey;
tailSiz: NativeInt;
begin
Result := False;
if Size <= 0 then
Exit;
if Size >= 16 then
begin
if not TCipher.GetKey(KeyBuff, k) then
Exit;
SetLength(k256, 32);
THashMD.GenerateLMDKey((@k256[0])^, 32, k);
TSerpent.InitKey(@k256[0], 32, Context);
JobData.cipherFunc := {$IFDEF FPC}@{$ENDIF FPC}Serpent_Parallel;
JobData.KeyBuffer := @Context;
JobData.OriginBuffer := sour;
JobData.BlockLen := 16;
JobData.TotalBlock := Size div JobData.BlockLen;
JobData.CompletedBlock := 0;
JobData.Encrypt := Encrypt;
RunParallel(@JobData, JobData.TotalBlock, BlockDepth);
end;
if ProcessTail then
begin
tailSiz := Size mod JobData.BlockLen;
if tailSiz > 0 then
TCipher.EncryptTail(Pointer(nativeUInt(sour) + Size - tailSiz), tailSiz);
end;
Result := True;
end;
function TParallelCipher.Mars(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
JobData: TParallelCipherJobData;
k, k256: TBytes;
Context: TMarskey;
tailSiz: NativeInt;
begin
Result := False;
if Size <= 0 then
Exit;
if Size >= 16 then
begin
if not TCipher.GetKey(KeyBuff, k) then
Exit;
SetLength(k256, 32);
THashMD.GenerateLMDKey((@k256[0])^, 32, k);
TMars.InitKey(@k256[0], 32, Context);
JobData.cipherFunc := {$IFDEF FPC}@{$ENDIF FPC}Mars_Parallel;
JobData.KeyBuffer := @Context;
JobData.OriginBuffer := sour;
JobData.BlockLen := 16;
JobData.TotalBlock := Size div JobData.BlockLen;
JobData.CompletedBlock := 0;
JobData.Encrypt := Encrypt;
RunParallel(@JobData, JobData.TotalBlock, BlockDepth);
end;
if ProcessTail then
begin
tailSiz := Size mod JobData.BlockLen;
if tailSiz > 0 then
TCipher.EncryptTail(Pointer(nativeUInt(sour) + Size - tailSiz), tailSiz);
end;
Result := True;
end;
function TParallelCipher.Rijndael(sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
JobData: TParallelCipherJobData;
k, k256: TBytes;
Context: TRijndaelkey;
tailSiz: NativeInt;
begin
Result := False;
if Size <= 0 then
Exit;
if Size >= 16 then
begin
if not TCipher.GetKey(KeyBuff, k) then
Exit;
SetLength(k256, 32);
THashMD.GenerateLMDKey((@k256[0])^, 32, k);
TRijndael.InitKey(@k256[0], 32, Context);
JobData.cipherFunc := {$IFDEF FPC}@{$ENDIF FPC}Rijndael_Parallel;
JobData.KeyBuffer := @Context;
JobData.OriginBuffer := sour;
JobData.BlockLen := 16;
JobData.TotalBlock := Size div JobData.BlockLen;
JobData.CompletedBlock := 0;
JobData.Encrypt := Encrypt;
RunParallel(@JobData, JobData.TotalBlock, BlockDepth);
end;
if ProcessTail then
begin
tailSiz := Size mod JobData.BlockLen;
if tailSiz > 0 then
TCipher.EncryptTail(Pointer(nativeUInt(sour) + Size - tailSiz), tailSiz);
end;
Result := True;
end;
procedure TParallelCipher.BlockCBC(sour: Pointer; Size: NativeInt; boxBuff: Pointer; boxSiz: NativeInt);
var
JobData: TParallelCipherJobData;
tailSiz: NativeInt;
begin
if Size <= 0 then
Exit;
if boxSiz <= 0 then
Exit;
if boxSiz >= Size then
begin
TCipher.BlockCBC(sour, Size, boxBuff, boxSiz);
Exit;
end;
JobData.cipherFunc := {$IFDEF FPC}@{$ENDIF FPC}BlockCBC_Parallel;
JobData.KeyBuffer := boxBuff;
JobData.OriginBuffer := sour;
JobData.BlockLen := boxSiz;
JobData.TotalBlock := Size div JobData.BlockLen;
JobData.CompletedBlock := 0;
JobData.Encrypt := True;
RunParallel(@JobData, JobData.TotalBlock, BlockDepth);
tailSiz := Size mod JobData.BlockLen;
if tailSiz > 0 then
TCipher.BlockCBC(Pointer(nativeUInt(sour) + Size - tailSiz), tailSiz, boxBuff, boxSiz);
end;
function TParallelCipher.EncryptBuffer(cs: TCipherSecurity; sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
begin
Result := False;
case cs of
csNone: Result := True;
csDES64: Result := DES64(sour, Size, KeyBuff, Encrypt, ProcessTail);
csDES128: Result := DES128(sour, Size, KeyBuff, Encrypt, ProcessTail);
csDES192: Result := DES192(sour, Size, KeyBuff, Encrypt, ProcessTail);
csBlowfish: Result := Blowfish(sour, Size, KeyBuff, Encrypt, ProcessTail);
csLBC: Result := LBC(sour, Size, KeyBuff, Encrypt, ProcessTail);
csLQC: Result := LQC(sour, Size, KeyBuff, Encrypt, ProcessTail);
csRNG32: Result := TCipher.RNG32(sour, Size, KeyBuff);
csRNG64: Result := TCipher.RNG64(sour, Size, KeyBuff);
csLSC: Result := TCipher.LSC(sour, Size, KeyBuff);
csTwoFish: Result := TwoFish(sour, Size, KeyBuff, Encrypt, ProcessTail);
csXXTea512: Result := XXTea512(sour, Size, KeyBuff, Encrypt, ProcessTail);
csRC6: Result := RC6(sour, Size, KeyBuff, Encrypt, ProcessTail);
csSerpent: Result := Serpent(sour, Size, KeyBuff, Encrypt, ProcessTail);
csMars: Result := Mars(sour, Size, KeyBuff, Encrypt, ProcessTail);
csRijndael: Result := Rijndael(sour, Size, KeyBuff, Encrypt, ProcessTail);
end;
end;
function TParallelCipher.EncryptBufferCBC(cs: TCipherSecurity; sour: Pointer; Size: NativeInt; KeyBuff: PCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
begin
if cs = TCipherSecurity.csNone then
begin
Result := True;
Exit;
end;
if Encrypt then
begin
Result := EncryptBuffer(cs, sour, Size, KeyBuff, Encrypt, ProcessTail);
if Result then
BlockCBC(sour, Size, @SystemCBC[0], length(SystemCBC));
end
else
begin
BlockCBC(sour, Size, @SystemCBC[0], length(SystemCBC));
Result := EncryptBuffer(cs, sour, Size, KeyBuff, Encrypt, ProcessTail);
end;
end;
{$ENDIF}
procedure InitSysCBCAndDefaultKey(rand: Int64);
var
i: Integer;
Seed: TInt64;
begin
{$IFDEF Parallel}
{ system default Parallel depth }
DefaultParallelDepth := CPUCount * 2;
ParallelTriggerCondition := 1024;
{$ENDIF}
SetLength(SystemCBC, 64 * 1024);
Seed.i := rand;
for i := 0 to (length(SystemCBC) div 4) - 1 do
PInteger(@SystemCBC[i * 4])^ := TMISC.Random64(Seed);
end;
function SequEncryptWithDirect(const cs: TCipherSecurity; sour: Pointer; Size: NativeInt; const key: TCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
k: TCipherKeyBuffer;
begin
TCipher.GenerateKey(cs, @key[0], length(key), k);
Result := TCipher.EncryptBuffer(cs, sour, Size, @k, Encrypt, ProcessTail);
end;
function SequEncryptWithDirect(const ca: TCipherSecurityArray; sour: Pointer; Size: NativeInt; const key: TCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
i: Integer;
begin
Result := True;
if Encrypt then
begin
for i := low(ca) to high(ca) do
Result := Result and SequEncryptWithDirect(ca[i], sour, Size, key, Encrypt, ProcessTail);
end
else
begin
for i := high(ca) downto low(ca) do
Result := Result and SequEncryptWithDirect(ca[i], sour, Size, key, Encrypt, ProcessTail);
end;
end;
{$IFDEF Parallel}
function SequEncryptWithParallel(const cs: TCipherSecurity; sour: Pointer; Size: NativeInt; const key: TCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
k: TCipherKeyBuffer;
Parallel: TParallelCipher;
begin
TCipher.GenerateKey(cs, @key[0], length(key), k);
Parallel := TParallelCipher.Create;
Parallel.BlockDepth := DefaultParallelDepth;
Result := Parallel.EncryptBuffer(cs, sour, Size, @k, Encrypt, ProcessTail);
DisposeObject(Parallel);
end;
function SequEncryptWithParallel(const ca: TCipherSecurityArray; sour: Pointer; Size: NativeInt; const key: TCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
i: Integer;
begin
Result := True;
if Encrypt then
begin
for i := low(ca) to high(ca) do
Result := Result and SequEncryptWithParallel(ca[i], sour, Size, key, Encrypt, ProcessTail);
end
else
begin
for i := high(ca) downto low(ca) do
Result := Result and SequEncryptWithParallel(ca[i], sour, Size, key, Encrypt, ProcessTail);
end;
end;
{$ENDIF}
function SequEncrypt(const ca: TCipherSecurityArray; sour: Pointer; Size: NativeInt; const key: TCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
begin
{$IFDEF Parallel}
if Size >= ParallelTriggerCondition then
Result := SequEncryptWithParallel(ca, sour, Size, key, Encrypt, ProcessTail)
else
{$ENDIF}
Result := SequEncryptWithDirect(ca, sour, Size, key, Encrypt, ProcessTail);
end;
function SequEncrypt(const cs: TCipherSecurity; sour: Pointer; Size: NativeInt; const key: TCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
begin
{$IFDEF Parallel}
if Size >= ParallelTriggerCondition then
Result := SequEncryptWithParallel(cs, sour, Size, key, Encrypt, ProcessTail)
else
{$ENDIF}
Result := SequEncryptWithDirect(cs, sour, Size, key, Encrypt, ProcessTail);
end;
function SequEncryptCBCWithDirect(const cs: TCipherSecurity; sour: Pointer; Size: NativeInt; const key: TCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
k: TCipherKeyBuffer;
begin
TCipher.GenerateKey(cs, @key[0], length(key), k);
Result := TCipher.EncryptBufferCBC(cs, sour, Size, @k, Encrypt, ProcessTail);
end;
function SequEncryptCBCWithDirect(const ca: TCipherSecurityArray; sour: Pointer; Size: NativeInt; const key: TCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
i: Integer;
begin
Result := True;
if Encrypt then
begin
for i := low(ca) to high(ca) do
Result := Result and SequEncryptCBCWithDirect(ca[i], sour, Size, key, Encrypt, ProcessTail);
end
else
begin
for i := high(ca) downto low(ca) do
Result := Result and SequEncryptCBCWithDirect(ca[i], sour, Size, key, Encrypt, ProcessTail);
end;
end;
{$IFDEF Parallel}
function SequEncryptCBCWithParallel(const cs: TCipherSecurity; sour: Pointer; Size: NativeInt; const key: TCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
k: TCipherKeyBuffer;
Parallel: TParallelCipher;
begin
TCipher.GenerateKey(cs, @key[0], length(key), k);
Parallel := TParallelCipher.Create;
Parallel.BlockDepth := DefaultParallelDepth;
Result := Parallel.EncryptBufferCBC(cs, sour, Size, @k, Encrypt, ProcessTail);
DisposeObject(Parallel);
end;
function SequEncryptCBCWithParallel(const ca: TCipherSecurityArray; sour: Pointer; Size: NativeInt; const key: TCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
var
i: Integer;
begin
Result := True;
if Encrypt then
begin
for i := low(ca) to high(ca) do
Result := Result and SequEncryptCBCWithParallel(ca[i], sour, Size, key, Encrypt, ProcessTail);
end
else
begin
for i := high(ca) downto low(ca) do
Result := Result and SequEncryptCBCWithParallel(ca[i], sour, Size, key, Encrypt, ProcessTail);
end;
end;
{$ENDIF}
function SequEncryptCBC(const ca: TCipherSecurityArray; sour: Pointer; Size: NativeInt; const key: TCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
begin
{$IFDEF Parallel}
if Size >= ParallelTriggerCondition then
Result := SequEncryptCBCWithParallel(ca, sour, Size, key, Encrypt, ProcessTail)
else
{$ENDIF}
Result := SequEncryptCBCWithDirect(ca, sour, Size, key, Encrypt, ProcessTail);
end;
function SequEncryptCBC(const cs: TCipherSecurity; sour: Pointer; Size: NativeInt; const key: TCipherKeyBuffer; Encrypt, ProcessTail: Boolean): Boolean;
begin
{$IFDEF Parallel}
if Size >= ParallelTriggerCondition then
Result := SequEncryptCBCWithParallel(cs, sour, Size, key, Encrypt, ProcessTail)
else
{$ENDIF}
Result := SequEncryptCBCWithDirect(cs, sour, Size, key, Encrypt, ProcessTail);
end;
function GenerateSequHash(hssArry: THashSecuritys; sour: Pointer; Size: NativeInt): TPascalString;
var
h: THashSecurity;
vl: THashStringList;
hBuff: TBytes;
n: SystemString;
begin
vl := THashStringList.Create;
for h in hssArry do
begin
TCipher.GenerateHashByte(h, sour, Size, hBuff);
n := '';
TCipher.HashToString(hBuff, n);
vl[TCipher.CHashName[h]] := '(' + n + ')';
end;
Result.Text := vl.AsText;
DisposeObject([vl]);
end;
procedure GenerateSequHash(hssArry: THashSecuritys; sour: Pointer; Size: NativeInt; output: TListPascalString);
var
h: THashSecurity;
vl: THashStringList;
hBuff: TBytes;
n: SystemString;
begin
vl := THashStringList.Create;
for h in hssArry do
begin
TCipher.GenerateHashByte(h, sour, Size, hBuff);
n := '';
TCipher.HashToString(hBuff, n);
vl[TCipher.CHashName[h]] := '(' + n + ')';
end;
vl.ExportAsStrings(output);
DisposeObject([vl]);
end;
procedure GenerateSequHash(hssArry: THashSecuritys; sour: Pointer; Size: NativeInt; output: TCoreClassStream);
var
h: THashSecurity;
vl: THashStringList;
hBuff: TBytes;
n: SystemString;
begin
vl := THashStringList.Create;
for h in hssArry do
begin
TCipher.GenerateHashByte(h, sour, Size, hBuff);
n := '';
TCipher.HashToString(hBuff, n);
vl[TCipher.CHashName[h]] := '(' + n + ')';
end;
vl.SaveToStream(output);
DisposeObject([vl]);
end;
function CompareSequHash(HashVL: THashStringList; sour: Pointer; Size: NativeInt): Boolean;
var
ns: TListString;
i: Integer;
sourHash, destHash: TBytes;
hName: SystemString;
hValue: TPascalString;
h: THashSecurity;
begin
Result := True;
ns := TListString.Create;
HashVL.GetNameList(ns);
for i := 0 to ns.Count - 1 do
begin
hName := ns[i];
hValue := umlTrimSpace(HashVL.GetDefaultValue(hName, ''));
if TCipher.NameToHashSecurity(hName, h) and ((hValue.Len >= 2) and (hValue.First = '(') and (hValue.Last = ')')) then
begin
hValue.DeleteFirst;
hValue.DeleteLast;
TCipher.GenerateHashByte(h, sour, Size, sourHash);
SetLength(destHash, length(sourHash));
if length(destHash) > 0 then
begin
Result := Result and TCipher.HexToBuffer(hValue, destHash[0], length(destHash));
Result := Result and TCipher.CompareHash(sourHash, destHash);
end;
end;
if not Result then
Break;
end;
DisposeObject([ns]);
end;
function CompareSequHash(hashData: TPascalString; sour: Pointer; Size: NativeInt): Boolean;
var
vl: THashStringList;
begin
vl := THashStringList.Create;
vl.AsText := hashData.Text;
Result := CompareSequHash(vl, sour, Size);
DisposeObject(vl);
end;
function CompareSequHash(hashData: TListPascalString; sour: Pointer; Size: NativeInt): Boolean;
var
vl: THashStringList;
begin
vl := THashStringList.Create;
vl.ImportFromStrings(hashData);
Result := CompareSequHash(vl, sour, Size);
DisposeObject(vl);
end;
function CompareSequHash(hashData: TCoreClassStream; sour: Pointer; Size: NativeInt): Boolean;
var
vl: THashStringList;
begin
vl := THashStringList.Create;
vl.LoadFromStream(hashData);
Result := CompareSequHash(vl, sour, Size);
DisposeObject(vl);
end;
function GenerateMemoryHash(hssArry: THashSecuritys; sour: Pointer; Size: NativeInt): TPascalString;
var
m64: TMemoryStream64;
begin
m64 := TMemoryStream64.Create;
GenerateSequHash(hssArry, sour, Size, m64);
umlEncodeStreamBASE64(m64, Result);
DisposeObject(m64);
Result := '(' + Result + ')';
end;
function CompareMemoryHash(sour: Pointer; Size: NativeInt; const hashBuff: TPascalString): Boolean;
var
n: TPascalString;
m64: TMemoryStream64;
begin
Result := False;
n := hashBuff.TrimChar(#32);
if (n.Len > 2) and (n.First = '(') and (n.Last = ')') then
begin
n.DeleteFirst;
n.DeleteLast;
m64 := TMemoryStream64.Create;
umlDecodeStreamBASE64(n, m64);
Result := CompareSequHash(m64, sour, Size);
DisposeObject(m64);
end;
end;
function GeneratePasswordHash(hssArry: THashSecuritys; const passwd: TPascalString): TPascalString;
var
buff: TBytes;
m64: TMemoryStream64;
begin
buff := passwd.Bytes;
m64 := TMemoryStream64.Create;
GenerateSequHash(hssArry, @buff[0], length(buff), m64);
umlEncodeStreamBASE64(m64, Result);
DisposeObject(m64);
Result := '(' + Result + ')';
SetLength(buff, 0);
end;
function ComparePasswordHash(const passwd, hashBuff: TPascalString): Boolean;
var
n: TPascalString;
buff: TBytes;
m64: TMemoryStream64;
begin
Result := False;
n := hashBuff.TrimChar(#32);
if (n.Len > 2) and (n.First = '(') and (n.Last = ')') then
begin
n.DeleteFirst;
n.DeleteLast;
buff := passwd.Bytes;
m64 := TMemoryStream64.Create;
umlDecodeStreamBASE64(n, m64);
Result := CompareSequHash(m64, @buff[0], length(buff));
DisposeObject(m64);
SetLength(buff, 0);
end;
end;
function GeneratePassword(const ca: TCipherSecurityArray; const passwd: TPascalString): TPascalString;
var
KeyBuff: TBytes;
buff: TBytes;
begin
KeyBuff := passwd.Bytes;
buff := passwd.Bytes;
SequEncryptCBC(ca, @buff[0], length(buff), KeyBuff, True, False);
umlBase64EncodeBytes(buff, Result);
Result := '(' + Result + ')';
SetLength(buff, 0);
SetLength(KeyBuff, 0);
end;
function ComparePassword(const ca: TCipherSecurityArray; const passwd, passwdDataSource: TPascalString): Boolean;
var
sour: TPascalString;
refBuff: TBytes;
KeyBuff: TBytes;
begin
Result := False;
sour := umlTrimSpace(passwdDataSource);
if (sour.Len > 2) and (sour.First = '(') and (sour.Last = ')') then
begin
sour.DeleteFirst;
sour.DeleteLast;
umlBase64DecodeBytes(sour, refBuff);
KeyBuff := passwd.Bytes;
SequEncryptCBC(ca, @refBuff[0], length(refBuff), KeyBuff, False, False);
Result := TCipher.CompareKey(refBuff, KeyBuff);
SetLength(refBuff, 0);
SetLength(KeyBuff, 0);
end;
end;
function GeneratePassword(const cs: TCipherSecurity; const passwd: TPascalString): TPascalString; overload;
var
KeyBuff: TBytes;
buff: TBytes;
begin
KeyBuff := passwd.Bytes;
buff := passwd.Bytes;
SequEncryptCBC(cs, @buff[0], length(buff), KeyBuff, True, False);
umlBase64EncodeBytes(buff, Result);
Result := '(' + Result + ')';
SetLength(buff, 0);
SetLength(KeyBuff, 0);
end;
function ComparePassword(const cs: TCipherSecurity; const passwd, passwdDataSource: TPascalString): Boolean; overload;
var
sour: TPascalString;
refBuff: TBytes;
KeyBuff: TBytes;
begin
Result := False;
sour := umlTrimSpace(passwdDataSource);
if (sour.Len > 2) and (sour.First = '(') and (sour.Last = ')') then
begin
sour.DeleteFirst;
sour.DeleteLast;
umlBase64DecodeBytes(sour, refBuff);
KeyBuff := passwd.Bytes;
SequEncryptCBC(cs, @refBuff[0], length(refBuff), KeyBuff, False, False);
Result := TCipher.CompareKey(refBuff, KeyBuff);
SetLength(refBuff, 0);
SetLength(KeyBuff, 0);
end;
end;
function GenerateQuantumCryptographyPassword(const passwd: TPascalString): TPascalString;
var
buff, cryptBuff: TBytes;
begin
buff := passwd.Bytes;
SetLength(cryptBuff, 512 div 8);
TSHA3.SHAKE256(@cryptBuff[0], @buff[0], length(buff), 512);
umlBase64EncodeBytes(cryptBuff, Result);
Result := '(' + Result + ')';
SetLength(buff, 0);
SetLength(cryptBuff, 0);
end;
function CompareQuantumCryptographyPassword(const passwd, passwdDataSource: TPascalString): Boolean;
var
sour: TPascalString;
refBuff, buff, cryptBuff: TBytes;
begin
Result := False;
sour := umlTrimSpace(passwdDataSource);
if (sour.Len > 2) and (sour.First = '(') and (sour.Last = ')') then
begin
sour.DeleteFirst;
sour.DeleteLast;
umlBase64DecodeBytes(sour, refBuff);
buff := passwd.Bytes;
SetLength(cryptBuff, 512 div 8);
TSHA3.SHAKE256(@cryptBuff[0], @buff[0], length(buff), 512);
Result := TCipher.CompareKey(refBuff, cryptBuff);
SetLength(refBuff, 0);
SetLength(buff, 0);
SetLength(cryptBuff, 0);
end;
end;
type
TQuantumEncryptHead = packed record
CipherSecurity: Byte;
Level: Word;
Size: Int64;
hash: TSHA3_512_Digest;
end;
procedure QuantumEncrypt(input, output: TCoreClassStream; SecurityLevel: Integer; key: TCipherKeyBuffer);
var
m64: TMemoryStream64;
head: TQuantumEncryptHead;
i: Integer;
hh: TSHA3_512_Digest;
begin
m64 := TMemoryStream64.Create;
input.Position := 0;
m64.CopyFrom(input, input.Size);
head.CipherSecurity := Byte(TCipherSecurity.csRijndael);
head.Level := SecurityLevel;
head.Size := m64.Size;
// 2x-sha3-512 Secure Hash
TSHA3.SHA512(hh, m64.Memory, head.Size);
TSHA3.SHA512(head.hash, @hh[0], 64);
// infinition encrypt
for i := 0 to head.Level - 1 do
SequEncryptCBC(TCipherSecurity(head.CipherSecurity), m64.Memory, m64.Size, key, True, True);
output.write(head, SizeOf(head));
output.write(m64.Memory^, m64.Size);
DisposeObject(m64);
end;
function QuantumDecrypt(input, output: TCoreClassStream; key: TCipherKeyBuffer): Boolean;
var
head: TQuantumEncryptHead;
m64: TMemoryStream64;
i: Integer;
hh, h: TSHA3_512_Digest;
begin
Result := False;
input.read(head, SizeOf(head));
m64 := TMemoryStream64.Create;
if m64.CopyFrom(input, head.Size) <> head.Size then
begin
DisposeObject(m64);
Exit;
end;
// infinition encrypt
for i := 0 to head.Level - 1 do
SequEncryptCBC(TCipherSecurity(head.CipherSecurity), m64.Memory, m64.Size, key, False, True);
// 2x-sha3-512 Secure Hash
TSHA3.SHA512(hh, m64.Memory, m64.Size);
TSHA3.SHA512(h, @hh[0], 64);
// compare
if not TCipher.CompareHash(h, head.hash) then
begin
DisposeObject(m64);
Exit;
end;
m64.Position := 0;
output.CopyFrom(m64, m64.Size);
DisposeObject(m64);
Result := True;
end;
procedure TestCoreCipher;
var
Buffer: TBytes;
sour, Dest: TMemoryStream64;
k: TCipherKeyBuffer;
cs: TCipherSecurity;
sourHash: TSHA1Digest;
d: TTimeTick;
hs: THashSecurity;
hByte: TBytes;
{$IFDEF Parallel}
Parallel: TParallelCipher;
{$ENDIF}
ps: TListPascalString;
s: TPascalString;
begin
sour := TMemoryStream64.Create;
sour.Size := Int64(10 * 1024 * 1024 + 9);
FillPtrByte(sour.Memory, sour.Size, $7F);
DoStatus('stream mode md5 :' + umlStreamMD5String(sour).Text);
DoStatus('pointer mode md5:' + umlMD5String(sour.Memory, sour.Size).Text);
DisposeObject(sour);
DoStatus('Generate and verify QuantumCryptographyPassword test');
s := GenerateQuantumCryptographyPassword('123456');
if not CompareQuantumCryptographyPassword('123456', s) then
DoStatus('QuantumCryptographyPassword failed!');
if CompareQuantumCryptographyPassword('1234560', s) then
DoStatus('QuantumCryptographyPassword failed!');
DoStatus('Generate and verify password test');
DoStatus('verify short password');
s := GeneratePasswordHash(TCipher.CAllHash, '1');
if not ComparePasswordHash('1', s) then
DoStatus('PasswordHash failed!');
if ComparePasswordHash('11', s) then
DoStatus('PasswordHash failed!');
DoStatus('verify long password');
s := GeneratePasswordHash(TCipher.CAllHash, 'hello world 123456');
if not ComparePasswordHash('hello world 123456', s) then
DoStatus('PasswordHash failed!');
if ComparePasswordHash('111 hello world 123456', s) then
DoStatus('PasswordHash failed!');
DoStatus('verify full chiher style password');
s := GeneratePassword(TCipher.AllCipher, 'hello world');
if not ComparePassword(TCipher.AllCipher, 'hello world', s) then
DoStatus('Password cipher test failed! cipher: %s', ['']);
if ComparePassword(TCipher.AllCipher, 'hello_world', s) then
DoStatus('Password cipher test failed! cipher: %s', ['']);
for cs in TCipher.AllCipher do
begin
DoStatus('verify %s chiher style password', [GetEnumName(TypeInfo(TCipherSecurity), Integer(cs))]);
s := GeneratePassword(TCipher.AllCipher, 'hello world');
if not ComparePassword(TCipher.AllCipher, 'hello world', s) then
DoStatus('Password cipher test failed! cipher: %s', [GetEnumName(TypeInfo(TCipherSecurity), Integer(cs))]);
if ComparePassword(TCipher.AllCipher, 'hello_world', s) then
DoStatus('Password cipher test failed! cipher: %s', [GetEnumName(TypeInfo(TCipherSecurity), Integer(cs))]);
end;
// hash and Sequence Encrypt
SetLength(Buffer, 128 * 1024);
FillPtrByte(@Buffer[0], length(Buffer), 99);
ps := TListPascalString.Create;
DoStatus('Generate Sequence Hash');
GenerateSequHash(TCipher.CAllHash, @Buffer[0], length(Buffer), ps);
// DoStatus(ps.Text);
if not CompareSequHash(ps, @Buffer[0], length(Buffer)) then
DoStatus('hash compare failed!');
DoStatus('test Sequence Encrypt');
k := TPascalString('hello world').Bytes;
if not SequEncryptWithDirect(TCipher.AllCipher, @Buffer[0], length(Buffer), k, True, True) then
DoStatus('SequEncrypt failed!');
if not SequEncryptWithDirect(TCipher.AllCipher, @Buffer[0], length(Buffer), k, False, True) then
DoStatus('SequEncrypt failed!');
DoStatus('verify Sequence Encrypt');
if not CompareSequHash(ps, @Buffer[0], length(Buffer)) then
DoStatus('hash compare failed!');
// cipher Encrypt performance
SetLength(Buffer, 1024 * 1024 * 1 + 99);
FillPtrByte(@Buffer[0], length(Buffer), $7F);
sour := TMemoryStream64.Create;
Dest := TMemoryStream64.Create;
sour.write(Buffer[0], high(Buffer));
Dest.Clear;
sour.Position := 0;
Dest.CopyFrom(sour, sour.Size);
sour.Position := 0;
Dest.Position := 0;
sourHash := TCipher.GenerateSHA1Hash(sour.Memory, sour.Size);
{$IFDEF Parallel}
DoStatus(#13#10'Parallel cipher performance test');
for cs in TCipher.AllCipher do
begin
TCipher.GenerateKey(cs, 'hello world', k);
Parallel := TParallelCipher.Create;
Dest.Clear;
sour.Position := 0;
Dest.CopyFrom(sour, sour.Size);
sour.Position := 0;
Dest.Position := 0;
d := GetTimeTick;
if not Parallel.EncryptBufferCBC(cs, Dest.Memory, Dest.Size, @k, True, True) then
DoStatus('%s: Parallel encode failed', [GetEnumName(TypeInfo(TCipherSecurity), Integer(cs))]);
if not Parallel.EncryptBufferCBC(cs, Dest.Memory, Dest.Size, @k, False, True) then
DoStatus('%s: Parallel decode failed', [GetEnumName(TypeInfo(TCipherSecurity), Integer(cs))]);
DoStatus('%s - Parallel performance:%dms', [GetEnumName(TypeInfo(TCipherSecurity), Integer(cs)), GetTimeTick - d]);
if not TCipher.CompareHash(TCipher.GenerateSHA1Hash(Dest.Memory, Dest.Size), sourHash) then
DoStatus('%s Parallel hash error!', [GetEnumName(TypeInfo(TCipherSecurity), Integer(cs))]);
DisposeObject(Parallel);
end;
for cs in TCipher.AllCipher do
begin
TCipher.GenerateKey(cs, 'hello world', k);
Parallel := TParallelCipher.Create;
Dest.Clear;
sour.Position := 0;
Dest.CopyFrom(sour, sour.Size);
sour.Position := 0;
Dest.Position := 0;
d := GetTimeTick;
if not TCipher.EncryptBufferCBC(cs, Dest.Memory, Dest.Size, @k, True, True) then
DoStatus('%s: normal 2 Parallel encode failed', [GetEnumName(TypeInfo(TCipherSecurity), Integer(cs))]);
if not Parallel.EncryptBufferCBC(cs, Dest.Memory, Dest.Size, @k, False, True) then
DoStatus('%s: normal 2 Parallel decode failed', [GetEnumName(TypeInfo(TCipherSecurity), Integer(cs))]);
DoStatus('%s - normal 2 Parallel performance:%dms', [GetEnumName(TypeInfo(TCipherSecurity), Integer(cs)), GetTimeTick - d]);
if not TCipher.CompareHash(TCipher.GenerateSHA1Hash(Dest.Memory, Dest.Size), sourHash) then
DoStatus('%s normal 2 Parallel hash error!', [GetEnumName(TypeInfo(TCipherSecurity), Integer(cs))]);
DisposeObject(Parallel);
end;
for cs in TCipher.AllCipher do
begin
TCipher.GenerateKey(cs, 'hello world', k);
Parallel := TParallelCipher.Create;
Dest.Clear;
sour.Position := 0;
Dest.CopyFrom(sour, sour.Size);
sour.Position := 0;
Dest.Position := 0;
d := GetTimeTick;
if not Parallel.EncryptBufferCBC(cs, Dest.Memory, Dest.Size, @k, True, True) then
DoStatus('%s: Parallel 2 normal encode failed', [GetEnumName(TypeInfo(TCipherSecurity), Integer(cs))]);
if not TCipher.EncryptBufferCBC(cs, Dest.Memory, Dest.Size, @k, False, True) then
DoStatus('%s: Parallel 2 normal decode failed', [GetEnumName(TypeInfo(TCipherSecurity), Integer(cs))]);
DoStatus('%s - Parallel 2 normal performance:%dms', [GetEnumName(TypeInfo(TCipherSecurity), Integer(cs)), GetTimeTick - d]);
if not TCipher.CompareHash(TCipher.GenerateSHA1Hash(Dest.Memory, Dest.Size), sourHash) then
DoStatus('%s Parallel 2 normal hash error!', [GetEnumName(TypeInfo(TCipherSecurity), Integer(cs))]);
DisposeObject(Parallel);
end;
{$ENDIF}
DoStatus(#13#10'normal cipher performance test');
for cs in TCipher.AllCipher do
begin
TCipher.GenerateKey(cs, 'hello world', k);
Dest.Clear;
sour.Position := 0;
Dest.CopyFrom(sour, sour.Size);
sour.Position := 0;
Dest.Position := 0;
d := GetTimeTick;
if not TCipher.EncryptBufferCBC(cs, Dest.Memory, Dest.Size, @k, True, True) then
DoStatus('%s: encode failed', [GetEnumName(TypeInfo(TCipherSecurity), Integer(cs))]);
if not TCipher.EncryptBufferCBC(cs, Dest.Memory, Dest.Size, @k, False, True) then
DoStatus('%s: decode failed', [GetEnumName(TypeInfo(TCipherSecurity), Integer(cs))]);
DoStatus('%s - normal performance:%dms', [GetEnumName(TypeInfo(TCipherSecurity), Integer(cs)), GetTimeTick - d]);
if not TCipher.CompareHash(TCipher.GenerateSHA1Hash(Dest.Memory, Dest.Size), sourHash) then
DoStatus('%s hash error!', [GetEnumName(TypeInfo(TCipherSecurity), Integer(cs))]);
end;
// hash performance
DoStatus(#13#10'hash performance test');
Dest.Clear;
sour.Position := 0;
Dest.CopyFrom(sour, sour.Size);
sour.Position := 0;
Dest.Position := 0;
for hs := low(THashSecurity) to high(THashSecurity) do
begin
d := GetTimeTick;
TCipher.GenerateHashByte(hs, Dest.Memory, Dest.Size, hByte);
DoStatus('%s - performance:%dms', [GetEnumName(TypeInfo(THashSecurity), Integer(hs)), (GetTimeTick - d)]);
end;
DoStatus(#13#10'Cipher test done!');
DisposeObject([ps, sour, Dest]);
end;
{ TBlowfish }
class procedure TBlowfish.EncryptBF(const Context: TBFContext; var Block: TBFBlock; Encrypt: Boolean);
var
i: Integer;
TmpBlock: TBFBlockEx; { !!.01 }
begin
CopyPtr(@Block, @TmpBlock, SizeOf(TmpBlock)); { !!.01 }
if Encrypt then begin
Block[0] := Block[0] xor Context.PBox[0];
{ 16 Rounds to go (8 double rounds to avoid swaps) }
i := 1;
repeat
{ first half round }
Block[1] := Block[1] xor Context.PBox[i] xor (((
Context.SBox[0, TmpBlock.Xl[3]] + Context.SBox[1, TmpBlock.Xl[2]])
xor Context.SBox[2, TmpBlock.Xl[1]]) + Context.SBox[3, TmpBlock.Xl[0]]);
{ second half round }
Block[0] := Block[0] xor Context.PBox[i + 1] xor (((
Context.SBox[0, TmpBlock.Xr[3]] + Context.SBox[1, TmpBlock.Xr[2]])
xor Context.SBox[2, TmpBlock.Xr[1]]) + Context.SBox[3, TmpBlock.Xr[0]]);
inc(i, 2);
until i > BFRounds;
Block[1] := Block[1] xor Context.PBox[(BFRounds + 1)];
end
else begin
Block[1] := Block[1] xor Context.PBox[(BFRounds + 1)];
{ 16 Rounds to go (8 double rounds to avoid swaps) }
i := BFRounds;
repeat
{ first half round }
Block[0] := Block[0] xor Context.PBox[i] xor (((
Context.SBox[0, TmpBlock.Xr[3]] + Context.SBox[1, TmpBlock.Xr[2]])
xor Context.SBox[2, TmpBlock.Xr[1]]) + Context.SBox[3, TmpBlock.Xr[0]]);
{ second half round }
Block[1] := Block[1] xor Context.PBox[i - 1] xor (((
Context.SBox[0, TmpBlock.Xl[3]] + Context.SBox[1, TmpBlock.Xl[2]])
xor Context.SBox[2, TmpBlock.Xl[1]]) + Context.SBox[3, TmpBlock.Xl[0]]);
dec(i, 2);
until i < 1;
Block[0] := Block[0] xor Context.PBox[0];
end;
end;
class procedure TBlowfish.InitEncryptBF(key: TKey128; var Context: TBFContext);
var
i: Integer;
j: Integer;
k: Integer;
Data: DWORD;
Block: TBFBlock;
begin
{ initialize PArray }
CopyPtr(@bf_P, @Context.PBox, SizeOf(Context.PBox));
{ initialize SBox }
CopyPtr(@bf_S, @Context.SBox, SizeOf(Context.SBox));
{ update PArray with the key bits }
j := 0;
for i := 0 to (BFRounds + 1) do begin
Data := 0;
for k := 0 to 3 do begin
Data := (Data shl 8) or key[j];
inc(j);
if j >= SizeOf(key) then
j := 0;
end;
Context.PBox[i] := Context.PBox[i] xor Data;
end;
{ encrypt an all-zero SystemString using the Blowfish algorithm and }
{ replace the elements of the P-array with the output of this process }
Block[0] := 0;
Block[1] := 0;
i := 0;
repeat
EncryptBF(Context, Block, True);
Context.PBox[i] := Block[0];
Context.PBox[i + 1] := Block[1];
inc(i, 2);
until i > BFRounds + 1;
{ continue the process, replacing the elements of the four S-boxes in }
{ order, with the output of the continuously changing Blowfish algorithm }
for j := 0 to 3 do begin
i := 0;
repeat
EncryptBF(Context, Block, True);
Context.SBox[j, i] := Block[0];
Context.SBox[j, i + 1] := Block[1];
inc(i, 2);
until i > 255;
end;
{ in total, 521 iterations are required to generate all required subkeys. }
end;
{ TDES }
class procedure TDES.EncryptDES(const Context: TDESContext; var Block: TDESBlock);
const
SPBox: array [0 .. 7, 0 .. 63] of DWORD =
(($01010400, $00000000, $00010000, $01010404, $01010004, $00010404, $00000004, $00010000,
$00000400, $01010400, $01010404, $00000400, $01000404, $01010004, $01000000, $00000004,
$00000404, $01000400, $01000400, $00010400, $00010400, $01010000, $01010000, $01000404,
$00010004, $01000004, $01000004, $00010004, $00000000, $00000404, $00010404, $01000000,
$00010000, $01010404, $00000004, $01010000, $01010400, $01000000, $01000000, $00000400,
$01010004, $00010000, $00010400, $01000004, $00000400, $00000004, $01000404, $00010404,
$01010404, $00010004, $01010000, $01000404, $01000004, $00000404, $00010404, $01010400,
$00000404, $01000400, $01000400, $00000000, $00010004, $00010400, $00000000, $01010004),
($80108020, $80008000, $00008000, $00108020, $00100000, $00000020, $80100020, $80008020,
$80000020, $80108020, $80108000, $80000000, $80008000, $00100000, $00000020, $80100020,
$00108000, $00100020, $80008020, $00000000, $80000000, $00008000, $00108020, $80100000,
$00100020, $80000020, $00000000, $00108000, $00008020, $80108000, $80100000, $00008020,
$00000000, $00108020, $80100020, $00100000, $80008020, $80100000, $80108000, $00008000,
$80100000, $80008000, $00000020, $80108020, $00108020, $00000020, $00008000, $80000000,
$00008020, $80108000, $00100000, $80000020, $00100020, $80008020, $80000020, $00100020,
$00108000, $00000000, $80008000, $00008020, $80000000, $80100020, $80108020, $00108000),
($00000208, $08020200, $00000000, $08020008, $08000200, $00000000, $00020208, $08000200,
$00020008, $08000008, $08000008, $00020000, $08020208, $00020008, $08020000, $00000208,
$08000000, $00000008, $08020200, $00000200, $00020200, $08020000, $08020008, $00020208,
$08000208, $00020200, $00020000, $08000208, $00000008, $08020208, $00000200, $08000000,
$08020200, $08000000, $00020008, $00000208, $00020000, $08020200, $08000200, $00000000,
$00000200, $00020008, $08020208, $08000200, $08000008, $00000200, $00000000, $08020008,
$08000208, $00020000, $08000000, $08020208, $00000008, $00020208, $00020200, $08000008,
$08020000, $08000208, $00000208, $08020000, $00020208, $00000008, $08020008, $00020200),
($00802001, $00002081, $00002081, $00000080, $00802080, $00800081, $00800001, $00002001,
$00000000, $00802000, $00802000, $00802081, $00000081, $00000000, $00800080, $00800001,
$00000001, $00002000, $00800000, $00802001, $00000080, $00800000, $00002001, $00002080,
$00800081, $00000001, $00002080, $00800080, $00002000, $00802080, $00802081, $00000081,
$00800080, $00800001, $00802000, $00802081, $00000081, $00000000, $00000000, $00802000,
$00002080, $00800080, $00800081, $00000001, $00802001, $00002081, $00002081, $00000080,
$00802081, $00000081, $00000001, $00002000, $00800001, $00002001, $00802080, $00800081,
$00002001, $00002080, $00800000, $00802001, $00000080, $00800000, $00002000, $00802080),
($00000100, $02080100, $02080000, $42000100, $00080000, $00000100, $40000000, $02080000,
$40080100, $00080000, $02000100, $40080100, $42000100, $42080000, $00080100, $40000000,
$02000000, $40080000, $40080000, $00000000, $40000100, $42080100, $42080100, $02000100,
$42080000, $40000100, $00000000, $42000000, $02080100, $02000000, $42000000, $00080100,
$00080000, $42000100, $00000100, $02000000, $40000000, $02080000, $42000100, $40080100,
$02000100, $40000000, $42080000, $02080100, $40080100, $00000100, $02000000, $42080000,
$42080100, $00080100, $42000000, $42080100, $02080000, $00000000, $40080000, $42000000,
$00080100, $02000100, $40000100, $00080000, $00000000, $40080000, $02080100, $40000100),
($20000010, $20400000, $00004000, $20404010, $20400000, $00000010, $20404010, $00400000,
$20004000, $00404010, $00400000, $20000010, $00400010, $20004000, $20000000, $00004010,
$00000000, $00400010, $20004010, $00004000, $00404000, $20004010, $00000010, $20400010,
$20400010, $00000000, $00404010, $20404000, $00004010, $00404000, $20404000, $20000000,
$20004000, $00000010, $20400010, $00404000, $20404010, $00400000, $00004010, $20000010,
$00400000, $20004000, $20000000, $00004010, $20000010, $20404010, $00404000, $20400000,
$00404010, $20404000, $00000000, $20400010, $00000010, $00004000, $20400000, $00404010,
$00004000, $00400010, $20004010, $00000000, $20404000, $20000000, $00400010, $20004010),
($00200000, $04200002, $04000802, $00000000, $00000800, $04000802, $00200802, $04200800,
$04200802, $00200000, $00000000, $04000002, $00000002, $04000000, $04200002, $00000802,
$04000800, $00200802, $00200002, $04000800, $04000002, $04200000, $04200800, $00200002,
$04200000, $00000800, $00000802, $04200802, $00200800, $00000002, $04000000, $00200800,
$04000000, $00200800, $00200000, $04000802, $04000802, $04200002, $04200002, $00000002,
$00200002, $04000000, $04000800, $00200000, $04200800, $00000802, $00200802, $04200800,
$00000802, $04000002, $04200802, $04200000, $00200800, $00000000, $00000002, $04200802,
$00000000, $00200802, $04200000, $00000800, $04000002, $04000800, $00000800, $00200002),
($10001040, $00001000, $00040000, $10041040, $10000000, $10001040, $00000040, $10000000,
$00040040, $10040000, $10041040, $00041000, $10041000, $00041040, $00001000, $00000040,
$10040000, $10000040, $10001000, $00001040, $00041000, $00040040, $10040040, $10041000,
$00001040, $00000000, $00000000, $10040040, $10000040, $10001000, $00041040, $00040000,
$00041040, $00040000, $10041000, $00001000, $00000040, $10040040, $00001000, $00041040,
$10001000, $00000040, $10000040, $10040000, $10040040, $10000000, $00040000, $10001040,
$00000000, $10041040, $00040040, $10000040, $10040000, $10001000, $10001040, $00000000,
$10041040, $00041000, $00041000, $00001040, $00001040, $00040040, $10000000, $10041000));
var
i, l, r, Work: DWORD;
CPtr: PDWORD;
procedure IPerm(var l, r: DWORD);
var
Work: DWORD;
begin
Work := ((l shr 4) xor r) and $0F0F0F0F;
r := r xor Work;
l := l xor Work shl 4;
Work := ((l shr 16) xor r) and $0000FFFF;
r := r xor Work;
l := l xor Work shl 16;
Work := ((r shr 2) xor l) and $33333333;
l := l xor Work;
r := r xor Work shl 2;
Work := ((r shr 8) xor l) and $00FF00FF;
l := l xor Work;
r := r xor Work shl 8;
r := (r shl 1) or (r shr 31);
Work := (l xor r) and $AAAAAAAA;
l := l xor Work;
r := r xor Work;
l := (l shl 1) or (l shr 31);
end;
procedure FPerm(var l, r: DWORD);
var
Work: DWORD;
begin
l := l;
r := (r shl 31) or (r shr 1);
Work := (l xor r) and $AAAAAAAA;
l := l xor Work;
r := r xor Work;
l := (l shr 1) or (l shl 31);
Work := ((l shr 8) xor r) and $00FF00FF;
r := r xor Work;
l := l xor Work shl 8;
Work := ((l shr 2) xor r) and $33333333;
r := r xor Work;
l := l xor Work shl 2;
Work := ((r shr 16) xor l) and $0000FFFF;
l := l xor Work;
r := r xor Work shl 16;
Work := ((r shr 4) xor l) and $0F0F0F0F;
l := l xor Work;
r := r xor Work shl 4;
end;
begin
SplitBlock(Block, l, r);
IPerm(l, r);
CPtr := @Context;
for i := 0 to 7 do begin
Work := (((r shr 4) or (r shl 28)) xor CPtr^);
inc(CPtr);
l := l xor SPBox[6, Work and $3F];
l := l xor SPBox[4, Work shr 8 and $3F];
l := l xor SPBox[2, Work shr 16 and $3F];
l := l xor SPBox[0, Work shr 24 and $3F];
Work := (r xor CPtr^);
inc(CPtr);
l := l xor SPBox[7, Work and $3F];
l := l xor SPBox[5, Work shr 8 and $3F];
l := l xor SPBox[3, Work shr 16 and $3F];
l := l xor SPBox[1, Work shr 24 and $3F];
Work := (((l shr 4) or (l shl 28)) xor CPtr^);
inc(CPtr);
r := r xor SPBox[6, Work and $3F];
r := r xor SPBox[4, Work shr 8 and $3F];
r := r xor SPBox[2, Work shr 16 and $3F];
r := r xor SPBox[0, Work shr 24 and $3F];
Work := (l xor CPtr^);
inc(CPtr);
r := r xor SPBox[7, Work and $3F];
r := r xor SPBox[5, Work shr 8 and $3F];
r := r xor SPBox[3, Work shr 16 and $3F];
r := r xor SPBox[1, Work shr 24 and $3F];
end;
FPerm(l, r);
JoinBlock(l, r, Block);
end;
class procedure TDES.EncryptTripleDES(const Context: TTripleDESContext; var Block: TDESBlock);
begin
EncryptDES(Context[0], Block);
EncryptDES(Context[1], Block);
EncryptDES(Context[0], Block);
end;
{ !!.01 }
class procedure TDES.EncryptTripleDES3Key(const Context: TTripleDESContext3Key; var Block: TDESBlock);
begin
EncryptDES(Context[2], Block);
EncryptDES(Context[1], Block);
EncryptDES(Context[0], Block);
end;
class procedure TDES.InitEncryptDES(const key: TKey64; var Context: TDESContext; Encrypt: Boolean);
const
PC1: array [0 .. 55] of Byte =
(56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26,
18, 10, 2, 59, 51, 43, 35, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3);
PC2: array [0 .. 47] of Byte =
(13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3, 25, 7,
15, 6, 26, 19, 12, 1, 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31);
CTotRot: array [0 .. 15] of Byte = (1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28);
CBitMask: array [0 .. 7] of Byte = (128, 64, 32, 16, 8, 4, 2, 1);
var
PC1M: array [0 .. 55] of Byte;
PC1R: array [0 .. 55] of Byte;
KS: array [0 .. 7] of Byte;
i, j, l, m: Integer;
begin
{ convert PC1 to bits of key }
for j := 0 to 55 do begin
l := PC1[j];
m := l mod 8;
PC1M[j] := Ord((key[l div 8] and CBitMask[m]) <> 0);
end;
{ key chunk for each iteration }
for i := 0 to 15 do begin
{ rotate PC1 the right amount }
for j := 0 to 27 do begin
l := j + CTotRot[i];
if (l < 28) then begin
PC1R[j] := PC1M[l];
PC1R[j + 28] := PC1M[l + 28];
end
else begin
PC1R[j] := PC1M[l - 28];
PC1R[j + 28] := PC1M[l];
end;
end;
{ select bits individually }
FillPtrByte(@KS, SizeOf(KS), 0);
for j := 0 to 47 do
if Boolean(PC1R[PC2[j]]) then begin
l := j div 6;
KS[l] := KS[l] or CBitMask[j mod 6] shr 2;
end;
{ now convert to odd/even interleaved form for use in F }
if Encrypt then begin
Context.TransformedKey[i * 2] := (Integer(KS[0]) shl 24) or (Integer(KS[2]) shl 16) or
(Integer(KS[4]) shl 8) or (Integer(KS[6]));
Context.TransformedKey[i * 2 + 1] := (Integer(KS[1]) shl 24) or (Integer(KS[3]) shl 16) or
(Integer(KS[5]) shl 8) or (Integer(KS[7]));
end
else begin
Context.TransformedKey[31 - (i * 2 + 1)] := (Integer(KS[0]) shl 24) or (Integer(KS[2]) shl 16) or
(Integer(KS[4]) shl 8) or (Integer(KS[6]));
Context.TransformedKey[31 - (i * 2)] := (Integer(KS[1]) shl 24) or (Integer(KS[3]) shl 16) or
(Integer(KS[5]) shl 8) or (Integer(KS[7]));
end;
end;
Context.Encrypt := Encrypt;
end;
class procedure TDES.InitEncryptTripleDES(const key: TKey128; var Context: TTripleDESContext; Encrypt: Boolean);
var
KeyArray: array [0 .. 1] of TKey64;
begin
CopyPtr(@key, @KeyArray, SizeOf(KeyArray)); { !!.01 }
if Encrypt then begin
InitEncryptDES(KeyArray[0], Context[0], True);
InitEncryptDES(KeyArray[1], Context[1], False);
end
else begin
InitEncryptDES(KeyArray[0], Context[0], False);
InitEncryptDES(KeyArray[1], Context[1], True);
end;
end;
{ !!.01 }
class procedure TDES.InitEncryptTripleDES3Key(const Key1, Key2, Key3: TKey64; var Context: TTripleDESContext3Key; Encrypt: Boolean);
begin
if Encrypt then begin
InitEncryptDES(Key1, Context[0], True);
InitEncryptDES(Key2, Context[1], False);
InitEncryptDES(Key3, Context[2], True);
end
else begin
InitEncryptDES(Key1, Context[2], False);
InitEncryptDES(Key2, Context[1], True);
InitEncryptDES(Key3, Context[0], False);
end;
end;
class procedure TDES.JoinBlock(const l, r: DWORD; var Block: TDESBlock);
var
Temp: TDesConverter;
i: Integer;
begin
Temp.DWords[0] := DWORD(l);
Temp.DWords[1] := DWORD(r);
for i := low(Block) to high(Block) do
Block[i] := Temp.Bytes[7 - i];
end;
class procedure TDES.ShrinkDESKey(var key: TKey64);
const
SK1: TKey64 = ($C4, $08, $B0, $54, $0B, $A1, $E0, $AE);
SK2: TKey64 = ($EF, $2C, $04, $1C, $E6, $38, $2F, $E6);
var
i: Integer;
Work1: TKey64;
Work2: TKey64;
Context: TDESContext;
begin
{ step #1 zero the parity bits - 8, 16, 24, ..., 64 }
for i := 0 to 7 do
Work1[i] := key[i] and $FE;
{ step #2 encrypt output of #1 with SK1 and xor with output of #1 }
InitEncryptDES(SK1, Context, True);
Work2 := Work1; { make copy }
EncryptDES(Context, TDESBlock(Work2));
for i := 0 to 7 do
Work1[i] := Work1[i] xor Work2[i];
{ step #3 zero bits 1,2,3,4,8,16,17,18,19,20,24,32,33,34,35,36,40,48,49,50,51,52,56,64 }
TInt64(Work1).Lo := TInt64(Work1).Lo and $F101F101;
TInt64(Work1).Hi := TInt64(Work1).Hi and $F101F101;
{ step #4 encrypt output of #3 with SK2 }
InitEncryptDES(SK2, Context, True);
EncryptDES(Context, TDESBlock(Work1));
key := Work1;
end;
class procedure TDES.SplitBlock(const Block: TDESBlock; var l, r: DWORD);
var
Temp: TDesConverter;
i: Integer;
begin
for i := low(Block) to high(Block) do
Temp.Bytes[7 - i] := Block[i];
l := Temp.DWords[1];
r := Temp.DWords[0];
end;
{ TSHA1 }
class procedure TSHA1.FinalizeSHA1(var Context: TSHA1Context; var Digest: TSHA1Digest);
begin
with Context do begin
sdBuf[sdIndex] := $80;
if sdIndex >= 56 then
SHA1Hash(Context);
PDWORD(@sdBuf[56])^ := SHA1SwapByteOrder(sdHi);
PDWORD(@sdBuf[60])^ := SHA1SwapByteOrder(sdLo);
SHA1Hash(Context);
sdHash[0] := SHA1SwapByteOrder(sdHash[0]);
sdHash[1] := SHA1SwapByteOrder(sdHash[1]);
sdHash[2] := SHA1SwapByteOrder(sdHash[2]);
sdHash[3] := SHA1SwapByteOrder(sdHash[3]);
sdHash[4] := SHA1SwapByteOrder(sdHash[4]);
CopyPtr(@sdHash, @Digest, SizeOf(Digest));
SHA1Clear(Context);
end;
end;
class procedure TSHA1.SHA1(var Digest: TSHA1Digest; const Buf; BufSize: nativeUInt);
var
Context: TSHA1Context;
begin
InitSHA1(Context);
UpdateSHA1(Context, Buf, BufSize);
FinalizeSHA1(Context, Digest);
end;
class procedure TSHA1.InitSHA1(var Context: TSHA1Context);
begin
SHA1Clear(Context);
Context.sdHash[0] := SHA1_A;
Context.sdHash[1] := SHA1_B;
Context.sdHash[2] := SHA1_C;
Context.sdHash[3] := SHA1_D;
Context.sdHash[4] := SHA1_E;
end;
class procedure TSHA1.SHA1Clear(var Context: TSHA1Context);
begin
FillPtrByte(@Context, SizeOf(Context), $00);
end;
class procedure TSHA1.SHA1Hash(var Context: TSHA1Context);
var
a: DWORD;
b: DWORD;
c: DWORD;
d: DWORD;
E: DWORD;
x: DWORD;
w: array [0 .. 79] of DWORD;
i: Integer;
begin
with Context do begin
sdIndex := 0;
CopyPtr(@sdBuf, @w, SizeOf(w));
// W := Mt, for t = 0 to 15 : Mt is M sub t
for i := 0 to 15 do
w[i] := SHA1SwapByteOrder(w[i]);
// Transform Message block from 16 32 bit words to 80 32 bit words
// Wt, = ( Wt-3 xor Wt-8 xor Wt-13 xor Wt-16 ) rolL 1 : Wt is W sub t
for i := 16 to 79 do
w[i] := TMISC.RolX(w[i - 3] xor w[i - 8] xor w[i - 14] xor w[i - 16], 1);
a := sdHash[0];
b := sdHash[1];
c := sdHash[2];
d := sdHash[3];
E := sdHash[4];
// the four rounds
for i := 0 to 19 do begin
x := TMISC.RolX(a, 5) + (d xor (b and (c xor d))) + E + w[i] + SHA1_K1;
E := d;
d := c;
c := TMISC.RolX(b, 30);
b := a;
a := x;
end;
for i := 20 to 39 do begin
x := TMISC.RolX(a, 5) + (b xor c xor d) + E + w[i] + SHA1_K2;
E := d;
d := c;
c := TMISC.RolX(b, 30);
b := a;
a := x;
end;
for i := 40 to 59 do begin
x := TMISC.RolX(a, 5) + ((b and c) or (d and (b or c))) + E + w[i] + SHA1_K3;
E := d;
d := c;
c := TMISC.RolX(b, 30);
b := a;
a := x;
end;
for i := 60 to 79 do
begin
x := TMISC.RolX(a, 5) + (b xor c xor d) + E + w[i] + SHA1_K4;
E := d;
d := c;
c := TMISC.RolX(b, 30);
b := a;
a := x;
end;
sdHash[0] := sdHash[0] + a;
sdHash[1] := sdHash[1] + b;
sdHash[2] := sdHash[2] + c;
sdHash[3] := sdHash[3] + d;
sdHash[4] := sdHash[4] + E;
FillPtrByte(@w, SizeOf(w), $00);
FillPtrByte(@sdBuf, SizeOf(sdBuf), $00);
end;
end;
class function TSHA1.SHA1SwapByteOrder(n: DWORD): DWORD;
begin
n := (n shr 24) or ((n shr 8) and LBMASK_LO) or ((n shl 8) and LBMASK_HI) or (n shl 24);
Result := n;
end;
class procedure TSHA1.SHA1UpdateLen(var Context: TSHA1Context; Len: DWORD);
begin
inc(Context.sdLo, (Len shl 3));
if Context.sdLo < (Len shl 3) then
inc(Context.sdHi);
inc(Context.sdHi, Len shr 29);
end;
class procedure TSHA1.ByteBuffSHA1(var Digest: TSHA1Digest; const ABytes: TBytes);
begin
SHA1(Digest, ABytes[0], length(ABytes));
end;
class procedure TSHA1.UpdateSHA1(var Context: TSHA1Context; const Buf; BufSize: nativeUInt);
var
PBuf: PByte;
begin
with Context do begin
SHA1UpdateLen(Context, BufSize);
PBuf := @Buf;
while BufSize > 0 do begin
if (SizeOf(sdBuf) - sdIndex) <= DWORD(BufSize) then begin
CopyPtr(PBuf, @sdBuf[sdIndex], SizeOf(sdBuf) - sdIndex);
dec(BufSize, SizeOf(sdBuf) - sdIndex);
inc(PBuf, SizeOf(sdBuf) - sdIndex);
SHA1Hash(Context);
end
else begin
CopyPtr(PBuf, @sdBuf[sdIndex], BufSize);
inc(sdIndex, BufSize);
BufSize := 0;
end;
end;
end;
end;
class procedure TSHA256.SwapDWORD(var a: DWORD);
begin
a := Endian(a);
end;
class procedure TSHA256.Compute(var Digest: TSHA256Digest; const buff: Pointer);
var
a, b, c, d, E, f, g, h, tmp1, tmp2: DWORD;
w: array [0 .. 63] of DWORD;
i: ShortInt;
begin
a := PDWORD(@Digest[0])^;
b := PDWORD(@Digest[4])^;
c := PDWORD(@Digest[8])^;
d := PDWORD(@Digest[12])^;
E := PDWORD(@Digest[16])^;
f := PDWORD(@Digest[20])^;
g := PDWORD(@Digest[24])^;
h := PDWORD(@Digest[28])^;
CopyPtr(buff, @w[0], 64);
for i := 0 to 15 do
SwapDWORD(w[i]);
for i := 16 to 63 do
w[i] := (((w[i - 2] shr 17) or (w[i - 2] shl 15)) xor ((w[i - 2] shr 19) or (w[i - 2] shl 13)) xor
(w[i - 2] shr 10)) + w[i - 7] + (((w[i - 15] shr 7) or (w[i - 15] shl 25)) xor
((w[i - 15] shr 18) or (w[i - 15] shl 14)) xor (w[i - 15] shr 3)) + w[i - 16];
tmp1 := h + (((E shr 6) or (E shl 26)) xor ((E shr 11) or (E shl 21)) xor ((E shr 25) or (E shl 7))) + ((E and f) xor (not E and g)) + $428A2F98 + w[0];
tmp2 := (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c));
h := tmp1 + tmp2;
d := d + tmp1;
tmp1 := g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and E) xor (not d and f)) + $71374491 + w[1];
tmp2 := (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b));
g := tmp1 + tmp2;
c := c + tmp1;
tmp1 := f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and E)) + $B5C0FBCF + w[2];
tmp2 := (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a));
f := tmp1 + tmp2;
b := b + tmp1;
tmp1 := E + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $E9B5DBA5 + w[3];
tmp2 := (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h));
E := tmp1 + tmp2;
a := a + tmp1;
tmp1 := d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $3956C25B + w[4];
tmp2 := (((E shr 2) or (E shl 30)) xor ((E shr 13) or (E shl 19)) xor ((E shr 22) xor (E shl 10))) + ((E and f) xor (E and g) xor (f and g));
d := tmp1 + tmp2;
h := h + tmp1;
tmp1 := c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $59F111F1 + w[5];
tmp2 := (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and E) xor (d and f) xor (E and f));
c := tmp1 + tmp2;
g := g + tmp1;
tmp1 := b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $923F82A4 + w[6];
tmp2 := (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and E) xor (d and E));
b := tmp1 + tmp2;
f := f + tmp1;
tmp1 := a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $AB1C5ED5 + w[7];
tmp2 := (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d));
a := tmp1 + tmp2;
E := E + tmp1;
tmp1 := h + (((E shr 6) or (E shl 26)) xor ((E shr 11) or (E shl 21)) xor ((E shr 25) or (E shl 7))) + ((E and f) xor (not E and g)) + $D807AA98 + w[8];
tmp2 := (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c));
h := tmp1 + tmp2;
d := d + tmp1;
tmp1 := g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and E) xor (not d and f)) + $12835B01 + w[9];
tmp2 := (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b));
g := tmp1 + tmp2;
c := c + tmp1;
tmp1 := f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and E)) + $243185BE + w[10];
tmp2 := (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a));
f := tmp1 + tmp2;
b := b + tmp1;
tmp1 := E + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $550C7DC3 + w[11];
tmp2 := (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h));
E := tmp1 + tmp2;
a := a + tmp1;
tmp1 := d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $72BE5D74 + w[12];
tmp2 := (((E shr 2) or (E shl 30)) xor ((E shr 13) or (E shl 19)) xor ((E shr 22) xor (E shl 10))) + ((E and f) xor (E and g) xor (f and g));
d := tmp1 + tmp2;
h := h + tmp1;
tmp1 := c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $80DEB1FE + w[13];
tmp2 := (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and E) xor (d and f) xor (E and f));
c := tmp1 + tmp2;
g := g + tmp1;
tmp1 := b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $9BDC06A7 + w[14];
tmp2 := (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and E) xor (d and E));
b := tmp1 + tmp2;
f := f + tmp1;
tmp1 := a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $C19BF174 + w[15];
tmp2 := (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d));
a := tmp1 + tmp2;
E := E + tmp1;
tmp1 := h + (((E shr 6) or (E shl 26)) xor ((E shr 11) or (E shl 21)) xor ((E shr 25) or (E shl 7))) + ((E and f) xor (not E and g)) + $E49B69C1 + w[16];
tmp2 := (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c));
h := tmp1 + tmp2;
d := d + tmp1;
tmp1 := g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and E) xor (not d and f)) + $EFBE4786 + w[17];
tmp2 := (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b));
g := tmp1 + tmp2;
c := c + tmp1;
tmp1 := f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and E)) + $0FC19DC6 + w[18];
tmp2 := (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a));
f := tmp1 + tmp2;
b := b + tmp1;
tmp1 := E + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $240CA1CC + w[19];
tmp2 := (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h));
E := tmp1 + tmp2;
a := a + tmp1;
tmp1 := d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $2DE92C6F + w[20];
tmp2 := (((E shr 2) or (E shl 30)) xor ((E shr 13) or (E shl 19)) xor ((E shr 22) xor (E shl 10))) + ((E and f) xor (E and g) xor (f and g));
d := tmp1 + tmp2;
h := h + tmp1;
tmp1 := c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $4A7484AA + w[21];
tmp2 := (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and E) xor (d and f) xor (E and f));
c := tmp1 + tmp2;
g := g + tmp1;
tmp1 := b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $5CB0A9DC + w[22];
tmp2 := (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and E) xor (d and E));
b := tmp1 + tmp2;
f := f + tmp1;
tmp1 := a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $76F988DA + w[23];
tmp2 := (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d));
a := tmp1 + tmp2;
E := E + tmp1;
tmp1 := h + (((E shr 6) or (E shl 26)) xor ((E shr 11) or (E shl 21)) xor ((E shr 25) or (E shl 7))) + ((E and f) xor (not E and g)) + $983E5152 + w[24];
tmp2 := (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c));
h := tmp1 + tmp2;
d := d + tmp1;
tmp1 := g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and E) xor (not d and f)) + $A831C66D + w[25];
tmp2 := (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b));
g := tmp1 + tmp2;
c := c + tmp1;
tmp1 := f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and E)) + $B00327C8 + w[26];
tmp2 := (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a));
f := tmp1 + tmp2;
b := b + tmp1;
tmp1 := E + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $BF597FC7 + w[27];
tmp2 := (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h));
E := tmp1 + tmp2;
a := a + tmp1;
tmp1 := d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $C6E00BF3 + w[28];
tmp2 := (((E shr 2) or (E shl 30)) xor ((E shr 13) or (E shl 19)) xor ((E shr 22) xor (E shl 10))) + ((E and f) xor (E and g) xor (f and g));
d := tmp1 + tmp2;
h := h + tmp1;
tmp1 := c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $D5A79147 + w[29];
tmp2 := (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and E) xor (d and f) xor (E and f));
c := tmp1 + tmp2;
g := g + tmp1;
tmp1 := b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $06CA6351 + w[30];
tmp2 := (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and E) xor (d and E));
b := tmp1 + tmp2;
f := f + tmp1;
tmp1 := a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $14292967 + w[31];
tmp2 := (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d));
a := tmp1 + tmp2;
E := E + tmp1;
tmp1 := h + (((E shr 6) or (E shl 26)) xor ((E shr 11) or (E shl 21)) xor ((E shr 25) or (E shl 7))) + ((E and f) xor (not E and g)) + $27B70A85 + w[32];
tmp2 := (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c));
h := tmp1 + tmp2;
d := d + tmp1;
tmp1 := g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and E) xor (not d and f)) + $2E1B2138 + w[33];
tmp2 := (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b));
g := tmp1 + tmp2;
c := c + tmp1;
tmp1 := f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and E)) + $4D2C6DFC + w[34];
tmp2 := (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a));
f := tmp1 + tmp2;
b := b + tmp1;
tmp1 := E + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $53380D13 + w[35];
tmp2 := (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h));
E := tmp1 + tmp2;
a := a + tmp1;
tmp1 := d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $650A7354 + w[36];
tmp2 := (((E shr 2) or (E shl 30)) xor ((E shr 13) or (E shl 19)) xor ((E shr 22) xor (E shl 10))) + ((E and f) xor (E and g) xor (f and g));
d := tmp1 + tmp2;
h := h + tmp1;
tmp1 := c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $766A0ABB + w[37];
tmp2 := (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and E) xor (d and f) xor (E and f));
c := tmp1 + tmp2;
g := g + tmp1;
tmp1 := b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $81C2C92E + w[38];
tmp2 := (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and E) xor (d and E));
b := tmp1 + tmp2;
f := f + tmp1;
tmp1 := a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $92722C85 + w[39];
tmp2 := (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d));
a := tmp1 + tmp2;
E := E + tmp1;
tmp1 := h + (((E shr 6) or (E shl 26)) xor ((E shr 11) or (E shl 21)) xor ((E shr 25) or (E shl 7))) + ((E and f) xor (not E and g)) + $A2BFE8A1 + w[40];
tmp2 := (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c));
h := tmp1 + tmp2;
d := d + tmp1;
tmp1 := g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and E) xor (not d and f)) + $A81A664B + w[41];
tmp2 := (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b));
g := tmp1 + tmp2;
c := c + tmp1;
tmp1 := f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and E)) + $C24B8B70 + w[42];
tmp2 := (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a));
f := tmp1 + tmp2;
b := b + tmp1;
tmp1 := E + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $C76C51A3 + w[43];
tmp2 := (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h));
E := tmp1 + tmp2;
a := a + tmp1;
tmp1 := d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $D192E819 + w[44];
tmp2 := (((E shr 2) or (E shl 30)) xor ((E shr 13) or (E shl 19)) xor ((E shr 22) xor (E shl 10))) + ((E and f) xor (E and g) xor (f and g));
d := tmp1 + tmp2;
h := h + tmp1;
tmp1 := c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $D6990624 + w[45];
tmp2 := (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and E) xor (d and f) xor (E and f));
c := tmp1 + tmp2;
g := g + tmp1;
tmp1 := b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $F40E3585 + w[46];
tmp2 := (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and E) xor (d and E));
b := tmp1 + tmp2;
f := f + tmp1;
tmp1 := a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $106AA070 + w[47];
tmp2 := (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d));
a := tmp1 + tmp2;
E := E + tmp1;
tmp1 := h + (((E shr 6) or (E shl 26)) xor ((E shr 11) or (E shl 21)) xor ((E shr 25) or (E shl 7))) + ((E and f) xor (not E and g)) + $19A4C116 + w[48];
tmp2 := (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c));
h := tmp1 + tmp2;
d := d + tmp1;
tmp1 := g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and E) xor (not d and f)) + $1E376C08 + w[49];
tmp2 := (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b));
g := tmp1 + tmp2;
c := c + tmp1;
tmp1 := f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and E)) + $2748774C + w[50];
tmp2 := (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a));
f := tmp1 + tmp2;
b := b + tmp1;
tmp1 := E + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $34B0BCB5 + w[51];
tmp2 := (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h));
E := tmp1 + tmp2;
a := a + tmp1;
tmp1 := d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $391C0CB3 + w[52];
tmp2 := (((E shr 2) or (E shl 30)) xor ((E shr 13) or (E shl 19)) xor ((E shr 22) xor (E shl 10))) + ((E and f) xor (E and g) xor (f and g));
d := tmp1 + tmp2;
h := h + tmp1;
tmp1 := c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $4ED8AA4A + w[53];
tmp2 := (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and E) xor (d and f) xor (E and f));
c := tmp1 + tmp2;
g := g + tmp1;
tmp1 := b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $5B9CCA4F + w[54];
tmp2 := (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and E) xor (d and E));
b := tmp1 + tmp2;
f := f + tmp1;
tmp1 := a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $682E6FF3 + w[55];
tmp2 := (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d));
a := tmp1 + tmp2;
E := E + tmp1;
tmp1 := h + (((E shr 6) or (E shl 26)) xor ((E shr 11) or (E shl 21)) xor ((E shr 25) or (E shl 7))) + ((E and f) xor (not E and g)) + $748F82EE + w[56];
tmp2 := (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c));
h := tmp1 + tmp2;
d := d + tmp1;
tmp1 := g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and E) xor (not d and f)) + $78A5636F + w[57];
tmp2 := (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b));
g := tmp1 + tmp2;
c := c + tmp1;
tmp1 := f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and E)) + $84C87814 + w[58];
tmp2 := (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a));
f := tmp1 + tmp2;
b := b + tmp1;
tmp1 := E + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $8CC70208 + w[59];
tmp2 := (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h));
E := tmp1 + tmp2;
a := a + tmp1;
tmp1 := d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $90BEFFFA + w[60];
tmp2 := (((E shr 2) or (E shl 30)) xor ((E shr 13) or (E shl 19)) xor ((E shr 22) xor (E shl 10))) + ((E and f) xor (E and g) xor (f and g));
d := tmp1 + tmp2;
h := h + tmp1;
tmp1 := c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $A4506CEB + w[61];
tmp2 := (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and E) xor (d and f) xor (E and f));
c := tmp1 + tmp2;
g := g + tmp1;
tmp1 := b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $BEF9A3F7 + w[62];
tmp2 := (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and E) xor (d and E));
b := tmp1 + tmp2;
f := f + tmp1;
tmp1 := a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $C67178F2 + w[63];
tmp2 := (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d));
a := tmp1 + tmp2;
E := E + tmp1;
inc(PDWORD(@Digest[0])^, a);
inc(PDWORD(@Digest[4])^, b);
inc(PDWORD(@Digest[8])^, c);
inc(PDWORD(@Digest[12])^, d);
inc(PDWORD(@Digest[16])^, E);
inc(PDWORD(@Digest[20])^, f);
inc(PDWORD(@Digest[24])^, g);
inc(PDWORD(@Digest[28])^, h);
end;
class procedure TSHA256.SHA256(var Digest: TSHA256Digest; const Buf; BufSize: nativeUInt);
var
Lo, Hi: DWORD;
p: PByte;
ChunkIndex: Byte;
ChunkBuf: array [0 .. 63] of Byte;
begin
PDWORD(@Digest[0])^ := $6A09E667;
PDWORD(@Digest[4])^ := $BB67AE85;
PDWORD(@Digest[8])^ := $3C6EF372;
PDWORD(@Digest[12])^ := $A54FF53A;
PDWORD(@Digest[16])^ := $510E527F;
PDWORD(@Digest[20])^ := $9B05688C;
PDWORD(@Digest[24])^ := $1F83D9AB;
PDWORD(@Digest[28])^ := $5BE0CD19;
Lo := 0;
inc(Lo, BufSize shl 3);
Hi := 0;
inc(Hi, BufSize shr 29);
SwapDWORD(Lo);
SwapDWORD(Hi);
p := @Buf;
while BufSize >= 64 do
begin
Compute(Digest, p);
inc(p, 64);
dec(BufSize, 64);
end;
if BufSize > 0 then
CopyPtr(p, @ChunkBuf[0], BufSize);
ChunkBuf[BufSize] := $80;
ChunkIndex := BufSize + 1;
if ChunkIndex > 56 then
begin
if ChunkIndex < 64 then
FillPtrByte(@ChunkBuf[ChunkIndex], 64 - ChunkIndex, 0);
Compute(Digest, @ChunkBuf);
ChunkIndex := 0
end;
FillPtrByte(@ChunkBuf[ChunkIndex], 56 - ChunkIndex, 0);
PDWORD(@ChunkBuf[56])^ := Hi;
PDWORD(@ChunkBuf[60])^ := Lo;
Compute(Digest, @ChunkBuf);
SwapDWORD(PDWORD(@Digest[0])^);
SwapDWORD(PDWORD(@Digest[4])^);
SwapDWORD(PDWORD(@Digest[8])^);
SwapDWORD(PDWORD(@Digest[12])^);
SwapDWORD(PDWORD(@Digest[16])^);
SwapDWORD(PDWORD(@Digest[20])^);
SwapDWORD(PDWORD(@Digest[24])^);
SwapDWORD(PDWORD(@Digest[28])^);
end;
class procedure TSHA512.SwapQWORD(var a: UInt64);
begin
a := Endian(a);
end;
class procedure TSHA512.Compute(var Digest: TSHA512Digest; const buff: Pointer);
var
a, b, c, d, E, f, g, h, T1, T2: UInt64;
w: array [0 .. 79] of UInt64;
i: ShortInt;
begin
{$IFDEF RangeCheck}{$R-}{$ENDIF}
a := PUInt64(@Digest[0])^;
b := PUInt64(@Digest[8])^;
c := PUInt64(@Digest[16])^;
d := PUInt64(@Digest[24])^;
E := PUInt64(@Digest[32])^;
f := PUInt64(@Digest[40])^;
g := PUInt64(@Digest[48])^;
h := PUInt64(@Digest[56])^;
CopyPtr(buff, @w[0], 128);
for i := 0 to 15 do
SwapQWORD(w[i]);
for i := 16 to 79 do
w[i] := (((w[i - 2] shr 19) or (w[i - 2] shl 45)) xor ((w[i - 2] shr 61) or (w[i - 2] shl 3)) xor (w[i - 2] shr 6)) +
w[i - 7] + (((w[i - 15] shr 1) or (w[i - 15] shl 63)) xor ((w[i - 15] shr 8) or (w[i - 15] shl 56)) xor (w[i - 15] shr 7)) + w[i - 16];
T1 := h + (((E shr 14) or (E shl 50)) xor ((E shr 18) or (E shl 46)) xor ((E shr 41) or (E shl 23))) + ((E and f) xor (not E and g)) + $428A2F98D728AE22 + w[0];
T2 := (((a shr 28) or (a shl 36)) xor ((a shr 34) or (a shl 30)) xor ((a shr 39) or (a shl 25))) + ((a and b) xor (a and c) xor (b and c));
d := d + T1;
h := T1 + T2;
T1 := g + (((d shr 14) or (d shl 50)) xor ((d shr 18) or (d shl 46)) xor ((d shr 41) or (d shl 23))) + ((d and E) xor (not d and f)) + $7137449123EF65CD + w[1];
T2 := (((h shr 28) or (h shl 36)) xor ((h shr 34) or (h shl 30)) xor ((h shr 39) or (h shl 25))) + ((h and a) xor (h and b) xor (a and b));
c := c + T1;
g := T1 + T2;
T1 := f + (((c shr 14) or (c shl 50)) xor ((c shr 18) or (c shl 46)) xor ((c shr 41) or (c shl 23))) + ((c and d) xor (not c and E)) + $B5C0FBCFEC4D3B2F + w[2];
T2 := (((g shr 28) or (g shl 36)) xor ((g shr 34) or (g shl 30)) xor ((g shr 39) or (g shl 25))) + ((g and h) xor (g and a) xor (h and a));
b := b + T1;
f := T1 + T2;
T1 := E + (((b shr 14) or (b shl 50)) xor ((b shr 18) or (b shl 46)) xor ((b shr 41) or (b shl 23))) + ((b and c) xor (not b and d)) + $E9B5DBA58189DBBC + w[3];
T2 := (((f shr 28) or (f shl 36)) xor ((f shr 34) or (f shl 30)) xor ((f shr 39) or (f shl 25))) + ((f and g) xor (f and h) xor (g and h));
a := a + T1;
E := T1 + T2;
T1 := d + (((a shr 14) or (a shl 50)) xor ((a shr 18) or (a shl 46)) xor ((a shr 41) or (a shl 23))) + ((a and b) xor (not a and c)) + $3956C25BF348B538 + w[4];
T2 := (((E shr 28) or (E shl 36)) xor ((E shr 34) or (E shl 30)) xor ((E shr 39) or (E shl 25))) + ((E and f) xor (E and g) xor (f and g));
h := h + T1;
d := T1 + T2;
T1 := c + (((h shr 14) or (h shl 50)) xor ((h shr 18) or (h shl 46)) xor ((h shr 41) or (h shl 23))) + ((h and a) xor (not h and b)) + $59F111F1B605D019 + w[5];
T2 := (((d shr 28) or (d shl 36)) xor ((d shr 34) or (d shl 30)) xor ((d shr 39) or (d shl 25))) + ((d and E) xor (d and f) xor (E and f));
g := g + T1;
c := T1 + T2;
T1 := b + (((g shr 14) or (g shl 50)) xor ((g shr 18) or (g shl 46)) xor ((g shr 41) or (g shl 23))) + ((g and h) xor (not g and a)) + $923F82A4AF194F9B + w[6];
T2 := (((c shr 28) or (c shl 36)) xor ((c shr 34) or (c shl 30)) xor ((c shr 39) or (c shl 25))) + ((c and d) xor (c and E) xor (d and E));
f := f + T1;
b := T1 + T2;
T1 := a + (((f shr 14) or (f shl 50)) xor ((f shr 18) or (f shl 46)) xor ((f shr 41) or (f shl 23))) + ((f and g) xor (not f and h)) + $AB1C5ED5DA6D8118 + w[7];
T2 := (((b shr 28) or (b shl 36)) xor ((b shr 34) or (b shl 30)) xor ((b shr 39) or (b shl 25))) + ((b and c) xor (b and d) xor (c and d));
E := E + T1;
a := T1 + T2;
T1 := h + (((E shr 14) or (E shl 50)) xor ((E shr 18) or (E shl 46)) xor ((E shr 41) or (E shl 23))) + ((E and f) xor (not E and g)) + $D807AA98A3030242 + w[8];
T2 := (((a shr 28) or (a shl 36)) xor ((a shr 34) or (a shl 30)) xor ((a shr 39) or (a shl 25))) + ((a and b) xor (a and c) xor (b and c));
d := d + T1;
h := T1 + T2;
T1 := g + (((d shr 14) or (d shl 50)) xor ((d shr 18) or (d shl 46)) xor ((d shr 41) or (d shl 23))) + ((d and E) xor (not d and f)) + $12835B0145706FBE + w[9];
T2 := (((h shr 28) or (h shl 36)) xor ((h shr 34) or (h shl 30)) xor ((h shr 39) or (h shl 25))) + ((h and a) xor (h and b) xor (a and b));
c := c + T1;
g := T1 + T2;
T1 := f + (((c shr 14) or (c shl 50)) xor ((c shr 18) or (c shl 46)) xor ((c shr 41) or (c shl 23))) + ((c and d) xor (not c and E)) + $243185BE4EE4B28C + w[10];
T2 := (((g shr 28) or (g shl 36)) xor ((g shr 34) or (g shl 30)) xor ((g shr 39) or (g shl 25))) + ((g and h) xor (g and a) xor (h and a));
b := b + T1;
f := T1 + T2;
T1 := E + (((b shr 14) or (b shl 50)) xor ((b shr 18) or (b shl 46)) xor ((b shr 41) or (b shl 23))) + ((b and c) xor (not b and d)) + $550C7DC3D5FFB4E2 + w[11];
T2 := (((f shr 28) or (f shl 36)) xor ((f shr 34) or (f shl 30)) xor ((f shr 39) or (f shl 25))) + ((f and g) xor (f and h) xor (g and h));
a := a + T1;
E := T1 + T2;
T1 := d + (((a shr 14) or (a shl 50)) xor ((a shr 18) or (a shl 46)) xor ((a shr 41) or (a shl 23))) + ((a and b) xor (not a and c)) + $72BE5D74F27B896F + w[12];
T2 := (((E shr 28) or (E shl 36)) xor ((E shr 34) or (E shl 30)) xor ((E shr 39) or (E shl 25))) + ((E and f) xor (E and g) xor (f and g));
h := h + T1;
d := T1 + T2;
T1 := c + (((h shr 14) or (h shl 50)) xor ((h shr 18) or (h shl 46)) xor ((h shr 41) or (h shl 23))) + ((h and a) xor (not h and b)) + $80DEB1FE3B1696B1 + w[13];
T2 := (((d shr 28) or (d shl 36)) xor ((d shr 34) or (d shl 30)) xor ((d shr 39) or (d shl 25))) + ((d and E) xor (d and f) xor (E and f));
g := g + T1;
c := T1 + T2;
T1 := b + (((g shr 14) or (g shl 50)) xor ((g shr 18) or (g shl 46)) xor ((g shr 41) or (g shl 23))) + ((g and h) xor (not g and a)) + $9BDC06A725C71235 + w[14];
T2 := (((c shr 28) or (c shl 36)) xor ((c shr 34) or (c shl 30)) xor ((c shr 39) or (c shl 25))) + ((c and d) xor (c and E) xor (d and E));
f := f + T1;
b := T1 + T2;
T1 := a + (((f shr 14) or (f shl 50)) xor ((f shr 18) or (f shl 46)) xor ((f shr 41) or (f shl 23))) + ((f and g) xor (not f and h)) + $C19BF174CF692694 + w[15];
T2 := (((b shr 28) or (b shl 36)) xor ((b shr 34) or (b shl 30)) xor ((b shr 39) or (b shl 25))) + ((b and c) xor (b and d) xor (c and d));
E := E + T1;
a := T1 + T2;
T1 := h + (((E shr 14) or (E shl 50)) xor ((E shr 18) or (E shl 46)) xor ((E shr 41) or (E shl 23))) + ((E and f) xor (not E and g)) + $E49B69C19EF14AD2 + w[16];
T2 := (((a shr 28) or (a shl 36)) xor ((a shr 34) or (a shl 30)) xor ((a shr 39) or (a shl 25))) + ((a and b) xor (a and c) xor (b and c));
d := d + T1;
h := T1 + T2;
T1 := g + (((d shr 14) or (d shl 50)) xor ((d shr 18) or (d shl 46)) xor ((d shr 41) or (d shl 23))) + ((d and E) xor (not d and f)) + $EFBE4786384F25E3 + w[17];
T2 := (((h shr 28) or (h shl 36)) xor ((h shr 34) or (h shl 30)) xor ((h shr 39) or (h shl 25))) + ((h and a) xor (h and b) xor (a and b));
c := c + T1;
g := T1 + T2;
T1 := f + (((c shr 14) or (c shl 50)) xor ((c shr 18) or (c shl 46)) xor ((c shr 41) or (c shl 23))) + ((c and d) xor (not c and E)) + $0FC19DC68B8CD5B5 + w[18];
T2 := (((g shr 28) or (g shl 36)) xor ((g shr 34) or (g shl 30)) xor ((g shr 39) or (g shl 25))) + ((g and h) xor (g and a) xor (h and a));
b := b + T1;
f := T1 + T2;
T1 := E + (((b shr 14) or (b shl 50)) xor ((b shr 18) or (b shl 46)) xor ((b shr 41) or (b shl 23))) + ((b and c) xor (not b and d)) + $240CA1CC77AC9C65 + w[19];
T2 := (((f shr 28) or (f shl 36)) xor ((f shr 34) or (f shl 30)) xor ((f shr 39) or (f shl 25))) + ((f and g) xor (f and h) xor (g and h));
a := a + T1;
E := T1 + T2;
T1 := d + (((a shr 14) or (a shl 50)) xor ((a shr 18) or (a shl 46)) xor ((a shr 41) or (a shl 23))) + ((a and b) xor (not a and c)) + $2DE92C6F592B0275 + w[20];
T2 := (((E shr 28) or (E shl 36)) xor ((E shr 34) or (E shl 30)) xor ((E shr 39) or (E shl 25))) + ((E and f) xor (E and g) xor (f and g));
h := h + T1;
d := T1 + T2;
T1 := c + (((h shr 14) or (h shl 50)) xor ((h shr 18) or (h shl 46)) xor ((h shr 41) or (h shl 23))) + ((h and a) xor (not h and b)) + $4A7484AA6EA6E483 + w[21];
T2 := (((d shr 28) or (d shl 36)) xor ((d shr 34) or (d shl 30)) xor ((d shr 39) or (d shl 25))) + ((d and E) xor (d and f) xor (E and f));
g := g + T1;
c := T1 + T2;
T1 := b + (((g shr 14) or (g shl 50)) xor ((g shr 18) or (g shl 46)) xor ((g shr 41) or (g shl 23))) + ((g and h) xor (not g and a)) + $5CB0A9DCBD41FBD4 + w[22];
T2 := (((c shr 28) or (c shl 36)) xor ((c shr 34) or (c shl 30)) xor ((c shr 39) or (c shl 25))) + ((c and d) xor (c and E) xor (d and E));
f := f + T1;
b := T1 + T2;
T1 := a + (((f shr 14) or (f shl 50)) xor ((f shr 18) or (f shl 46)) xor ((f shr 41) or (f shl 23))) + ((f and g) xor (not f and h)) + $76F988DA831153B5 + w[23];
T2 := (((b shr 28) or (b shl 36)) xor ((b shr 34) or (b shl 30)) xor ((b shr 39) or (b shl 25))) + ((b and c) xor (b and d) xor (c and d));
E := E + T1;
a := T1 + T2;
T1 := h + (((E shr 14) or (E shl 50)) xor ((E shr 18) or (E shl 46)) xor ((E shr 41) or (E shl 23))) + ((E and f) xor (not E and g)) + $983E5152EE66DFAB + w[24];
T2 := (((a shr 28) or (a shl 36)) xor ((a shr 34) or (a shl 30)) xor ((a shr 39) or (a shl 25))) + ((a and b) xor (a and c) xor (b and c));
d := d + T1;
h := T1 + T2;
T1 := g + (((d shr 14) or (d shl 50)) xor ((d shr 18) or (d shl 46)) xor ((d shr 41) or (d shl 23))) + ((d and E) xor (not d and f)) + $A831C66D2DB43210 + w[25];
T2 := (((h shr 28) or (h shl 36)) xor ((h shr 34) or (h shl 30)) xor ((h shr 39) or (h shl 25))) + ((h and a) xor (h and b) xor (a and b));
c := c + T1;
g := T1 + T2;
T1 := f + (((c shr 14) or (c shl 50)) xor ((c shr 18) or (c shl 46)) xor ((c shr 41) or (c shl 23))) + ((c and d) xor (not c and E)) + $B00327C898FB213F + w[26];
T2 := (((g shr 28) or (g shl 36)) xor ((g shr 34) or (g shl 30)) xor ((g shr 39) or (g shl 25))) + ((g and h) xor (g and a) xor (h and a));
b := b + T1;
f := T1 + T2;
T1 := E + (((b shr 14) or (b shl 50)) xor ((b shr 18) or (b shl 46)) xor ((b shr 41) or (b shl 23))) + ((b and c) xor (not b and d)) + $BF597FC7BEEF0EE4 + w[27];
T2 := (((f shr 28) or (f shl 36)) xor ((f shr 34) or (f shl 30)) xor ((f shr 39) or (f shl 25))) + ((f and g) xor (f and h) xor (g and h));
a := a + T1;
E := T1 + T2;
T1 := d + (((a shr 14) or (a shl 50)) xor ((a shr 18) or (a shl 46)) xor ((a shr 41) or (a shl 23))) + ((a and b) xor (not a and c)) + $C6E00BF33DA88FC2 + w[28];
T2 := (((E shr 28) or (E shl 36)) xor ((E shr 34) or (E shl 30)) xor ((E shr 39) or (E shl 25))) + ((E and f) xor (E and g) xor (f and g));
h := h + T1;
d := T1 + T2;
T1 := c + (((h shr 14) or (h shl 50)) xor ((h shr 18) or (h shl 46)) xor ((h shr 41) or (h shl 23))) + ((h and a) xor (not h and b)) + $D5A79147930AA725 + w[29];
T2 := (((d shr 28) or (d shl 36)) xor ((d shr 34) or (d shl 30)) xor ((d shr 39) or (d shl 25))) + ((d and E) xor (d and f) xor (E and f));
g := g + T1;
c := T1 + T2;
T1 := b + (((g shr 14) or (g shl 50)) xor ((g shr 18) or (g shl 46)) xor ((g shr 41) or (g shl 23))) + ((g and h) xor (not g and a)) + $06CA6351E003826F + w[30];
T2 := (((c shr 28) or (c shl 36)) xor ((c shr 34) or (c shl 30)) xor ((c shr 39) or (c shl 25))) + ((c and d) xor (c and E) xor (d and E));
f := f + T1;
b := T1 + T2;
T1 := a + (((f shr 14) or (f shl 50)) xor ((f shr 18) or (f shl 46)) xor ((f shr 41) or (f shl 23))) + ((f and g) xor (not f and h)) + $142929670A0E6E70 + w[31];
T2 := (((b shr 28) or (b shl 36)) xor ((b shr 34) or (b shl 30)) xor ((b shr 39) or (b shl 25))) + ((b and c) xor (b and d) xor (c and d));
E := E + T1;
a := T1 + T2;
T1 := h + (((E shr 14) or (E shl 50)) xor ((E shr 18) or (E shl 46)) xor ((E shr 41) or (E shl 23))) + ((E and f) xor (not E and g)) + $27B70A8546D22FFC + w[32];
T2 := (((a shr 28) or (a shl 36)) xor ((a shr 34) or (a shl 30)) xor ((a shr 39) or (a shl 25))) + ((a and b) xor (a and c) xor (b and c));
d := d + T1;
h := T1 + T2;
T1 := g + (((d shr 14) or (d shl 50)) xor ((d shr 18) or (d shl 46)) xor ((d shr 41) or (d shl 23))) + ((d and E) xor (not d and f)) + $2E1B21385C26C926 + w[33];
T2 := (((h shr 28) or (h shl 36)) xor ((h shr 34) or (h shl 30)) xor ((h shr 39) or (h shl 25))) + ((h and a) xor (h and b) xor (a and b));
c := c + T1;
g := T1 + T2;
T1 := f + (((c shr 14) or (c shl 50)) xor ((c shr 18) or (c shl 46)) xor ((c shr 41) or (c shl 23))) + ((c and d) xor (not c and E)) + $4D2C6DFC5AC42AED + w[34];
T2 := (((g shr 28) or (g shl 36)) xor ((g shr 34) or (g shl 30)) xor ((g shr 39) or (g shl 25))) + ((g and h) xor (g and a) xor (h and a));
b := b + T1;
f := T1 + T2;
T1 := E + (((b shr 14) or (b shl 50)) xor ((b shr 18) or (b shl 46)) xor ((b shr 41) or (b shl 23))) + ((b and c) xor (not b and d)) + $53380D139D95B3DF + w[35];
T2 := (((f shr 28) or (f shl 36)) xor ((f shr 34) or (f shl 30)) xor ((f shr 39) or (f shl 25))) + ((f and g) xor (f and h) xor (g and h));
a := a + T1;
E := T1 + T2;
T1 := d + (((a shr 14) or (a shl 50)) xor ((a shr 18) or (a shl 46)) xor ((a shr 41) or (a shl 23))) + ((a and b) xor (not a and c)) + $650A73548BAF63DE + w[36];
T2 := (((E shr 28) or (E shl 36)) xor ((E shr 34) or (E shl 30)) xor ((E shr 39) or (E shl 25))) + ((E and f) xor (E and g) xor (f and g));
h := h + T1;
d := T1 + T2;
T1 := c + (((h shr 14) or (h shl 50)) xor ((h shr 18) or (h shl 46)) xor ((h shr 41) or (h shl 23))) + ((h and a) xor (not h and b)) + $766A0ABB3C77B2A8 + w[37];
T2 := (((d shr 28) or (d shl 36)) xor ((d shr 34) or (d shl 30)) xor ((d shr 39) or (d shl 25))) + ((d and E) xor (d and f) xor (E and f));
g := g + T1;
c := T1 + T2;
T1 := b + (((g shr 14) or (g shl 50)) xor ((g shr 18) or (g shl 46)) xor ((g shr 41) or (g shl 23))) + ((g and h) xor (not g and a)) + $81C2C92E47EDAEE6 + w[38];
T2 := (((c shr 28) or (c shl 36)) xor ((c shr 34) or (c shl 30)) xor ((c shr 39) or (c shl 25))) + ((c and d) xor (c and E) xor (d and E));
f := f + T1;
b := T1 + T2;
T1 := a + (((f shr 14) or (f shl 50)) xor ((f shr 18) or (f shl 46)) xor ((f shr 41) or (f shl 23))) + ((f and g) xor (not f and h)) + $92722C851482353B + w[39];
T2 := (((b shr 28) or (b shl 36)) xor ((b shr 34) or (b shl 30)) xor ((b shr 39) or (b shl 25))) + ((b and c) xor (b and d) xor (c and d));
E := E + T1;
a := T1 + T2;
T1 := h + (((E shr 14) or (E shl 50)) xor ((E shr 18) or (E shl 46)) xor ((E shr 41) or (E shl 23))) + ((E and f) xor (not E and g)) + $A2BFE8A14CF10364 + w[40];
T2 := (((a shr 28) or (a shl 36)) xor ((a shr 34) or (a shl 30)) xor ((a shr 39) or (a shl 25))) + ((a and b) xor (a and c) xor (b and c));
d := d + T1;
h := T1 + T2;
T1 := g + (((d shr 14) or (d shl 50)) xor ((d shr 18) or (d shl 46)) xor ((d shr 41) or (d shl 23))) + ((d and E) xor (not d and f)) + $A81A664BBC423001 + w[41];
T2 := (((h shr 28) or (h shl 36)) xor ((h shr 34) or (h shl 30)) xor ((h shr 39) or (h shl 25))) + ((h and a) xor (h and b) xor (a and b));
c := c + T1;
g := T1 + T2;
T1 := f + (((c shr 14) or (c shl 50)) xor ((c shr 18) or (c shl 46)) xor ((c shr 41) or (c shl 23))) + ((c and d) xor (not c and E)) + $C24B8B70D0F89791 + w[42];
T2 := (((g shr 28) or (g shl 36)) xor ((g shr 34) or (g shl 30)) xor ((g shr 39) or (g shl 25))) + ((g and h) xor (g and a) xor (h and a));
b := b + T1;
f := T1 + T2;
T1 := E + (((b shr 14) or (b shl 50)) xor ((b shr 18) or (b shl 46)) xor ((b shr 41) or (b shl 23))) + ((b and c) xor (not b and d)) + $C76C51A30654BE30 + w[43];
T2 := (((f shr 28) or (f shl 36)) xor ((f shr 34) or (f shl 30)) xor ((f shr 39) or (f shl 25))) + ((f and g) xor (f and h) xor (g and h));
a := a + T1;
E := T1 + T2;
T1 := d + (((a shr 14) or (a shl 50)) xor ((a shr 18) or (a shl 46)) xor ((a shr 41) or (a shl 23))) + ((a and b) xor (not a and c)) + $D192E819D6EF5218 + w[44];
T2 := (((E shr 28) or (E shl 36)) xor ((E shr 34) or (E shl 30)) xor ((E shr 39) or (E shl 25))) + ((E and f) xor (E and g) xor (f and g));
h := h + T1;
d := T1 + T2;
T1 := c + (((h shr 14) or (h shl 50)) xor ((h shr 18) or (h shl 46)) xor ((h shr 41) or (h shl 23))) + ((h and a) xor (not h and b)) + $D69906245565A910 + w[45];
T2 := (((d shr 28) or (d shl 36)) xor ((d shr 34) or (d shl 30)) xor ((d shr 39) or (d shl 25))) + ((d and E) xor (d and f) xor (E and f));
g := g + T1;
c := T1 + T2;
T1 := b + (((g shr 14) or (g shl 50)) xor ((g shr 18) or (g shl 46)) xor ((g shr 41) or (g shl 23))) + ((g and h) xor (not g and a)) + $F40E35855771202A + w[46];
T2 := (((c shr 28) or (c shl 36)) xor ((c shr 34) or (c shl 30)) xor ((c shr 39) or (c shl 25))) + ((c and d) xor (c and E) xor (d and E));
f := f + T1;
b := T1 + T2;
T1 := a + (((f shr 14) or (f shl 50)) xor ((f shr 18) or (f shl 46)) xor ((f shr 41) or (f shl 23))) + ((f and g) xor (not f and h)) + $106AA07032BBD1B8 + w[47];
T2 := (((b shr 28) or (b shl 36)) xor ((b shr 34) or (b shl 30)) xor ((b shr 39) or (b shl 25))) + ((b and c) xor (b and d) xor (c and d));
E := E + T1;
a := T1 + T2;
T1 := h + (((E shr 14) or (E shl 50)) xor ((E shr 18) or (E shl 46)) xor ((E shr 41) or (E shl 23))) + ((E and f) xor (not E and g)) + $19A4C116B8D2D0C8 + w[48];
T2 := (((a shr 28) or (a shl 36)) xor ((a shr 34) or (a shl 30)) xor ((a shr 39) or (a shl 25))) + ((a and b) xor (a and c) xor (b and c));
d := d + T1;
h := T1 + T2;
T1 := g + (((d shr 14) or (d shl 50)) xor ((d shr 18) or (d shl 46)) xor ((d shr 41) or (d shl 23))) + ((d and E) xor (not d and f)) + $1E376C085141AB53 + w[49];
T2 := (((h shr 28) or (h shl 36)) xor ((h shr 34) or (h shl 30)) xor ((h shr 39) or (h shl 25))) + ((h and a) xor (h and b) xor (a and b));
c := c + T1;
g := T1 + T2;
T1 := f + (((c shr 14) or (c shl 50)) xor ((c shr 18) or (c shl 46)) xor ((c shr 41) or (c shl 23))) + ((c and d) xor (not c and E)) + $2748774CDF8EEB99 + w[50];
T2 := (((g shr 28) or (g shl 36)) xor ((g shr 34) or (g shl 30)) xor ((g shr 39) or (g shl 25))) + ((g and h) xor (g and a) xor (h and a));
b := b + T1;
f := T1 + T2;
T1 := E + (((b shr 14) or (b shl 50)) xor ((b shr 18) or (b shl 46)) xor ((b shr 41) or (b shl 23))) + ((b and c) xor (not b and d)) + $34B0BCB5E19B48A8 + w[51];
T2 := (((f shr 28) or (f shl 36)) xor ((f shr 34) or (f shl 30)) xor ((f shr 39) or (f shl 25))) + ((f and g) xor (f and h) xor (g and h));
a := a + T1;
E := T1 + T2;
T1 := d + (((a shr 14) or (a shl 50)) xor ((a shr 18) or (a shl 46)) xor ((a shr 41) or (a shl 23))) + ((a and b) xor (not a and c)) + $391C0CB3C5C95A63 + w[52];
T2 := (((E shr 28) or (E shl 36)) xor ((E shr 34) or (E shl 30)) xor ((E shr 39) or (E shl 25))) + ((E and f) xor (E and g) xor (f and g));
h := h + T1;
d := T1 + T2;
T1 := c + (((h shr 14) or (h shl 50)) xor ((h shr 18) or (h shl 46)) xor ((h shr 41) or (h shl 23))) + ((h and a) xor (not h and b)) + $4ED8AA4AE3418ACB + w[53];
T2 := (((d shr 28) or (d shl 36)) xor ((d shr 34) or (d shl 30)) xor ((d shr 39) or (d shl 25))) + ((d and E) xor (d and f) xor (E and f));
g := g + T1;
c := T1 + T2;
T1 := b + (((g shr 14) or (g shl 50)) xor ((g shr 18) or (g shl 46)) xor ((g shr 41) or (g shl 23))) + ((g and h) xor (not g and a)) + $5B9CCA4F7763E373 + w[54];
T2 := (((c shr 28) or (c shl 36)) xor ((c shr 34) or (c shl 30)) xor ((c shr 39) or (c shl 25))) + ((c and d) xor (c and E) xor (d and E));
f := f + T1;
b := T1 + T2;
T1 := a + (((f shr 14) or (f shl 50)) xor ((f shr 18) or (f shl 46)) xor ((f shr 41) or (f shl 23))) + ((f and g) xor (not f and h)) + $682E6FF3D6B2B8A3 + w[55];
T2 := (((b shr 28) or (b shl 36)) xor ((b shr 34) or (b shl 30)) xor ((b shr 39) or (b shl 25))) + ((b and c) xor (b and d) xor (c and d));
E := E + T1;
a := T1 + T2;
T1 := h + (((E shr 14) or (E shl 50)) xor ((E shr 18) or (E shl 46)) xor ((E shr 41) or (E shl 23))) + ((E and f) xor (not E and g)) + $748F82EE5DEFB2FC + w[56];
T2 := (((a shr 28) or (a shl 36)) xor ((a shr 34) or (a shl 30)) xor ((a shr 39) or (a shl 25))) + ((a and b) xor (a and c) xor (b and c));
d := d + T1;
h := T1 + T2;
T1 := g + (((d shr 14) or (d shl 50)) xor ((d shr 18) or (d shl 46)) xor ((d shr 41) or (d shl 23))) + ((d and E) xor (not d and f)) + $78A5636F43172F60 + w[57];
T2 := (((h shr 28) or (h shl 36)) xor ((h shr 34) or (h shl 30)) xor ((h shr 39) or (h shl 25))) + ((h and a) xor (h and b) xor (a and b));
c := c + T1;
g := T1 + T2;
T1 := f + (((c shr 14) or (c shl 50)) xor ((c shr 18) or (c shl 46)) xor ((c shr 41) or (c shl 23))) + ((c and d) xor (not c and E)) + $84C87814A1F0AB72 + w[58];
T2 := (((g shr 28) or (g shl 36)) xor ((g shr 34) or (g shl 30)) xor ((g shr 39) or (g shl 25))) + ((g and h) xor (g and a) xor (h and a));
b := b + T1;
f := T1 + T2;
T1 := E + (((b shr 14) or (b shl 50)) xor ((b shr 18) or (b shl 46)) xor ((b shr 41) or (b shl 23))) + ((b and c) xor (not b and d)) + $8CC702081A6439EC + w[59];
T2 := (((f shr 28) or (f shl 36)) xor ((f shr 34) or (f shl 30)) xor ((f shr 39) or (f shl 25))) + ((f and g) xor (f and h) xor (g and h));
a := a + T1;
E := T1 + T2;
T1 := d + (((a shr 14) or (a shl 50)) xor ((a shr 18) or (a shl 46)) xor ((a shr 41) or (a shl 23))) + ((a and b) xor (not a and c)) + $90BEFFFA23631E28 + w[60];
T2 := (((E shr 28) or (E shl 36)) xor ((E shr 34) or (E shl 30)) xor ((E shr 39) or (E shl 25))) + ((E and f) xor (E and g) xor (f and g));
h := h + T1;
d := T1 + T2;
T1 := c + (((h shr 14) or (h shl 50)) xor ((h shr 18) or (h shl 46)) xor ((h shr 41) or (h shl 23))) + ((h and a) xor (not h and b)) + $A4506CEBDE82BDE9 + w[61];
T2 := (((d shr 28) or (d shl 36)) xor ((d shr 34) or (d shl 30)) xor ((d shr 39) or (d shl 25))) + ((d and E) xor (d and f) xor (E and f));
g := g + T1;
c := T1 + T2;
T1 := b + (((g shr 14) or (g shl 50)) xor ((g shr 18) or (g shl 46)) xor ((g shr 41) or (g shl 23))) + ((g and h) xor (not g and a)) + $BEF9A3F7B2C67915 + w[62];
T2 := (((c shr 28) or (c shl 36)) xor ((c shr 34) or (c shl 30)) xor ((c shr 39) or (c shl 25))) + ((c and d) xor (c and E) xor (d and E));
f := f + T1;
b := T1 + T2;
T1 := a + (((f shr 14) or (f shl 50)) xor ((f shr 18) or (f shl 46)) xor ((f shr 41) or (f shl 23))) + ((f and g) xor (not f and h)) + $C67178F2E372532B + w[63];
T2 := (((b shr 28) or (b shl 36)) xor ((b shr 34) or (b shl 30)) xor ((b shr 39) or (b shl 25))) + ((b and c) xor (b and d) xor (c and d));
E := E + T1;
a := T1 + T2;
T1 := h + (((E shr 14) or (E shl 50)) xor ((E shr 18) or (E shl 46)) xor ((E shr 41) or (E shl 23))) + ((E and f) xor (not E and g)) + $CA273ECEEA26619C + w[64];
T2 := (((a shr 28) or (a shl 36)) xor ((a shr 34) or (a shl 30)) xor ((a shr 39) or (a shl 25))) + ((a and b) xor (a and c) xor (b and c));
d := d + T1;
h := T1 + T2;
T1 := g + (((d shr 14) or (d shl 50)) xor ((d shr 18) or (d shl 46)) xor ((d shr 41) or (d shl 23))) + ((d and E) xor (not d and f)) + $D186B8C721C0C207 + w[65];
T2 := (((h shr 28) or (h shl 36)) xor ((h shr 34) or (h shl 30)) xor ((h shr 39) or (h shl 25))) + ((h and a) xor (h and b) xor (a and b));
c := c + T1;
g := T1 + T2;
T1 := f + (((c shr 14) or (c shl 50)) xor ((c shr 18) or (c shl 46)) xor ((c shr 41) or (c shl 23))) + ((c and d) xor (not c and E)) + $EADA7DD6CDE0EB1E + w[66];
T2 := (((g shr 28) or (g shl 36)) xor ((g shr 34) or (g shl 30)) xor ((g shr 39) or (g shl 25))) + ((g and h) xor (g and a) xor (h and a));
b := b + T1;
f := T1 + T2;
T1 := E + (((b shr 14) or (b shl 50)) xor ((b shr 18) or (b shl 46)) xor ((b shr 41) or (b shl 23))) + ((b and c) xor (not b and d)) + $F57D4F7FEE6ED178 + w[67];
T2 := (((f shr 28) or (f shl 36)) xor ((f shr 34) or (f shl 30)) xor ((f shr 39) or (f shl 25))) + ((f and g) xor (f and h) xor (g and h));
a := a + T1;
E := T1 + T2;
T1 := d + (((a shr 14) or (a shl 50)) xor ((a shr 18) or (a shl 46)) xor ((a shr 41) or (a shl 23))) + ((a and b) xor (not a and c)) + $06F067AA72176FBA + w[68];
T2 := (((E shr 28) or (E shl 36)) xor ((E shr 34) or (E shl 30)) xor ((E shr 39) or (E shl 25))) + ((E and f) xor (E and g) xor (f and g));
h := h + T1;
d := T1 + T2;
T1 := c + (((h shr 14) or (h shl 50)) xor ((h shr 18) or (h shl 46)) xor ((h shr 41) or (h shl 23))) + ((h and a) xor (not h and b)) + $0A637DC5A2C898A6 + w[69];
T2 := (((d shr 28) or (d shl 36)) xor ((d shr 34) or (d shl 30)) xor ((d shr 39) or (d shl 25))) + ((d and E) xor (d and f) xor (E and f));
g := g + T1;
c := T1 + T2;
T1 := b + (((g shr 14) or (g shl 50)) xor ((g shr 18) or (g shl 46)) xor ((g shr 41) or (g shl 23))) + ((g and h) xor (not g and a)) + $113F9804BEF90DAE + w[70];
T2 := (((c shr 28) or (c shl 36)) xor ((c shr 34) or (c shl 30)) xor ((c shr 39) or (c shl 25))) + ((c and d) xor (c and E) xor (d and E));
f := f + T1;
b := T1 + T2;
T1 := a + (((f shr 14) or (f shl 50)) xor ((f shr 18) or (f shl 46)) xor ((f shr 41) or (f shl 23))) + ((f and g) xor (not f and h)) + $1B710B35131C471B + w[71];
T2 := (((b shr 28) or (b shl 36)) xor ((b shr 34) or (b shl 30)) xor ((b shr 39) or (b shl 25))) + ((b and c) xor (b and d) xor (c and d));
E := E + T1;
a := T1 + T2;
T1 := h + (((E shr 14) or (E shl 50)) xor ((E shr 18) or (E shl 46)) xor ((E shr 41) or (E shl 23))) + ((E and f) xor (not E and g)) + $28DB77F523047D84 + w[72];
T2 := (((a shr 28) or (a shl 36)) xor ((a shr 34) or (a shl 30)) xor ((a shr 39) or (a shl 25))) + ((a and b) xor (a and c) xor (b and c));
d := d + T1;
h := T1 + T2;
T1 := g + (((d shr 14) or (d shl 50)) xor ((d shr 18) or (d shl 46)) xor ((d shr 41) or (d shl 23))) + ((d and E) xor (not d and f)) + $32CAAB7B40C72493 + w[73];
T2 := (((h shr 28) or (h shl 36)) xor ((h shr 34) or (h shl 30)) xor ((h shr 39) or (h shl 25))) + ((h and a) xor (h and b) xor (a and b));
c := c + T1;
g := T1 + T2;
T1 := f + (((c shr 14) or (c shl 50)) xor ((c shr 18) or (c shl 46)) xor ((c shr 41) or (c shl 23))) + ((c and d) xor (not c and E)) + $3C9EBE0A15C9BEBC + w[74];
T2 := (((g shr 28) or (g shl 36)) xor ((g shr 34) or (g shl 30)) xor ((g shr 39) or (g shl 25))) + ((g and h) xor (g and a) xor (h and a));
b := b + T1;
f := T1 + T2;
T1 := E + (((b shr 14) or (b shl 50)) xor ((b shr 18) or (b shl 46)) xor ((b shr 41) or (b shl 23))) + ((b and c) xor (not b and d)) + $431D67C49C100D4C + w[75];
T2 := (((f shr 28) or (f shl 36)) xor ((f shr 34) or (f shl 30)) xor ((f shr 39) or (f shl 25))) + ((f and g) xor (f and h) xor (g and h));
a := a + T1;
E := T1 + T2;
T1 := d + (((a shr 14) or (a shl 50)) xor ((a shr 18) or (a shl 46)) xor ((a shr 41) or (a shl 23))) + ((a and b) xor (not a and c)) + $4CC5D4BECB3E42B6 + w[76];
T2 := (((E shr 28) or (E shl 36)) xor ((E shr 34) or (E shl 30)) xor ((E shr 39) or (E shl 25))) + ((E and f) xor (E and g) xor (f and g));
h := h + T1;
d := T1 + T2;
T1 := c + (((h shr 14) or (h shl 50)) xor ((h shr 18) or (h shl 46)) xor ((h shr 41) or (h shl 23))) + ((h and a) xor (not h and b)) + $597F299CFC657E2A + w[77];
T2 := (((d shr 28) or (d shl 36)) xor ((d shr 34) or (d shl 30)) xor ((d shr 39) or (d shl 25))) + ((d and E) xor (d and f) xor (E and f));
g := g + T1;
c := T1 + T2;
T1 := b + (((g shr 14) or (g shl 50)) xor ((g shr 18) or (g shl 46)) xor ((g shr 41) or (g shl 23))) + ((g and h) xor (not g and a)) + $5FCB6FAB3AD6FAEC + w[78];
T2 := (((c shr 28) or (c shl 36)) xor ((c shr 34) or (c shl 30)) xor ((c shr 39) or (c shl 25))) + ((c and d) xor (c and E) xor (d and E));
f := f + T1;
b := T1 + T2;
T1 := a + (((f shr 14) or (f shl 50)) xor ((f shr 18) or (f shl 46)) xor ((f shr 41) or (f shl 23))) + ((f and g) xor (not f and h)) + $6C44198C4A475817 + w[79];
T2 := (((b shr 28) or (b shl 36)) xor ((b shr 34) or (b shl 30)) xor ((b shr 39) or (b shl 25))) + ((b and c) xor (b and d) xor (c and d));
E := E + T1;
a := T1 + T2;
inc(PUInt64(@Digest[0])^, a);
inc(PUInt64(@Digest[8])^, b);
inc(PUInt64(@Digest[16])^, c);
inc(PUInt64(@Digest[24])^, d);
inc(PUInt64(@Digest[32])^, E);
inc(PUInt64(@Digest[40])^, f);
inc(PUInt64(@Digest[48])^, g);
inc(PUInt64(@Digest[56])^, h);
{$IFDEF RangeCheck}{$R+}{$ENDIF}
end;
class procedure TSHA512.SHA512(var Digest: TSHA512Digest; const Buf; BufSize: UInt64);
var
Lo, Hi: UInt64;
p: PByte;
ChunkIndex: Byte;
ChunkBuf: array [0 .. 127] of Byte;
begin
{$IFDEF RangeCheck}{$R-}{$ENDIF}
{$IFDEF OverflowCheck}{$Q-}{$ENDIF}
PUInt64(@Digest[0])^ := $6A09E667F3BCC908;
PUInt64(@Digest[8])^ := $BB67AE8584CAA73B;
PUInt64(@Digest[16])^ := $3C6EF372FE94F82B;
PUInt64(@Digest[24])^ := $A54FF53A5F1D36F1;
PUInt64(@Digest[32])^ := $510E527FADE682D1;
PUInt64(@Digest[40])^ := $9B05688C2B3E6C1F;
PUInt64(@Digest[48])^ := $1F83D9ABFB41BD6B;
PUInt64(@Digest[56])^ := $5BE0CD19137E2179;
Lo := 0;
Hi := 0;
inc(Lo, BufSize shl 3);
inc(Hi, BufSize shr 61);
SwapQWORD(Lo);
SwapQWORD(Hi);
p := @Buf;
while BufSize >= 128 do
begin
Compute(Digest, p);
inc(p, 128);
dec(BufSize, 128);
end;
if BufSize > 0 then
CopyPtr(p, @ChunkBuf[0], BufSize);
ChunkBuf[BufSize] := $80;
ChunkIndex := BufSize + 1;
if ChunkIndex > 112 then
begin
if ChunkIndex < 128 then
FillPtrByte(@ChunkBuf[ChunkIndex], 128 - ChunkIndex, 0);
Compute(Digest, @ChunkBuf);
ChunkIndex := 0
end;
FillPtrByte(@ChunkBuf[ChunkIndex], 112 - ChunkIndex, 0);
PUInt64(@ChunkBuf[112])^ := Hi;
PUInt64(@ChunkBuf[120])^ := Lo;
Compute(Digest, @ChunkBuf);
SwapQWORD(PUInt64(@Digest[0])^);
SwapQWORD(PUInt64(@Digest[8])^);
SwapQWORD(PUInt64(@Digest[16])^);
SwapQWORD(PUInt64(@Digest[24])^);
SwapQWORD(PUInt64(@Digest[32])^);
SwapQWORD(PUInt64(@Digest[40])^);
SwapQWORD(PUInt64(@Digest[48])^);
SwapQWORD(PUInt64(@Digest[56])^);
{$IFDEF RangeCheck}{$R+}{$ENDIF}
{$IFDEF OverflowCheck}{$Q+}{$ENDIF}
end;
{$IFDEF RangeCheck}{$R-}{$ENDIF}
{$IFDEF OverflowCheck}{$Q-}{$ENDIF}
class function TSHA3.ComputeX(const x: Integer): Integer;
begin
if x < 0 then
Result := ComputeX(x + 5)
else
Result := x mod 5;
end;
class function TSHA3.ComputeXY(const x, y: Integer): Integer;
begin
Result := ComputeX(x) + 5 * ComputeX(y);
end;
class procedure TSHA3.BlockSHA3(var Context: TSHA3Context);
var
i, x, y: Integer;
begin
i := 0;
while i < Context.BlockLen do
begin
Context.a[i shr 3] := Context.a[i shr 3] Xor PUInt64(@Context.Buffer[i])^;
inc(i, 8);
end;
// keccakf
for i := 0 to 23 do
begin
for x := 0 to 4 do
Context.c[x] :=
Context.a[ComputeXY(x, 0)] Xor
Context.a[ComputeXY(x, 1)] Xor
Context.a[ComputeXY(x, 2)] Xor
Context.a[ComputeXY(x, 3)] Xor
Context.a[ComputeXY(x, 4)];
for x := 0 to 4 do
begin
Context.d[x] := Context.c[ComputeX(x - 1)] Xor ROL64(Context.c[ComputeX(x + 1)], 1);
for y := 0 to 4 do
Context.a[ComputeXY(x, y)] := Context.a[ComputeXY(x, y)] Xor Context.d[x];
end;
for x := 0 to 4 do
for y := 0 to 4 do
Context.b[ComputeXY(y, x * 2 + 3 * y)] := ROL64(Context.a[ComputeXY(x, y)], RO[ComputeXY(x, y)]);
for x := 0 to 4 do
for y := 0 to 4 do
Context.a[ComputeXY(x, y)] := Context.b[ComputeXY(x, y)] Xor ((not Context.b[ComputeXY(x + 1, y)]) And Context.b[ComputeXY(x + 2, y)]);
Context.a[0] := Context.a[0] Xor RC[i];
end;
Context.BufSize := 0;
end;
{$IFDEF RangeCheck}{$R+}{$ENDIF}
{$IFDEF OverflowCheck}{$Q+}{$ENDIF}
class procedure TSHA3.InitializeSHA3(var Context: TSHA3Context; HashLength: Integer);
var
i: Integer;
begin
Context.HashLength := HashLength;
Context.BlockLen := 200 - 2 * HashLength;
SetLength(Context.Buffer, Context.BlockLen);
Context.BufSize := 0;
for i := 0 to 24 do
begin
Context.a[i] := 0;
Context.b[i] := 0;
end;
for i := 0 to 4 do
begin
Context.c[i] := 0;
Context.d[i] := 0;
end;
end;
class procedure TSHA3.SHA3(var Context: TSHA3Context; Chunk: PByte; Size: NativeInt);
var
Needed: NativeInt;
begin
while Size > 0 do
begin
Needed := Min(NativeInt(Context.BlockLen - Context.BufSize), Size);
CopyPtr(Chunk, @Context.Buffer[Context.BufSize], Needed);
inc(Context.BufSize, Needed);
dec(Size, Needed);
if Context.BufSize = Context.BlockLen then
begin
BlockSHA3(Context);
Context.BufSize := 0;
inc(Chunk, Needed);
end;
end;
end;
class procedure TSHA3.FinalizeSHA3(var Context: TSHA3Context; const output: PCCByteArray);
var
i: Integer;
begin
if (Context.BufSize = Context.BlockLen - 1) then
Context.Buffer[Context.BufSize] := Byte($81)
else
begin
Context.Buffer[Context.BufSize] := Byte($06);
FillPtrByte(@Context.Buffer[Context.BufSize + 1], (Context.BlockLen - 2) - (Context.BufSize + 1), 0);
Context.Buffer[Context.BlockLen - 1] := Byte($80);
end;
BlockSHA3(Context);
i := 0;
while i < Context.HashLength do
begin
PUInt64(@output^[i])^ := Context.a[i shr 3];
inc(i, 8);
end;
for i := 0 to 24 do
Context.a[i] := 0;
Context.BufSize := 0;
SetLength(Context.Buffer, 0);
end;
class procedure TSHA3.FinalizeSHAKE(var Context: TSHA3Context; Limit: Integer; const output: PCCByteArray);
var
tmp: array of Byte;
i, k, Size: Integer;
begin
if Context.BufSize = Context.BlockLen - 1 then
Context.Buffer[Context.BufSize] := Byte($9F)
else
begin
Context.Buffer[Context.BufSize] := Byte($1F);
FillPtrByte(@Context.Buffer[Context.BufSize + 1], (Context.BlockLen - 2) - (Context.BufSize + 1), 0);
Context.Buffer[Context.BlockLen - 1] := Byte($80);
end;
BlockSHA3(Context);
FillPtrByte(@Context.Buffer[0], length(Context.Buffer), 0);
SetLength(tmp, Context.BlockLen);
k := 0;
while True do
begin
i := 0;
while i < Context.BlockLen do
begin
PUInt64(@tmp[i])^ := Context.a[i shr 3];
inc(i, 8);
end;
Size := Min(Limit, Context.BlockLen);
CopyPtr(@tmp[0], @output^[k], Min(Size, Limit - k));
dec(Limit, Size);
inc(k, Size);
if Limit <= 0 then
Break;
BlockSHA3(Context);
end;
for i := 0 to 24 do
Context.a[i] := 0;
Context.BufSize := 0;
SetLength(Context.Buffer, 0);
end;
class procedure TSHA3.SHA224(var Digest: TSHA3_224_Digest; Buf: PByte; BufSize: NativeInt);
var
Ctx: TSHA3Context;
begin
InitializeSHA3(Ctx, 224 div 8);
SHA3(Ctx, Buf, BufSize);
FinalizeSHA3(Ctx, @Digest[0]);
end;
class procedure TSHA3.SHA256(var Digest: TSHA3_256_Digest; Buf: PByte; BufSize: NativeInt);
var
Ctx: TSHA3Context;
begin
InitializeSHA3(Ctx, 256 div 8);
SHA3(Ctx, Buf, BufSize);
FinalizeSHA3(Ctx, @Digest[0]);
end;
class procedure TSHA3.SHA384(var Digest: TSHA3_384_Digest; Buf: PByte; BufSize: NativeInt);
var
Ctx: TSHA3Context;
begin
InitializeSHA3(Ctx, 384 div 8);
SHA3(Ctx, Buf, BufSize);
FinalizeSHA3(Ctx, @Digest[0]);
end;
class procedure TSHA3.SHA512(var Digest: TSHA3_512_Digest; Buf: PByte; BufSize: NativeInt);
var
Ctx: TSHA3Context;
begin
InitializeSHA3(Ctx, 512 div 8);
SHA3(Ctx, Buf, BufSize);
FinalizeSHA3(Ctx, @Digest[0]);
end;
class procedure TSHA3.SHAKE128(const Digest: PCCByteArray; Buf: PByte; BufSize: NativeInt; Limit: Integer);
var
Ctx: TSHA3Context;
begin
InitializeSHA3(Ctx, 128 div 8);
SHA3(Ctx, Buf, BufSize);
FinalizeSHAKE(Ctx, Limit div 8, Digest);
end;
class procedure TSHA3.SHAKE256(const Digest: PCCByteArray; Buf: PByte; BufSize: NativeInt; Limit: Integer);
var
Ctx: TSHA3Context;
begin
InitializeSHA3(Ctx, 256 div 8);
SHA3(Ctx, Buf, BufSize);
FinalizeSHAKE(Ctx, Limit div 8, Digest);
end;
{ TLBC }
class procedure TLBC.EncryptLBC(const Context: TLBCContext; var Block: TLBCBlock);
var
Blocks: array [0 .. 1] of TBCHalfBlock; { !!.01 }
Work: TBCHalfBlock;
Right: TBCHalfBlock;
Left: TBCHalfBlock;
AA, BB: Integer;
CC, DD: Integer;
r, t: Integer;
begin
CopyPtr(@Block, @Blocks, SizeOf(Blocks)); { !!.01 }
Right := Blocks[0];
Left := Blocks[1];
for r := 0 to Context.Rounds - 1 do begin
{ transform the right side }
AA := Right[0];
BB := TBCHalfBlock(Context.SubKeys64[r])[0];
CC := Right[1];
DD := TBCHalfBlock(Context.SubKeys64[r])[1];
{ mix it once... }
AA := AA + DD;
DD := DD + AA;
AA := AA xor (AA shr 7);
BB := BB + AA;
AA := AA + BB;
BB := BB xor (BB shl 13);
CC := CC + BB;
BB := BB + CC;
CC := CC xor (CC shr 17);
DD := DD + CC;
CC := CC + DD;
DD := DD xor (DD shl 9);
AA := AA + DD;
DD := DD + AA;
AA := AA xor (AA shr 3);
BB := BB + AA;
AA := AA + BB;
BB := BB xor (BB shl 7);
CC := CC + BB;
BB := BB + CC;
CC := CC xor (DD shr 15);
DD := DD + CC;
CC := CC + DD;
DD := DD xor (DD shl 11);
{ swap sets... }
t := AA;
AA := CC;
CC := t;
t := BB;
BB := DD;
DD := t;
{ mix it twice }
AA := AA + DD;
DD := DD + AA;
AA := AA xor (AA shr 7);
BB := BB + AA;
AA := AA + BB;
BB := BB xor (BB shl 13);
CC := CC + BB;
BB := BB + CC;
CC := CC xor (CC shr 17);
DD := DD + CC;
CC := CC + DD;
DD := DD xor (DD shl 9);
AA := AA + DD;
DD := DD + AA;
AA := AA xor (AA shr 3);
BB := BB + AA;
AA := AA + BB;
BB := BB xor (BB shl 7);
CC := CC + BB;
BB := BB + CC;
CC := CC xor (DD shr 15);
DD := DD + CC;
CC := CC + DD;
DD := DD xor (DD shl 11);
Work[0] := Left[0] xor AA xor BB;
Work[1] := Left[1] xor CC xor DD;
Left := Right;
Right := Work;
end;
Blocks[0] := Left;
Blocks[1] := Right;
CopyPtr(@Blocks, @Block, SizeOf(Block)); { !!.01 }
end;
class procedure TLBC.EncryptLQC(const key: TKey128; var Block: TLQCBlock; Encrypt: Boolean);
const
CKeyBox: array [False .. True, 0 .. 3, 0 .. 2] of Integer =
(((0, 3, 1), (2, 1, 3), (1, 0, 2), (3, 2, 0)),
((3, 2, 0), (1, 0, 2), (2, 1, 3), (0, 3, 1)));
var
KeyInts: array [0 .. 3] of Integer; { !!.01 }
Blocks: array [0 .. 1] of Integer; { !!.01 }
Work: Integer;
Right: Integer;
Left: Integer;
r: Integer;
AA, BB: Integer;
CC, DD: Integer;
begin
CopyPtr(@key, @KeyInts, SizeOf(KeyInts)); { !!.01 }
CopyPtr(@Block, @Blocks, SizeOf(Blocks)); { !!.01 }
Right := Blocks[0];
Left := Blocks[1];
for r := 0 to 3 do begin
{ transform the right side }
AA := Right;
BB := KeyInts[CKeyBox[Encrypt, r, 0]];
CC := KeyInts[CKeyBox[Encrypt, r, 1]];
DD := KeyInts[CKeyBox[Encrypt, r, 2]];
{ commented code does not affect results - removed for speed }
AA := AA + DD;
DD := DD + AA;
AA := AA xor (AA shr 7);
BB := BB + AA;
AA := AA + BB;
BB := BB xor (BB shl 13);
CC := CC + BB;
BB := BB + CC;
CC := CC xor (CC shr 17);
DD := DD + CC;
CC := CC + DD;
DD := DD xor (DD shl 9);
AA := AA + DD;
DD := DD + AA;
AA := AA xor (AA shr 3);
BB := BB + AA; { AA := AA + BB; }
BB := BB xor (BB shl 7);
CC := CC + BB; { BB := BB + CC; }
CC := CC xor (DD shr 15);
DD := DD + CC; { CC := CC + DD; }
DD := DD xor (DD shl 11);
Work := Left xor DD;
Left := Right;
Right := Work;
end;
Blocks[0] := Left;
Blocks[1] := Right;
CopyPtr(@Blocks, @Block, SizeOf(Block)); { !!.01 }
end;
class procedure TLBC.InitEncryptLBC(const key: TKey128; var Context: TLBCContext; Rounds: Integer; Encrypt: Boolean);
type
TDCPTFSubKeys = packed record
case Byte of
0: (SubKeys64: array [0 .. 15] of TKey64);
1: (SubKeysInts: array [0 .. 3, 0 .. 7] of DWORD);
end;
var
KeyArray: PDWordArray;
AA, BB: DWORD;
CC, DD: DWORD;
EE, FF: DWORD;
GG, hh: DWORD;
i, r: Integer;
Temp: TDCPTFSubKeys;
begin
KeyArray := @key;
Context.Encrypt := Encrypt;
Context.Rounds := Max(4, Min(16, Rounds));
{ fill subkeys by propagating seed }
for i := 0 to 3 do begin
{ interleave the key with the salt }
AA := KeyArray^[0];
BB := BCSalts[i];
CC := KeyArray^[1];
DD := BCSalts[i];
EE := KeyArray^[2];
FF := BCSalts[i];
GG := KeyArray^[3];
hh := BCSalts[i];
{ mix all the bits around for 8 rounds }
{ achieves avalanche and eliminates funnels }
for r := 0 to 7 do begin
AA := AA xor (BB shl 11);
DD := DD + AA;
BB := BB + CC;
BB := BB xor (CC shr 2);
EE := EE + BB;
CC := CC + DD;
CC := CC xor (DD shl 8);
FF := FF + CC;
DD := DD + EE;
DD := DD xor (EE shr 16);
GG := GG + DD;
EE := EE + FF;
EE := EE xor (FF shl 10);
hh := hh + EE;
FF := FF + GG;
FF := FF xor (GG shr 4);
AA := AA + FF;
GG := GG + hh;
GG := GG xor (hh shl 8);
BB := BB + GG;
hh := hh + AA;
hh := hh xor (AA shr 9);
CC := CC + hh;
AA := AA + BB;
end;
{ assign value to subkey }
Context.SubKeysInts[i, 0] := AA;
Context.SubKeysInts[i, 1] := BB;
Context.SubKeysInts[i, 2] := CC;
Context.SubKeysInts[i, 3] := DD;
Context.SubKeysInts[i, 4] := EE;
Context.SubKeysInts[i, 5] := FF;
Context.SubKeysInts[i, 6] := GG;
Context.SubKeysInts[i, 7] := hh;
end;
{ reverse subkeys if decrypting - easier for EncryptLBC routine }
if not Encrypt then begin
for i := 0 to Context.Rounds - 1 do
Temp.SubKeys64[(Context.Rounds - 1) - i] := Context.SubKeys64[i];
for i := 0 to Context.Rounds - 1 do
Context.SubKeys64[i] := Temp.SubKeys64[i];
end;
end;
{ THashMD5 }
class procedure THashMD5.FinalizeMD5(var Context: TMD5Context; var Digest: TMD5Digest);
const
Padding: array [0 .. 63] of Byte = (
$80, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00);
var
InBuf: TTransformInput;
MDI: Integer;
i: Word;
II: Word;
PadLen: Word;
begin
{ save number of bits }
InBuf[14] := Context.Count[0];
InBuf[15] := Context.Count[1];
{ compute number of bytes mod 64 }
MDI := (Context.Count[0] shr 3) and $3F;
{ pad out to 56 mod 64 }
if (MDI < 56) then
PadLen := 56 - MDI
else
PadLen := 120 - MDI;
UpdateMD5(Context, Padding, PadLen);
CopyPtr(@Context, @Context, SizeOf(Context)); { !!.01 }
{ append length in bits and transform }
II := 0;
for i := 0 to 13 do
begin
InBuf[i] := (DWORD(Context.Buf[II + 3]) shl 24) or (DWORD(Context.Buf[II + 2]) shl 16) or (DWORD(Context.Buf[II + 1]) shl 8) or DWORD(Context.Buf[II]);
inc(II, 4);
end;
TMISC.Transform(Context.State, InBuf);
{ store buffer in digest }
II := 0;
for i := 0 to 3 do begin
Digest[II] := Byte(Context.State[i] and $FF);
Digest[II + 1] := Byte((Context.State[i] shr 8) and $FF);
Digest[II + 2] := Byte((Context.State[i] shr 16) and $FF);
Digest[II + 3] := Byte((Context.State[i] shr 24) and $FF);
inc(II, 4);
end;
end;
class procedure THashMD5.GenerateMD5Key(var key: TKey128; const ABytes: TBytes);
var
d: TMD5Digest;
begin
HashMD5(d, ABytes[0], length(ABytes));
end;
class procedure THashMD5.HashMD5(var Digest: TMD5Digest; const Buf; BufSize: NativeInt);
var
Context: TMD5Context;
begin
FillPtrByte(@Context, SizeOf(Context), $00);
InitMD5(Context);
UpdateMD5(Context, Buf, BufSize);
FinalizeMD5(Context, Digest);
end;
class procedure THashMD5.InitMD5(var Context: TMD5Context);
begin
Context.Count[0] := 0;
Context.Count[1] := 0;
{ load magic initialization constants }
Context.State[0] := $67452301;
Context.State[1] := $EFCDAB89;
Context.State[2] := $98BADCFE;
Context.State[3] := $10325476;
end;
class procedure THashMD5.ByteBuffHashMD5(var Digest: TMD5Digest; const ABytes: TBytes);
begin
HashMD5(Digest, ABytes[0], length(ABytes));
end;
class procedure THashMD5.UpdateMD5(var Context: TMD5Context; const Buf; BufSize: NativeInt);
var
InBuf: TTransformInput;
BufOfs: DWORD;
MDI: DWORD;
i: DWORD;
begin
// { compute number of bytes mod 64 }
MDI := (Context.Count[0] shr 3) and $3F;
// { update number of bits }
if BufSize shl 3 < 0 then
inc(Context.Count[1]);
inc(Context.Count[0], BufSize shl 3);
inc(Context.Count[1], BufSize shr 29);
{ add new byte acters to buffer }
BufOfs := 0;
while (BufSize > 0) do
begin
dec(BufSize);
Context.Buf[MDI] := TCCByteArray(Buf)[BufOfs]; { !!.01 }
inc(MDI);
inc(BufOfs);
if (MDI = $40) then
begin
for i := 0 to 15 do
InBuf[i] := PDWORD(@Context.Buf[i * 4])^;
TMISC.Transform(Context.State, InBuf);
MDI := 0;
end;
end;
end;
{ TRNG }
class procedure TRNG.EncryptRNG32(var Context: TRNG32Context; var Buf; BufSize: Integer);
var
i: Integer;
begin
for i := 0 to BufSize - 1 do
TCCByteArray(Buf)[i] := TCCByteArray(Buf)[i] xor { !!.01 }
TMISC.Random32Byte(Integer(Context));
end;
class procedure TRNG.EncryptRNG64(var Context: TRNG64Context; var Buf; BufSize: Integer);
var
i: Integer;
begin
for i := 0 to BufSize - 1 do
TCCByteArray(Buf)[i] := TCCByteArray(Buf)[i] xor { !!.01 }
TMISC.Random64Byte(TInt64(Context));
end;
class procedure TRNG.InitEncryptRNG32(key: DWORD; var Context: TRNG32Context);
begin
DWORD(Context) := key;
end;
class procedure TRNG.InitEncryptRNG64(KeyHi, KeyLo: DWORD; var Context: TRNG64Context);
begin
TInt64(Context).Lo := Integer(KeyLo);
TInt64(Context).Hi := Integer(KeyHi);
end;
{ THashMD }
class procedure THashMD.FinalizeLMD(var Context: TLMDContext; var Digest; DigestSize: Integer);
const
Padding: array [0 .. 7] of Byte = (1, 0, 0, 0, 0, 0, 0, 0);
var
BCContext: TLBCContext;
i: Integer;
begin
{ pad with "1", followed by as many "0"s as needed to fill the block }
UpdateLMD(Context, Padding, SizeOf(Padding) - Context.KeyIndex);
{ mix context using block cipher }
TLBC.InitEncryptLBC(Context.key, BCContext, 8, True);
for i := 0 to (SizeOf(Context.Digest) div SizeOf(TLBCBlock)) - 1 do
TLBC.EncryptLBC(BCContext, PLBCBlock(@Context.Digest[i * SizeOf(TLBCBlock)])^);
{ return Digest of requested DigestSize }
{ max digest is 2048-bit, although it could be greater if Pi2048 was larger }
if DigestSize > SizeOf(Context.Digest) then
FillPtrByte(@Digest, DigestSize, 0);
CopyPtr(@Context.Digest, @Digest, Min(SizeOf(Context.Digest), DigestSize));
end;
class procedure THashMD.GenerateLMDKey(var key; KeySize: Integer; const ABytes: TBytes);
begin
HashLMD(key, KeySize, ABytes[0], length(ABytes));
end;
class procedure THashMD.HashLMD(var Digest; DigestSize: Integer; const Buf; BufSize: NativeInt);
var
Context: TLMDContext;
begin
InitLMD(Context);
UpdateLMD(Context, Buf, BufSize);
FinalizeLMD(Context, Digest, DigestSize);
end;
class procedure THashMD.InitLMD(var Context: TLMDContext);
begin
Context.DigestIndex := 0;
TBlock2048(Context.Digest) := TBlock2048(Pi2048);
Context.KeyIndex := 0;
Context.KeyInts[0] := $55555555;
Context.KeyInts[1] := $55555555;
Context.KeyInts[2] := $55555555;
Context.KeyInts[3] := $55555555;
end;
class procedure THashMD.ByteBuffHashLMD(var Digest; DigestSize: Integer; const ABytes: TBytes);
begin
HashLMD(Digest, DigestSize, ABytes[0], length(ABytes));
end;
class procedure THashMD.UpdateLMD(var Context: TLMDContext; const Buf; BufSize: NativeInt);
var
AA, BB, CC, DD: DWORD;
i, r: NativeInt;
begin
for i := 0 to BufSize - 1 do
with Context do begin
{ update Digest }
Digest[DigestIndex] := Digest[DigestIndex] xor
TCCByteArray(Buf)[i]; { !!.01 }
DigestIndex := DigestIndex + 1;
if (DigestIndex = SizeOf(Digest)) then
DigestIndex := 0;
{ update BlockKey }
key[KeyIndex] := key[KeyIndex] xor TCCByteArray(Buf)[i]; { !!.01 }
KeyIndex := KeyIndex + 1;
if (KeyIndex = SizeOf(key) div 2) then begin
AA := KeyInts[3];
BB := KeyInts[2];
CC := KeyInts[1];
DD := KeyInts[0];
{ mix all the bits around for 4 rounds }
{ achieves avalanche and eliminates funnels }
for r := 0 to 3 do
begin
inc(AA, DD);
inc(DD, AA);
AA := AA xor (AA shr 7);
inc(BB, AA);
inc(AA, BB);
BB := BB xor (BB shl 13);
inc(CC, BB);
inc(BB, CC);
CC := CC xor (CC shr 17);
inc(DD, CC);
inc(CC, DD);
DD := DD xor (DD shl 9);
inc(AA, DD);
inc(DD, AA);
AA := AA xor (AA shr 3);
inc(BB, AA);
inc(AA, BB);
BB := BB xor (BB shl 7);
inc(CC, BB);
inc(BB, CC);
CC := CC xor (DD shr 15);
inc(DD, CC);
inc(CC, DD);
DD := DD xor (DD shl 11);
end;
KeyInts[0] := AA;
KeyInts[1] := BB;
KeyInts[2] := CC;
KeyInts[3] := DD;
KeyIndex := 0;
end;
end;
end;
{ TLSC }
class procedure TLSC.EncryptLSC(var Context: TLSCContext; var Buf; BufSize: Integer);
var
l, y, x: Integer;
i, a: Integer;
begin
i := Context.index;
a := Context.Accumulator;
for l := 0 to BufSize - 1 do begin
i := i + 1;
x := Context.SBox[Byte(i)];
y := Context.SBox[Byte(x)] + x;
Context.SBox[Byte(i)] := Context.SBox[Byte(y)];
Context.SBox[Byte(y)] := x;
a := a + Context.SBox[Byte(Byte(y shr 8) + Byte(y))];
TCCByteArray(Buf)[l] := TCCByteArray(Buf)[l] xor Byte(a); { !!.01 }
end;
Context.index := i;
Context.Accumulator := a;
end;
class procedure TLSC.InitEncryptLSC(const key; KeySize: Integer; var Context: TLSCContext);
var
r, i, a: Integer;
x: Byte;
begin
{ initialize SBox }
for i := 0 to 255 do
Context.SBox[i] := i;
a := 0;
for r := 0 to 2 do { 3 rounds - "A" accumulates }
for i := 0 to 255 do
begin
a := a + Context.SBox[i] + TCCByteArray(key)[i mod KeySize]; { !!.01 }
x := Context.SBox[i];
Context.SBox[i] := Context.SBox[Byte(a)];
Context.SBox[Byte(a)] := x;
end;
Context.index := 0;
Context.Accumulator := a;
end;
{ TMISC }
class procedure TMISC.GenerateRandomKey(var key; KeySize: Integer);
var
i: Integer;
begin
MT19937Randomize;
for i := 0 to KeySize - 1 do
TCCByteArray(key)[i] := MT19937Rand32(256); { !!.01 }
end;
class procedure TMISC.HashELF(var Digest: DWORD; const Buf; BufSize: nativeUInt);
var
i: nativeUInt;
x: DWORD;
begin
Digest := 0;
for i := 0 to BufSize - 1 do begin
Digest := (Digest shl 4) + TCCByteArray(Buf)[i]; { !!.01 }
x := Digest and $F0000000;
if (x <> 0) then
Digest := Digest xor (x shr 24);
Digest := Digest and (not x);
end;
end;
class procedure TMISC.HashELF64(var Digest: Int64; const Buf; BufSize: nativeUInt);
var
i: nativeUInt;
x: Int64;
begin
Digest := 0;
for i := 0 to BufSize - 1 do begin
Digest := (Digest shl 4) + TCCByteArray(Buf)[i]; { !!.01 }
x := Digest and Int64($F000000000000000);
if (x <> 0) then
Digest := Digest xor (x shr 56);
Digest := Digest and (not x);
end;
end;
class procedure TMISC.HashMix128(var Digest: DWORD; const Buf; BufSize: NativeInt);
type
T128BitArray = array [0 .. MaxStructSize div SizeOf(T128Bit) - 1] of T128Bit;
var
Temp: T128Bit;
PTemp: PCCByteArray;
i, l: NativeInt;
begin
{$IFDEF RangeCheck}{$R-}{$ENDIF}
Temp[0] := $243F6A88; { first 16 bytes of Pi in binary }
Temp[1] := $93F40317;
Temp[2] := $0C110496;
Temp[3] := $C709C289;
l := BufSize div SizeOf(T128Bit);
for i := 0 to l - 1 do begin
Temp[0] := Temp[0] + T128BitArray(Buf)[i][0]; { !!.01 }
Temp[1] := Temp[1] + T128BitArray(Buf)[i][1]; { !!.01 }
Temp[2] := Temp[2] + T128BitArray(Buf)[i][2]; { !!.01 }
Temp[3] := Temp[3] + T128BitArray(Buf)[i][3]; { !!.01 }
Mix128(Temp);
end;
PTemp := @Temp;
if (BufSize > l * SizeOf(T128Bit)) then
begin
for i := 0 to (BufSize - l * SizeOf(T128Bit)) - 1 do
inc(PTemp^[i], PCCByteArray(@Buf)^[(l * SizeOf(T128Bit)) + i]); { !!.01 }
Mix128(Temp);
end;
Digest := Temp[3];
{$IFDEF RangeCheck}{$R+}{$ENDIF}
end;
class procedure TMISC.Mix128(var x: T128Bit);
var
AA, BB, CC, DD: DWORD;
begin
AA := x[0];
BB := x[1];
CC := x[2];
DD := x[3];
AA := AA + DD;
DD := DD + AA;
AA := AA xor (AA shr 7);
BB := BB + AA;
AA := AA + BB;
BB := BB xor (BB shl 13);
CC := CC + BB;
BB := BB + CC;
CC := CC xor (CC shr 17);
DD := DD + CC;
CC := CC + DD;
DD := DD xor (DD shl 9);
AA := AA + DD;
DD := DD + AA;
AA := AA xor (AA shr 3);
BB := BB + AA;
AA := AA + BB;
BB := BB xor (BB shl 7);
CC := CC + BB;
BB := BB + CC;
CC := CC xor (DD shr 15);
DD := DD + CC;
CC := CC + DD;
DD := DD xor (DD shl 11);
x[0] := AA;
x[1] := BB;
x[2] := CC;
x[3] := DD;
end;
class function TMISC.Ran01(var Seed: Integer): Integer;
begin
Result := Ran0Prim(Seed, 16807, 127773, 2836);
end;
class function TMISC.Ran02(var Seed: Integer): Integer;
begin
Result := Ran0Prim(Seed, 48271, 44488, 3399);
end;
class function TMISC.Ran03(var Seed: Integer): Integer;
begin
Result := Ran0Prim(Seed, 69621, 30845, 23902);
end;
class function TMISC.Ran0Prim(var Seed: Integer; IA, IQ, IR: Integer): Integer;
const
IM = 2147483647;
MA = 123459876;
var
i, k: Integer;
begin
{ XORing with mask avoids seeds of zero }
i := Seed xor MA;
k := i div IQ;
i := (IA * (i - (k * IQ))) - (IR * k);
if i < 0 then
i := i + IM;
Result := i xor MA;
Seed := Result;
end;
class function TMISC.Random32Byte(var Seed: Integer): Byte;
var
l: Integer;
r: TInt32;
begin
l := Ran01(Seed);
r := TInt32(l);
Result := r.LoLo xor r.LoHi xor r.HiLo xor r.HiHi;
end;
class function TMISC.Random64(var Seed: TInt64): Integer;
begin
Ran01(Seed.Lo);
Ran01(Seed.Hi);
Result := Seed.Lo xor Seed.Hi;
end;
class function TMISC.Random64Byte(var Seed: TInt64): Byte;
var
l: Integer;
r: TInt32;
begin
l := Random64(Seed);
r := TInt32(l);
Result := r.LoLo xor r.LoHi xor r.HiLo xor r.HiHi;
end;
class function TMISC.RolX(i, c: DWORD): DWORD;
begin
Result := (i shl (c and 31)) or (i shr (32 - (c and 31)));
end;
class procedure TMISC.ByteBuffHashELF(var Digest: DWORD; const ABytes: TBytes);
begin
HashELF(Digest, ABytes[0], length(ABytes));
end;
class procedure TMISC.ByteBuffHashMix128(var Digest: DWORD; const ABytes: TBytes);
begin
HashMix128(Digest, ABytes[0], length(ABytes));
end;
class procedure TMISC.Transform(var OutputBuffer: TTransformOutput; var InBuf: TTransformInput);
const
S11 = 7;
S12 = 12;
S13 = 17;
S14 = 22;
S21 = 5;
S22 = 9;
S23 = 14;
S24 = 20;
S31 = 4;
S32 = 11;
S33 = 16;
S34 = 23;
S41 = 6;
S42 = 10;
S43 = 15;
S44 = 21;
var
a: DWORD;
b: DWORD;
c: DWORD;
d: DWORD;
procedure FF(var a: DWORD; const b, c, d, x, s, AC: DWORD);
begin
a := RolX(a + ((b and c) or (not b and d)) + x + AC, s) + b;
end;
procedure GG(var a: DWORD; const b, c, d, x, s, AC: DWORD);
begin
a := RolX(a + ((b and d) or (c and not d)) + x + AC, s) + b;
end;
procedure hh(var a: DWORD; const b, c, d, x, s, AC: DWORD);
begin
a := RolX(a + (b xor c xor d) + x + AC, s) + b;
end;
procedure II(var a: DWORD; const b, c, d, x, s, AC: DWORD);
begin
a := RolX(a + (c xor (b or not d)) + x + AC, s) + b;
end;
begin
a := OutputBuffer[0];
b := OutputBuffer[1];
c := OutputBuffer[2];
d := OutputBuffer[3];
{ round 1 }
FF(a, b, c, d, InBuf[0], S11, $D76AA478); { 1 }
FF(d, a, b, c, InBuf[1], S12, $E8C7B756); { 2 }
FF(c, d, a, b, InBuf[2], S13, $242070DB); { 3 }
FF(b, c, d, a, InBuf[3], S14, $C1BDCEEE); { 4 }
FF(a, b, c, d, InBuf[4], S11, $F57C0FAF); { 5 }
FF(d, a, b, c, InBuf[5], S12, $4787C62A); { 6 }
FF(c, d, a, b, InBuf[6], S13, $A8304613); { 7 }
FF(b, c, d, a, InBuf[7], S14, $FD469501); { 8 }
FF(a, b, c, d, InBuf[8], S11, $698098D8); { 9 }
FF(d, a, b, c, InBuf[9], S12, $8B44F7AF); { 10 }
FF(c, d, a, b, InBuf[10], S13, $FFFF5BB1); { 11 }
FF(b, c, d, a, InBuf[11], S14, $895CD7BE); { 12 }
FF(a, b, c, d, InBuf[12], S11, $6B901122); { 13 }
FF(d, a, b, c, InBuf[13], S12, $FD987193); { 14 }
FF(c, d, a, b, InBuf[14], S13, $A679438E); { 15 }
FF(b, c, d, a, InBuf[15], S14, $49B40821); { 16 }
{ round 2 }
GG(a, b, c, d, InBuf[1], S21, $F61E2562); { 17 }
GG(d, a, b, c, InBuf[6], S22, $C040B340); { 18 }
GG(c, d, a, b, InBuf[11], S23, $265E5A51); { 19 }
GG(b, c, d, a, InBuf[0], S24, $E9B6C7AA); { 20 }
GG(a, b, c, d, InBuf[5], S21, $D62F105D); { 21 }
GG(d, a, b, c, InBuf[10], S22, $02441453); { 22 }
GG(c, d, a, b, InBuf[15], S23, $D8A1E681); { 23 }
GG(b, c, d, a, InBuf[4], S24, $E7D3FBC8); { 24 }
GG(a, b, c, d, InBuf[9], S21, $21E1CDE6); { 25 }
GG(d, a, b, c, InBuf[14], S22, $C33707D6); { 26 }
GG(c, d, a, b, InBuf[3], S23, $F4D50D87); { 27 }
GG(b, c, d, a, InBuf[8], S24, $455A14ED); { 28 }
GG(a, b, c, d, InBuf[13], S21, $A9E3E905); { 29 }
GG(d, a, b, c, InBuf[2], S22, $FCEFA3F8); { 30 }
GG(c, d, a, b, InBuf[7], S23, $676F02D9); { 31 }
GG(b, c, d, a, InBuf[12], S24, $8D2A4C8A); { 32 }
{ round 3 }
hh(a, b, c, d, InBuf[5], S31, $FFFA3942); { 33 }
hh(d, a, b, c, InBuf[8], S32, $8771F681); { 34 }
hh(c, d, a, b, InBuf[11], S33, $6D9D6122); { 35 }
hh(b, c, d, a, InBuf[14], S34, $FDE5380C); { 36 }
hh(a, b, c, d, InBuf[1], S31, $A4BEEA44); { 37 }
hh(d, a, b, c, InBuf[4], S32, $4BDECFA9); { 38 }
hh(c, d, a, b, InBuf[7], S33, $F6BB4B60); { 39 }
hh(b, c, d, a, InBuf[10], S34, $BEBFBC70); { 40 }
hh(a, b, c, d, InBuf[13], S31, $289B7EC6); { 41 }
hh(d, a, b, c, InBuf[0], S32, $EAA127FA); { 42 }
hh(c, d, a, b, InBuf[3], S33, $D4EF3085); { 43 }
hh(b, c, d, a, InBuf[6], S34, $4881D05); { 44 }
hh(a, b, c, d, InBuf[9], S31, $D9D4D039); { 45 }
hh(d, a, b, c, InBuf[12], S32, $E6DB99E5); { 46 }
hh(c, d, a, b, InBuf[15], S33, $1FA27CF8); { 47 }
hh(b, c, d, a, InBuf[2], S34, $C4AC5665); { 48 }
{ round 4 }
II(a, b, c, d, InBuf[0], S41, $F4292244); { 49 }
II(d, a, b, c, InBuf[7], S42, $432AFF97); { 50 }
II(c, d, a, b, InBuf[14], S43, $AB9423A7); { 51 }
II(b, c, d, a, InBuf[5], S44, $FC93A039); { 52 }
II(a, b, c, d, InBuf[12], S41, $655B59C3); { 53 }
II(d, a, b, c, InBuf[3], S42, $8F0CCC92); { 54 }
II(c, d, a, b, InBuf[10], S43, $FFEFF47D); { 55 }
II(b, c, d, a, InBuf[1], S44, $85845DD1); { 56 }
II(a, b, c, d, InBuf[8], S41, $6FA87E4F); { 57 }
II(d, a, b, c, InBuf[15], S42, $FE2CE6E0); { 58 }
II(c, d, a, b, InBuf[6], S43, $A3014314); { 59 }
II(b, c, d, a, InBuf[13], S44, $4E0811A1); { 60 }
II(a, b, c, d, InBuf[4], S41, $F7537E82); { 61 }
II(d, a, b, c, InBuf[11], S42, $BD3AF235); { 62 }
II(c, d, a, b, InBuf[2], S43, $2AD7D2BB); { 63 }
II(b, c, d, a, InBuf[9], S44, $EB86D391); { 64 }
inc(OutputBuffer[0], a);
inc(OutputBuffer[1], b);
inc(OutputBuffer[2], c);
inc(OutputBuffer[3], d);
end;
class procedure TMISC.XorMem(var Mem1; const Mem2; Count: NativeInt);
var
siz: Byte;
i: Integer;
p1, p2: nativeUInt;
begin
p1 := nativeUInt(@Mem1);
p2 := nativeUInt(@Mem2);
siz := SizeOf(nativeUInt);
for i := 1 to Count div siz do
begin
PNativeUInt(p1)^ := PNativeUInt(p1)^ xor PNativeUInt(p2)^;
p1 := p1 + siz;
p2 := p2 + siz;
end;
for i := 1 to Count mod siz do
begin
PByte(p1)^ := PByte(p1)^ xor PByte(p2)^;
p1 := p1 + 1;
p2 := p2 + 1;
end;
end;
function XXTeaMX(Sum, y, z, p, E: DWORD; const k: PDWordArray): DWORD;
begin
{$IFDEF OverflowCheck}{$Q-}{$ENDIF}
{$IFDEF RangeCheck}{$R-}{$ENDIF}
Result := (((z shr 5) xor (y shl 2)) + ((y shr 3) xor (z shl 4))) xor ((Sum xor y) + (k^[p and 3 xor E] xor z));
{$IFDEF RangeCheck}{$R+}{$ENDIF}
{$IFDEF OverflowCheck}{$Q+}{$ENDIF}
end;
procedure XXTEAEncrypt(var key: TKey128; var Block: TXXTEABlock);
const
XXTeaDelta = $9E3779B9;
var
k, v: PDWordArray;
n, z, y, Sum, E, p, q: DWORD;
begin
{$IFDEF RangeCheck}{$R-}{$ENDIF}
n := 64 div 4 - 1;
k := PDWordArray(@key[0]);
v := PDWordArray(@Block[0]);
z := v^[n];
Sum := 0;
q := 6 + 52 div (n + 1);
repeat
inc(Sum, XXTeaDelta);
E := (Sum shr 2) and 3;
for p := 0 to n - 1 do begin
y := v^[p + 1];
inc(v^[p], XXTeaMX(Sum, y, z, p, E, k));
z := v^[p];
end;
p := n;
y := v^[0];
inc(v^[p], XXTeaMX(Sum, y, z, p, E, k));
z := v^[p];
dec(q);
until q = 0;
{$IFDEF RangeCheck}{$R+}{$ENDIF}
end;
procedure XXTEADecrypt(var key: TKey128; var Block: TXXTEABlock);
const
XXTeaDelta = $9E3779B9;
var
k, v: PDWordArray;
n, z, y, Sum, E, p, q: DWORD;
begin
{$IFDEF RangeCheck}{$R-}{$ENDIF}
n := 64 div 4 - 1;
k := PDWordArray(@key[0]);
v := PDWordArray(@Block[0]);
y := v^[0];
q := 6 + 52 div (n + 1);
Sum := q * XXTeaDelta;
while (Sum <> 0) do
begin
E := (Sum shr 2) and 3;
for p := n downto 1 do begin
z := v^[p - 1];
dec(v^[p], XXTeaMX(Sum, y, z, p, E, k));
y := v^[p];
end;
p := 0;
z := v^[n];
dec(v^[0], XXTeaMX(Sum, y, z, p, E, k));
y := v^[0];
dec(Sum, XXTeaDelta);
end;
{$IFDEF RangeCheck}{$R+}{$ENDIF}
end;
class function TRC6.LRot32(x, c: DWORD): DWORD;
begin
LRot32 := ROL32(x, Byte(c));
end;
class function TRC6.RRot32(x, c: DWORD): DWORD;
begin
RRot32 := ROR32(x, Byte(c))
end;
class procedure TRC6.InitKey(buff: Pointer; Size: Integer; var KeyContext: TRC6Key);
const
cRC6_sBox: array [0 .. 51] of DWORD = (
$B7E15163, $5618CB1C, $F45044D5, $9287BE8E, $30BF3847, $CEF6B200,
$6D2E2BB9, $0B65A572, $A99D1F2B, $47D498E4, $E60C129D, $84438C56,
$227B060F, $C0B27FC8, $5EE9F981, $FD21733A, $9B58ECF3, $399066AC,
$D7C7E065, $75FF5A1E, $1436D3D7, $B26E4D90, $50A5C749, $EEDD4102,
$8D14BABB, $2B4C3474, $C983AE2D, $67BB27E6, $05F2A19F, $A42A1B58,
$42619511, $E0990ECA, $7ED08883, $1D08023C, $BB3F7BF5, $5976F5AE,
$F7AE6F67, $95E5E920, $341D62D9, $D254DC92, $708C564B, $0EC3D004,
$ACFB49BD, $4B32C376, $E96A3D2F, $87A1B6E8, $25D930A1, $C410AA5A,
$62482413, $007F9DCC, $9EB71785, $3CEE913E);
var
xKeyD: array [0 .. 63] of DWORD;
i, j, k, xKeyLen, a, b: DWORD;
begin
Size := Size div 8;
CopyPtr(buff, @xKeyD, Size);
xKeyLen := Size div 4;
if (Size mod 4) <> 0 then
inc(xKeyLen);
CopyPtr(@cRC6_sBox, @KeyContext, ((cRC6_NumRounds * 2) + 4) * 4);
i := 0;
j := 0;
a := 0;
b := 0;
if xKeyLen > ((cRC6_NumRounds * 2) + 4) then
k := xKeyLen * 3
else
k := ((cRC6_NumRounds * 2) + 4) * 3;
for k := 1 to k do
begin
a := LRot32(KeyContext[i] + a + b, 3);
KeyContext[i] := a;
b := LRot32(xKeyD[j] + a + b, a + b);
xKeyD[j] := b;
i := (i + 1) mod ((cRC6_NumRounds * 2) + 4);
j := (j + 1) mod xKeyLen;
end;
end;
class procedure TRC6.Encrypt(var KeyContext: TRC6Key; var Data: TRC6Block);
var
x0, x1, x2, x3: PDWORD;
u, t, i: DWORD;
begin
{$IFDEF RangeCheck}{$R-}{$ENDIF}
x0 := PDWORD(@Data[0]);
x1 := PDWORD(@Data[4]);
x2 := PDWORD(@Data[8]);
x3 := PDWORD(@Data[12]);
x1^ := x1^ + KeyContext[0];
x3^ := x3^ + KeyContext[1];
for i := 1 to cRC6_NumRounds do
begin
t := LRot32(x1^ * (2 * x1^ + 1), 5);
u := LRot32(x3^ * (2 * x3^ + 1), 5);
x0^ := LRot32(x0^ xor t, u) + KeyContext[2 * i];
x2^ := LRot32(x2^ xor u, t) + KeyContext[2 * i + 1];
t := x0^;
x0^ := x1^;
x1^ := x2^;
x2^ := x3^;
x3^ := t;
end;
x0^ := x0^ + KeyContext[(2 * cRC6_NumRounds) + 2];
x2^ := x2^ + KeyContext[(2 * cRC6_NumRounds) + 3];
{$IFDEF RangeCheck}{$R+}{$ENDIF}
end;
class procedure TRC6.Decrypt(var KeyContext: TRC6Key; var Data: TRC6Block);
var
x0, x1, x2, x3: PDWORD;
u, t, i: DWORD;
begin
{$IFDEF RangeCheck}{$R-}{$ENDIF}
x0 := PDWORD(@Data[0]);
x1 := PDWORD(@Data[4]);
x2 := PDWORD(@Data[8]);
x3 := PDWORD(@Data[12]);
x2^ := x2^ - KeyContext[(2 * cRC6_NumRounds) + 3];
x0^ := x0^ - KeyContext[(2 * cRC6_NumRounds) + 2];
for i := cRC6_NumRounds downto 1 do
begin
t := x0^;
x0^ := x3^;
x3^ := x2^;
x2^ := x1^;
x1^ := t;
u := LRot32(x3^ * (2 * x3^ + 1), 5);
t := LRot32(x1^ * (2 * x1^ + 1), 5);
x2^ := RRot32(x2^ - KeyContext[2 * i + 1], t) xor u;
x0^ := RRot32(x0^ - KeyContext[2 * i], u) xor t;
end;
x3^ := x3^ - KeyContext[1];
x1^ := x1^ - KeyContext[0];
{$IFDEF RangeCheck}{$R+}{$ENDIF}
end;
class procedure TSerpent.InitKey(buff: Pointer; Size: Integer; var KeyContext: TSerpentkey);
var
kp: array [0 .. 139] of DWORD;
i, n: DWORD;
t0, T1, T2, T3, T4, T5, T6, T7, T8, t9, t10, t11, t12, t13, t14, t15, t16, t17: DWORD;
a, b, c, d: DWORD;
begin
FillPtrByte(@kp[0], SizeOf(kp), 0);
CopyPtr(buff, @kp[0], Size);
for i := 8 to 139 do
begin
t0 := kp[i - 8] xor kp[i - 5] xor kp[i - 3] xor kp[i - 1] xor $9E3779B9 xor DWORD(i - 8);
kp[i] := (t0 shl 11) or (t0 shr 21);
end;
for i := 0 to 3 do
begin
n := i * 32;
a := kp[n + 4 * 0 + 8];
b := kp[n + 4 * 0 + 9];
c := kp[n + 4 * 0 + 10];
d := kp[n + 4 * 0 + 11];
T1 := a xor c;
T2 := a or d;
T3 := a and b;
T4 := a and d;
T5 := b or T4;
T6 := T1 and T2;
kp[9 + n] := T5 xor T6;
T8 := b xor d;
t9 := c or T3;
t10 := T6 xor T8;
kp[11 + n] := t9 xor t10;
t12 := c xor T3;
t13 := T2 and kp[11 + n];
kp[10 + n] := t12 xor t13;
t15 := not kp[10 + n];
t16 := T2 xor T3;
t17 := kp[9 + n] and t15;
kp[8 + n] := t16 xor t17;
a := kp[n + 4 * 1 + 8];
b := kp[n + 4 * 1 + 9];
c := kp[n + 4 * 1 + 10];
d := kp[n + 4 * 1 + 11];
T1 := not a;
T2 := b xor d;
T3 := c and T1;
kp[12 + n] := T2 xor T3;
T5 := c xor T1;
T6 := c xor kp[12 + n];
T7 := b and T6;
kp[15 + n] := T5 xor T7;
t9 := d or T7;
t10 := kp[12 + n] or T5;
t11 := t9 and t10;
kp[14 + n] := a xor t11;
t13 := d or T1;
t14 := T2 xor kp[15 + n];
t15 := kp[14 + n] xor t13;
kp[13 + n] := t14 xor t15;
a := kp[n + 4 * 2 + 8];
b := kp[n + 4 * 2 + 9];
c := kp[n + 4 * 2 + 10];
d := kp[n + 4 * 2 + 11];
T1 := a xor d;
T2 := b xor d;
T3 := a and b;
T4 := not c;
T5 := T2 xor T3;
kp[18 + n] := T4 xor T5;
T7 := a xor T2;
T8 := b or T4;
t9 := d or kp[18 + n];
t10 := T7 and t9;
kp[17 + n] := T8 xor t10;
t12 := c xor d;
t13 := T1 or T2;
t14 := kp[17 + n] xor t12;
kp[19 + n] := t13 xor t14;
t16 := T1 or kp[18 + n];
t17 := T8 xor t14;
kp[16 + n] := t16 xor t17;
a := kp[n + 4 * 3 + 8];
b := kp[n + 4 * 3 + 9];
c := kp[n + 4 * 3 + 10];
d := kp[n + 4 * 3 + 11];
T1 := b xor d;
T2 := not T1;
T3 := a or d;
T4 := b xor c;
kp[23 + n] := T3 xor T4;
T6 := a xor b;
T7 := a or T4;
T8 := c and T6;
t9 := T2 or T8;
kp[20 + n] := T7 xor t9;
t11 := a xor kp[23 + n];
t12 := T1 and T6;
t13 := kp[20 + n] xor t11;
kp[21 + n] := t12 xor t13;
t15 := kp[20 + n] or kp[21 + n];
t16 := T3 and t15;
kp[22 + n] := b xor t16;
a := kp[n + 4 * 4 + 8];
b := kp[n + 4 * 4 + 9];
c := kp[n + 4 * 4 + 10];
d := kp[n + 4 * 4 + 11];
T1 := not c;
T2 := b xor c;
T3 := b or T1;
T4 := d xor T3;
T5 := a and T4;
kp[27 + n] := T2 xor T5;
T7 := a xor d;
T8 := b xor T5;
t9 := T2 or T8;
kp[25 + n] := T7 xor t9;
t11 := d and T3;
t12 := T5 xor kp[25 + n];
t13 := kp[27 + n] and t12;
kp[26 + n] := t11 xor t13;
t15 := T1 or T4;
t16 := t12 xor kp[26 + n];
kp[24 + n] := t15 xor t16;
a := kp[n + 4 * 5 + 8];
b := kp[n + 4 * 5 + 9];
c := kp[n + 4 * 5 + 10];
d := kp[n + 4 * 5 + 11];
T1 := a xor c;
T2 := b or d;
T3 := b xor c;
T4 := not T3;
T5 := a and d;
kp[29 + n] := T4 xor T5;
T7 := b or c;
T8 := d xor T1;
t9 := T7 and T8;
kp[31 + n] := T2 xor t9;
t11 := T1 and T7;
t12 := T4 xor T8;
t13 := kp[31 + n] and t11;
kp[28 + n] := t12 xor t13;
t15 := T3 xor t11;
t16 := kp[31 + n] or t15;
kp[30 + n] := t12 xor t16;
a := kp[n + 4 * 6 + 8];
b := kp[n + 4 * 6 + 9];
c := kp[n + 4 * 6 + 10];
d := kp[n + 4 * 6 + 11];
T1 := not a;
T2 := a xor b;
T3 := a xor d;
T4 := c xor T1;
T5 := T2 or T3;
kp[32 + n] := T4 xor T5;
T7 := not d;
T8 := kp[32 + n] and T7;
kp[33 + n] := T2 xor T8;
t10 := b or kp[33 + n];
t11 := c or kp[32 + n];
t12 := T7 xor t10;
kp[35 + n] := t11 xor t12;
t14 := d or kp[33 + n];
t15 := T1 xor t14;
t16 := kp[32 + n] or kp[35 + n];
kp[34 + n] := t15 xor t16;
a := kp[n + 4 * 7 + 8];
b := kp[n + 4 * 7 + 9];
c := kp[n + 4 * 7 + 10];
d := kp[n + 4 * 7 + 11];
T1 := not a;
T2 := a xor d;
T3 := a xor b;
T4 := c xor T1;
T5 := T2 or T3;
kp[36 + n] := T4 xor T5;
T7 := not kp[36 + n];
T8 := b or T7;
kp[39 + n] := T2 xor T8;
t10 := a and kp[36 + n];
t11 := b xor kp[39 + n];
t12 := T8 and t11;
kp[38 + n] := t10 xor t12;
t14 := a or T7;
t15 := T3 xor t14;
t16 := kp[39 + n] and kp[38 + n];
kp[37 + n] := t15 xor t16;
end;
a := kp[136];
b := kp[137];
c := kp[138];
d := kp[139];
T1 := a xor c;
T2 := a or d;
T3 := a and b;
T4 := a and d;
T5 := b or T4;
T6 := T1 and T2;
kp[137] := T5 xor T6;
T8 := b xor d;
t9 := c or T3;
t10 := T6 xor T8;
kp[139] := t9 xor t10;
t12 := c xor T3;
t13 := T2 and kp[139];
kp[138] := t12 xor t13;
t15 := not kp[138];
t16 := T2 xor T3;
t17 := kp[137] and t15;
kp[136] := t16 xor t17;
CopyPtr(@kp, @KeyContext, SizeOf(KeyContext));
end;
class procedure TSerpent.Encrypt(var KeyContext: TSerpentkey; var Data: TSerpentBlock);
var
i: DWORD;
a, b, c, d, E, f, g, h: DWORD;
T1, T2, T3, T4, T5, T6, T7, T8, t9, t10, t11, t12, t13, t14, t15, t16, t17: DWORD;
begin
a := PDWORD(@Data[0])^;
b := PDWORD(@Data[4])^;
c := PDWORD(@Data[8])^;
d := PDWORD(@Data[12])^;
i := 0;
while i < 32 do
begin
a := a xor KeyContext[4 * (i)];
b := b xor KeyContext[4 * (i) + 1];
c := c xor KeyContext[4 * (i) + 2];
d := d xor KeyContext[4 * (i) + 3];
T1 := b xor d;
T2 := not T1;
T3 := a or d;
T4 := b xor c;
h := T3 xor T4;
T6 := a xor b;
T7 := a or T4;
T8 := c and T6;
t9 := T2 or T8;
E := T7 xor t9;
t11 := a xor h;
t12 := T1 and T6;
t13 := E xor t11;
f := t12 xor t13;
t15 := E or f;
t16 := T3 and t15;
g := b xor t16;
E := (E shl 13) or (E shr 19);
g := (g shl 3) or (g shr 29);
f := f xor E xor g;
h := h xor g xor (E shl 3);
f := (f shl 1) or (f shr 31);
h := (h shl 7) or (h shr 25);
E := E xor f xor h;
g := g xor h xor (f shl 7);
E := (E shl 5) or (E shr 27);
g := (g shl 22) or (g shr 10);
E := E xor KeyContext[4 * (i + 1)];
f := f xor KeyContext[4 * (i + 1) + 1];
g := g xor KeyContext[4 * (i + 1) + 2];
h := h xor KeyContext[4 * (i + 1) + 3];
T1 := E xor h;
T2 := f xor h;
T3 := E and f;
T4 := not g;
T5 := T2 xor T3;
c := T4 xor T5;
T7 := E xor T2;
T8 := f or T4;
t9 := h or c;
t10 := T7 and t9;
b := T8 xor t10;
t12 := g xor h;
t13 := T1 or T2;
t14 := b xor t12;
d := t13 xor t14;
t16 := T1 or c;
t17 := T8 xor t14;
a := t16 xor t17;
a := (a shl 13) or (a shr 19);
c := (c shl 3) or (c shr 29);
b := b xor a xor c;
d := d xor c xor (a shl 3);
b := (b shl 1) or (b shr 31);
d := (d shl 7) or (d shr 25);
a := a xor b xor d;
c := c xor d xor (b shl 7);
a := (a shl 5) or (a shr 27);
c := (c shl 22) or (c shr 10);
a := a xor KeyContext[4 * (i + 2)];
b := b xor KeyContext[4 * (i + 2) + 1];
c := c xor KeyContext[4 * (i + 2) + 2];
d := d xor KeyContext[4 * (i + 2) + 3];
T1 := not a;
T2 := b xor d;
T3 := c and T1;
E := T2 xor T3;
T5 := c xor T1;
T6 := c xor E;
T7 := b and T6;
h := T5 xor T7;
t9 := d or T7;
t10 := E or T5;
t11 := t9 and t10;
g := a xor t11;
t13 := d or T1;
t14 := T2 xor h;
t15 := g xor t13;
f := t14 xor t15;
E := (E shl 13) or (E shr 19);
g := (g shl 3) or (g shr 29);
f := f xor E xor g;
h := h xor g xor (E shl 3);
f := (f shl 1) or (f shr 31);
h := (h shl 7) or (h shr 25);
E := E xor f xor h;
g := g xor h xor (f shl 7);
E := (E shl 5) or (E shr 27);
g := (g shl 22) or (g shr 10);
E := E xor KeyContext[4 * (i + 3)];
f := f xor KeyContext[4 * (i + 3) + 1];
g := g xor KeyContext[4 * (i + 3) + 2];
h := h xor KeyContext[4 * (i + 3) + 3];
T1 := E xor g;
T2 := E or h;
T3 := E and f;
T4 := E and h;
T5 := f or T4;
T6 := T1 and T2;
b := T5 xor T6;
T8 := f xor h;
t9 := g or T3;
t10 := T6 xor T8;
d := t9 xor t10;
t12 := g xor T3;
t13 := T2 and d;
c := t12 xor t13;
t15 := not c;
t16 := T2 xor T3;
t17 := b and t15;
a := t16 xor t17;
a := (a shl 13) or (a shr 19);
c := (c shl 3) or (c shr 29);
b := b xor a xor c;
d := d xor c xor (a shl 3);
b := (b shl 1) or (b shr 31);
d := (d shl 7) or (d shr 25);
a := a xor b xor d;
c := c xor d xor (b shl 7);
a := (a shl 5) or (a shr 27);
c := (c shl 22) or (c shr 10);
a := a xor KeyContext[4 * (i + 4)];
b := b xor KeyContext[4 * (i + 4) + 1];
c := c xor KeyContext[4 * (i + 4) + 2];
d := d xor KeyContext[4 * (i + 4) + 3];
T1 := not a;
T2 := a xor d;
T3 := a xor b;
T4 := c xor T1;
T5 := T2 or T3;
E := T4 xor T5;
T7 := not E;
T8 := b or T7;
h := T2 xor T8;
t10 := a and E;
t11 := b xor h;
t12 := T8 and t11;
g := t10 xor t12;
t14 := a or T7;
t15 := T3 xor t14;
t16 := h and g;
f := t15 xor t16;
E := (E shl 13) or (E shr 19);
g := (g shl 3) or (g shr 29);
f := f xor E xor g;
h := h xor g xor (E shl 3);
f := (f shl 1) or (f shr 31);
h := (h shl 7) or (h shr 25);
E := E xor f xor h;
g := g xor h xor (f shl 7);
E := (E shl 5) or (E shr 27);
g := (g shl 22) or (g shr 10);
E := E xor KeyContext[4 * (i + 5)];
f := f xor KeyContext[4 * (i + 5) + 1];
g := g xor KeyContext[4 * (i + 5) + 2];
h := h xor KeyContext[4 * (i + 5) + 3];
T1 := not E;
T2 := E xor f;
T3 := E xor h;
T4 := g xor T1;
T5 := T2 or T3;
a := T4 xor T5;
T7 := not h;
T8 := a and T7;
b := T2 xor T8;
t10 := f or b;
t11 := g or a;
t12 := T7 xor t10;
d := t11 xor t12;
t14 := h or b;
t15 := T1 xor t14;
t16 := a or d;
c := t15 xor t16;
a := (a shl 13) or (a shr 19);
c := (c shl 3) or (c shr 29);
b := b xor a xor c;
d := d xor c xor (a shl 3);
b := (b shl 1) or (b shr 31);
d := (d shl 7) or (d shr 25);
a := a xor b xor d;
c := c xor d xor (b shl 7);
a := (a shl 5) or (a shr 27);
c := (c shl 22) or (c shr 10);
a := a xor KeyContext[4 * (i + 6)];
b := b xor KeyContext[4 * (i + 6) + 1];
c := c xor KeyContext[4 * (i + 6) + 2];
d := d xor KeyContext[4 * (i + 6) + 3];
T1 := a xor c;
T2 := b or d;
T3 := b xor c;
T4 := not T3;
T5 := a and d;
f := T4 xor T5;
T7 := b or c;
T8 := d xor T1;
t9 := T7 and T8;
h := T2 xor t9;
t11 := T1 and T7;
t12 := T4 xor T8;
t13 := h and t11;
E := t12 xor t13;
t15 := T3 xor t11;
t16 := h or t15;
g := t12 xor t16;
E := (E shl 13) or (E shr 19);
g := (g shl 3) or (g shr 29);
f := f xor E xor g;
h := h xor g xor (E shl 3);
f := (f shl 1) or (f shr 31);
h := (h shl 7) or (h shr 25);
E := E xor f xor h;
g := g xor h xor (f shl 7);
E := (E shl 5) or (E shr 27);
g := (g shl 22) or (g shr 10);
E := E xor KeyContext[4 * (i + 7)];
f := f xor KeyContext[4 * (i + 7) + 1];
g := g xor KeyContext[4 * (i + 7) + 2];
h := h xor KeyContext[4 * (i + 7) + 3];
T1 := not g;
T2 := f xor g;
T3 := f or T1;
T4 := h xor T3;
T5 := E and T4;
d := T2 xor T5;
T7 := E xor h;
T8 := f xor T5;
t9 := T2 or T8;
b := T7 xor t9;
t11 := h and T3;
t12 := T5 xor b;
t13 := d and t12;
c := t11 xor t13;
t15 := T1 or T4;
t16 := t12 xor c;
a := t15 xor t16;
inc(i, 8);
if i < 32 then
begin
a := (a shl 13) or (a shr 19);
c := (c shl 3) or (c shr 29);
b := b xor a xor c;
d := d xor c xor (a shl 3);
b := (b shl 1) or (b shr 31);
d := (d shl 7) or (d shr 25);
a := a xor b xor d;
c := c xor d xor (b shl 7);
a := (a shl 5) or (a shr 27);
c := (c shl 22) or (c shr 10);
end;
end;
a := a xor KeyContext[128];
b := b xor KeyContext[128 + 1];
c := c xor KeyContext[128 + 2];
d := d xor KeyContext[128 + 3];
PDWORD(@Data[0])^ := a;
PDWORD(@Data[4])^ := b;
PDWORD(@Data[8])^ := c;
PDWORD(@Data[12])^ := d;
end;
class procedure TSerpent.Decrypt(var KeyContext: TSerpentkey; var Data: TSerpentBlock);
var
i: DWORD;
a, b, c, d, E, f, g, h: DWORD;
T1, T2, T3, T4, T5, T6, T7, T8, t9, t10, t11, t12, t13, t14, t15, t16: DWORD;
begin
a := PDWORD(@Data[0])^;
b := PDWORD(@Data[4])^;
c := PDWORD(@Data[8])^;
d := PDWORD(@Data[12])^;
i := 32;
a := a xor KeyContext[4 * 32];
b := b xor KeyContext[4 * 32 + 1];
c := c xor KeyContext[4 * 32 + 2];
d := d xor KeyContext[4 * 32 + 3];
while i > 0 do
begin
if i < 32 then
begin
c := (c shr 22) or (c shl 10);
a := (a shr 5) or (a shl 27);
c := c xor d xor (b shl 7);
a := a xor b xor d;
d := (d shr 7) or (d shl 25);
b := (b shr 1) or (b shl 31);
d := d xor c xor (a shl 3);
b := b xor a xor c;
c := (c shr 3) or (c shl 29);
a := (a shr 13) or (a shl 19);
end;
T1 := a and b;
T2 := a or b;
T3 := c or T1;
T4 := d and T2;
h := T3 xor T4;
T6 := not d;
T7 := b xor T4;
T8 := h xor T6;
t9 := T7 or T8;
f := a xor t9;
t11 := c xor T7;
t12 := d or f;
E := t11 xor t12;
t14 := a and h;
t15 := T3 xor f;
t16 := E xor t14;
g := t15 xor t16;
E := E xor KeyContext[4 * (i - 1)];
f := f xor KeyContext[4 * (i - 1) + 1];
g := g xor KeyContext[4 * (i - 1) + 2];
h := h xor KeyContext[4 * (i - 1) + 3];
g := (g shr 22) or (g shl 10);
E := (E shr 5) or (E shl 27);
g := g xor h xor (f shl 7);
E := E xor f xor h;
h := (h shr 7) or (h shl 25);
f := (f shr 1) or (f shl 31);
h := h xor g xor (E shl 3);
f := f xor E xor g;
g := (g shr 3) or (g shl 29);
E := (E shr 13) or (E shl 19);
T1 := not g;
T2 := E xor g;
T3 := f xor h;
T4 := E or T1;
b := T3 xor T4;
T6 := E or f;
T7 := f and T2;
T8 := b xor T6;
t9 := T7 or T8;
a := g xor t9;
t11 := not b;
t12 := h or T2;
t13 := t9 xor t11;
d := t12 xor t13;
t15 := f xor t11;
t16 := a and d;
c := t15 xor t16;
a := a xor KeyContext[4 * (i - 2)];
b := b xor KeyContext[4 * (i - 2) + 1];
c := c xor KeyContext[4 * (i - 2) + 2];
d := d xor KeyContext[4 * (i - 2) + 3];
c := (c shr 22) or (c shl 10);
a := (a shr 5) or (a shl 27);
c := c xor d xor (b shl 7);
a := a xor b xor d;
d := (d shr 7) or (d shl 25);
b := (b shr 1) or (b shl 31);
d := d xor c xor (a shl 3);
b := b xor a xor c;
c := (c shr 3) or (c shl 29);
a := (a shr 13) or (a shl 19);
T1 := not c;
T2 := b and T1;
T3 := d xor T2;
T4 := a and T3;
T5 := b xor T1;
h := T4 xor T5;
T7 := b or h;
T8 := a and T7;
f := T3 xor T8;
t10 := a or d;
t11 := T1 xor T7;
E := t10 xor t11;
t13 := a xor c;
t14 := b and t10;
t15 := T4 or t13;
g := t14 xor t15;
E := E xor KeyContext[4 * (i - 3)];
f := f xor KeyContext[4 * (i - 3) + 1];
g := g xor KeyContext[4 * (i - 3) + 2];
h := h xor KeyContext[4 * (i - 3) + 3];
g := (g shr 22) or (g shl 10);
E := (E shr 5) or (E shl 27);
g := g xor h xor (f shl 7);
E := E xor f xor h;
h := (h shr 7) or (h shl 25);
f := (f shr 1) or (f shl 31);
h := h xor g xor (E shl 3);
f := f xor E xor g;
g := (g shr 3) or (g shl 29);
E := (E shr 13) or (E shl 19);
T1 := g xor h;
T2 := g or h;
T3 := f xor T2;
T4 := E and T3;
b := T1 xor T4;
T6 := E xor h;
T7 := f or h;
T8 := T6 and T7;
d := T3 xor T8;
t10 := not E;
t11 := g xor d;
t12 := t10 or t11;
a := T3 xor t12;
t14 := g or T4;
t15 := T7 xor t14;
t16 := d or t10;
c := t15 xor t16;
a := a xor KeyContext[4 * (i - 4)];
b := b xor KeyContext[4 * (i - 4) + 1];
c := c xor KeyContext[4 * (i - 4) + 2];
d := d xor KeyContext[4 * (i - 4) + 3];
c := (c shr 22) or (c shl 10);
a := (a shr 5) or (a shl 27);
c := c xor d xor (b shl 7);
a := a xor b xor d;
d := (d shr 7) or (d shl 25);
b := (b shr 1) or (b shl 31);
d := d xor c xor (a shl 3);
b := b xor a xor c;
c := (c shr 3) or (c shl 29);
a := (a shr 13) or (a shl 19);
T1 := b xor c;
T2 := b or c;
T3 := a xor c;
T4 := T2 xor T3;
T5 := d or T4;
E := T1 xor T5;
T7 := a xor d;
T8 := T1 or T5;
t9 := T2 xor T7;
g := T8 xor t9;
t11 := a and T4;
t12 := E or t9;
f := t11 xor t12;
t14 := a and g;
t15 := T2 xor t14;
t16 := E and t15;
h := T4 xor t16;
E := E xor KeyContext[4 * (i - 5)];
f := f xor KeyContext[4 * (i - 5) + 1];
g := g xor KeyContext[4 * (i - 5) + 2];
h := h xor KeyContext[4 * (i - 5) + 3];
g := (g shr 22) or (g shl 10);
E := (E shr 5) or (E shl 27);
g := g xor h xor (f shl 7);
E := E xor f xor h;
h := (h shr 7) or (h shl 25);
f := (f shr 1) or (f shl 31);
h := h xor g xor (E shl 3);
f := f xor E xor g;
g := (g shr 3) or (g shl 29);
E := (E shr 13) or (E shl 19);
T1 := f xor h;
T2 := not T1;
T3 := E xor g;
T4 := g xor T1;
T5 := f and T4;
a := T3 xor T5;
T7 := E or T2;
T8 := h xor T7;
t9 := T3 or T8;
d := T1 xor t9;
t11 := not T4;
t12 := a or d;
b := t11 xor t12;
t14 := h and t11;
t15 := T3 xor t12;
c := t14 xor t15;
a := a xor KeyContext[4 * (i - 6)];
b := b xor KeyContext[4 * (i - 6) + 1];
c := c xor KeyContext[4 * (i - 6) + 2];
d := d xor KeyContext[4 * (i - 6) + 3];
c := (c shr 22) or (c shl 10);
a := (a shr 5) or (a shl 27);
c := c xor d xor (b shl 7);
a := a xor b xor d;
d := (d shr 7) or (d shl 25);
b := (b shr 1) or (b shl 31);
d := d xor c xor (a shl 3);
b := b xor a xor c;
c := (c shr 3) or (c shl 29);
a := (a shr 13) or (a shl 19);
T1 := a xor d;
T2 := a and b;
T3 := b xor c;
T4 := a xor T3;
T5 := b or d;
h := T4 xor T5;
T7 := c or T1;
T8 := b xor T7;
t9 := T4 and T8;
f := T1 xor t9;
t11 := not T2;
t12 := h and f;
t13 := t9 xor t11;
g := t12 xor t13;
t15 := a and d;
t16 := c xor t13;
E := t15 xor t16;
E := E xor KeyContext[4 * (i - 7)];
f := f xor KeyContext[4 * (i - 7) + 1];
g := g xor KeyContext[4 * (i - 7) + 2];
h := h xor KeyContext[4 * (i - 7) + 3];
g := (g shr 22) or (g shl 10);
E := (E shr 5) or (E shl 27);
g := g xor h xor (f shl 7);
E := E xor f xor h;
h := (h shr 7) or (h shl 25);
f := (f shr 1) or (f shl 31);
h := h xor g xor (E shl 3);
f := f xor E xor g;
g := (g shr 3) or (g shl 29);
E := (E shr 13) or (E shl 19);
T1 := E xor h;
T2 := g xor h;
T3 := not T2;
T4 := E or f;
c := T3 xor T4;
T6 := f xor T1;
T7 := g or T6;
T8 := E xor T7;
t9 := T2 and T8;
b := T6 xor t9;
t11 := not T8;
t12 := f and h;
t13 := b or t12;
d := t11 xor t13;
t15 := T2 xor t12;
t16 := b or d;
a := t15 xor t16;
a := a xor KeyContext[4 * (i - 8)];
b := b xor KeyContext[4 * (i - 8) + 1];
c := c xor KeyContext[4 * (i - 8) + 2];
d := d xor KeyContext[4 * (i - 8) + 3];
dec(i, 8);
end;
PDWORD(@Data[0])^ := a;
PDWORD(@Data[4])^ := b;
PDWORD(@Data[8])^ := c;
PDWORD(@Data[12])^ := d;
end;
class procedure TMars.gen_mask(var x, m: DWORD);
var
u: DWORD;
begin
u := x and (x shr 1);
u := u and (u shr 2);
u := u and (u shr 4);
u := u and (u shr 1) and (u shr 2);
m := u;
u := (x xor $FFFFFFFF) and ((x xor $FFFFFFFF) shr 1);
u := u and (u shr 2);
u := u and (u shr 4);
u := u and (u shr 1) and (u shr 2);
u := u or m;
m := (u shl 1) or (u shl 2) or (u shl 3) or (u shl 4) or (u shl 5) or (u shl 6) or (u shl 7) or (u shl 8);
m := (m or u or (u shl 9)) and ((x xor $FFFFFFFF) xor (x shl 1)) and ((x xor $FFFFFFFF) xor (x shr 1));
m := m and $FFFFFFFC;
end;
class procedure TMars.InitKey(buff: Pointer; Size: Integer; var KeyContext: TMarskey);
const
vk: array [0 .. 6] of DWORD = ($09D0C479, $28C8FFE0, $84AA6C39, $9DAD7287, $7DFF9BE3, $D4268361, $C96DA1D4);
var
i, j: Integer;
m, u, w, siz4: DWORD;
t: array [-7 .. 39] of DWORD;
KeyB: array [0 .. 39] of DWORD;
begin
m := 0;
FillPtrByte(@KeyB, SizeOf(KeyB), 0);
FillPtrByte(@t, SizeOf(t), 0);
CopyPtr(buff, @KeyB, Size);
siz4 := Size div 4;
CopyPtr(@vk, @t, SizeOf(vk));
for i := 0 to 38 do
begin
u := t[i - 7] xor t[i - 2];
t[i] := TRC6.LRot32(u, 3) xor KeyB[i mod siz4] xor i;
end;
t[39] := siz4;
for j := 0 to 6 do
begin
for i := 1 to 39 do
begin
u := t[i] + Mars_SBox[t[i - 1] and $1FF];
t[i] := TRC6.LRot32(u, 9);
end;
u := t[0] + Mars_SBox[t[39] and $1FF];
t[0] := TRC6.LRot32(u, 9);
end;
for i := 0 to 39 do
KeyContext[(7 * i) mod 40] := t[i];
i := 5;
repeat
u := Mars_SBox[265 + (KeyContext[i] and $3)];
j := KeyContext[i + 3] and $1F;
w := KeyContext[i] or $3;
gen_mask(w, m);
KeyContext[i] := w xor (TRC6.LRot32(u, j) and m);
inc(i, 2);
until i >= 37;
end;
class procedure TMars.Encrypt(var KeyContext: TMarskey; var Data: TMarsBlock);
var
l, m, r, t, a, b, c, d: DWORD;
begin
{$IFDEF RangeCheck}{$R-}{$ENDIF}
a := PDWORD(@Data[0])^;
b := PDWORD(@Data[4])^;
c := PDWORD(@Data[8])^;
d := PDWORD(@Data[12])^;
a := a + KeyContext[0];
b := b + KeyContext[1];
c := c + KeyContext[2];
d := d + KeyContext[3];
b := b xor Mars_SBox[a and $FF];
b := b + Mars_SBox[((a shr 8) and $FF) + 256];
c := c + Mars_SBox[(a shr 16) and $FF];
d := d xor Mars_SBox[((a shr 24) and $FF) + 256];
a := TRC6.RRot32(a, 24);
a := a + d;
c := c xor Mars_SBox[b and $FF];
c := c + Mars_SBox[((b shr 8) and $FF) + 256];
d := d + Mars_SBox[(b shr 16) and $FF];
a := a xor Mars_SBox[((b shr 24) and $FF) + 256];
b := TRC6.RRot32(b, 24);
b := b + c;
d := d xor Mars_SBox[c and $FF];
d := d + Mars_SBox[((c shr 8) and $FF) + 256];
a := a + Mars_SBox[(c shr 16) and $FF];
b := b xor Mars_SBox[((c shr 24) and $FF) + 256];
c := TRC6.RRot32(c, 24);
a := a xor Mars_SBox[d and $FF];
a := a + Mars_SBox[((d shr 8) and $FF) + 256];
b := b + Mars_SBox[(d shr 16) and $FF];
c := c xor Mars_SBox[((d shr 24) and $FF) + 256];
d := TRC6.RRot32(d, 24);
b := b xor Mars_SBox[a and $FF];
b := b + Mars_SBox[((a shr 8) and $FF) + 256];
c := c + Mars_SBox[(a shr 16) and $FF];
d := d xor Mars_SBox[((a shr 24) and $FF) + 256];
a := TRC6.RRot32(a, 24);
a := a + d;
c := c xor Mars_SBox[b and $FF];
c := c + Mars_SBox[((b shr 8) and $FF) + 256];
d := d + Mars_SBox[(b shr 16) and $FF];
a := a xor Mars_SBox[((b shr 24) and $FF) + 256];
b := TRC6.RRot32(b, 24);
b := b + c;
d := d xor Mars_SBox[c and $FF];
d := d + Mars_SBox[((c shr 8) and $FF) + 256];
a := a + Mars_SBox[(c shr 16) and $FF];
b := b xor Mars_SBox[((c shr 24) and $FF) + 256];
c := TRC6.RRot32(c, 24);
a := a xor Mars_SBox[d and $FF];
a := a + Mars_SBox[((d shr 8) and $FF) + 256];
b := b + Mars_SBox[(d shr 16) and $FF];
c := c xor Mars_SBox[((d shr 24) and $FF) + 256];
d := TRC6.RRot32(d, 24);
m := a + KeyContext[4];
r := TRC6.LRot32(a, 13) * KeyContext[5];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
a := TRC6.LRot32(a, 13);
b := b + l;
c := c + m;
d := d xor r;
m := b + KeyContext[6];
r := TRC6.LRot32(b, 13) * KeyContext[7];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
b := TRC6.LRot32(b, 13);
c := c + l;
d := d + m;
a := a xor r;
m := c + KeyContext[8];
r := TRC6.LRot32(c, 13) * KeyContext[9];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
c := TRC6.LRot32(c, 13);
d := d + l;
a := a + m;
b := b xor r;
m := d + KeyContext[10];
r := TRC6.LRot32(d, 13) * KeyContext[11];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
d := TRC6.LRot32(d, 13);
a := a + l;
b := b + m;
c := c xor r;
m := a + KeyContext[12];
r := TRC6.LRot32(a, 13) * KeyContext[13];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
a := TRC6.LRot32(a, 13);
b := b + l;
c := c + m;
d := d xor r;
m := b + KeyContext[14];
r := TRC6.LRot32(b, 13) * KeyContext[15];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
b := TRC6.LRot32(b, 13);
c := c + l;
d := d + m;
a := a xor r;
m := c + KeyContext[16];
r := TRC6.LRot32(c, 13) * KeyContext[17];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
c := TRC6.LRot32(c, 13);
d := d + l;
a := a + m;
b := b xor r;
m := d + KeyContext[18];
r := TRC6.LRot32(d, 13) * KeyContext[19];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
d := TRC6.LRot32(d, 13);
a := a + l;
b := b + m;
c := c xor r;
m := a + KeyContext[20];
r := TRC6.LRot32(a, 13) * KeyContext[21];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
a := TRC6.LRot32(a, 13);
d := d + l;
c := c + m;
b := b xor r;
m := b + KeyContext[22];
r := TRC6.LRot32(b, 13) * KeyContext[23];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
b := TRC6.LRot32(b, 13);
a := a + l;
d := d + m;
c := c xor r;
m := c + KeyContext[24];
r := TRC6.LRot32(c, 13) * KeyContext[25];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
c := TRC6.LRot32(c, 13);
b := b + l;
a := a + m;
d := d xor r;
m := d + KeyContext[26];
r := TRC6.LRot32(d, 13) * KeyContext[27];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
d := TRC6.LRot32(d, 13);
c := c + l;
b := b + m;
a := a xor r;
m := a + KeyContext[28];
r := TRC6.LRot32(a, 13) * KeyContext[29];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
a := TRC6.LRot32(a, 13);
d := d + l;
c := c + m;
b := b xor r;
m := b + KeyContext[30];
r := TRC6.LRot32(b, 13) * KeyContext[31];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
b := TRC6.LRot32(b, 13);
a := a + l;
d := d + m;
c := c xor r;
m := c + KeyContext[32];
r := TRC6.LRot32(c, 13) * KeyContext[33];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
c := TRC6.LRot32(c, 13);
b := b + l;
a := a + m;
d := d xor r;
m := d + KeyContext[34];
r := TRC6.LRot32(d, 13) * KeyContext[35];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
d := TRC6.LRot32(d, 13);
c := c + l;
b := b + m;
a := a xor r;
b := b xor Mars_SBox[(a and $FF) + 256];
c := c - Mars_SBox[(a shr 24) and $FF];
d := d - Mars_SBox[((a shr 16) and $FF) + 256];
d := d xor Mars_SBox[(a shr 8) and $FF];
a := TRC6.LRot32(a, 24);
c := c xor Mars_SBox[(b and $FF) + 256];
d := d - Mars_SBox[(b shr 24) and $FF];
a := a - Mars_SBox[((b shr 16) and $FF) + 256];
a := a xor Mars_SBox[(b shr 8) and $FF];
b := TRC6.LRot32(b, 24);
c := c - b;
d := d xor Mars_SBox[(c and $FF) + 256];
a := a - Mars_SBox[(c shr 24) and $FF];
b := b - Mars_SBox[((c shr 16) and $FF) + 256];
b := b xor Mars_SBox[(c shr 8) and $FF];
c := TRC6.LRot32(c, 24);
d := d - a;
a := a xor Mars_SBox[(d and $FF) + 256];
b := b - Mars_SBox[(d shr 24) and $FF];
c := c - Mars_SBox[((d shr 16) and $FF) + 256];
c := c xor Mars_SBox[(d shr 8) and $FF];
d := TRC6.LRot32(d, 24);
b := b xor Mars_SBox[(a and $FF) + 256];
c := c - Mars_SBox[(a shr 24) and $FF];
d := d - Mars_SBox[((a shr 16) and $FF) + 256];
d := d xor Mars_SBox[(a shr 8) and $FF];
a := TRC6.LRot32(a, 24);
c := c xor Mars_SBox[(b and $FF) + 256];
d := d - Mars_SBox[(b shr 24) and $FF];
a := a - Mars_SBox[((b shr 16) and $FF) + 256];
a := a xor Mars_SBox[(b shr 8) and $FF];
b := TRC6.LRot32(b, 24);
c := c - b;
d := d xor Mars_SBox[(c and $FF) + 256];
a := a - Mars_SBox[(c shr 24) and $FF];
b := b - Mars_SBox[((c shr 16) and $FF) + 256];
b := b xor Mars_SBox[(c shr 8) and $FF];
c := TRC6.LRot32(c, 24);
d := d - a;
a := a xor Mars_SBox[(d and $FF) + 256];
b := b - Mars_SBox[(d shr 24) and $FF];
c := c - Mars_SBox[((d shr 16) and $FF) + 256];
c := c xor Mars_SBox[(d shr 8) and $FF];
d := TRC6.LRot32(d, 24);
a := a - KeyContext[36];
b := b - KeyContext[37];
c := c - KeyContext[38];
d := d - KeyContext[39];
PDWORD(@Data[0])^ := a;
PDWORD(@Data[4])^ := b;
PDWORD(@Data[8])^ := c;
PDWORD(@Data[12])^ := d;
{$IFDEF RangeCheck}{$R+}{$ENDIF}
end;
class procedure TMars.Decrypt(var KeyContext: TMarskey; var Data: TMarsBlock);
var
l, m, r, t, a, b, c, d: DWORD;
begin
{$IFDEF RangeCheck}{$R-}{$ENDIF}
a := PDWORD(@Data[0])^;
b := PDWORD(@Data[4])^;
c := PDWORD(@Data[8])^;
d := PDWORD(@Data[12])^;
a := a + KeyContext[36];
b := b + KeyContext[37];
c := c + KeyContext[38];
d := d + KeyContext[39];
d := TRC6.RRot32(d, 24);
c := c xor Mars_SBox[(d shr 8) and $FF];
c := c + Mars_SBox[((d shr 16) and $FF) + 256];
b := b + Mars_SBox[(d shr 24) and $FF];
a := a xor Mars_SBox[(d and $FF) + 256];
d := d + a;
c := TRC6.RRot32(c, 24);
b := b xor Mars_SBox[(c shr 8) and $FF];
b := b + Mars_SBox[((c shr 16) and $FF) + 256];
a := a + Mars_SBox[(c shr 24) and $FF];
d := d xor Mars_SBox[(c and $FF) + 256];
c := c + b;
b := TRC6.RRot32(b, 24);
a := a xor Mars_SBox[(b shr 8) and $FF];
a := a + Mars_SBox[((b shr 16) and $FF) + 256];
d := d + Mars_SBox[(b shr 24) and $FF];
c := c xor Mars_SBox[(b and $FF) + 256];
a := TRC6.RRot32(a, 24);
d := d xor Mars_SBox[(a shr 8) and $FF];
d := d + Mars_SBox[((a shr 16) and $FF) + 256];
c := c + Mars_SBox[(a shr 24) and $FF];
b := b xor Mars_SBox[(a and $FF) + 256];
d := TRC6.RRot32(d, 24);
c := c xor Mars_SBox[(d shr 8) and $FF];
c := c + Mars_SBox[((d shr 16) and $FF) + 256];
b := b + Mars_SBox[(d shr 24) and $FF];
a := a xor Mars_SBox[(d and $FF) + 256];
d := d + a;
c := TRC6.RRot32(c, 24);
b := b xor Mars_SBox[(c shr 8) and $FF];
b := b + Mars_SBox[((c shr 16) and $FF) + 256];
a := a + Mars_SBox[(c shr 24) and $FF];
d := d xor Mars_SBox[(c and $FF) + 256];
c := c + b;
b := TRC6.RRot32(b, 24);
a := a xor Mars_SBox[(b shr 8) and $FF];
a := a + Mars_SBox[((b shr 16) and $FF) + 256];
d := d + Mars_SBox[(b shr 24) and $FF];
c := c xor Mars_SBox[(b and $FF) + 256];
a := TRC6.RRot32(a, 24);
d := d xor Mars_SBox[(a shr 8) and $FF];
d := d + Mars_SBox[((a shr 16) and $FF) + 256];
c := c + Mars_SBox[(a shr 24) and $FF];
b := b xor Mars_SBox[(a and $FF) + 256];
d := TRC6.RRot32(d, 13);
m := d + KeyContext[34];
r := TRC6.LRot32(d, 13) * KeyContext[35];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
c := c - l;
b := b - m;
a := a xor r;
c := TRC6.RRot32(c, 13);
m := c + KeyContext[32];
r := TRC6.LRot32(c, 13) * KeyContext[33];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
b := b - l;
a := a - m;
d := d xor r;
b := TRC6.RRot32(b, 13);
m := b + KeyContext[30];
r := TRC6.LRot32(b, 13) * KeyContext[31];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
a := a - l;
d := d - m;
c := c xor r;
a := TRC6.RRot32(a, 13);
m := a + KeyContext[28];
r := TRC6.LRot32(a, 13) * KeyContext[29];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
d := d - l;
c := c - m;
b := b xor r;
d := TRC6.RRot32(d, 13);
m := d + KeyContext[26];
r := TRC6.LRot32(d, 13) * KeyContext[27];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
c := c - l;
b := b - m;
a := a xor r;
c := TRC6.RRot32(c, 13);
m := c + KeyContext[24];
r := TRC6.LRot32(c, 13) * KeyContext[25];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
b := b - l;
a := a - m;
d := d xor r;
b := TRC6.RRot32(b, 13);
m := b + KeyContext[22];
r := TRC6.LRot32(b, 13) * KeyContext[23];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
a := a - l;
d := d - m;
c := c xor r;
a := TRC6.RRot32(a, 13);
m := a + KeyContext[20];
r := TRC6.LRot32(a, 13) * KeyContext[21];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
d := d - l;
c := c - m;
b := b xor r;
d := TRC6.RRot32(d, 13);
m := d + KeyContext[18];
r := TRC6.LRot32(d, 13) * KeyContext[19];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
a := a - l;
b := b - m;
c := c xor r;
c := TRC6.RRot32(c, 13);
m := c + KeyContext[16];
r := TRC6.LRot32(c, 13) * KeyContext[17];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
d := d - l;
a := a - m;
b := b xor r;
b := TRC6.RRot32(b, 13);
m := b + KeyContext[14];
r := TRC6.LRot32(b, 13) * KeyContext[15];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
c := c - l;
d := d - m;
a := a xor r;
a := TRC6.RRot32(a, 13);
m := a + KeyContext[12];
r := TRC6.LRot32(a, 13) * KeyContext[13];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
b := b - l;
c := c - m;
d := d xor r;
d := TRC6.RRot32(d, 13);
m := d + KeyContext[10];
r := TRC6.LRot32(d, 13) * KeyContext[11];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
a := a - l;
b := b - m;
c := c xor r;
c := TRC6.RRot32(c, 13);
m := c + KeyContext[8];
r := TRC6.LRot32(c, 13) * KeyContext[9];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
d := d - l;
a := a - m;
b := b xor r;
b := TRC6.RRot32(b, 13);
m := b + KeyContext[6];
r := TRC6.LRot32(b, 13) * KeyContext[7];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
c := c - l;
d := d - m;
a := a xor r;
a := TRC6.RRot32(a, 13);
m := a + KeyContext[4];
r := TRC6.LRot32(a, 13) * KeyContext[5];
l := Mars_SBox[m and $1FF];
r := TRC6.LRot32(r, 5);
t := r and $1F;
m := TRC6.LRot32(m, t);
l := l xor r;
r := TRC6.LRot32(r, 5);
l := l xor r;
t := r and $1F;
l := TRC6.LRot32(l, t);
b := b - l;
c := c - m;
d := d xor r;
d := TRC6.LRot32(d, 24);
c := c xor Mars_SBox[((d shr 24) and $FF) + 256];
b := b - Mars_SBox[(d shr 16) and $FF];
a := a - Mars_SBox[((d shr 8) and $FF) + 256];
a := a xor Mars_SBox[d and $FF];
c := TRC6.LRot32(c, 24);
b := b xor Mars_SBox[((c shr 24) and $FF) + 256];
a := a - Mars_SBox[(c shr 16) and $FF];
d := d - Mars_SBox[((c shr 8) and $FF) + 256];
d := d xor Mars_SBox[c and $FF];
b := b - c;
b := TRC6.LRot32(b, 24);
a := a xor Mars_SBox[((b shr 24) and $FF) + 256];
d := d - Mars_SBox[(b shr 16) and $FF];
c := c - Mars_SBox[((b shr 8) and $FF) + 256];
c := c xor Mars_SBox[b and $FF];
a := a - d;
a := TRC6.LRot32(a, 24);
d := d xor Mars_SBox[((a shr 24) and $FF) + 256];
c := c - Mars_SBox[(a shr 16) and $FF];
b := b - Mars_SBox[((a shr 8) and $FF) + 256];
b := b xor Mars_SBox[a and $FF];
d := TRC6.LRot32(d, 24);
c := c xor Mars_SBox[((d shr 24) and $FF) + 256];
b := b - Mars_SBox[(d shr 16) and $FF];
a := a - Mars_SBox[((d shr 8) and $FF) + 256];
a := a xor Mars_SBox[d and $FF];
c := TRC6.LRot32(c, 24);
b := b xor Mars_SBox[((c shr 24) and $FF) + 256];
a := a - Mars_SBox[(c shr 16) and $FF];
d := d - Mars_SBox[((c shr 8) and $FF) + 256];
d := d xor Mars_SBox[c and $FF];
b := b - c;
b := TRC6.LRot32(b, 24);
a := a xor Mars_SBox[((b shr 24) and $FF) + 256];
d := d - Mars_SBox[(b shr 16) and $FF];
c := c - Mars_SBox[((b shr 8) and $FF) + 256];
c := c xor Mars_SBox[b and $FF];
a := a - d;
a := TRC6.LRot32(a, 24);
d := d xor Mars_SBox[((a shr 24) and $FF) + 256];
c := c - Mars_SBox[(a shr 16) and $FF];
b := b - Mars_SBox[((a shr 8) and $FF) + 256];
b := b xor Mars_SBox[a and $FF];
a := a - KeyContext[0];
b := b - KeyContext[1];
c := c - KeyContext[2];
d := d - KeyContext[3];
PDWORD(@Data[0])^ := a;
PDWORD(@Data[4])^ := b;
PDWORD(@Data[8])^ := c;
PDWORD(@Data[12])^ := d;
{$IFDEF RangeCheck}{$R+}{$ENDIF}
end;
class procedure TRijndael.InvMixColumn(const a: PByteArray; const BC: Byte);
var
j: Integer;
begin
for j := 0 to (BC - 1) do
PDWORD(@(a^[j * 4]))^ := PDWORD(@U1[a^[j * 4 + 0]])^ xor PDWORD(@U2[a^[j * 4 + 1]])^ xor PDWORD(@U3[a^[j * 4 + 2]])^ xor PDWORD(@U4[a^[j * 4 + 3]])^;
end;
class procedure TRijndael.InitKey(buff: Pointer; Size: Integer; var KeyContext: TRijndaelkey);
const
s_box: array [0 .. 255] of Byte = (
99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,
202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,
4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,
9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,
208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,
205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,
96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,
186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,
112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22);
var
KC, Rounds: DWORD;
j, r, t, rconpointer: Integer;
tk: array [0 .. 8 - 1, 0 .. 3] of Byte;
begin
FillPtrByte(@tk, SizeOf(tk), 0);
CopyPtr(buff, @tk, Size);
if Size <= 16 then
begin
KC := 4;
Rounds := 10;
end
else if Size <= 24 then
begin
KC := 6;
Rounds := 12;
end
else
begin
KC := 8;
Rounds := 14;
end;
KeyContext.NumRounds := Rounds;
r := 0;
t := 0;
j := 0;
while (j < KC) and (r < (Rounds + 1)) do
begin
while (j < KC) and (t < 4) do
begin
KeyContext.rk[r, t] := PDWORD(@tk[j])^;
inc(j);
inc(t);
end;
if t = 4 then
begin
t := 0;
inc(r);
end;
end;
rconpointer := 0;
while (r < (Rounds + 1)) do
begin
tk[0, 0] := tk[0, 0] xor s_box[tk[KC - 1, 1]];
tk[0, 1] := tk[0, 1] xor s_box[tk[KC - 1, 2]];
tk[0, 2] := tk[0, 2] xor s_box[tk[KC - 1, 3]];
tk[0, 3] := tk[0, 3] xor s_box[tk[KC - 1, 0]];
tk[0, 0] := tk[0, 0] xor rcon[rconpointer];
inc(rconpointer);
if KC <> 8 then
begin
for j := 1 to (KC - 1) do
PDWORD(@tk[j])^ := PDWORD(@tk[j])^ xor PDWORD(@tk[j - 1])^;
end
else
begin
for j := 1 to ((KC div 2) - 1) do
PDWORD(@tk[j])^ := PDWORD(@tk[j])^ xor PDWORD(@tk[j - 1])^;
tk[KC div 2, 0] := tk[KC div 2, 0] xor s_box[tk[KC div 2 - 1, 0]];
tk[KC div 2, 1] := tk[KC div 2, 1] xor s_box[tk[KC div 2 - 1, 1]];
tk[KC div 2, 2] := tk[KC div 2, 2] xor s_box[tk[KC div 2 - 1, 2]];
tk[KC div 2, 3] := tk[KC div 2, 3] xor s_box[tk[KC div 2 - 1, 3]];
for j := ((KC div 2) + 1) to (KC - 1) do
PDWORD(@tk[j])^ := PDWORD(@tk[j])^ xor PDWORD(@tk[j - 1])^;
end;
j := 0;
while (j < KC) and (r < (Rounds + 1)) do
begin
while (j < KC) and (t < 4) do
begin
KeyContext.rk[r, t] := PDWORD(@tk[j])^;
inc(j);
inc(t);
end;
if t = 4 then
begin
inc(r);
t := 0;
end;
end;
end;
CopyPtr(@KeyContext.rk, @KeyContext.drk, SizeOf(KeyContext.rk));
for r := 1 to (Rounds - 1) do
InvMixColumn(@KeyContext.drk[r], 4);
end;
class procedure TRijndael.Encrypt(var KeyContext: TRijndaelkey; var Data: TRijndaelBlock);
begin
Encrypt(KeyContext, PDWORD(@Data[0])^, PDWORD(@Data[4])^, PDWORD(@Data[8])^, PDWORD(@Data[12])^);
end;
class procedure TRijndael.Encrypt(var KeyContext: TRijndaelkey; var B1, B2, B3, B4: DWORD);
var
r: DWORD;
tempb: array [0 .. 3, 0 .. 3] of Byte;
a: array [0 .. 3, 0 .. 3] of Byte;
begin
PDWORD(@a[0, 0])^ := B1;
PDWORD(@a[1, 0])^ := B2;
PDWORD(@a[2, 0])^ := B3;
PDWORD(@a[3, 0])^ := B4;
for r := 0 to (KeyContext.NumRounds - 2) do
begin
PDWORD(@tempb[0])^ := PDWORD(@a[0])^ xor KeyContext.rk[r, 0];
PDWORD(@tempb[1])^ := PDWORD(@a[1])^ xor KeyContext.rk[r, 1];
PDWORD(@tempb[2])^ := PDWORD(@a[2])^ xor KeyContext.rk[r, 2];
PDWORD(@tempb[3])^ := PDWORD(@a[3])^ xor KeyContext.rk[r, 3];
PDWORD(@a[0])^ := PDWORD(@T1[tempb[0, 0]])^ xor PDWORD(@T2[tempb[1, 1]])^ xor PDWORD(@T3[tempb[2, 2]])^ xor PDWORD(@T4[tempb[3, 3]])^;
PDWORD(@a[1])^ := PDWORD(@T1[tempb[1, 0]])^ xor PDWORD(@T2[tempb[2, 1]])^ xor PDWORD(@T3[tempb[3, 2]])^ xor PDWORD(@T4[tempb[0, 3]])^;
PDWORD(@a[2])^ := PDWORD(@T1[tempb[2, 0]])^ xor PDWORD(@T2[tempb[3, 1]])^ xor PDWORD(@T3[tempb[0, 2]])^ xor PDWORD(@T4[tempb[1, 3]])^;
PDWORD(@a[3])^ := PDWORD(@T1[tempb[3, 0]])^ xor PDWORD(@T2[tempb[0, 1]])^ xor PDWORD(@T3[tempb[1, 2]])^ xor PDWORD(@T4[tempb[2, 3]])^;
end;
PDWORD(@tempb[0])^ := PDWORD(@a[0])^ xor KeyContext.rk[KeyContext.NumRounds - 1, 0];
PDWORD(@tempb[1])^ := PDWORD(@a[1])^ xor KeyContext.rk[KeyContext.NumRounds - 1, 1];
PDWORD(@tempb[2])^ := PDWORD(@a[2])^ xor KeyContext.rk[KeyContext.NumRounds - 1, 2];
PDWORD(@tempb[3])^ := PDWORD(@a[3])^ xor KeyContext.rk[KeyContext.NumRounds - 1, 3];
a[0, 0] := T1[tempb[0, 0], 1];
a[0, 1] := T1[tempb[1, 1], 1];
a[0, 2] := T1[tempb[2, 2], 1];
a[0, 3] := T1[tempb[3, 3], 1];
a[1, 0] := T1[tempb[1, 0], 1];
a[1, 1] := T1[tempb[2, 1], 1];
a[1, 2] := T1[tempb[3, 2], 1];
a[1, 3] := T1[tempb[0, 3], 1];
a[2, 0] := T1[tempb[2, 0], 1];
a[2, 1] := T1[tempb[3, 1], 1];
a[2, 2] := T1[tempb[0, 2], 1];
a[2, 3] := T1[tempb[1, 3], 1];
a[3, 0] := T1[tempb[3, 0], 1];
a[3, 1] := T1[tempb[0, 1], 1];
a[3, 2] := T1[tempb[1, 2], 1];
a[3, 3] := T1[tempb[2, 3], 1];
B1 := PDWORD(@a[0])^ xor KeyContext.rk[KeyContext.NumRounds, 0];
B2 := PDWORD(@a[1])^ xor KeyContext.rk[KeyContext.NumRounds, 1];
B3 := PDWORD(@a[2])^ xor KeyContext.rk[KeyContext.NumRounds, 2];
B4 := PDWORD(@a[3])^ xor KeyContext.rk[KeyContext.NumRounds, 3];
end;
class procedure TRijndael.Decrypt(var KeyContext: TRijndaelkey; var Data: TRijndaelBlock);
begin
Decrypt(KeyContext, PDWORD(@Data[0])^, PDWORD(@Data[4])^, PDWORD(@Data[8])^, PDWORD(@Data[12])^);
end;
class procedure TRijndael.Decrypt(var KeyContext: TRijndaelkey; var B1, B2, B3, B4: DWORD);
var
r: Integer;
tempb: array [0 .. 3, 0 .. 3] of Byte;
a: array [0 .. 3, 0 .. 3] of Byte;
begin
PDWORD(@a[0, 0])^ := B1;
PDWORD(@a[1, 0])^ := B2;
PDWORD(@a[2, 0])^ := B3;
PDWORD(@a[3, 0])^ := B4;
for r := KeyContext.NumRounds downto 2 do
begin
PDWORD(@tempb[0])^ := PDWORD(@a[0])^ xor KeyContext.drk[r, 0];
PDWORD(@tempb[1])^ := PDWORD(@a[1])^ xor KeyContext.drk[r, 1];
PDWORD(@tempb[2])^ := PDWORD(@a[2])^ xor KeyContext.drk[r, 2];
PDWORD(@tempb[3])^ := PDWORD(@a[3])^ xor KeyContext.drk[r, 3];
PDWORD(@a[0])^ := PDWORD(@T5[tempb[0, 0]])^ xor PDWORD(@T6[tempb[3, 1]])^ xor PDWORD(@T7[tempb[2, 2]])^ xor PDWORD(@T8[tempb[1, 3]])^;
PDWORD(@a[1])^ := PDWORD(@T5[tempb[1, 0]])^ xor PDWORD(@T6[tempb[0, 1]])^ xor PDWORD(@T7[tempb[3, 2]])^ xor PDWORD(@T8[tempb[2, 3]])^;
PDWORD(@a[2])^ := PDWORD(@T5[tempb[2, 0]])^ xor PDWORD(@T6[tempb[1, 1]])^ xor PDWORD(@T7[tempb[0, 2]])^ xor PDWORD(@T8[tempb[3, 3]])^;
PDWORD(@a[3])^ := PDWORD(@T5[tempb[3, 0]])^ xor PDWORD(@T6[tempb[2, 1]])^ xor PDWORD(@T7[tempb[1, 2]])^ xor PDWORD(@T8[tempb[0, 3]])^;
end;
PDWORD(@tempb[0])^ := PDWORD(@a[0])^ xor KeyContext.drk[1, 0];
PDWORD(@tempb[1])^ := PDWORD(@a[1])^ xor KeyContext.drk[1, 1];
PDWORD(@tempb[2])^ := PDWORD(@a[2])^ xor KeyContext.drk[1, 2];
PDWORD(@tempb[3])^ := PDWORD(@a[3])^ xor KeyContext.drk[1, 3];
a[0, 0] := S5[tempb[0, 0]];
a[0, 1] := S5[tempb[3, 1]];
a[0, 2] := S5[tempb[2, 2]];
a[0, 3] := S5[tempb[1, 3]];
a[1, 0] := S5[tempb[1, 0]];
a[1, 1] := S5[tempb[0, 1]];
a[1, 2] := S5[tempb[3, 2]];
a[1, 3] := S5[tempb[2, 3]];
a[2, 0] := S5[tempb[2, 0]];
a[2, 1] := S5[tempb[1, 1]];
a[2, 2] := S5[tempb[0, 2]];
a[2, 3] := S5[tempb[3, 3]];
a[3, 0] := S5[tempb[3, 0]];
a[3, 1] := S5[tempb[2, 1]];
a[3, 2] := S5[tempb[1, 2]];
a[3, 3] := S5[tempb[0, 3]];
B1 := PDWORD(@a[0])^ xor KeyContext.drk[0, 0];
B2 := PDWORD(@a[1])^ xor KeyContext.drk[0, 1];
B3 := PDWORD(@a[2])^ xor KeyContext.drk[0, 2];
B4 := PDWORD(@a[3])^ xor KeyContext.drk[0, 3];
end;
class function TTwofish.TwofishCalculateSBoxes(x: DWORD; l: Pointer; KeySize: DWORD): DWORD;
var
b0, B1, B2, B3: Byte;
begin
{ precalculating permutations for H function }
b0 := x and $FF;
B1 := (x shr 8) and $FF;
B2 := (x shr 16) and $FF;
B3 := x shr 24;
if KeySize > 192 then
begin
b0 := P8x8[1, b0] xor PByte(nativeUInt(l) + 12)^;
B1 := P8x8[0, B1] xor PByte(nativeUInt(l) + 13)^;
B2 := P8x8[0, B2] xor PByte(nativeUInt(l) + 14)^;
B3 := P8x8[1, B3] xor PByte(nativeUInt(l) + 15)^;
end;
if KeySize > 128 then
begin
b0 := P8x8[1, b0] xor PByte(nativeUInt(l) + 8)^;
B1 := P8x8[1, B1] xor PByte(nativeUInt(l) + 9)^;
B2 := P8x8[0, B2] xor PByte(nativeUInt(l) + 10)^;
B3 := P8x8[0, B3] xor PByte(nativeUInt(l) + 11)^;
end;
b0 := P8x8[0, b0] xor PByte(nativeUInt(l) + 4)^;
B1 := P8x8[1, B1] xor PByte(nativeUInt(l) + 5)^;
B2 := P8x8[0, B2] xor PByte(nativeUInt(l) + 6)^;
B3 := P8x8[1, B3] xor PByte(nativeUInt(l) + 7)^;
b0 := P8x8[1, P8x8[0, b0] xor PByte(l)^];
B1 := P8x8[0, P8x8[0, B1] xor PByte(nativeUInt(l) + 1)^];
B2 := P8x8[1, P8x8[1, B2] xor PByte(nativeUInt(l) + 2)^];
B3 := P8x8[0, P8x8[1, B3] xor PByte(nativeUInt(l) + 3)^];
Result := DWORD(b0) or (DWORD(B1) shl 8) or (DWORD(B2) shl 16) or (DWORD(B3) shl 24);
end;
class function TTwofish.TwofishH(x: DWORD; l: Pointer; KeySize: DWORD): DWORD;
var
b0, B1, B2, B3, z0, z1, z2, z3: Byte;
begin
b0 := x and $FF;
B1 := (x shr 8) and $FF;
B2 := (x shr 16) and $FF;
B3 := x shr 24;
if KeySize > 192 then
begin
b0 := P8x8[1, b0] xor PByte(nativeUInt(l) + 12)^;
B1 := P8x8[0, B1] xor PByte(nativeUInt(l) + 13)^;
B2 := P8x8[0, B2] xor PByte(nativeUInt(l) + 14)^;
B3 := P8x8[1, B3] xor PByte(nativeUInt(l) + 15)^;
end;
if KeySize > 128 then
begin
b0 := P8x8[1, b0] xor PByte(nativeUInt(l) + 8)^;
B1 := P8x8[1, B1] xor PByte(nativeUInt(l) + 9)^;
B2 := P8x8[0, B2] xor PByte(nativeUInt(l) + 10)^;
B3 := P8x8[0, B3] xor PByte(nativeUInt(l) + 11)^;
end;
b0 := P8x8[0, b0] xor PByte(nativeUInt(l) + 4)^;
B1 := P8x8[1, B1] xor PByte(nativeUInt(l) + 5)^;
B2 := P8x8[0, B2] xor PByte(nativeUInt(l) + 6)^;
B3 := P8x8[1, B3] xor PByte(nativeUInt(l) + 7)^;
b0 := P8x8[1, P8x8[0, b0] xor PByte(l)^];
B1 := P8x8[0, P8x8[0, B1] xor PByte(nativeUInt(l) + 1)^];
B2 := P8x8[1, P8x8[1, B2] xor PByte(nativeUInt(l) + 2)^];
B3 := P8x8[0, P8x8[1, B3] xor PByte(nativeUInt(l) + 3)^];
z0 := b0 xor ArrEF[B1] xor Arr5B[B2] xor Arr5B[B3];
z1 := Arr5B[b0] xor ArrEF[B1] xor ArrEF[B2] xor B3;
z2 := ArrEF[b0] xor Arr5B[B1] xor B2 xor ArrEF[B3];
z3 := ArrEF[b0] xor B1 xor ArrEF[B2] xor Arr5B[B3];
Result := DWORD(z0) or (DWORD(z1) shl 8) or (DWORD(z2) shl 16) or (DWORD(z3) shl 24);
end;
class function TTwofish.TwofishH(const x: DWORD; const key: TTwofishKey): DWORD;
var
b0, B1, B2, B3, z0, z1, z2, z3: Byte;
begin
b0 := key.SBox0[x and $FF];
B1 := key.SBox1[(x shr 8) and $FF];
B2 := key.SBox2[(x shr 16) and $FF];
B3 := key.SBox3[x shr 24];
{ P8x8 permutations are precalculated and stored in Key.SBoxes }
z0 := b0 xor ArrEF[B1] xor Arr5B[B2] xor Arr5B[B3];
z1 := Arr5B[b0] xor ArrEF[B1] xor ArrEF[B2] xor B3;
z2 := ArrEF[b0] xor Arr5B[B1] xor B2 xor ArrEF[B3];
z3 := ArrEF[b0] xor B1 xor ArrEF[B2] xor Arr5B[B3];
Result := DWORD(z0) or (DWORD(z1) shl 8) or (DWORD(z2) shl 16) or (DWORD(z3) shl 24);
end;
class function TTwofish.RSMDSMul(const x, y: Byte): Byte;
var
Res: DWORD;
index: Byte;
begin
Res := 0;
for Index := 7 downto 0 do
begin
if (y and (1 shl Index)) <> 0 then
Res := Res xor (DWORD(x) shl Index);
if (Res and (1 shl (8 + Index))) <> 0 then
Res := Res xor ($14D shl Index);
end;
Result := Byte(Res);
end;
class function TTwofish.MultiplyMDS(const E, O: DWORD): DWORD;
var
E0, E1, E2, E3, O0, O1, O2, O3, R0, R1, R2, R3: Byte;
begin
E0 := E and $FF;
E1 := (E shr 8) and $FF;
E2 := (E shr 16) and $FF;
E3 := (E shr 24) and $FF;
O0 := O and $FF;
O1 := (O shr 8) and $FF;
O2 := (O shr 16) and $FF;
O3 := (O shr 24) and $FF;
R0 :=
RSMDSMul(E0, MDS[0, 0]) xor RSMDSMul(E1, MDS[0, 1]) xor
RSMDSMul(E2, MDS[0, 2]) xor RSMDSMul(E3, MDS[0, 3]) xor
RSMDSMul(O0, MDS[0, 4]) xor RSMDSMul(O1, MDS[0, 5]) xor
RSMDSMul(O2, MDS[0, 6]) xor RSMDSMul(O3, MDS[0, 7]);
R1 :=
RSMDSMul(E0, MDS[1, 0]) xor RSMDSMul(E1, MDS[1, 1]) xor
RSMDSMul(E2, MDS[1, 2]) xor RSMDSMul(E3, MDS[1, 3]) xor
RSMDSMul(O0, MDS[1, 4]) xor RSMDSMul(O1, MDS[1, 5]) xor
RSMDSMul(O2, MDS[1, 6]) xor RSMDSMul(O3, MDS[1, 7]);
R2 :=
RSMDSMul(E0, MDS[2, 0]) xor RSMDSMul(E1, MDS[2, 1]) xor
RSMDSMul(E2, MDS[2, 2]) xor RSMDSMul(E3, MDS[2, 3]) xor
RSMDSMul(O0, MDS[2, 4]) xor RSMDSMul(O1, MDS[2, 5]) xor
RSMDSMul(O2, MDS[2, 6]) xor RSMDSMul(O3, MDS[2, 7]);
R3 :=
RSMDSMul(E0, MDS[3, 0]) xor RSMDSMul(E1, MDS[3, 1]) xor
RSMDSMul(E2, MDS[3, 2]) xor RSMDSMul(E3, MDS[3, 3]) xor
RSMDSMul(O0, MDS[3, 4]) xor RSMDSMul(O1, MDS[3, 5]) xor
RSMDSMul(O2, MDS[3, 6]) xor RSMDSMul(O3, MDS[3, 7]);
Result := R0 or (R1 shl 8) or (R2 shl 16) or (R3 shl 24);
end;
class procedure TTwofish.InitKey(buff: PCCByteArray; Size: Integer; var KeyContext: TTwofishKey);
var
i: DWORD;
Cnt: DWORD;
KE: array [0 .. 3] of DWORD;
KO: array [0 .. 3] of DWORD;
a, b: DWORD;
begin
Cnt := (Size shl 3 + 63) shr 6;
KeyContext.KeyLen := Size shl 3;
for i := 0 to Cnt - 1 do
begin
KE[i] := buff^[i shl 3] + buff^[i shl 3 + 1] shl 8 + buff^[i shl 3 + 2] shl 16 + buff^[i shl 3 + 3] shl 24;
KO[i] := buff^[i shl 3 + 4] + buff^[i shl 3 + 5] shl 8 + buff^[i shl 3 + 6] shl 16 + buff^[i shl 3 + 7] shl 24;
KeyContext.SBoxKey[Cnt - i - 1] := MultiplyMDS(KE[i], KO[i]);
end;
for i := 0 to 19 do
begin
a := TwofishH(i * $02020202, @KE, KeyContext.KeyLen);
b := TwofishH(i * $02020202 + $01010101, @KO, KeyContext.KeyLen);
b := (b shl 8) or (b shr 24);
KeyContext.ExpandedKey[i shl 1] := a + b;
b := a + b shl 1;
KeyContext.ExpandedKey[i shl 1 + 1] := (b shl 9) or (b shr 23);
end;
for i := 0 to 255 do
begin
a := (i and $FF) or ((i and $FF) shl 8) or ((i and $FF) shl 16) or ((i and $FF) shl 24);
a := TwofishCalculateSBoxes(a, @KeyContext.SBoxKey, KeyContext.KeyLen);
KeyContext.SBox0[i] := a and $FF;
KeyContext.SBox1[i] := (a shr 8) and $FF;
KeyContext.SBox2[i] := (a shr 16) and $FF;
KeyContext.SBox3[i] := (a shr 24) and $FF;
end;
end;
class procedure TTwofish.Encrypt(var KeyContext: TTwofishKey; var Data: TTwofishBlock);
var
R0, R1, R2, R3, t0, T1, F0, F1: DWORD;
begin
{ prewhitening }
R0 := PDWORD(@Data[0])^ xor KeyContext.ExpandedKey[0];
R1 := PDWORD(@Data[4])^ xor KeyContext.ExpandedKey[1];
R2 := PDWORD(@Data[8])^ xor KeyContext.ExpandedKey[2];
R3 := PDWORD(@Data[12])^ xor KeyContext.ExpandedKey[3];
{ 0 round }
t0 := TwofishH(R0, KeyContext);
T1 := (R1 shl 8) or (R1 shr 24);
T1 := TwofishH(T1, KeyContext);
F0 := (t0 + T1 + KeyContext.ExpandedKey[8]);
F1 := (t0 + T1 shl 1 + KeyContext.ExpandedKey[9]);
R2 := R2 xor F0;
R2 := (R2 shr 1) or (R2 shl 31);
R3 := (R3 shl 1) or (R3 shr 31) xor F1;
{ 1 round }
t0 := TwofishH(R2, KeyContext);
T1 := DWORD(R3 shl 8) or (R3 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[10]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[11]);
R0 := R0 xor F0;
R0 := (R0 shr 1) or DWORD(R0 shl 31);
R1 := DWORD(R1 shl 1) or (R1 shr 31) xor F1;
{ 2 round }
t0 := TwofishH(R0, KeyContext);
T1 := DWORD(R1 shl 8) or (R1 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[12]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[13]);
R2 := R2 xor F0;
R2 := (R2 shr 1) or DWORD(R2 shl 31);
R3 := DWORD(R3 shl 1) or (R3 shr 31) xor F1;
{ 3 round }
t0 := TwofishH(R2, KeyContext);
T1 := DWORD(R3 shl 8) or (R3 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[14]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[15]);
R0 := R0 xor F0;
R0 := (R0 shr 1) or DWORD(R0 shl 31);
R1 := DWORD(R1 shl 1) or (R1 shr 31) xor F1;
{ 4 round }
t0 := TwofishH(R0, KeyContext);
T1 := DWORD(R1 shl 8) or (R1 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[16]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[17]);
R2 := R2 xor F0;
R2 := (R2 shr 1) or DWORD(R2 shl 31);
R3 := DWORD(R3 shl 1) or (R3 shr 31) xor F1;
{ 5 round }
t0 := TwofishH(R2, KeyContext);
T1 := DWORD(R3 shl 8) or (R3 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[18]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[19]);
R0 := R0 xor F0;
R0 := (R0 shr 1) or DWORD(R0 shl 31);
R1 := DWORD(R1 shl 1) or (R1 shr 31) xor F1;
{ 6 round }
t0 := TwofishH(R0, KeyContext);
T1 := DWORD(R1 shl 8) or (R1 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[20]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[21]);
R2 := R2 xor F0;
R2 := (R2 shr 1) or DWORD(R2 shl 31);
R3 := DWORD(R3 shl 1) or (R3 shr 31) xor F1;
{ 7 round }
t0 := TwofishH(R2, KeyContext);
T1 := DWORD(R3 shl 8) or (R3 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[22]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[23]);
R0 := R0 xor F0;
R0 := (R0 shr 1) or DWORD(R0 shl 31);
R1 := DWORD(R1 shl 1) or (R1 shr 31) xor F1;
{ 8 round }
t0 := TwofishH(R0, KeyContext);
T1 := DWORD(R1 shl 8) or (R1 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[24]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[25]);
R2 := R2 xor F0;
R2 := (R2 shr 1) or DWORD(R2 shl 31);
R3 := DWORD(R3 shl 1) or (R3 shr 31) xor F1;
{ 9 round }
t0 := TwofishH(R2, KeyContext);
T1 := DWORD(R3 shl 8) or (R3 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[26]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[27]);
R0 := R0 xor F0;
R0 := (R0 shr 1) or DWORD(R0 shl 31);
R1 := DWORD(R1 shl 1) or (R1 shr 31) xor F1;
{ 10 round }
t0 := TwofishH(R0, KeyContext);
T1 := DWORD(R1 shl 8) or (R1 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[28]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[29]);
R2 := R2 xor F0;
R2 := (R2 shr 1) or DWORD(R2 shl 31);
R3 := DWORD(R3 shl 1) or (R3 shr 31) xor F1;
{ 11 round }
t0 := TwofishH(R2, KeyContext);
T1 := DWORD(R3 shl 8) or (R3 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[30]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[31]);
R0 := R0 xor F0;
R0 := (R0 shr 1) or DWORD(R0 shl 31);
R1 := DWORD(R1 shl 1) or (R1 shr 31) xor F1;
{ 12 round }
t0 := TwofishH(R0, KeyContext);
T1 := DWORD(R1 shl 8) or (R1 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[32]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[33]);
R2 := R2 xor F0;
R2 := (R2 shr 1) or DWORD(R2 shl 31);
R3 := DWORD(R3 shl 1) or (R3 shr 31) xor F1;
{ 13 round }
t0 := TwofishH(R2, KeyContext);
T1 := DWORD(R3 shl 8) or (R3 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[34]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[35]);
R0 := R0 xor F0;
R0 := (R0 shr 1) or DWORD(R0 shl 31);
R1 := DWORD(R1 shl 1) or (R1 shr 31) xor F1;
{ 14 round }
t0 := TwofishH(R0, KeyContext);
T1 := DWORD(R1 shl 8) or (R1 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[36]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[37]);
R2 := R2 xor F0;
R2 := (R2 shr 1) or DWORD(R2 shl 31);
R3 := DWORD(R3 shl 1) or (R3 shr 31) xor F1;
{ 15 round }
t0 := TwofishH(R2, KeyContext);
T1 := DWORD(R3 shl 8) or (R3 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[38]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[39]);
R0 := R0 xor F0;
R0 := (R0 shr 1) or DWORD(R0 shl 31);
R1 := DWORD(R1 shl 1) or (R1 shr 31) xor F1;
PDWORD(@Data[0])^ := R2 xor KeyContext.ExpandedKey[4];
PDWORD(@Data[4])^ := R3 xor KeyContext.ExpandedKey[5];
PDWORD(@Data[8])^ := R0 xor KeyContext.ExpandedKey[6];
PDWORD(@Data[12])^ := R1 xor KeyContext.ExpandedKey[7];
end;
class procedure TTwofish.Decrypt(var KeyContext: TTwofishKey; var Data: TTwofishBlock);
var
R0, R1, R2, R3, t0, T1, F0, F1: DWORD;
begin
{ prewhitening }
R0 := PDWORD(@Data[0])^ xor KeyContext.ExpandedKey[4];
R1 := PDWORD(@Data[4])^ xor KeyContext.ExpandedKey[5];
R2 := PDWORD(@Data[8])^ xor KeyContext.ExpandedKey[6];
R3 := PDWORD(@Data[12])^ xor KeyContext.ExpandedKey[7];
{ R0,R1 and R2,R3 are replaced from round to round - small optimization }
{ 15 round }
t0 := TwofishH(R0, KeyContext);;
T1 := DWORD(R1 shl 8) or (R1 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[38]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[39]);
R2 := (R2 shl 1) or DWORD(R2 shr 31) xor F0;
R3 := R3 xor F1;
R3 := DWORD(R3 shr 1) or (R3 shl 31);
{ 14 round }
t0 := TwofishH(R2, KeyContext);;
T1 := DWORD(R3 shl 8) or (R3 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[36]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[37]);
R0 := (R0 shl 1) or DWORD(R0 shr 31) xor F0;
R1 := R1 xor F1;
R1 := DWORD(R1 shr 1) or (R1 shl 31);
{ 13 round }
t0 := TwofishH(R0, KeyContext);;
T1 := DWORD(R1 shl 8) or (R1 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[34]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[35]);
R2 := (R2 shl 1) or DWORD(R2 shr 31) xor F0;
R3 := R3 xor F1;
R3 := DWORD(R3 shr 1) or (R3 shl 31);
{ 12 round }
t0 := TwofishH(R2, KeyContext);;
T1 := DWORD(R3 shl 8) or (R3 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[32]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[33]);
R0 := (R0 shl 1) or DWORD(R0 shr 31) xor F0;
R1 := R1 xor F1;
R1 := DWORD(R1 shr 1) or (R1 shl 31);
{ 11 round }
t0 := TwofishH(R0, KeyContext);;
T1 := DWORD(R1 shl 8) or (R1 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[30]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[31]);
R2 := (R2 shl 1) or DWORD(R2 shr 31) xor F0;
R3 := R3 xor F1;
R3 := DWORD(R3 shr 1) or (R3 shl 31);
{ 10 round }
t0 := TwofishH(R2, KeyContext);;
T1 := DWORD(R3 shl 8) or (R3 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[28]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[29]);
R0 := (R0 shl 1) or DWORD(R0 shr 31) xor F0;
R1 := R1 xor F1;
R1 := DWORD(R1 shr 1) or (R1 shl 31);
{ 9 round }
t0 := TwofishH(R0, KeyContext);;
T1 := DWORD(R1 shl 8) or (R1 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[26]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[27]);
R2 := (R2 shl 1) or DWORD(R2 shr 31) xor F0;
R3 := R3 xor F1;
R3 := DWORD(R3 shr 1) or (R3 shl 31);
{ 8 round }
t0 := TwofishH(R2, KeyContext);;
T1 := DWORD(R3 shl 8) or (R3 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[24]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[25]);
R0 := (R0 shl 1) or DWORD(R0 shr 31) xor F0;
R1 := R1 xor F1;
R1 := DWORD(R1 shr 1) or (R1 shl 31);
{ 7 round }
t0 := TwofishH(R0, KeyContext);
T1 := DWORD(R1 shl 8) or (R1 shr 24);
T1 := TwofishH(T1, KeyContext);
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[22]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[23]);
R2 := (R2 shl 1) or DWORD(R2 shr 31) xor F0;
R3 := R3 xor F1;
R3 := DWORD(R3 shr 1) or (R3 shl 31);
{ 6 round }
t0 := TwofishH(R2, KeyContext);;
T1 := DWORD(R3 shl 8) or (R3 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[20]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[21]);
R0 := (R0 shl 1) or DWORD(R0 shr 31) xor F0;
R1 := R1 xor F1;
R1 := DWORD(R1 shr 1) or (R1 shl 31);
{ 5 round }
t0 := TwofishH(R0, KeyContext);;
T1 := DWORD(R1 shl 8) or (R1 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[18]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[19]);
R2 := (R2 shl 1) or DWORD(R2 shr 31) xor F0;
R3 := R3 xor F1;
R3 := DWORD(R3 shr 1) or (R3 shl 31);
{ 4 round }
t0 := TwofishH(R2, KeyContext);;
T1 := DWORD(R3 shl 8) or (R3 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[16]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[17]);
R0 := (R0 shl 1) or DWORD(R0 shr 31) xor F0;
R1 := R1 xor F1;
R1 := DWORD(R1 shr 1) or (R1 shl 31);
{ 3 round }
t0 := TwofishH(R0, KeyContext);;
T1 := DWORD(R1 shl 8) or (R1 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[14]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[15]);
R2 := (R2 shl 1) or DWORD(R2 shr 31) xor F0;
R3 := R3 xor F1;
R3 := DWORD(R3 shr 1) or (R3 shl 31);
{ 2 round }
t0 := TwofishH(R2, KeyContext);;
T1 := DWORD(R3 shl 8) or (R3 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[12]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[13]);
R0 := (R0 shl 1) or DWORD(R0 shr 31) xor F0;
R1 := R1 xor F1;
R1 := DWORD(R1 shr 1) or (R1 shl 31);
{ 1 round }
t0 := TwofishH(R0, KeyContext);;
T1 := DWORD(R1 shl 8) or (R1 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[10]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[11]);
R2 := (R2 shl 1) or DWORD(R2 shr 31) xor F0;
R3 := R3 xor F1;
R3 := DWORD(R3 shr 1) or (R3 shl 31);
{ 0 round }
t0 := TwofishH(R2, KeyContext);;
T1 := DWORD(R3 shl 8) or (R3 shr 24);
T1 := TwofishH(T1, KeyContext);;
F0 := DWORD(t0 + T1 + KeyContext.ExpandedKey[8]);
F1 := DWORD(t0 + T1 shl 1 + KeyContext.ExpandedKey[9]);
R0 := (R0 shl 1) or DWORD(R0 shr 31) xor F0;
R1 := R1 xor F1;
R1 := DWORD(R1 shr 1) or (R1 shl 31);
PDWORD(@Data[0])^ := R2 xor KeyContext.ExpandedKey[0];
PDWORD(@Data[4])^ := R3 xor KeyContext.ExpandedKey[1];
PDWORD(@Data[8])^ := R0 xor KeyContext.ExpandedKey[2];
PDWORD(@Data[12])^ := R1 xor KeyContext.ExpandedKey[3];
end;
initialization
InitSysCBCAndDefaultKey(Int64($F0F0F0F0F0F00F0F));
finalization
SetLength(SystemCBC, 0);
end.