source upload
This commit is contained in:
22
contrib/fundamentals/Cipher/flcCipher.inc
Normal file
22
contrib/fundamentals/Cipher/flcCipher.inc
Normal file
@@ -0,0 +1,22 @@
|
||||
{******************************************************************************}
|
||||
{ }
|
||||
{ Library: Fundamentals 5.00 }
|
||||
{ File name: flcCipher.inc }
|
||||
{ Description: Cipher library defines }
|
||||
{ }
|
||||
{******************************************************************************}
|
||||
|
||||
{.DEFINE DEBUG}
|
||||
{.DEFINE TEST}
|
||||
|
||||
{$INCLUDE ..\flcInclude.inc}
|
||||
|
||||
{$IFDEF DEBUG}
|
||||
{$IFDEF TEST}
|
||||
{$DEFINE CIPHER_TEST}
|
||||
{$ENDIF}
|
||||
{$IFDEF PROFILE}
|
||||
{$DEFINE CIPHER_PROFILE}
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
|
1297
contrib/fundamentals/Cipher/flcCipher.pas
Normal file
1297
contrib/fundamentals/Cipher/flcCipher.pas
Normal file
File diff suppressed because it is too large
Load Diff
761
contrib/fundamentals/Cipher/flcCipherAES.pas
Normal file
761
contrib/fundamentals/Cipher/flcCipherAES.pas
Normal file
@@ -0,0 +1,761 @@
|
||||
{******************************************************************************}
|
||||
{ }
|
||||
{ Library: Fundamentals 5.00 }
|
||||
{ File name: flcCipherAES.pas }
|
||||
{ File version: 5.02 }
|
||||
{ Description: AES cipher routines }
|
||||
{ }
|
||||
{ Copyright: Copyright (c) 2010-2020, David J Butler }
|
||||
{ All rights reserved. }
|
||||
{ This file is licensed under the BSD License. }
|
||||
{ See http://www.opensource.org/licenses/bsd-license.php }
|
||||
{ Redistribution and use in source and binary forms, with }
|
||||
{ or without modification, are permitted provided that }
|
||||
{ the following conditions are met: }
|
||||
{ Redistributions of source code must retain the above }
|
||||
{ copyright notice, this list of conditions and the }
|
||||
{ following disclaimer. }
|
||||
{ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND }
|
||||
{ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED }
|
||||
{ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED }
|
||||
{ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A }
|
||||
{ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL }
|
||||
{ THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, }
|
||||
{ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR }
|
||||
{ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, }
|
||||
{ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF }
|
||||
{ USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) }
|
||||
{ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER }
|
||||
{ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING }
|
||||
{ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE }
|
||||
{ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE }
|
||||
{ POSSIBILITY OF SUCH DAMAGE. }
|
||||
{ }
|
||||
{ Github: https://github.com/fundamentalslib }
|
||||
{ E-mail: fundamentals.library at gmail.com }
|
||||
{ }
|
||||
{ References: }
|
||||
{ }
|
||||
{ http://www.comms.scitech.sussex.ac.uk/fft/crypto/aesspec.pdf }
|
||||
{ http://people.eku.edu/styere/Encrypt/JS-AES.html }
|
||||
{ }
|
||||
{ Revision history: }
|
||||
{ }
|
||||
{ 2010/12/15 4.01 Initial version. }
|
||||
{ 2019/09/23 5.02 Optimisation. }
|
||||
{ }
|
||||
{******************************************************************************}
|
||||
|
||||
{$INCLUDE flcCipher.inc}
|
||||
|
||||
unit flcCipherAES;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
{ Fundamentals }
|
||||
flcStdTypes;
|
||||
|
||||
|
||||
|
||||
{ }
|
||||
{ AES }
|
||||
{ }
|
||||
const
|
||||
AESBlockSize = 16; // 128 bits
|
||||
AES_Nb = 4; // Input bits (128) divided by 32. Fixed number for AES-128, AES-192 and AES-256.
|
||||
AES_Nr_Max = 14; // Maximum number of rounds
|
||||
AES_KeyScheduleSize = AES_Nb * (AES_Nr_Max + 1);
|
||||
|
||||
type
|
||||
TAESState = array[0..3, 0..AES_Nb - 1] of Byte;
|
||||
TAESKeySchedule = array[0..AES_KeyScheduleSize - 1] of Word32;
|
||||
TAESContext = record
|
||||
Nk : Byte; // Nk = length of cipher key in multiples of 32 bits (4, 6 or 8)
|
||||
Nr : Byte; // Nr = number of rounds
|
||||
State : TAESState;
|
||||
W : TAESKeySchedule;
|
||||
end;
|
||||
PAESContext = ^TAESContext;
|
||||
|
||||
const
|
||||
AESContextSize = SizeOf(TAESContext);
|
||||
|
||||
procedure AESContextInit(var Context: TAESContext; const KeySize: Integer);
|
||||
procedure AESContextFinalise(var Context: TAESContext);
|
||||
|
||||
procedure AESInit(var Context: TAESContext;
|
||||
const KeySize: Integer;
|
||||
const KeyBuf; const KeyBufSize: Integer);
|
||||
procedure AESEncryptBlock(
|
||||
var Context: TAESContext;
|
||||
const DataBuf; const DataBufSize: Integer;
|
||||
var CipherBuf; const CipherBufSize: Integer);
|
||||
procedure AESDecryptBlock(
|
||||
var Context: TAESContext;
|
||||
const DataBuf; const DataBufSize: Integer;
|
||||
var CipherBuf; const CipherBufSize: Integer);
|
||||
procedure AESFinalise(var Context: TAESContext);
|
||||
|
||||
procedure AESEncrypt(
|
||||
const KeySize: Integer;
|
||||
const KeyBuf; const KeyBufSize: Integer;
|
||||
const DataBuf; const DataBufSize: Integer;
|
||||
var CipherBuf; const CipherBufSize: Integer);
|
||||
procedure AESDecrypt(
|
||||
const KeySize: Integer;
|
||||
const KeyBuf; const KeyBufSize: Integer;
|
||||
const DataBuf; const DataBufSize: Integer;
|
||||
var CipherBuf; const CipherBufSize: Integer);
|
||||
|
||||
|
||||
|
||||
{ }
|
||||
{ Test cases }
|
||||
{ }
|
||||
{$IFDEF CIPHER_TEST}
|
||||
procedure Test;
|
||||
{$ENDIF}
|
||||
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
{ Cipher }
|
||||
flcCipherUtils;
|
||||
|
||||
|
||||
|
||||
{ AES S-Box and inverse S-Box }
|
||||
|
||||
const
|
||||
AES_S : array[Byte] of Byte = (
|
||||
$63, $7c, $77, $7b, $f2, $6b, $6f, $c5, $30, $01, $67, $2b, $fe, $d7, $ab, $76,
|
||||
$ca, $82, $c9, $7d, $fa, $59, $47, $f0, $ad, $d4, $a2, $af, $9c, $a4, $72, $c0,
|
||||
$b7, $fd, $93, $26, $36, $3f, $f7, $cc, $34, $a5, $e5, $f1, $71, $d8, $31, $15,
|
||||
$04, $c7, $23, $c3, $18, $96, $05, $9a, $07, $12, $80, $e2, $eb, $27, $b2, $75,
|
||||
$09, $83, $2c, $1a, $1b, $6e, $5a, $a0, $52, $3b, $d6, $b3, $29, $e3, $2f, $84,
|
||||
$53, $d1, $00, $ed, $20, $fc, $b1, $5b, $6a, $cb, $be, $39, $4a, $4c, $58, $cf,
|
||||
$d0, $ef, $aa, $fb, $43, $4d, $33, $85, $45, $f9, $02, $7f, $50, $3c, $9f, $a8,
|
||||
$51, $a3, $40, $8f, $92, $9d, $38, $f5, $bc, $b6, $da, $21, $10, $ff, $f3, $d2,
|
||||
$cd, $0c, $13, $ec, $5f, $97, $44, $17, $c4, $a7, $7e, $3d, $64, $5d, $19, $73,
|
||||
$60, $81, $4f, $dc, $22, $2a, $90, $88, $46, $ee, $b8, $14, $de, $5e, $0b, $db,
|
||||
$e0, $32, $3a, $0a, $49, $06, $24, $5c, $c2, $d3, $ac, $62, $91, $95, $e4, $79,
|
||||
$e7, $c8, $37, $6d, $8d, $d5, $4e, $a9, $6c, $56, $f4, $ea, $65, $7a, $ae, $08,
|
||||
$ba, $78, $25, $2e, $1c, $a6, $b4, $c6, $e8, $dd, $74, $1f, $4b, $bd, $8b, $8a,
|
||||
$70, $3e, $b5, $66, $48, $03, $f6, $0e, $61, $35, $57, $b9, $86, $c1, $1d, $9e,
|
||||
$e1, $f8, $98, $11, $69, $d9, $8e, $94, $9b, $1e, $87, $e9, $ce, $55, $28, $df,
|
||||
$8c, $a1, $89, $0d, $bf, $e6, $42, $68, $41, $99, $2d, $0f, $b0, $54, $bb, $16
|
||||
);
|
||||
|
||||
AES_InvS : array[Byte] 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
|
||||
);
|
||||
|
||||
|
||||
|
||||
{ AES parameters }
|
||||
|
||||
function AES_Nr(const KeySize: Integer): Integer; // Number of rounds
|
||||
begin
|
||||
case KeySize of
|
||||
128 : Result := 10;
|
||||
192 : Result := 12;
|
||||
256 : Result := 14;
|
||||
else
|
||||
raise ECipher.Create(CipherError_InvalidKeySize, 'Invalid AES key length');
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{ AES context }
|
||||
|
||||
procedure AESContextInit(var Context: TAESContext; const KeySize: Integer);
|
||||
begin
|
||||
if (KeySize <> 128) and
|
||||
(KeySize <> 192) and
|
||||
(KeySize <> 256) then
|
||||
raise ECipher.Create(CipherError_InvalidKeySize, 'Invalid AES key length');
|
||||
FillChar(Context, SizeOf(Context), 0);
|
||||
Context.Nk := KeySize div 32;
|
||||
Context.Nr := AES_Nr(KeySize);
|
||||
end;
|
||||
|
||||
procedure AESContextFinalise(var Context: TAESContext);
|
||||
begin
|
||||
SecureClear(Context, SizeOf(Context));
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{ AES transformations }
|
||||
|
||||
{$R-,Q-}
|
||||
|
||||
procedure SubBytes(var State: TAESState);
|
||||
var R : Byte;
|
||||
P : PByte;
|
||||
begin
|
||||
// assumes AES_Nb = 4
|
||||
for R := 0 to 3 do
|
||||
begin
|
||||
P := @State[R, 0];
|
||||
P^ := AES_S[P^];
|
||||
Inc(P);
|
||||
P^ := AES_S[P^];
|
||||
Inc(P);
|
||||
P^ := AES_S[P^];
|
||||
Inc(P);
|
||||
P^ := AES_S[P^];
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure InvSubBytes(var State: TAESState);
|
||||
var R : Byte;
|
||||
P : PByte;
|
||||
begin
|
||||
// assumes AES_Nb = 4
|
||||
for R := 0 to 3 do
|
||||
begin
|
||||
P := @State[R, 0];
|
||||
P^ := AES_InvS[P^];
|
||||
Inc(P);
|
||||
P^ := AES_InvS[P^];
|
||||
Inc(P);
|
||||
P^ := AES_InvS[P^];
|
||||
Inc(P);
|
||||
P^ := AES_InvS[P^];
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure ShiftRows(var State: TAESState);
|
||||
// assumes AES_Nb = 4
|
||||
var
|
||||
// T : Word32;
|
||||
T0, T1, T2, T3 : Byte;
|
||||
begin
|
||||
{
|
||||
T := PWord32(@State[1])^;
|
||||
T := (T shr 8) or Word32(T shl 24);
|
||||
PWord32(@State[1])^ := T;
|
||||
}
|
||||
T0 := State[1, 1];
|
||||
T1 := State[1, 2];
|
||||
T2 := State[1, 3];
|
||||
T3 := State[1, 0];
|
||||
State[1, 0] := T0;
|
||||
State[1, 1] := T1;
|
||||
State[1, 2] := T2;
|
||||
State[1, 3] := T3;
|
||||
|
||||
{
|
||||
T := PWord32(@State[2])^;
|
||||
T := (T shr 16) or Word32(T shl 16);
|
||||
PWord32(@State[2])^ := T;
|
||||
}
|
||||
T0 := State[2, 2];
|
||||
T1 := State[2, 3];
|
||||
T2 := State[2, 0];
|
||||
T3 := State[2, 1];
|
||||
State[2, 0] := T0;
|
||||
State[2, 1] := T1;
|
||||
State[2, 2] := T2;
|
||||
State[2, 3] := T3;
|
||||
|
||||
{
|
||||
T := PWord32(@State[3])^;
|
||||
T := (T shr 24) or Word32(T shl 8);
|
||||
PWord32(@State[3])^ := T;
|
||||
}
|
||||
T0 := State[3, 3];
|
||||
T1 := State[3, 0];
|
||||
T2 := State[3, 1];
|
||||
T3 := State[3, 2];
|
||||
State[3, 0] := T0;
|
||||
State[3, 1] := T1;
|
||||
State[3, 2] := T2;
|
||||
State[3, 3] := T3;
|
||||
end;
|
||||
|
||||
procedure InvShiftRows(var State: TAESState);
|
||||
// assumes AES_Nb = 4
|
||||
var
|
||||
T0, T1, T2, T3 : Byte;
|
||||
begin
|
||||
T1 := State[1, 0];
|
||||
T2 := State[1, 1];
|
||||
T3 := State[1, 2];
|
||||
T0 := State[1, 3];
|
||||
State[1, 0] := T0;
|
||||
State[1, 1] := T1;
|
||||
State[1, 2] := T2;
|
||||
State[1, 3] := T3;
|
||||
|
||||
T2 := State[2, 0];
|
||||
T3 := State[2, 1];
|
||||
T0 := State[2, 2];
|
||||
T1 := State[2, 3];
|
||||
State[2, 0] := T0;
|
||||
State[2, 1] := T1;
|
||||
State[2, 2] := T2;
|
||||
State[2, 3] := T3;
|
||||
|
||||
T3 := State[3, 0];
|
||||
T0 := State[3, 1];
|
||||
T1 := State[3, 2];
|
||||
T2 := State[3, 3];
|
||||
State[3, 0] := T0;
|
||||
State[3, 1] := T1;
|
||||
State[3, 2] := T2;
|
||||
State[3, 3] := T3;
|
||||
end;
|
||||
|
||||
const
|
||||
FFLog : array[Byte] of Byte = (
|
||||
$00, $00, $19, $01, $32, $02, $1a, $c6, $4b, $c7, $1b, $68, $33, $ee, $df, $03,
|
||||
$64, $04, $e0, $0e, $34, $8d, $81, $ef, $4c, $71, $08, $c8, $f8, $69, $1c, $c1,
|
||||
$7d, $c2, $1d, $b5, $f9, $b9, $27, $6a, $4d, $e4, $a6, $72, $9a, $c9, $09, $78,
|
||||
$65, $2f, $8a, $05, $21, $0f, $e1, $24, $12, $f0, $82, $45, $35, $93, $da, $8e,
|
||||
$96, $8f, $db, $bd, $36, $d0, $ce, $94, $13, $5c, $d2, $f1, $40, $46, $83, $38,
|
||||
$66, $dd, $fd, $30, $bf, $06, $8b, $62, $b3, $25, $e2, $98, $22, $88, $91, $10,
|
||||
$7e, $6e, $48, $c3, $a3, $b6, $1e, $42, $3a, $6b, $28, $54, $fa, $85, $3d, $ba,
|
||||
$2b, $79, $0a, $15, $9b, $9f, $5e, $ca, $4e, $d4, $ac, $e5, $f3, $73, $a7, $57,
|
||||
$af, $58, $a8, $50, $f4, $ea, $d6, $74, $4f, $ae, $e9, $d5, $e7, $e6, $ad, $e8,
|
||||
$2c, $d7, $75, $7a, $eb, $16, $0b, $f5, $59, $cb, $5f, $b0, $9c, $a9, $51, $a0,
|
||||
$7f, $0c, $f6, $6f, $17, $c4, $49, $ec, $d8, $43, $1f, $2d, $a4, $76, $7b, $b7,
|
||||
$cc, $bb, $3e, $5a, $fb, $60, $b1, $86, $3b, $52, $a1, $6c, $aa, $55, $29, $9d,
|
||||
$97, $b2, $87, $90, $61, $be, $dc, $fc, $bc, $95, $cf, $cd, $37, $3f, $5b, $d1,
|
||||
$53, $39, $84, $3c, $41, $a2, $6d, $47, $14, $2a, $9e, $5d, $56, $f2, $d3, $ab,
|
||||
$44, $11, $92, $d9, $23, $20, $2e, $89, $b4, $7c, $b8, $26, $77, $99, $e3, $a5,
|
||||
$67, $4a, $ed, $de, $c5, $31, $fe, $18, $0d, $63, $8c, $80, $c0, $f7, $70, $07);
|
||||
|
||||
FFPow : array[Byte] of Byte = (
|
||||
$01, $03, $05, $0f, $11, $33, $55, $ff, $1a, $2e, $72, $96, $a1, $f8, $13, $35,
|
||||
$5f, $e1, $38, $48, $d8, $73, $95, $a4, $f7, $02, $06, $0a, $1e, $22, $66, $aa,
|
||||
$e5, $34, $5c, $e4, $37, $59, $eb, $26, $6a, $be, $d9, $70, $90, $ab, $e6, $31,
|
||||
$53, $f5, $04, $0c, $14, $3c, $44, $cc, $4f, $d1, $68, $b8, $d3, $6e, $b2, $cd,
|
||||
$4c, $d4, $67, $a9, $e0, $3b, $4d, $d7, $62, $a6, $f1, $08, $18, $28, $78, $88,
|
||||
$83, $9e, $b9, $d0, $6b, $bd, $dc, $7f, $81, $98, $b3, $ce, $49, $db, $76, $9a,
|
||||
$b5, $c4, $57, $f9, $10, $30, $50, $f0, $0b, $1d, $27, $69, $bb, $d6, $61, $a3,
|
||||
$fe, $19, $2b, $7d, $87, $92, $ad, $ec, $2f, $71, $93, $ae, $e9, $20, $60, $a0,
|
||||
$fb, $16, $3a, $4e, $d2, $6d, $b7, $c2, $5d, $e7, $32, $56, $fa, $15, $3f, $41,
|
||||
$c3, $5e, $e2, $3d, $47, $c9, $40, $c0, $5b, $ed, $2c, $74, $9c, $bf, $da, $75,
|
||||
$9f, $ba, $d5, $64, $ac, $ef, $2a, $7e, $82, $9d, $bc, $df, $7a, $8e, $89, $80,
|
||||
$9b, $b6, $c1, $58, $e8, $23, $65, $af, $ea, $25, $6f, $b1, $c8, $43, $c5, $54,
|
||||
$fc, $1f, $21, $63, $a5, $f4, $07, $09, $1b, $2d, $77, $99, $b0, $cb, $46, $ca,
|
||||
$45, $cf, $4a, $de, $79, $8b, $86, $91, $a8, $e3, $3e, $42, $c6, $51, $f3, $0e,
|
||||
$12, $36, $5a, $ee, $29, $7b, $8d, $8c, $8f, $8a, $85, $94, $a7, $f2, $0d, $17,
|
||||
$39, $4b, $dd, $7c, $84, $97, $a2, $fd, $1c, $24, $6c, $b4, $c7, $52, $f6, $01);
|
||||
|
||||
function FFmul(const A, B: Byte): Byte; {$IFDEF UseInline}inline;{$ENDIF}
|
||||
var
|
||||
T : Word;
|
||||
begin
|
||||
if (A <> 0) and (B <> 0) then
|
||||
begin
|
||||
T := FFLog[A] + FFLog[B];
|
||||
if T >= 255 then
|
||||
Dec(T, 255);
|
||||
Result := FFPow[T];
|
||||
end
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function FFmul2(const B: Byte): Byte; {$IFDEF UseInline}inline;{$ENDIF}
|
||||
var
|
||||
T : Word;
|
||||
begin
|
||||
if B <> 0 then
|
||||
begin
|
||||
T := $19 + FFLog[B];
|
||||
if T >= 255 then
|
||||
Dec(T, 255);
|
||||
Result := FFPow[T];
|
||||
end
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function FFmul3(const B: Byte): Byte; {$IFDEF UseInline}inline;{$ENDIF}
|
||||
var
|
||||
T : Word;
|
||||
begin
|
||||
if B <> 0 then
|
||||
begin
|
||||
T := $01 + FFLog[B];
|
||||
if T >= 255 then
|
||||
Dec(T, 255);
|
||||
Result := FFPow[T];
|
||||
end
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function FFmulE(const B: Byte): Byte; {$IFDEF UseInline}inline;{$ENDIF}
|
||||
var
|
||||
T : Word;
|
||||
begin
|
||||
if B <> 0 then
|
||||
begin
|
||||
T := $df + FFLog[B];
|
||||
if T >= 255 then
|
||||
Dec(T, 255);
|
||||
Result := FFPow[T];
|
||||
end
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function FFmulB(const B: Byte): Byte; {$IFDEF UseInline}inline;{$ENDIF}
|
||||
var
|
||||
T : Word;
|
||||
begin
|
||||
if B <> 0 then
|
||||
begin
|
||||
T := $68 + FFLog[B];
|
||||
if T >= 255 then
|
||||
Dec(T, 255);
|
||||
Result := FFPow[T];
|
||||
end
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function FFmulD(const B: Byte): Byte; {$IFDEF UseInline}inline;{$ENDIF}
|
||||
var
|
||||
T : Word;
|
||||
begin
|
||||
if B <> 0 then
|
||||
begin
|
||||
T := $ee + FFLog[B];
|
||||
if T >= 255 then
|
||||
Dec(T, 255);
|
||||
Result := FFPow[T];
|
||||
end
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function FFmul9(const B: Byte): Byte; {$IFDEF UseInline}inline;{$ENDIF}
|
||||
var
|
||||
T : Word;
|
||||
begin
|
||||
if B <> 0 then
|
||||
begin
|
||||
T := $c7 + FFLog[B];
|
||||
if T >= 255 then
|
||||
Dec(T, 255);
|
||||
Result := FFPow[T];
|
||||
end
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
procedure MixColumns(var State: TAESState);
|
||||
var
|
||||
T0, T1, T2, T3 : Byte;
|
||||
C : Byte;
|
||||
begin
|
||||
for C := 0 to AES_Nb - 1 do
|
||||
begin
|
||||
T0 := State[0, C];
|
||||
T1 := State[1, C];
|
||||
T2 := State[2, C];
|
||||
T3 := State[3, C];
|
||||
State[0, C] := FFmul2(T0) xor FFmul3(T1) xor T2 xor T3;
|
||||
State[1, C] := FFmul2(T1) xor FFmul3(T2) xor T3 xor T0;
|
||||
State[2, C] := FFmul2(T2) xor FFmul3(T3) xor T0 xor T1;
|
||||
State[3, C] := FFmul2(T3) xor FFmul3(T0) xor T1 xor T2;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure InvMixColumns(var State: TAESState);
|
||||
var
|
||||
T0, T1, T2, T3 : Byte;
|
||||
C : Byte;
|
||||
begin
|
||||
for C := 0 to AES_Nb - 1 do
|
||||
begin
|
||||
T0 := State[0, C];
|
||||
T1 := State[1, C];
|
||||
T2 := State[2, C];
|
||||
T3 := State[3, C];
|
||||
State[0, C] := FFmulE(T0) xor FFmulB(T1) xor FFmulD(T2) xor FFmul9(T3);
|
||||
State[1, C] := FFmulE(T1) xor FFmulB(T2) xor FFmulD(T3) xor FFmul9(T0);
|
||||
State[2, C] := FFmulE(T2) xor FFmulB(T3) xor FFmulD(T0) xor FFmul9(T1);
|
||||
State[3, C] := FFmulE(T3) xor FFmulB(T0) xor FFmulD(T1) xor FFmul9(T2);
|
||||
end;
|
||||
end;
|
||||
|
||||
function xbyte(const R: Byte; const K: Word32): Byte; {$IFDEF UseInline}inline;{$ENDIF}
|
||||
begin
|
||||
Result := Byte((K shr (R * 8)) and $FF);
|
||||
end;
|
||||
|
||||
procedure XorRoundKey(var State: TAESState; const Rk: TAESKeySchedule; const RkIdx: Integer);
|
||||
var C : Byte;
|
||||
P : PByte;
|
||||
RkP : PWord32;
|
||||
RkC : Word32;
|
||||
begin
|
||||
RkP := @Rk[RkIdx];
|
||||
for C := 0 to AES_Nb - 1 do
|
||||
begin
|
||||
RkC := RkP^;
|
||||
P := @State[0, C];
|
||||
P^ := P^ xor xbyte(0, RkC);
|
||||
P := @State[1, C];
|
||||
P^ := P^ xor xbyte(1, RkC);
|
||||
P := @State[2, C];
|
||||
P^ := P^ xor xbyte(2, RkC);
|
||||
P := @State[3, C];
|
||||
P^ := P^ xor xbyte(3, RkC);
|
||||
Inc(RkP);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{ AES key expansion }
|
||||
|
||||
function SubWord(const A: Word32): Word32; {$IFDEF UseInline}inline;{$ENDIF}
|
||||
begin
|
||||
Result :=
|
||||
AES_S[Byte (A and $000000FF)] or
|
||||
(AES_S[Byte((A and $0000FF00) shr 8)] shl 8) or
|
||||
(AES_S[Byte((A and $00FF0000) shr 16)] shl 16) or
|
||||
(AES_S[Byte((A and $FF000000) shr 24)] shl 24);
|
||||
end;
|
||||
|
||||
function RotWord(const A: Word32): Word32; {$IFDEF UseInline}inline;{$ENDIF}
|
||||
begin
|
||||
Result :=
|
||||
((A and $FFFFFF00) shr 8) or
|
||||
((A and $000000FF) shl 24);
|
||||
end;
|
||||
|
||||
const
|
||||
AES_Rcon : array[Byte] of Byte = (
|
||||
$8d, $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, $39,
|
||||
$72, $e4, $d3, $bd, $61, $c2, $9f, $25, $4a, $94, $33, $66, $cc, $83, $1d, $3a,
|
||||
$74, $e8, $cb, $8d, $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, $39, $72, $e4, $d3, $bd, $61, $c2, $9f, $25, $4a, $94, $33, $66, $cc,
|
||||
$83, $1d, $3a, $74, $e8, $cb, $8d, $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, $39, $72, $e4, $d3, $bd, $61, $c2, $9f, $25, $4a, $94,
|
||||
$33, $66, $cc, $83, $1d, $3a, $74, $e8, $cb, $8d, $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, $39, $72, $e4, $d3, $bd, $61, $c2, $9f,
|
||||
$25, $4a, $94, $33, $66, $cc, $83, $1d, $3a, $74, $e8, $cb, $8d, $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, $39, $72, $e4, $d3, $bd,
|
||||
$61, $c2, $9f, $25, $4a, $94, $33, $66, $cc, $83, $1d, $3a, $74, $e8, $cb, $00);
|
||||
|
||||
procedure AESKeyExpansion(var Context: TAESContext; const KeyBuf; const KeyBufSize: Integer);
|
||||
var Nk : Byte;
|
||||
I : Integer;
|
||||
T : Word32;
|
||||
P : PWord32;
|
||||
begin
|
||||
Nk := Context.Nk;
|
||||
if KeyBufSize <> Nk * 4 then
|
||||
raise ECipher.Create(CipherError_InvalidBufferSize, 'Invalid key size');
|
||||
P := @KeyBuf;
|
||||
for I := 0 to Nk - 1 do
|
||||
begin
|
||||
Context.W[I] := P^;
|
||||
Inc(P);
|
||||
end;
|
||||
for I := Nk to AES_Nb * (Context.Nr + 1) - 1 do
|
||||
begin
|
||||
T := Context.W[I - 1];
|
||||
if I mod Nk = 0 then
|
||||
begin
|
||||
T := RotWord(T);
|
||||
T := SubWord(T);
|
||||
T := T xor AES_Rcon[I div Nk];
|
||||
end else
|
||||
if (Nk = 8) and (I mod Nk = 4) then
|
||||
T := SubWord(T);
|
||||
Context.W[I] := Context.W[I - Nk] xor T;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{ AES cipher and inverse cipher }
|
||||
|
||||
procedure InBufToState(var Context: TAESContext; const InBuf; const InBufSize: Integer);
|
||||
var R, C : Byte;
|
||||
P : PByte;
|
||||
begin
|
||||
if InBufSize <> AES_Nb * 4 then
|
||||
raise ECipher.Create(CipherError_InvalidBufferSize, 'Invalid buffer size');
|
||||
for R := 0 to 3 do
|
||||
for C := 0 to AES_Nb - 1 do
|
||||
begin
|
||||
P := @InBuf;
|
||||
Inc(P, R + 4 * C);
|
||||
Context.State[R, C] := P^;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure StateToOutBuf(var Context: TAESContext; var OutBuf; const OutBufSize: Integer);
|
||||
var R, C : Byte;
|
||||
P : PByte;
|
||||
begin
|
||||
if OutBufSize < AES_Nb * 4 then
|
||||
raise ECipher.Create(CipherError_InvalidBufferSize, 'Invalid buffer size');
|
||||
for C := 0 to AES_Nb - 1 do
|
||||
for R := 0 to 3 do
|
||||
begin
|
||||
P := @OutBuf;
|
||||
Inc(P, R + 4 * C);
|
||||
P^ := Context.State[R, C];
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure AESCipher(var Context: TAESContext;
|
||||
const InBuf; const InBufSize: Integer;
|
||||
var OutBuf; const OutBufSize: Integer);
|
||||
var R : Integer;
|
||||
begin
|
||||
InBufToState(Context, InBuf, InBufSize);
|
||||
XorRoundKey(Context.State, Context.W, 0);
|
||||
for R := 1 to Context.Nr - 1 do
|
||||
begin
|
||||
SubBytes(Context.State);
|
||||
ShiftRows(Context.State);
|
||||
MixColumns(Context.State);
|
||||
XorRoundKey(Context.State, Context.W, R * AES_Nb);
|
||||
end;
|
||||
SubBytes(Context.State);
|
||||
ShiftRows(Context.State);
|
||||
XorRoundKey(Context.State, Context.W, Context.Nr * AES_Nb);
|
||||
StateToOutBuf(Context, OutBuf, OutBufSize);
|
||||
end;
|
||||
|
||||
procedure AESInvCipher(var Context: TAESContext;
|
||||
const InBuf; const InBufSize: Integer;
|
||||
var OutBuf; const OutBufSize: Integer);
|
||||
var R : Integer;
|
||||
begin
|
||||
InBufToState(Context, InBuf, InBufSize);
|
||||
XorRoundKey(Context.State, Context.W, Context.Nr * AES_Nb);
|
||||
for R := Context.Nr - 1 downto 1 do
|
||||
begin
|
||||
InvShiftRows(Context.State);
|
||||
InvSubBytes(Context.State);
|
||||
XorRoundKey(Context.State, Context.W, R * AES_Nb);
|
||||
InvMixColumns(Context.State);
|
||||
end;
|
||||
InvShiftRows(Context.State);
|
||||
InvSubBytes(Context.State);
|
||||
XorRoundKey(Context.State, Context.W, 0);
|
||||
StateToOutBuf(Context, OutBuf, OutBufSize);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{ AES encrypt and decrypt }
|
||||
|
||||
procedure AESInit(var Context: TAESContext;
|
||||
const KeySize: Integer;
|
||||
const KeyBuf; const KeyBufSize: Integer);
|
||||
begin
|
||||
AESContextInit(Context, KeySize);
|
||||
AESKeyExpansion(Context, KeyBuf, KeyBufSize);
|
||||
end;
|
||||
|
||||
procedure AESEncryptBlock(
|
||||
var Context: TAESContext;
|
||||
const DataBuf; const DataBufSize: Integer;
|
||||
var CipherBuf; const CipherBufSize: Integer);
|
||||
begin
|
||||
AESCipher(Context, DataBuf, DataBufSize, CipherBuf, CipherBufSize)
|
||||
end;
|
||||
|
||||
procedure AESDecryptBlock(
|
||||
var Context: TAESContext;
|
||||
const DataBuf; const DataBufSize: Integer;
|
||||
var CipherBuf; const CipherBufSize: Integer);
|
||||
begin
|
||||
AESInvCipher(Context, DataBuf, DataBufSize, CipherBuf, CipherBufSize)
|
||||
end;
|
||||
|
||||
procedure AESFinalise(var Context: TAESContext);
|
||||
begin
|
||||
AESContextFinalise(Context);
|
||||
end;
|
||||
|
||||
procedure AESEncrypt(
|
||||
const KeySize: Integer;
|
||||
const KeyBuf; const KeyBufSize: Integer;
|
||||
const DataBuf; const DataBufSize: Integer;
|
||||
var CipherBuf; const CipherBufSize: Integer);
|
||||
var Context: TAESContext;
|
||||
begin
|
||||
AESContextInit(Context, KeySize);
|
||||
AESKeyExpansion(Context, KeyBuf, KeyBufSize);
|
||||
AESCipher(Context, DataBuf, DataBufSize, CipherBuf, CipherBufSize);
|
||||
AESContextFinalise(Context);
|
||||
end;
|
||||
|
||||
procedure AESDecrypt(
|
||||
const KeySize: Integer;
|
||||
const KeyBuf; const KeyBufSize: Integer;
|
||||
const DataBuf; const DataBufSize: Integer;
|
||||
var CipherBuf; const CipherBufSize: Integer);
|
||||
var Context: TAESContext;
|
||||
begin
|
||||
AESContextInit(Context, KeySize);
|
||||
AESKeyExpansion(Context, KeyBuf, KeyBufSize);
|
||||
AESInvCipher(Context, DataBuf, DataBufSize, CipherBuf, CipherBufSize);
|
||||
AESContextFinalise(Context);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{ }
|
||||
{ Test cases }
|
||||
{ }
|
||||
{$IFDEF CIPHER_TEST}
|
||||
{$ASSERTIONS ON}
|
||||
procedure Test;
|
||||
var K, T, B : RawByteString;
|
||||
begin
|
||||
K := RawByteString(#$0f#$15#$71#$c9#$47#$d9#$e8#$59#$0c#$b7#$ad#$d6#$af#$7f#$67#$98);
|
||||
T := '1234567890123456';
|
||||
SetLength(B, 16);
|
||||
AESEncrypt(128, K[1], Length(K), T[1], Length(T), B[1], Length(B));
|
||||
Assert(B = #$2f#$7d#$76#$42#$5e#$bb#$85#$e4#$f2#$e7#$b0#$08#$68#$bf#$0f#$ce);
|
||||
T := '00000000000000000';
|
||||
AESDecrypt(128, K[1], Length(K), B[1], Length(B), T[1], Length(T));
|
||||
Assert(T = '12345678901234560');
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
|
||||
|
||||
end.
|
||||
|
590
contrib/fundamentals/Cipher/flcCipherDES.pas
Normal file
590
contrib/fundamentals/Cipher/flcCipherDES.pas
Normal file
@@ -0,0 +1,590 @@
|
||||
{******************************************************************************}
|
||||
{ }
|
||||
{ Library: Fundamentals 5.00 }
|
||||
{ File name: flcCipherDES.pas }
|
||||
{ File version: 5.04 }
|
||||
{ Description: DES cipher routines }
|
||||
{ }
|
||||
{ Copyright: Copyright (c) 2007-2020, David J Butler }
|
||||
{ All rights reserved. }
|
||||
{ This file is licensed under the BSD License. }
|
||||
{ See http://www.opensource.org/licenses/bsd-license.php }
|
||||
{ Redistribution and use in source and binary forms, with }
|
||||
{ or without modification, are permitted provided that }
|
||||
{ the following conditions are met: }
|
||||
{ Redistributions of source code must retain the above }
|
||||
{ copyright notice, this list of conditions and the }
|
||||
{ following disclaimer. }
|
||||
{ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND }
|
||||
{ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED }
|
||||
{ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED }
|
||||
{ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A }
|
||||
{ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL }
|
||||
{ THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, }
|
||||
{ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR }
|
||||
{ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, }
|
||||
{ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF }
|
||||
{ USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) }
|
||||
{ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER }
|
||||
{ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING }
|
||||
{ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE }
|
||||
{ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE }
|
||||
{ POSSIBILITY OF SUCH DAMAGE. }
|
||||
{ }
|
||||
{ Github: https://github.com/fundamentalslib }
|
||||
{ E-mail: fundamentals.library at gmail.com }
|
||||
{ }
|
||||
{ References: }
|
||||
{ }
|
||||
{ DES 40 - http://www.watersprings.org/pub/id/draft-hoffman-des40-00.txt }
|
||||
{ }
|
||||
{ Revision history: }
|
||||
{ }
|
||||
{ 2007/01/06 4.01 DES and Triple-DES }
|
||||
{ 2010/12/16 4.02 DES-40 }
|
||||
{ 2019/06/09 5.03 Triple-DES3 buffer functions for Encrypt and Decrypt. }
|
||||
{ 2019/09/22 5.04 Optimisations. }
|
||||
{ }
|
||||
{******************************************************************************}
|
||||
|
||||
{$INCLUDE flcCipher.inc}
|
||||
|
||||
{$IFDEF FREEPASCAL}
|
||||
{$R-}
|
||||
{$ENDIF}
|
||||
|
||||
unit flcCipherDES;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
{ Fundamentals }
|
||||
flcStdTypes;
|
||||
|
||||
|
||||
|
||||
{ }
|
||||
{ DES }
|
||||
{ Data Encryption Standard. }
|
||||
{ FIPS-46 became a US NBS standard in 1977. }
|
||||
{ }
|
||||
type
|
||||
TDESKey = array[0..7] of Byte;
|
||||
PDESKey = ^TDESKey;
|
||||
|
||||
TDESWord32Pair = array[0..1] of Word32;
|
||||
PDESWord32Pair = ^TDESWord32Pair;
|
||||
|
||||
TDESContext = array[1..16] of TDESWord32Pair;
|
||||
PDESContext = ^TDESContext;
|
||||
|
||||
TDESBlock = array[0..7] of Byte;
|
||||
PDESBlock = ^TDESBlock;
|
||||
|
||||
const
|
||||
DESBlockSize = 8;
|
||||
DESContextSize = SizeOf(TDESContext);
|
||||
|
||||
procedure DESInit(const Encrypt: Boolean; const Key: TDESKey; var Context: TDESContext);
|
||||
procedure DESBuffer(const Context: TDESContext; var Block: TDESBlock);
|
||||
|
||||
|
||||
|
||||
{ }
|
||||
{ DES-40 }
|
||||
{ }
|
||||
procedure DESKeyConvertToDES40(var Key: TDESKey);
|
||||
|
||||
|
||||
|
||||
{ }
|
||||
{ Triple-DES-EDE }
|
||||
{ Also known as 2-key Triple-DES }
|
||||
{ }
|
||||
type
|
||||
TTripleDESKey = array[0..1] of TDESKey;
|
||||
PTripleDESKey = ^TTripleDESKey;
|
||||
TTripleDESContext = array[0..1] of TDESContext;
|
||||
PTripleDESContext = ^TTripleDESContext;
|
||||
|
||||
const
|
||||
TripleDESContextSize = SizeOf(TTripleDESContext);
|
||||
|
||||
procedure TripleDESInit(const Encrypt: Boolean; const Key: TTripleDESKey;
|
||||
var Context: TTripleDESContext);
|
||||
procedure TripleDESBuffer(const Context: TTripleDESContext; var Block: TDESBlock);
|
||||
|
||||
|
||||
|
||||
{ }
|
||||
{ Triple-DES-3 (EDE and EEE modes) }
|
||||
{ Also known as 3-key Triple-DES }
|
||||
{ }
|
||||
type
|
||||
TTripleDES3Key = array[0..2] of TDESKey;
|
||||
PTripleDES3Key = ^TTripleDES3Key;
|
||||
TTripleDES3Context = array[0..2] of TDESContext;
|
||||
PTripleDES3Context = ^TTripleDES3Context;
|
||||
|
||||
const
|
||||
TripleDES3ContextSize = SizeOf(TTripleDES3Context);
|
||||
|
||||
procedure TripleDES3Init(const Encrypt: Boolean; const Key: TTripleDES3Key;
|
||||
const EEEMode: Boolean; var Context: TTripleDES3Context);
|
||||
procedure TripleDES3BufferEncrypt(const Context: TTripleDES3Context; var Block: TDESBlock);
|
||||
procedure TripleDES3BufferDecrypt(const Context: TTripleDES3Context; var Block: TDESBlock);
|
||||
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
{ Cipher }
|
||||
flcCipherUtils;
|
||||
|
||||
|
||||
|
||||
{ }
|
||||
{ DES }
|
||||
{ }
|
||||
const
|
||||
// DES PC-1 (key permutation 1) table
|
||||
DESPC1Table : array[0..55] of Byte = (
|
||||
57, 49, 41, 33, 25, 17, 9,
|
||||
1, 58, 50, 42, 34, 26, 18,
|
||||
10, 2, 59, 51, 43, 35, 27,
|
||||
19, 11, 3, 60, 52, 44, 36,
|
||||
63, 55, 47, 39, 31, 23, 15,
|
||||
7, 62, 54, 46, 38, 30, 22,
|
||||
14, 6, 61, 53, 45, 37, 29,
|
||||
21, 13, 5, 28, 20, 12, 4);
|
||||
|
||||
// DES key shift table
|
||||
DESKeyShiftTable : array[1..16] of Byte = (
|
||||
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1);
|
||||
|
||||
// DES PC-2 (key permuation 2) table
|
||||
DESPC2Table : array[0..47] of Byte = (
|
||||
14, 17, 11, 24, 1, 5,
|
||||
3, 28, 15, 6, 21, 10,
|
||||
23, 19, 12, 4, 26, 8,
|
||||
16, 7, 27, 20, 13, 2,
|
||||
41, 52, 31, 37, 47, 55,
|
||||
30, 40, 51, 45, 33, 48,
|
||||
44, 49, 39, 56, 34, 53,
|
||||
46, 42, 50, 36, 29, 32);
|
||||
|
||||
// DES IP (initial permutation) table
|
||||
DESIPTable : array[0..63] of Byte = (
|
||||
58, 50, 42, 34, 26, 18, 10, 2,
|
||||
60, 52, 44, 36, 28, 20, 12, 4,
|
||||
62, 54, 46, 38, 30, 22, 14, 6,
|
||||
64, 56, 48, 40, 32, 24, 16, 8,
|
||||
57, 49, 41, 33, 25, 17, 9, 1,
|
||||
59, 51, 43, 35, 27, 19, 11, 3,
|
||||
61, 53, 45, 37, 29, 21, 13, 5,
|
||||
63, 55, 47, 39, 31, 23, 15, 7);
|
||||
|
||||
// DES E bit-selection table
|
||||
DESETable : array[0..47] of Byte = (
|
||||
32, 1, 2, 3, 4, 5,
|
||||
4, 5, 6, 7, 8, 9,
|
||||
8, 9, 10, 11, 12, 13,
|
||||
12, 13, 14, 15, 16, 17,
|
||||
16, 17, 18, 19, 20, 21,
|
||||
20, 21, 22, 23, 24, 25,
|
||||
24, 25, 26, 27, 28, 29,
|
||||
28, 29, 30, 31, 32, 1);
|
||||
|
||||
// DES S boxes (S1..S8)
|
||||
DESSTable : array[0..7, 0..63] of Byte = (
|
||||
(14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
|
||||
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
|
||||
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
|
||||
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13),
|
||||
(15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
|
||||
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
|
||||
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
|
||||
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9),
|
||||
(10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
|
||||
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
|
||||
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
|
||||
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12),
|
||||
( 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
|
||||
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
|
||||
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
|
||||
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14),
|
||||
( 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
|
||||
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
|
||||
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
|
||||
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3),
|
||||
(12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
|
||||
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
|
||||
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
|
||||
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13),
|
||||
( 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
|
||||
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
|
||||
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
|
||||
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12),
|
||||
(13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
|
||||
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
|
||||
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
|
||||
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11));
|
||||
|
||||
// DES P (permutation) table
|
||||
DESPTable : array[0..31] of Byte = (
|
||||
16, 7, 20, 21, 29, 12, 28, 17,
|
||||
1, 15, 23, 26, 5, 18, 31, 10,
|
||||
2, 8, 24, 14, 32, 27, 3, 9,
|
||||
19, 13, 30, 6, 22, 11, 4, 25);
|
||||
|
||||
// DES IP-1 table
|
||||
DESIP1Table : array[0..63] of Byte = (
|
||||
40, 8, 48, 16, 56, 24, 64, 32,
|
||||
39, 7, 47, 15, 55, 23, 63, 31,
|
||||
38, 6, 46, 14, 54, 22, 62, 30,
|
||||
37, 5, 45, 13, 53, 21, 61, 29,
|
||||
36, 4, 44, 12, 52, 20, 60, 28,
|
||||
35, 3, 43, 11, 51, 19, 59, 27,
|
||||
34, 2, 42, 10, 50, 18, 58, 26,
|
||||
33, 1, 41, 9, 49, 17, 57, 25);
|
||||
|
||||
// 28 bit ROL operation
|
||||
function DESROL28(const Value: Word32; const Bits: Byte): Word32;
|
||||
var I : Integer;
|
||||
begin
|
||||
Result := Value;
|
||||
for I := 1 to Bits do
|
||||
if Result and $08000000 = 0 then
|
||||
Result := Result shl 1
|
||||
else
|
||||
Result := ((Result and $07FFFFFF) shl 1) or 1;
|
||||
end;
|
||||
|
||||
// 32 bit swap endian
|
||||
{$IFDEF ASM386}
|
||||
function DESSwapEndian32(const Value: Word32): Word32;
|
||||
asm
|
||||
XCHG AH, AL
|
||||
ROL EAX, 16
|
||||
XCHG AH, AL
|
||||
end;
|
||||
{$ELSE}
|
||||
function DESSwapEndian32(const Value: Word32): Word32;
|
||||
begin
|
||||
Result := ((Value and $000000FF) shl 24) or
|
||||
((Value and $0000FF00) shl 8) or
|
||||
((Value and $00FF0000) shr 8) or
|
||||
((Value and $FF000000) shr 24);
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
// PC-1 permutation from K (64 bits) to K+ (56 bits)
|
||||
function DESPC1Permutation(const K: TDESWord32Pair): TDESWord32Pair;
|
||||
var I : Integer;
|
||||
N : Byte;
|
||||
begin
|
||||
Result[0] := 0;
|
||||
Result[1] := 0;
|
||||
for I := 0 to 55 do
|
||||
begin
|
||||
N := DESPC1Table[I] - 1;
|
||||
if K[N div 32] and (1 shl (31 - (N mod 32))) <> 0 then
|
||||
Result[I div 32] := Result[I div 32] or (1 shl (31 - (I mod 32)));
|
||||
end;
|
||||
end;
|
||||
|
||||
// PC-2 permutation from CnDn (56 bits) to Kn (48 bits)
|
||||
function DESPC2Permutation(const K: TDESWord32Pair): TDESWord32Pair;
|
||||
var I : Integer;
|
||||
N : Byte;
|
||||
begin
|
||||
Result[0] := 0;
|
||||
Result[1] := 0;
|
||||
for I := 0 to 47 do
|
||||
begin
|
||||
N := DESPC2Table[I] - 1;
|
||||
if K[N div 32] and (1 shl (31 - (N mod 32))) <> 0 then
|
||||
Result[I div 32] := Result[I div 32] or (1 shl (31 - (I mod 32)));
|
||||
end;
|
||||
end;
|
||||
|
||||
// DES initialization
|
||||
procedure DESInit(const Encrypt: Boolean; const Key: TDESKey; var Context: TDESContext);
|
||||
var K : TDESWord32Pair;
|
||||
C, D : array[0..16] of Word32;
|
||||
I, J : Integer;
|
||||
N : Byte;
|
||||
E : TDESWord32Pair;
|
||||
begin
|
||||
// Move key into K and swap endian
|
||||
Move(Key, K, Sizeof(K));
|
||||
K[0] := DESSwapEndian32(K[0]);
|
||||
K[1] := DESSwapEndian32(K[1]);
|
||||
// PC-1 permutation from KD (64 bits) into KP (56 bits)
|
||||
K := DESPC1Permutation(K);
|
||||
// Split KP into C0 and D0 (28 bits each)
|
||||
C[0] := (K[0] and $FFFFFFF0) shr 4;
|
||||
D[0] := ((K[0] and $0000000F) shl 24) or ((K[1] and $FFFFFF00) shr 8);
|
||||
SecureClear(K, Sizeof(K));
|
||||
// Generate C1..C16 and D1..D16 using shift table
|
||||
for I := 1 to 16 do
|
||||
begin
|
||||
N := DESKeyShiftTable[I];
|
||||
C[I] := DESROL28(C[I - 1], N);
|
||||
D[I] := DESROL28(D[I - 1], N);
|
||||
end;
|
||||
// PC-2 permutation from C1..16 (28 bits) and D1..16 (28 bits) into K1..K16 (48 bits)
|
||||
for I := 1 to 16 do
|
||||
begin
|
||||
E[0] := (C[I] shl 4) or (D[I] shr 24);
|
||||
E[1] := D[I] shl 8;
|
||||
if Encrypt then
|
||||
J := I
|
||||
else
|
||||
J := 17 - I;
|
||||
Context[J] := DESPC2Permutation(E);
|
||||
end;
|
||||
SecureClear(C, Sizeof(C));
|
||||
SecureClear(D, Sizeof(D));
|
||||
SecureClear(E, Sizeof(E));
|
||||
end;
|
||||
|
||||
{$R-,Q-}
|
||||
|
||||
// DES E bit-selection table (modified for bit operation optimisation)
|
||||
const
|
||||
DESETable_Mod : array[0..47] of Word32 = (
|
||||
1 shl (32 - 32), Word32(1) shl (32 - 1), 1 shl (32 - 2), 1 shl (32 - 3), 1 shl (32 - 4), 1 shl (32 - 5),
|
||||
1 shl (32 - 4), 1 shl (32 - 5), 1 shl (32 - 6), 1 shl (32 - 7), 1 shl (32 - 8), 1 shl (32 - 9),
|
||||
1 shl (32 - 8), 1 shl (32 - 9), 1 shl (32 - 10), 1 shl (32 - 11), 1 shl (32 - 12), 1 shl (32 - 13),
|
||||
1 shl (32 - 12), 1 shl (32 - 13), 1 shl (32 - 14), 1 shl (32 - 15), 1 shl (32 - 16), 1 shl (32 - 17),
|
||||
1 shl (32 - 16), 1 shl (32 - 17), 1 shl (32 - 18), 1 shl (32 - 19), 1 shl (32 - 20), 1 shl (32 - 21),
|
||||
1 shl (32 - 20), 1 shl (32 - 21), 1 shl (32 - 22), 1 shl (32 - 23), 1 shl (32 - 24), 1 shl (32 - 25),
|
||||
1 shl (32 - 24), 1 shl (32 - 25), 1 shl (32 - 26), 1 shl (32 - 27), 1 shl (32 - 28), 1 shl (32 - 29),
|
||||
1 shl (32 - 28), 1 shl (32 - 29), 1 shl (32 - 30), 1 shl (32 - 31), 1 shl (32 - 32), Word32(1) shl (32 - 1));
|
||||
|
||||
// DES P (permutation) table (modified for bit operation optimisation)
|
||||
DESPTable_Mod : array[0..31] of Word32 = (
|
||||
1 shl (32 - 16), 1 shl (32 - 7), 1 shl (32 - 20), 1 shl (32 - 21), 1 shl (32 - 29), 1 shl (32 - 12), 1 shl (32 - 28), 1 shl (32 - 17),
|
||||
Word32(1) shl (32 - 1), 1 shl (32 - 15), 1 shl (32 - 23), 1 shl (32 - 26), 1 shl (32 - 5), 1 shl (32 - 18), 1 shl (32 - 31), 1 shl (32 - 10),
|
||||
1 shl (32 - 2), 1 shl (32 - 8), 1 shl (32 - 24), 1 shl (32 - 14), 1 shl (32 - 32), 1 shl (32 - 27), 1 shl (32 - 3), 1 shl (32 - 9),
|
||||
1 shl (32 - 19), 1 shl (32 - 13), 1 shl (32 - 30), 1 shl (32 - 6), 1 shl (32 - 22), 1 shl (32 - 11), 1 shl (32 - 4), 1 shl (32 - 25));
|
||||
|
||||
// DES E-function
|
||||
function DESEFunc(const R: Word32; const K: TDESWord32Pair): Word32;
|
||||
var E0, E1 : Word32;
|
||||
B : Word32;
|
||||
I : Integer;
|
||||
BI, SI : Byte;
|
||||
X, Y : Byte;
|
||||
S : Word32;
|
||||
begin
|
||||
// Expand R (32 bits) to E (48 bits) using E bit-selection table
|
||||
E0 := 0;
|
||||
E1 := 0;
|
||||
B := Word32(1) shl 31;
|
||||
for I := 0 to 31 do
|
||||
begin
|
||||
if R and DESETable_Mod[I] <> 0 then
|
||||
E0 := E0 or B;
|
||||
B := B shr 1;
|
||||
end;
|
||||
B := Word32(1) shl 31;
|
||||
for I := 32 to 47 do
|
||||
begin
|
||||
if R and DESETable_Mod[I] <> 0 then
|
||||
E1 := E1 or B;
|
||||
B := B shr 1;
|
||||
end;
|
||||
// Apply key (48 bits) to E
|
||||
E0 := E0 xor K[0];
|
||||
E1 := E1 xor K[1];
|
||||
// Apply S boxes on 8 groups of 6 bits
|
||||
S := 0;
|
||||
for I := 0 to 7 do
|
||||
begin
|
||||
case I of
|
||||
0..4 : BI := (E0 shr (26 - (I * 6))) and $3F;
|
||||
5 : BI := ((E0 and $00000003) shl 4) or
|
||||
((E1 and $F0000000) shr 28);
|
||||
else BI := (E1 shr (22 + 36 - (I * 6))) and $3F;
|
||||
end; // BI = Bi (6 bits) from E
|
||||
Y := (BI and 1) or ((BI and $20) shr 4); // Y = Row (first and last bits of Bi)
|
||||
X := (BI and $1E) shr 1; // X = Column (middle 4 bits of Bi)
|
||||
SI := DESSTable[I, Y * 16 + X]; // SI = Si (4 bits)
|
||||
S := S or (SI shl (28 - (I * 4))); // S = S0..S7 (32 bits)
|
||||
end;
|
||||
|
||||
// Apply permutation table to S
|
||||
Result := 0;
|
||||
B := Word32(1) shl 31;
|
||||
for I := 0 to 31 do
|
||||
begin
|
||||
if S and DESPTable_Mod[I] <> 0 then
|
||||
Result := Result or B;
|
||||
B := B shr 1;
|
||||
end;
|
||||
end;
|
||||
|
||||
// DES block function
|
||||
procedure DESBuffer(const Context: TDESContext; var Block: TDESBlock);
|
||||
var IP : TDESBlock;
|
||||
IPP : PByte;
|
||||
I : Integer;
|
||||
IH : Byte;
|
||||
IL : Byte;
|
||||
N : Byte;
|
||||
L, R : array[0..16] of Word32;
|
||||
P : array[0..1] of Word32;
|
||||
begin
|
||||
// Apply initial permuation on M (64 bits) to get IP (64 bits)
|
||||
FillChar(IP, Sizeof(TDESBlock), 0);
|
||||
IH := 0;
|
||||
IPP := @IP[IH];
|
||||
for I := 0 to 63 do
|
||||
begin
|
||||
IL := I and 7;
|
||||
if IL = 0 then
|
||||
begin
|
||||
IH := I shr 3;
|
||||
IPP := @IP[IH];
|
||||
end;
|
||||
N := DESIPTable[I] - 1;
|
||||
if Block[N shr 3] and (1 shl (7 - (N and 7))) <> 0 then
|
||||
IPP^ := IPP^ or (1 shl (7 - IL));
|
||||
end;
|
||||
// Split IP into L0 and R0 (32 bits each)
|
||||
L[0] := IP[3] or (IP[2] shl 8) or (IP[1] shl 16) or (IP[0] shl 24);
|
||||
R[0] := IP[7] or (IP[6] shl 8) or (IP[5] shl 16) or (IP[4] shl 24);
|
||||
SecureClear(IP, Sizeof(IP));
|
||||
// Generate L1..L16 and R1..R16
|
||||
for I := 1 to 16 do
|
||||
begin
|
||||
L[I] := R[I - 1];
|
||||
R[I] := L[I - 1] xor DESEFunc(R[I - 1], Context[I]);
|
||||
end;
|
||||
// Combine R16L16 (64 bits)
|
||||
P[0] := R[16];
|
||||
P[1] := L[16];
|
||||
SecureClear(L, Sizeof(L));
|
||||
SecureClear(R, Sizeof(R));
|
||||
// Apply IP-1 permutation to R16L16 to get result (64 bits)
|
||||
FillChar(Block, Sizeof(TDESBlock), 0);
|
||||
IH := 0;
|
||||
IPP := @Block[IH];
|
||||
for I := 0 to 63 do
|
||||
begin
|
||||
IL := I and 7;
|
||||
if IL = 0 then
|
||||
begin
|
||||
IH := I shr 3;
|
||||
IPP := @Block[IH];
|
||||
end;
|
||||
N := DESIP1Table[I] - 1;
|
||||
if P[N shr 5] and (1 shl (31 - (N and $1F))) <> 0 then
|
||||
IPP^ := IPP^ or (1 shl (7 - IL));
|
||||
end;
|
||||
SecureClear(P, Sizeof(P));
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{ }
|
||||
{ DES-40 }
|
||||
{ }
|
||||
const
|
||||
BitCountTable : array[Byte] of Byte =
|
||||
(0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8);
|
||||
|
||||
procedure DESSetOddParity(var A: Byte);
|
||||
begin
|
||||
if not Odd(BitCountTable[A]) then
|
||||
A := A xor $80;
|
||||
end;
|
||||
|
||||
procedure DESKeyConvertToDES40(var Key: TDESKey);
|
||||
var A, B, C, D : Byte;
|
||||
begin
|
||||
// clear lower 4 bits of every second byte starting at first byte
|
||||
A := Key[0] and $F0;
|
||||
B := Key[2] and $F0;
|
||||
C := Key[4] and $F0;
|
||||
D := Key[6] and $F0;
|
||||
// make parity odd on modified bytes by toggling high bit
|
||||
DESSetOddParity(A);
|
||||
DESSetOddParity(B);
|
||||
DESSetOddParity(C);
|
||||
DESSetOddParity(D);
|
||||
// modify key
|
||||
Key[0] := A;
|
||||
Key[2] := B;
|
||||
Key[4] := C;
|
||||
Key[6] := D;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{ }
|
||||
{ Triple-DES-EDE }
|
||||
{ }
|
||||
procedure TripleDESInit(const Encrypt: Boolean; const Key: TTripleDESKey;
|
||||
var Context: TTripleDESContext);
|
||||
begin
|
||||
DESInit(Encrypt, Key[0], Context[0]);
|
||||
DESInit(not Encrypt, Key[1], Context[1]);
|
||||
end;
|
||||
|
||||
procedure TripleDESBuffer(const Context: TTripleDESContext; var Block: TDESBlock);
|
||||
begin
|
||||
DESBuffer(Context[0], Block);
|
||||
DESBuffer(Context[1], Block);
|
||||
DESBuffer(Context[0], Block);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{ }
|
||||
{ Triple-DES-EDE-3 }
|
||||
{ }
|
||||
procedure TripleDES3Init(const Encrypt: Boolean; const Key: TTripleDES3Key;
|
||||
const EEEMode: Boolean; var Context: TTripleDES3Context);
|
||||
begin
|
||||
DESInit(Encrypt, Key[0], Context[0]);
|
||||
DESInit(not Encrypt xor EEEMode, Key[1], Context[1]);
|
||||
DESInit(Encrypt, Key[2], Context[2]);
|
||||
end;
|
||||
|
||||
procedure TripleDES3BufferEncrypt(const Context: TTripleDES3Context; var Block: TDESBlock);
|
||||
begin
|
||||
DESBuffer(Context[0], Block);
|
||||
DESBuffer(Context[1], Block);
|
||||
DESBuffer(Context[2], Block);
|
||||
end;
|
||||
|
||||
procedure TripleDES3BufferDecrypt(const Context: TTripleDES3Context; var Block: TDESBlock);
|
||||
begin
|
||||
DESBuffer(Context[2], Block);
|
||||
DESBuffer(Context[1], Block);
|
||||
DESBuffer(Context[0], Block);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
end.
|
||||
|
1695
contrib/fundamentals/Cipher/flcCipherDH.pas
Normal file
1695
contrib/fundamentals/Cipher/flcCipherDH.pas
Normal file
File diff suppressed because it is too large
Load Diff
273
contrib/fundamentals/Cipher/flcCipherRC2.pas
Normal file
273
contrib/fundamentals/Cipher/flcCipherRC2.pas
Normal file
@@ -0,0 +1,273 @@
|
||||
{******************************************************************************}
|
||||
{ }
|
||||
{ Library: Fundamentals 5.00 }
|
||||
{ File name: flcCipherRC2.pas }
|
||||
{ File version: 5.01 }
|
||||
{ Description: RC2 cipher routines }
|
||||
{ }
|
||||
{ Copyright: Copyright (c) 2007-2020, David J Butler }
|
||||
{ All rights reserved. }
|
||||
{ This file is licensed under the BSD License. }
|
||||
{ See http://www.opensource.org/licenses/bsd-license.php }
|
||||
{ Redistribution and use in source and binary forms, with }
|
||||
{ or without modification, are permitted provided that }
|
||||
{ the following conditions are met: }
|
||||
{ Redistributions of source code must retain the above }
|
||||
{ copyright notice, this list of conditions and the }
|
||||
{ following disclaimer. }
|
||||
{ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND }
|
||||
{ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED }
|
||||
{ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED }
|
||||
{ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A }
|
||||
{ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL }
|
||||
{ THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, }
|
||||
{ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR }
|
||||
{ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, }
|
||||
{ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF }
|
||||
{ USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) }
|
||||
{ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER }
|
||||
{ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING }
|
||||
{ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE }
|
||||
{ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE }
|
||||
{ POSSIBILITY OF SUCH DAMAGE. }
|
||||
{ }
|
||||
{ Github: https://github.com/fundamentalslib }
|
||||
{ E-mail: fundamentals.library at gmail.com }
|
||||
{ }
|
||||
{ Revision history: }
|
||||
{ }
|
||||
{ 2007/01/05 4.01 Initial version. }
|
||||
{ }
|
||||
{******************************************************************************}
|
||||
|
||||
{$INCLUDE flcCipher.inc}
|
||||
|
||||
unit flcCipherRC2;
|
||||
|
||||
interface
|
||||
|
||||
|
||||
|
||||
{ }
|
||||
{ RC2 }
|
||||
{ RC2 was developed by Ron Rivest in 1987. }
|
||||
{ }
|
||||
type
|
||||
TRC2CipherKey = packed record
|
||||
case Integer of
|
||||
0 : (Bytes: array[0..127] of Byte);
|
||||
1 : (Words: array[0..63] of Word);
|
||||
end;
|
||||
PRC2CipherKey = ^TRC2CipherKey;
|
||||
|
||||
TRC2Block = packed record
|
||||
case Integer of
|
||||
0 : (Bytes: array[0..7] of Byte);
|
||||
1 : (Words: array[0..3] of Word);
|
||||
2 : (A, B, C, D: Word);
|
||||
end;
|
||||
PRC2Block = ^TRC2Block;
|
||||
|
||||
const
|
||||
RC2BlockSize = 8;
|
||||
|
||||
procedure RC2Init(const Key; const KeySize: Integer; const KeyBits: Integer;
|
||||
var CipherKey: TRC2CipherKey);
|
||||
procedure RC2EncryptBlock(const CipherKey: TRC2CipherKey; var Block: TRC2Block);
|
||||
procedure RC2DecryptBlock(const CipherKey: TRC2CipherKey; var Block: TRC2Block);
|
||||
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
{ Cipher }
|
||||
flcCipherUtils;
|
||||
|
||||
|
||||
|
||||
{ }
|
||||
{ RC2 }
|
||||
{ See RFC 2268 for details on the algorithm. }
|
||||
{ }
|
||||
|
||||
// RC2 PITABLE - "Random" values based on value of Pi
|
||||
const
|
||||
RC2Table: array[Byte] of Byte = (
|
||||
$D9, $78, $F9, $C4, $19, $DD, $B5, $ED, $28, $E9, $FD, $79, $4A, $A0, $D8, $9D,
|
||||
$C6, $7E, $37, $83, $2B, $76, $53, $8E, $62, $4C, $64, $88, $44, $8B, $FB, $A2,
|
||||
$17, $9A, $59, $F5, $87, $B3, $4F, $13, $61, $45, $6D, $8D, $09, $81, $7D, $32,
|
||||
$BD, $8F, $40, $EB, $86, $B7, $7B, $0B, $F0, $95, $21, $22, $5C, $6B, $4E, $82,
|
||||
$54, $D6, $65, $93, $CE, $60, $B2, $1C, $73, $56, $C0, $14, $A7, $8C, $F1, $DC,
|
||||
$12, $75, $CA, $1F, $3B, $BE, $E4, $D1, $42, $3D, $D4, $30, $A3, $3C, $B6, $26,
|
||||
$6F, $BF, $0E, $DA, $46, $69, $07, $57, $27, $F2, $1D, $9B, $BC, $94, $43, $03,
|
||||
$F8, $11, $C7, $F6, $90, $EF, $3E, $E7, $06, $C3, $D5, $2F, $C8, $66, $1E, $D7,
|
||||
$08, $E8, $EA, $DE, $80, $52, $EE, $F7, $84, $AA, $72, $AC, $35, $4D, $6A, $2A,
|
||||
$96, $1A, $D2, $71, $5A, $15, $49, $74, $4B, $9F, $D0, $5E, $04, $18, $A4, $EC,
|
||||
$C2, $E0, $41, $6E, $0F, $51, $CB, $CC, $24, $91, $AF, $50, $A1, $F4, $70, $39,
|
||||
$99, $7C, $3A, $85, $23, $B8, $B4, $7A, $FC, $02, $36, $5B, $25, $55, $97, $31,
|
||||
$2D, $5D, $FA, $98, $E3, $8A, $92, $AE, $05, $DF, $29, $10, $67, $6C, $BA, $C9,
|
||||
$D3, $00, $E6, $CF, $E1, $9E, $A8, $2C, $63, $16, $01, $3F, $58, $E2, $89, $A9,
|
||||
$0D, $38, $34, $1B, $AB, $33, $FF, $B0, $BB, $48, $0C, $5F, $B9, $B1, $CD, $2E,
|
||||
$C5, $F3, $DB, $47, $E5, $A5, $9C, $77, $0A, $A6, $20, $68, $FE, $7F, $C1, $AD);
|
||||
|
||||
// RC2 ROR helper function (16 bit rotate right)
|
||||
{$IFDEF ASM386_DELPHI}
|
||||
function RC2ROR(const Value: Word; const Bits: Byte): Word;
|
||||
asm
|
||||
MOV CL, DL
|
||||
ROR AX, CL
|
||||
end;
|
||||
{$ELSE}
|
||||
function RC2ROR(const Value: Word; const Bits: Byte): Word;
|
||||
var I : Integer;
|
||||
begin
|
||||
Result := Value;
|
||||
for I := 1 to Bits do
|
||||
if Result and 1 = 0 then
|
||||
Result := Result shr 1
|
||||
else
|
||||
Result := (Result shr 1) or $8000;
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
// RC2 ROL helper function (16 bit rotate left)
|
||||
{$IFDEF ASM386_DELPHI}
|
||||
function RC2ROL(const Value: Word; const Bits: Byte): Word;
|
||||
asm
|
||||
MOV CL, DL
|
||||
ROL AX, CL
|
||||
end;
|
||||
{$ELSE}
|
||||
function RC2ROL(const Value: Word; const Bits: Byte): Word;
|
||||
var I : Integer;
|
||||
begin
|
||||
Result := Value;
|
||||
for I := 1 to Bits do
|
||||
if Result and $8000 = 0 then
|
||||
Result := Result shl 1
|
||||
else
|
||||
Result := Word(Result shl 1) or 1;
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
// RC2 initialization
|
||||
procedure RC2Init(
|
||||
const Key; const KeySize: Integer;
|
||||
const KeyBits: Integer;
|
||||
var CipherKey: TRC2CipherKey);
|
||||
var I : Integer;
|
||||
T8 : Byte;
|
||||
TM : Byte;
|
||||
begin
|
||||
// Validate parameters
|
||||
if KeySize > 128 then
|
||||
raise ECipher.Create(CipherError_InvalidKeySize, 'Maximum RC2 key length is 128');
|
||||
if KeySize < 1 then
|
||||
raise ECipher.Create(CipherError_InvalidKeySize, 'Minimum RC2 key length is 1');
|
||||
if (KeyBits <= 0) or (KeyBits > 1024) then
|
||||
raise ECipher.Create(CipherError_InvalidKeyBits, 'Invalid number of key bits');
|
||||
// RC2 key expansion
|
||||
Move(Key, CipherKey, KeySize);
|
||||
with CipherKey do
|
||||
begin
|
||||
for I := KeySize to 127 do
|
||||
Bytes[I] := RC2Table[Byte(Bytes[I - 1] + Bytes[I - KeySize])];
|
||||
T8 := (KeyBits + 7) div 8;
|
||||
TM := 255 mod (1 shl (8 + KeyBits - 8 * T8));
|
||||
Bytes[128 - T8] := RC2Table[Bytes[128 - T8] and TM];
|
||||
for I := 127 - T8 downto 0 do
|
||||
Bytes[I] := RC2Table[Bytes[I + 1] xor Bytes[I + T8]];
|
||||
end;
|
||||
end;
|
||||
|
||||
// RC2 Encrypt
|
||||
// RC2 Mix: R[i] = R[i] + K[j] + (R[i-1] & R[i-2]) + ((~R[i-1]) & R[i-3])
|
||||
// R[i] = R[i] rol s[i]
|
||||
// RC2 Mash: R[i] = R[i] + K[R[i-1] & 63]
|
||||
procedure RC2EncryptBlock(const CipherKey: TRC2CipherKey; var Block: TRC2Block);
|
||||
var J : PWord;
|
||||
I : Integer;
|
||||
begin
|
||||
J := @CipherKey.Words[0];
|
||||
with Block do
|
||||
begin
|
||||
for I := 1 to 5 do
|
||||
begin
|
||||
A := RC2ROL(Word(A + J^ + (D and C) + (not D and B)), 1); Inc(J);
|
||||
B := RC2ROL(Word(B + J^ + (A and D) + (not A and C)), 2); Inc(J);
|
||||
C := RC2ROL(Word(C + J^ + (B and A) + (not B and D)), 3); Inc(J);
|
||||
D := RC2ROL(Word(D + J^ + (C and B) + (not C and A)), 5); Inc(J);
|
||||
end;
|
||||
A := Word(A + CipherKey.Words[D and $3F]);
|
||||
B := Word(B + CipherKey.Words[A and $3F]);
|
||||
C := Word(C + CipherKey.Words[B and $3F]);
|
||||
D := Word(D + CipherKey.Words[C and $3F]);
|
||||
for I := 1 to 6 do
|
||||
begin
|
||||
A := RC2ROL(Word(A + J^ + (D and C) + (not D and B)), 1); Inc(J);
|
||||
B := RC2ROL(Word(B + J^ + (A and D) + (not A and C)), 2); Inc(J);
|
||||
C := RC2ROL(Word(C + J^ + (B and A) + (not B and D)), 3); Inc(J);
|
||||
D := RC2ROL(Word(D + J^ + (C and B) + (not C and A)), 5); Inc(J);
|
||||
end;
|
||||
A := Word(A + CipherKey.Words[D and $3F]);
|
||||
B := Word(B + CipherKey.Words[A and $3F]);
|
||||
C := Word(C + CipherKey.Words[B and $3F]);
|
||||
D := Word(D + CipherKey.Words[C and $3F]);
|
||||
for I := 1 to 5 do
|
||||
begin
|
||||
A := RC2ROL(Word(A + J^ + (D and C) + (not D and B)), 1); Inc(J);
|
||||
B := RC2ROL(Word(B + J^ + (A and D) + (not A and C)), 2); Inc(J);
|
||||
C := RC2ROL(Word(C + J^ + (B and A) + (not B and D)), 3); Inc(J);
|
||||
D := RC2ROL(Word(D + J^ + (C and B) + (not C and A)), 5); Inc(J);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
// RC2 Decrypt
|
||||
// RC2 r-Mix: R[i] = R[i] ror s[i]
|
||||
// R[i] = R[i] - K[j] - (R[i-1] & R[i-2]) - ((~R[i-1]) & R[i-3])
|
||||
// RC2 r-Mash: R[i] = R[i] - K[R[i-1] & 63]
|
||||
procedure RC2DecryptBlock(const CipherKey: TRC2CipherKey; var Block: TRC2Block);
|
||||
var J : PWord;
|
||||
I : Integer;
|
||||
begin
|
||||
J := @CipherKey.Words[63];
|
||||
with Block do
|
||||
begin
|
||||
for I := 1 to 5 do
|
||||
begin
|
||||
D := Word(RC2ROR(D, 5) - J^ - (C and B) - (not C and A)); Dec(J);
|
||||
C := Word(RC2ROR(C, 3) - J^ - (B and A) - (not B and D)); Dec(J);
|
||||
B := Word(RC2ROR(B, 2) - J^ - (A and D) - (not A and C)); Dec(J);
|
||||
A := Word(RC2ROR(A, 1) - J^ - (D and C) - (not D and B)); Dec(J);
|
||||
end;
|
||||
D := Word(D - CipherKey.Words[C and $3F]);
|
||||
C := Word(C - CipherKey.Words[B and $3F]);
|
||||
B := Word(B - CipherKey.Words[A and $3F]);
|
||||
A := Word(A - CipherKey.Words[D and $3F]);
|
||||
for I := 1 to 6 do
|
||||
begin
|
||||
D := Word(RC2ROR(D, 5) - J^ - (C and B) - (not C and A)); Dec(J);
|
||||
C := Word(RC2ROR(C, 3) - J^ - (B and A) - (not B and D)); Dec(J);
|
||||
B := Word(RC2ROR(B, 2) - J^ - (A and D) - (not A and C)); Dec(J);
|
||||
A := Word(RC2ROR(A, 1) - J^ - (D and C) - (not D and B)); Dec(J);
|
||||
end;
|
||||
D := Word(D - CipherKey.Words[C and $3F]);
|
||||
C := Word(C - CipherKey.Words[B and $3F]);
|
||||
B := Word(B - CipherKey.Words[A and $3F]);
|
||||
A := Word(A - CipherKey.Words[D and $3F]);
|
||||
for I := 1 to 5 do
|
||||
begin
|
||||
D := Word(RC2ROR(D, 5) - J^ - (C and B) - (not C and A)); Dec(J);
|
||||
C := Word(RC2ROR(C, 3) - J^ - (B and A) - (not B and D)); Dec(J);
|
||||
B := Word(RC2ROR(B, 2) - J^ - (A and D) - (not A and C)); Dec(J);
|
||||
A := Word(RC2ROR(A, 1) - J^ - (D and C) - (not D and B)); Dec(J);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
end.
|
||||
|
148
contrib/fundamentals/Cipher/flcCipherRC4.pas
Normal file
148
contrib/fundamentals/Cipher/flcCipherRC4.pas
Normal file
@@ -0,0 +1,148 @@
|
||||
{******************************************************************************}
|
||||
{ }
|
||||
{ Library: Fundamentals 5.00 }
|
||||
{ File name: flcCipherRC4.pas }
|
||||
{ File version: 5.06 }
|
||||
{ Description: RC4 cipher routines }
|
||||
{ }
|
||||
{ Copyright: Copyright (c) 2007-2020, David J Butler }
|
||||
{ All rights reserved. }
|
||||
{ This file is licensed under the BSD License. }
|
||||
{ See http://www.opensource.org/licenses/bsd-license.php }
|
||||
{ Redistribution and use in source and binary forms, with }
|
||||
{ or without modification, are permitted provided that }
|
||||
{ the following conditions are met: }
|
||||
{ Redistributions of source code must retain the above }
|
||||
{ copyright notice, this list of conditions and the }
|
||||
{ following disclaimer. }
|
||||
{ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND }
|
||||
{ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED }
|
||||
{ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED }
|
||||
{ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A }
|
||||
{ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL }
|
||||
{ THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, }
|
||||
{ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR }
|
||||
{ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, }
|
||||
{ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF }
|
||||
{ USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) }
|
||||
{ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER }
|
||||
{ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING }
|
||||
{ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE }
|
||||
{ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE }
|
||||
{ POSSIBILITY OF SUCH DAMAGE. }
|
||||
{ }
|
||||
{ Github: https://github.com/fundamentalslib }
|
||||
{ E-mail: fundamentals.library at gmail.com }
|
||||
{ }
|
||||
{ References: }
|
||||
{ }
|
||||
{ * www.mozilla.org/projects/security/pki/nss/ }
|
||||
{ draft-kaukonen-cipher-arcfour-03.txt }
|
||||
{ }
|
||||
{ Revision history: }
|
||||
{ }
|
||||
{ 2007/01/05 4.01 Initial version. }
|
||||
{ }
|
||||
{******************************************************************************}
|
||||
|
||||
{$INCLUDE flcCipher.inc}
|
||||
|
||||
unit flcCipherRC4;
|
||||
|
||||
interface
|
||||
|
||||
|
||||
|
||||
{ }
|
||||
{ RC4 }
|
||||
{ Also known as Arcfour. }
|
||||
{ }
|
||||
type
|
||||
TRC4SBox = packed array[Byte] of Byte;
|
||||
TRC4Context = packed record
|
||||
S : TRC4SBox;
|
||||
SI : Byte;
|
||||
SJ : Byte;
|
||||
end;
|
||||
PRC4Context = ^TRC4Context;
|
||||
|
||||
procedure RC4Init(const Key; const KeySize: Integer; var Context: TRC4Context);
|
||||
procedure RC4Buffer(var Context: TRC4Context; var Buffer; const BufferSize: NativeInt);
|
||||
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
{ Cipher }
|
||||
flcCipherUtils;
|
||||
|
||||
|
||||
|
||||
{ }
|
||||
{ RC4 }
|
||||
{ }
|
||||
procedure RC4Init(const Key; const KeySize: Integer; var Context: TRC4Context);
|
||||
type
|
||||
TRC4KeyBuffer = array[Byte] of Byte;
|
||||
PRC4KeyBuffer = ^TRC4KeyBuffer;
|
||||
var I, J, T : Byte;
|
||||
K : PRC4KeyBuffer;
|
||||
begin
|
||||
// Validate parameters
|
||||
if KeySize > 256 then
|
||||
raise ECipher.Create(CipherError_InvalidKeySize, 'Maximum RC4 key length is 256');
|
||||
if KeySize < 1 then
|
||||
raise ECipher.Create(CipherError_InvalidKeySize, 'Minimum RC4 key length is 1');
|
||||
// Prepare RC4 context
|
||||
with Context do
|
||||
begin
|
||||
for I := 0 to 255 do
|
||||
S[I] := I;
|
||||
K := @Key;
|
||||
J := 0;
|
||||
for I := 0 to 255 do
|
||||
begin
|
||||
J := Byte(Byte(J + S[I]) + K^[I mod KeySize]);
|
||||
T := S[I];
|
||||
S[I] := S[J];
|
||||
S[J] := T;
|
||||
end;
|
||||
SI := 0;
|
||||
SJ := 0;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure RC4Buffer(var Context: TRC4Context; var Buffer; const BufferSize: NativeInt);
|
||||
var
|
||||
SI : Byte;
|
||||
SJ : Byte;
|
||||
P : PByte;
|
||||
F : NativeInt;
|
||||
T : Byte;
|
||||
U : Byte;
|
||||
begin
|
||||
SI := Context.SI;
|
||||
SJ := Context.SJ;
|
||||
P := @Buffer;
|
||||
for F := 0 to BufferSize - 1 do
|
||||
begin
|
||||
SI := Byte(SI + 1);
|
||||
T := Context.S[SI];
|
||||
SJ := Byte(SJ + T);
|
||||
U := Context.S[SJ];
|
||||
Context.S[SI] := U;
|
||||
Context.S[SJ] := T;
|
||||
T := Byte(T + U);
|
||||
T := Context.S[T];
|
||||
P^ := P^ xor T;
|
||||
Inc(P);
|
||||
end;
|
||||
Context.SI := SI;
|
||||
Context.SJ := SJ;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
end.
|
||||
|
1965
contrib/fundamentals/Cipher/flcCipherRSA.pas
Normal file
1965
contrib/fundamentals/Cipher/flcCipherRSA.pas
Normal file
File diff suppressed because it is too large
Load Diff
318
contrib/fundamentals/Cipher/flcCipherRandom.pas
Normal file
318
contrib/fundamentals/Cipher/flcCipherRandom.pas
Normal file
@@ -0,0 +1,318 @@
|
||||
{******************************************************************************}
|
||||
{ }
|
||||
{ Library: Fundamentals 5.00 }
|
||||
{ File name: flcCipherRandom.pas }
|
||||
{ File version: 5.06 }
|
||||
{ Description: Cipher random }
|
||||
{ }
|
||||
{ Copyright: Copyright (c) 2010-2020, David J Butler }
|
||||
{ All rights reserved. }
|
||||
{ This file is licensed under the BSD License. }
|
||||
{ See http://www.opensource.org/licenses/bsd-license.php }
|
||||
{ Redistribution and use in source and binary forms, with }
|
||||
{ or without modification, are permitted provided that }
|
||||
{ the following conditions are met: }
|
||||
{ Redistributions of source code must retain the above }
|
||||
{ copyright notice, this list of conditions and the }
|
||||
{ following disclaimer. }
|
||||
{ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND }
|
||||
{ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED }
|
||||
{ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED }
|
||||
{ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A }
|
||||
{ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL }
|
||||
{ THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, }
|
||||
{ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR }
|
||||
{ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, }
|
||||
{ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF }
|
||||
{ USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) }
|
||||
{ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER }
|
||||
{ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING }
|
||||
{ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE }
|
||||
{ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE }
|
||||
{ POSSIBILITY OF SUCH DAMAGE. }
|
||||
{ }
|
||||
{ Github: https://github.com/fundamentalslib }
|
||||
{ E-mail: fundamentals.library at gmail.com }
|
||||
{ }
|
||||
{ Revision history: }
|
||||
{ }
|
||||
{ 2010/12/17 4.01 Initial version. }
|
||||
{ 2013/09/25 4.02 UnicodeString version. }
|
||||
{ 2015/05/05 4.03 Multiple PRNGs and PRSS and SHA512 hash in random block }
|
||||
{ generator. }
|
||||
{ 2016/01/09 5.04 Revised for Fundamentals 5. }
|
||||
{ 2019/06/06 5.05 SecureRandomBytes function. }
|
||||
{ 2020/02/13 5.06 Remove MD5 from generator. }
|
||||
{ Use 8 random bits in generator for each secure }
|
||||
{ random bit. }
|
||||
{ }
|
||||
{******************************************************************************}
|
||||
|
||||
{$INCLUDE flcCipher.inc}
|
||||
|
||||
unit flcCipherRandom;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
{ System }
|
||||
SysUtils,
|
||||
|
||||
{ Fundamentals }
|
||||
flcStdTypes;
|
||||
|
||||
|
||||
|
||||
procedure SecureRandomBuf(var Buf; const Size: Integer);
|
||||
|
||||
function SecureRandomBytes(const Size: Integer): TBytes;
|
||||
|
||||
function SecureRandomStrA(const Size: Integer): RawByteString;
|
||||
|
||||
function SecureRandomHexStr(const Digits: Integer; const UpperCase: Boolean = True): String;
|
||||
function SecureRandomHexStrB(const Digits: Integer; const UpperCase: Boolean = True): RawByteString;
|
||||
function SecureRandomHexStrU(const Digits: Integer; const UpperCase: Boolean = True): UnicodeString;
|
||||
|
||||
function SecureRandomWord32: Word32;
|
||||
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
{ Fundamentals }
|
||||
flcUtils,
|
||||
flcRandom,
|
||||
flcHash;
|
||||
|
||||
|
||||
|
||||
const
|
||||
SecureRandomBlockBits = 128;
|
||||
SecureRandomBlockSize = SecureRandomBlockBits div 8; // 16 bytes
|
||||
|
||||
type
|
||||
TSecureRandomBlock = array[0..SecureRandomBlockSize - 1] of Byte;
|
||||
PSecureRandomBlock = ^TSecureRandomBlock;
|
||||
|
||||
// produces a block of SecureRandomBlockSize bytes of secure random material
|
||||
procedure SecureRandomBlockGenerator(var Block: TSecureRandomBlock);
|
||||
const
|
||||
RandomDataBits = SecureRandomBlockBits * 8; // 1024 bits (128 bytes)
|
||||
RandomDataLen = RandomDataBits div 32; // 32 * Word32
|
||||
var
|
||||
I : Integer;
|
||||
RData : array[0..RandomDataLen - 1] of Word32;
|
||||
S32 : Word32;
|
||||
H512 : T512BitDigest;
|
||||
H256 : T256BitDigest;
|
||||
begin
|
||||
try
|
||||
// initialise 1024 bits with multiple Pseudo Random Numbers Generators (PRNG)
|
||||
// and Pseudo Random System State (PRSS)
|
||||
FillChar(RData, SizeOf(RData), $FF);
|
||||
S32 := RandomSeed32;
|
||||
RData[0] := RData[0] xor S32;
|
||||
for I := 0 to RandomDataLen - 1 do
|
||||
RData[I] := RData[I] xor RandomUniform32;
|
||||
for I := 0 to RandomDataLen - 1 do
|
||||
RData[I] := RData[I] xor urnRandom32;
|
||||
S32 := RandomSeed32;
|
||||
RData[RandomDataLen - 1] := RData[RandomDataLen - 1] xor S32;
|
||||
// hash 1024 bits using SHA512 into 512 bits
|
||||
H512 := CalcSHA512(RData, SizeOf(RData));
|
||||
// hash 512 bits using SHA256 into 256 bits
|
||||
H256 := CalcSHA256(H512, SizeOf(T512BitDigest));
|
||||
// move 128 bits to secure random block
|
||||
Assert(SizeOf(H256) >= SecureRandomBlockSize);
|
||||
Move(H256, Block, SecureRandomBlockSize);
|
||||
finally
|
||||
SecureClear(H256, SizeOf(T256BitDigest));
|
||||
SecureClear(H512, SizeOf(T512BitDigest));
|
||||
SecureClear(RData, SizeOf(RData));
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure SecureRandomBuf(var Buf; const Size: Integer);
|
||||
var
|
||||
P : PSecureRandomBlock;
|
||||
L : Integer;
|
||||
B : TSecureRandomBlock;
|
||||
begin
|
||||
P := @Buf;
|
||||
L := Size;
|
||||
while L >= SecureRandomBlockSize do
|
||||
begin
|
||||
SecureRandomBlockGenerator(P^);
|
||||
Inc(P);
|
||||
Dec(L, SecureRandomBlockSize);
|
||||
end;
|
||||
if L > 0 then
|
||||
begin
|
||||
SecureRandomBlockGenerator(B);
|
||||
Move(B, P^, L);
|
||||
SecureClear(B, SecureRandomBlockSize);
|
||||
end;
|
||||
end;
|
||||
|
||||
function SecureRandomBytes(const Size: Integer): TBytes;
|
||||
begin
|
||||
SetLength(Result, Size);
|
||||
if Size <= 0 then
|
||||
exit;
|
||||
SecureRandomBuf(Pointer(Result)^, Size);
|
||||
end;
|
||||
|
||||
function SecureRandomStrA(const Size: Integer): RawByteString;
|
||||
begin
|
||||
SetLength(Result, Size);
|
||||
if Size <= 0 then
|
||||
exit;
|
||||
SecureRandomBuf(Result[1], Size);
|
||||
end;
|
||||
|
||||
function SecureRandomHexStr(const Digits: Integer; const UpperCase: Boolean = True): String;
|
||||
var
|
||||
B : TSecureRandomBlock;
|
||||
S, T : String;
|
||||
L, N : Integer;
|
||||
P : PWord32;
|
||||
Q : PChar;
|
||||
begin
|
||||
if Digits <= 0 then
|
||||
begin
|
||||
Result := '';
|
||||
exit;
|
||||
end;
|
||||
SetLength(S, Digits);
|
||||
Q := PChar(S);
|
||||
L := Digits;
|
||||
while L >= 8 do
|
||||
begin
|
||||
SecureRandomBlockGenerator(B);
|
||||
P := @B;
|
||||
N := SecureRandomBlockSize div 4;
|
||||
while (L >= 8) and (N > 0) do
|
||||
begin
|
||||
T := Word32ToHex(P^, 8, UpperCase);
|
||||
Move(PChar(T)^, Q^, 8 * SizeOf(Char));
|
||||
SecureClearStr(T);
|
||||
Inc(Q, 8);
|
||||
Dec(N);
|
||||
Inc(P);
|
||||
Dec(L, 8);
|
||||
end;
|
||||
end;
|
||||
if L > 0 then
|
||||
begin
|
||||
SecureRandomBlockGenerator(B);
|
||||
P := @B;
|
||||
T := Word32ToHex(P^, L, UpperCase);
|
||||
Move(PChar(T)^, Q^, L * SizeOf(Char));
|
||||
SecureClearStr(T);
|
||||
end;
|
||||
SecureClear(B, SecureRandomBlockSize);
|
||||
Result := S;
|
||||
end;
|
||||
|
||||
function SecureRandomHexStrB(const Digits: Integer; const UpperCase: Boolean): RawByteString;
|
||||
var
|
||||
B : TSecureRandomBlock;
|
||||
S, T : RawByteString;
|
||||
L, N : Integer;
|
||||
P : PWord32;
|
||||
Q : PByte;
|
||||
begin
|
||||
if Digits <= 0 then
|
||||
begin
|
||||
Result := '';
|
||||
exit;
|
||||
end;
|
||||
SetLength(S, Digits);
|
||||
Q := PByte(S);
|
||||
L := Digits;
|
||||
while L >= 8 do
|
||||
begin
|
||||
SecureRandomBlockGenerator(B);
|
||||
P := @B;
|
||||
N := SecureRandomBlockSize div 4;
|
||||
while (L >= 8) and (N > 0) do
|
||||
begin
|
||||
T := Word32ToHexB(P^, 8, UpperCase);
|
||||
Move(PByte(T)^, Q^, 8);
|
||||
SecureClearStrB(T);
|
||||
Inc(Q, 8);
|
||||
Dec(N);
|
||||
Inc(P);
|
||||
Dec(L, 8);
|
||||
end;
|
||||
end;
|
||||
if L > 0 then
|
||||
begin
|
||||
SecureRandomBlockGenerator(B);
|
||||
P := @B;
|
||||
T := Word32ToHexB(P^, L, UpperCase);
|
||||
Move(PByte(T)^, Q^, L);
|
||||
SecureClearStrB(T);
|
||||
end;
|
||||
SecureClear(B, SecureRandomBlockSize);
|
||||
Result := S;
|
||||
end;
|
||||
|
||||
function SecureRandomHexStrU(const Digits: Integer; const UpperCase: Boolean): UnicodeString;
|
||||
var
|
||||
B : TSecureRandomBlock;
|
||||
S, T : UnicodeString;
|
||||
L, N : Integer;
|
||||
P : PWord32;
|
||||
Q : PWideChar;
|
||||
begin
|
||||
if Digits <= 0 then
|
||||
begin
|
||||
Result := '';
|
||||
exit;
|
||||
end;
|
||||
SetLength(S, Digits);
|
||||
Q := PWideChar(S);
|
||||
L := Digits;
|
||||
while L >= 8 do
|
||||
begin
|
||||
SecureRandomBlockGenerator(B);
|
||||
P := @B;
|
||||
N := SecureRandomBlockSize div 4;
|
||||
while (L >= 8) and (N > 0) do
|
||||
begin
|
||||
T := Word32ToHexU(P^, 8, UpperCase);
|
||||
Move(PWideChar(T)^, Q^, 8 * SizeOf(WideChar));
|
||||
SecureClear(T[1], 8 * SizeOf(WideChar));
|
||||
Inc(Q, 8);
|
||||
Dec(N);
|
||||
Inc(P);
|
||||
Dec(L, 8);
|
||||
end;
|
||||
end;
|
||||
if L > 0 then
|
||||
begin
|
||||
SecureRandomBlockGenerator(B);
|
||||
P := @B;
|
||||
T := Word32ToHexU(P^, L, UpperCase);
|
||||
Move(PWideChar(T)^, Q^, L * SizeOf(WideChar));
|
||||
SecureClear(T[1], 8 * SizeOf(WideChar));
|
||||
end;
|
||||
SecureClear(B, SecureRandomBlockSize);
|
||||
Result := S;
|
||||
end;
|
||||
|
||||
function SecureRandomWord32: Word32;
|
||||
var
|
||||
L : Word32;
|
||||
begin
|
||||
SecureRandomBuf(L, SizeOf(Word32));
|
||||
Result := L;
|
||||
SecureClear(L, SizeOf(Word32));
|
||||
end;
|
||||
|
||||
|
||||
|
||||
end.
|
||||
|
495
contrib/fundamentals/Cipher/flcCipherTest.pas
Normal file
495
contrib/fundamentals/Cipher/flcCipherTest.pas
Normal file
@@ -0,0 +1,495 @@
|
||||
{******************************************************************************}
|
||||
{ }
|
||||
{ Library: Fundamentals 5.00 }
|
||||
{ File name: flcCipherTest.pas }
|
||||
{ File version: 5.08 }
|
||||
{ Description: Cipher Test }
|
||||
{ }
|
||||
{ Copyright: Copyright (c) 2007-2020, David J Butler }
|
||||
{ All rights reserved. }
|
||||
{ This file is licensed under the BSD License. }
|
||||
{ See http://www.opensource.org/licenses/bsd-license.php }
|
||||
{ Redistribution and use in source and binary forms, with }
|
||||
{ or without modification, are permitted provided that }
|
||||
{ the following conditions are met: }
|
||||
{ Redistributions of source code must retain the above }
|
||||
{ copyright notice, this list of conditions and the }
|
||||
{ following disclaimer. }
|
||||
{ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND }
|
||||
{ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED }
|
||||
{ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED }
|
||||
{ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A }
|
||||
{ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL }
|
||||
{ THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, }
|
||||
{ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR }
|
||||
{ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, }
|
||||
{ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF }
|
||||
{ USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) }
|
||||
{ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER }
|
||||
{ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING }
|
||||
{ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE }
|
||||
{ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE }
|
||||
{ POSSIBILITY OF SUCH DAMAGE. }
|
||||
{ }
|
||||
{ Github: https://github.com/fundamentalslib }
|
||||
{ E-mail: fundamentals.library at gmail.com }
|
||||
{ }
|
||||
{ Revision history: }
|
||||
{ }
|
||||
{ 2007/01/05 0.01 Initial version. }
|
||||
{ 2007/01/07 0.02 ECB and padding support. }
|
||||
{ 2008/06/15 0.03 CBC mode. }
|
||||
{ 2008/06/17 0.04 CFB and OFB modes. }
|
||||
{ 2010/12/16 4.05 AES cipher. }
|
||||
{ 2016/01/09 5.06 Revised for Fundamentals 5. }
|
||||
{ 2019/06/09 5.07 Tests for Triple-DES-EDE-3. }
|
||||
{ 2020/05/20 5.08 Create flcCipherTest unit from flcCipher unit. }
|
||||
{ }
|
||||
{******************************************************************************}
|
||||
|
||||
{$INCLUDE flcCipher.inc}
|
||||
|
||||
{$DEFINE Cipher_SupportEC}
|
||||
|
||||
unit flcCipherTest;
|
||||
|
||||
interface
|
||||
|
||||
|
||||
|
||||
{ }
|
||||
{ Test }
|
||||
{ }
|
||||
{$IFDEF CIPHER_TEST}
|
||||
procedure Test;
|
||||
{$ENDIF}
|
||||
{$IFDEF CIPHER_PROFILE}
|
||||
procedure Profile;
|
||||
{$ENDIF}
|
||||
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
SysUtils,
|
||||
|
||||
flcStdTypes,
|
||||
flcUtils,
|
||||
flcCipherRandom,
|
||||
flcCipherRC2,
|
||||
flcCipherAES,
|
||||
flcCipherDES,
|
||||
flcCipherDH,
|
||||
flcCipherRSA,
|
||||
{$IFDEF Cipher_SupportEC}
|
||||
flcCipherEllipticCurve,
|
||||
{$ENDIF}
|
||||
flcCipher;
|
||||
|
||||
|
||||
|
||||
{ }
|
||||
{ Test }
|
||||
{ }
|
||||
{$IFDEF CIPHER_TEST}
|
||||
{$ASSERTIONS ON}
|
||||
type
|
||||
TCipherTestCase = record
|
||||
Cipher : TCipherType;
|
||||
Mode : TCipherMode;
|
||||
KeyBits : Integer; // Effective key length (bits)
|
||||
Key : RawByteString;
|
||||
InitVector : RawByteString;
|
||||
PlainText : RawByteString;
|
||||
CipherText : RawByteString;
|
||||
end;
|
||||
|
||||
const
|
||||
CipherTestCaseCount = 36;
|
||||
|
||||
var
|
||||
CipherTestCases : array[0..CipherTestCaseCount - 1] of TCipherTestCase = (
|
||||
// RC2 test vectors from RFC 2268
|
||||
(Cipher: ctRC2;
|
||||
Mode: cmECB;
|
||||
KeyBits: 63;
|
||||
Key: RawByteString(#$00#$00#$00#$00#$00#$00#$00#$00);
|
||||
PlainText: RawByteString(#$00#$00#$00#$00#$00#$00#$00#$00);
|
||||
CipherText: RawByteString(#$eb#$b7#$73#$f9#$93#$27#$8e#$ff)),
|
||||
(Cipher: ctRC2;
|
||||
Mode: cmECB;
|
||||
KeyBits: 64;
|
||||
Key: RawByteString(#$ff#$ff#$ff#$ff#$ff#$ff#$ff#$ff);
|
||||
PlainText: RawByteString(#$ff#$ff#$ff#$ff#$ff#$ff#$ff#$ff);
|
||||
CipherText: RawByteString(#$27#$8b#$27#$e4#$2e#$2f#$0d#$49)),
|
||||
(Cipher: ctRC2;
|
||||
Mode: cmECB;
|
||||
KeyBits: 64;
|
||||
Key: RawByteString(#$30#$00#$00#$00#$00#$00#$00#$00);
|
||||
PlainText: RawByteString(#$10#$00#$00#$00#$00#$00#$00#$01);
|
||||
CipherText: RawByteString(#$30#$64#$9e#$df#$9b#$e7#$d2#$c2)),
|
||||
(Cipher: ctRC2;
|
||||
Mode: cmECB;
|
||||
KeyBits: 64;
|
||||
Key: RawByteString(#$88);
|
||||
PlainText: RawByteString(#$00#$00#$00#$00#$00#$00#$00#$00);
|
||||
CipherText: RawByteString(#$61#$a8#$a2#$44#$ad#$ac#$cc#$f0)),
|
||||
(Cipher: ctRC2;
|
||||
Mode: cmECB;
|
||||
KeyBits: 64;
|
||||
Key: RawByteString(#$88#$bc#$a9#$0e#$90#$87#$5a);
|
||||
PlainText: RawByteString(#$00#$00#$00#$00#$00#$00#$00#$00);
|
||||
CipherText: RawByteString(#$6c#$cf#$43#$08#$97#$4c#$26#$7f)),
|
||||
(Cipher: ctRC2;
|
||||
Mode: cmECB;
|
||||
KeyBits: 64;
|
||||
Key: RawByteString(#$88#$bc#$a9#$0e#$90#$87#$5a#$7f#$0f#$79#$c3#$84#$62#$7b#$af#$b2);
|
||||
PlainText: RawByteString(#$00#$00#$00#$00#$00#$00#$00#$00);
|
||||
CipherText: RawByteString(#$1a#$80#$7d#$27#$2b#$be#$5d#$b1)),
|
||||
(Cipher: ctRC2;
|
||||
Mode: cmECB;
|
||||
KeyBits: 128;
|
||||
Key: RawByteString(#$88#$bc#$a9#$0e#$90#$87#$5a#$7f#$0f#$79#$c3#$84#$62#$7b#$af#$b2);
|
||||
PlainText: RawByteString(#$00#$00#$00#$00#$00#$00#$00#$00);
|
||||
CipherText: RawByteString(#$22#$69#$55#$2a#$b0#$f8#$5c#$a6)),
|
||||
(Cipher: ctRC2;
|
||||
Mode: cmECB;
|
||||
KeyBits: 129;
|
||||
Key: RawByteString(#$88#$bc#$a9#$0e#$90#$87#$5a#$7f#$0f#$79#$c3#$84#$62#$7b#$af#$b2#$16#$f8#$0a#$6f#$85#$92#$05#$84#$c4#$2f#$ce#$b0#$be#$25#$5d#$af#$1e);
|
||||
PlainText: RawByteString(#$00#$00#$00#$00#$00#$00#$00#$00);
|
||||
CipherText: RawByteString(#$5b#$78#$d3#$a4#$3d#$ff#$f1#$f1)),
|
||||
// RC4 test vectors from http://en.wikipedia.org/wiki/RC4
|
||||
(Cipher: ctRC4;
|
||||
Mode: cmECB;
|
||||
KeyBits: 24;
|
||||
Key: 'Key';
|
||||
PlainText: 'Plaintext';
|
||||
CipherText: RawByteString(#$BB#$F3#$16#$E8#$D9#$40#$AF#$0A#$D3)),
|
||||
(Cipher: ctRC4;
|
||||
Mode: cmECB;
|
||||
KeyBits: 32;
|
||||
Key: 'Wiki';
|
||||
PlainText: 'pedia';
|
||||
CipherText: RawByteString(#$10#$21#$BF#$04#$20)),
|
||||
(Cipher: ctRC4;
|
||||
Mode: cmECB;
|
||||
KeyBits: 48;
|
||||
Key: 'Secret';
|
||||
PlainText: 'Attack at dawn';
|
||||
CipherText: RawByteString(#$45#$A0#$1F#$64#$5F#$C3#$5B#$38#$35#$52#$54#$4B#$9B#$F5)),
|
||||
// RC4 test vectors from Internet Draft on ARCFOUR
|
||||
(Cipher: ctRC4;
|
||||
Mode: cmECB;
|
||||
KeyBits: 64;
|
||||
Key: RawByteString(#$01#$23#$45#$67#$89#$AB#$CD#$EF);
|
||||
PlainText: RawByteString(#$00#$00#$00#$00#$00#$00#$00#$00);
|
||||
CipherText: RawByteString(#$74#$94#$C2#$E7#$10#$4B#$08#$79)),
|
||||
(Cipher: ctRC4;
|
||||
Mode: cmECB;
|
||||
KeyBits: 40;
|
||||
Key: RawByteString(#$61#$8a#$63#$d2#$fb);
|
||||
PlainText: RawByteString(#$dc#$ee#$4c#$f9#$2c);
|
||||
CipherText: RawByteString(#$f1#$38#$29#$c9#$de)),
|
||||
(Cipher: ctRC4;
|
||||
Mode: cmECB;
|
||||
KeyBits: 128;
|
||||
Key: RawByteString(#$29#$04#$19#$72#$fb#$42#$ba#$5f#$c7#$12#$77#$12#$f1#$38#$29#$c9);
|
||||
PlainText: RawByteString(#$52#$75#$69#$73#$6c#$69#$6e#$6e#$75#$6e#$20#$6c#$61#$75#$6c#$75 +
|
||||
#$20#$6b#$6f#$72#$76#$69#$73#$73#$73#$61#$6e#$69#$2c#$20#$74#$e4 +
|
||||
#$68#$6b#$e4#$70#$e4#$69#$64#$65#$6e#$20#$70#$e4#$e4#$6c#$6c#$e4 +
|
||||
#$20#$74#$e4#$79#$73#$69#$6b#$75#$75#$2e#$20#$4b#$65#$73#$e4#$79 +
|
||||
#$f6#$6e#$20#$6f#$6e#$20#$6f#$6e#$6e#$69#$20#$6f#$6d#$61#$6e#$61 +
|
||||
#$6e#$69#$2c#$20#$6b#$61#$73#$6b#$69#$73#$61#$76#$75#$75#$6e#$20 +
|
||||
#$6c#$61#$61#$6b#$73#$6f#$74#$20#$76#$65#$72#$68#$6f#$75#$75#$2e +
|
||||
#$20#$45#$6e#$20#$6d#$61#$20#$69#$6c#$6f#$69#$74#$73#$65#$2c#$20 +
|
||||
#$73#$75#$72#$65#$20#$68#$75#$6f#$6b#$61#$61#$2c#$20#$6d#$75#$74 +
|
||||
#$74#$61#$20#$6d#$65#$74#$73#$e4#$6e#$20#$74#$75#$6d#$6d#$75#$75 +
|
||||
#$73#$20#$6d#$75#$6c#$6c#$65#$20#$74#$75#$6f#$6b#$61#$61#$2e#$20 +
|
||||
#$50#$75#$75#$6e#$74#$6f#$20#$70#$69#$6c#$76#$65#$6e#$2c#$20#$6d +
|
||||
#$69#$20#$68#$75#$6b#$6b#$75#$75#$2c#$20#$73#$69#$69#$6e#$74#$6f +
|
||||
#$20#$76#$61#$72#$61#$6e#$20#$74#$75#$75#$6c#$69#$73#$65#$6e#$2c +
|
||||
#$20#$6d#$69#$20#$6e#$75#$6b#$6b#$75#$75#$2e#$20#$54#$75#$6f#$6b +
|
||||
#$73#$75#$74#$20#$76#$61#$6e#$61#$6d#$6f#$6e#$20#$6a#$61#$20#$76 +
|
||||
#$61#$72#$6a#$6f#$74#$20#$76#$65#$65#$6e#$2c#$20#$6e#$69#$69#$73 +
|
||||
#$74#$e4#$20#$73#$79#$64#$e4#$6d#$65#$6e#$69#$20#$6c#$61#$75#$6c +
|
||||
#$75#$6e#$20#$74#$65#$65#$6e#$2e#$20#$2d#$20#$45#$69#$6e#$6f#$20 +
|
||||
#$4c#$65#$69#$6e#$6f);
|
||||
CipherText: RawByteString(#$35#$81#$86#$99#$90#$01#$e6#$b5#$da#$f0#$5e#$ce#$eb#$7e#$ee#$21 +
|
||||
#$e0#$68#$9c#$1f#$00#$ee#$a8#$1f#$7d#$d2#$ca#$ae#$e1#$d2#$76#$3e +
|
||||
#$68#$af#$0e#$ad#$33#$d6#$6c#$26#$8b#$c9#$46#$c4#$84#$fb#$e9#$4c +
|
||||
#$5f#$5e#$0b#$86#$a5#$92#$79#$e4#$f8#$24#$e7#$a6#$40#$bd#$22#$32 +
|
||||
#$10#$b0#$a6#$11#$60#$b7#$bc#$e9#$86#$ea#$65#$68#$80#$03#$59#$6b +
|
||||
#$63#$0a#$6b#$90#$f8#$e0#$ca#$f6#$91#$2a#$98#$eb#$87#$21#$76#$e8 +
|
||||
#$3c#$20#$2c#$aa#$64#$16#$6d#$2c#$ce#$57#$ff#$1b#$ca#$57#$b2#$13 +
|
||||
#$f0#$ed#$1a#$a7#$2f#$b8#$ea#$52#$b0#$be#$01#$cd#$1e#$41#$28#$67 +
|
||||
#$72#$0b#$32#$6e#$b3#$89#$d0#$11#$bd#$70#$d8#$af#$03#$5f#$b0#$d8 +
|
||||
#$58#$9d#$bc#$e3#$c6#$66#$f5#$ea#$8d#$4c#$79#$54#$c5#$0c#$3f#$34 +
|
||||
#$0b#$04#$67#$f8#$1b#$42#$59#$61#$c1#$18#$43#$07#$4d#$f6#$20#$f2 +
|
||||
#$08#$40#$4b#$39#$4c#$f9#$d3#$7f#$f5#$4b#$5f#$1a#$d8#$f6#$ea#$7d +
|
||||
#$a3#$c5#$61#$df#$a7#$28#$1f#$96#$44#$63#$d2#$cc#$35#$a4#$d1#$b0 +
|
||||
#$34#$90#$de#$c5#$1b#$07#$11#$fb#$d6#$f5#$5f#$79#$23#$4d#$5b#$7c +
|
||||
#$76#$66#$22#$a6#$6d#$e9#$2b#$e9#$96#$46#$1d#$5e#$4d#$c8#$78#$ef +
|
||||
#$9b#$ca#$03#$05#$21#$e8#$35#$1e#$4b#$ae#$d2#$fd#$04#$f9#$46#$73 +
|
||||
#$68#$c4#$ad#$6a#$c1#$86#$d0#$82#$45#$b2#$63#$a2#$66#$6d#$1f#$6c +
|
||||
#$54#$20#$f1#$59#$9d#$fd#$9f#$43#$89#$21#$c2#$f5#$a4#$63#$93#$8c +
|
||||
#$e0#$98#$22#$65#$ee#$f7#$01#$79#$bc#$55#$3f#$33#$9e#$b1#$a4#$c1 +
|
||||
#$af#$5f#$6a#$54#$7f)),
|
||||
// AES test vectors generated from online AES calculator at http://www.unsw.adfa.edu.au/~lpb/src/AEScalc/AEScalc.html
|
||||
(Cipher: ctAES;
|
||||
Mode: cmECB;
|
||||
KeyBits: 128;
|
||||
Key: RawByteString(#$0f#$15#$71#$c9#$47#$d9#$e8#$59#$0c#$b7#$ad#$d6#$af#$7f#$67#$98);
|
||||
PlainText: '1234567890123456';
|
||||
CipherText: RawByteString(#$2f#$7d#$76#$42#$5e#$bb#$85#$e4#$f2#$e7#$b0#$08#$68#$bf#$0f#$ce)),
|
||||
(Cipher: ctAES;
|
||||
Mode: cmECB;
|
||||
KeyBits: 128;
|
||||
Key: RawByteString(#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00);
|
||||
PlainText: RawByteString(#$14#$0f#$0f#$10#$11#$b5#$22#$3d#$79#$58#$77#$17#$ff#$d9#$ec#$3a);
|
||||
CipherText: RawByteString(#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00)),
|
||||
(Cipher: ctAES;
|
||||
Mode: cmECB;
|
||||
KeyBits: 192;
|
||||
Key: RawByteString(#$96#$43#$D8#$33#$4A#$63#$DF#$4D#$48#$E3#$1E#$9E#$25#$67#$18#$F2#$92#$29#$31#$9C#$19#$F1#$5B#$A4);
|
||||
PlainText: RawByteString(#$23#$00#$ea#$46#$3f#$43#$72#$64#$12#$75#$5f#$4c#$83#$e2#$cb#$78);
|
||||
CipherText: RawByteString(#$48#$E3#$1E#$9E#$25#$67#$18#$F2#$92#$29#$31#$9C#$19#$F1#$5B#$A4)),
|
||||
(Cipher: ctAES;
|
||||
Mode: cmECB;
|
||||
KeyBits: 256;
|
||||
Key: RawByteString(#$85#$C6#$B2#$BB#$23#$00#$14#$8F#$94#$5A#$EB#$F1#$F0#$21#$CF#$79#$05#$8C#$CF#$FD#$BB#$CB#$38#$2D#$1F#$6F#$56#$58#$5D#$8A#$4A#$DE);
|
||||
PlainText: RawByteString(#$e7#$0f#$9e#$09#$08#$87#$0a#$1d#$cf#$09#$60#$ae#$13#$d0#$7c#$68);
|
||||
CipherText: RawByteString(#$05#$8C#$CF#$FD#$BB#$CB#$38#$2D#$1F#$6F#$56#$58#$5D#$8A#$4A#$DE)),
|
||||
// AES test vectors generated from online AES calculator at http://www.riscure.com/tech-corner/online-crypto-tools/aes.html
|
||||
(Cipher: ctAES;
|
||||
Mode: cmCBC;
|
||||
KeyBits: 128;
|
||||
Key: RawByteString(#$84#$52#$35#$BA#$BE#$BD#$14#$84#$63#$E9#$DB#$46#$74#$77#$F9#$D2);
|
||||
InitVector: RawByteString(#$01#$02#$03#$04#$05#$06#$07#$08#$09#$10#$11#$12#$13#$14#$15#$16);
|
||||
PlainText: RawByteString(#$8F#$98#$3F#$D0#$99#$A3#$6D#$1E#$2F#$A5#$B3#$86#$31#$14#$42#$08);
|
||||
CipherText: RawByteString(#$7E#$50#$7D#$C5#$D8#$ED#$3B#$A9#$F4#$C9#$30#$C8#$13#$D4#$A7#$BC)),
|
||||
// DES test vectors from http://www.aci.net/Kalliste/des.htm
|
||||
(Cipher: ctDES;
|
||||
Mode: cmECB;
|
||||
KeyBits: 64;
|
||||
Key: RawByteString(#$13#$34#$57#$79#$9B#$BC#$DF#$F1);
|
||||
PlainText: RawByteString(#$01#$23#$45#$67#$89#$AB#$CD#$EF);
|
||||
CipherText: RawByteString(#$85#$E8#$13#$54#$0F#$0A#$B4#$05)),
|
||||
(Cipher: ctDES;
|
||||
Mode: cmECB;
|
||||
KeyBits: 64;
|
||||
Key: RawByteString(#$0E#$32#$92#$32#$EA#$6D#$0D#$73);
|
||||
PlainText: RawByteString(#$87#$87#$87#$87#$87#$87#$87#$87);
|
||||
CipherText: RawByteString(#$00#$00#$00#$00#$00#$00#$00#$00)),
|
||||
// DES test vectors from http://groups.google.com/group/sci.crypt/msg/1e08a60f44daa890?&hl=en
|
||||
(Cipher: ctDES;
|
||||
Mode: cmECB;
|
||||
KeyBits: 64;
|
||||
Key: RawByteString(#$01#$01#$01#$01#$01#$01#$01#$01);
|
||||
PlainText: RawByteString(#$95#$F8#$A5#$E5#$DD#$31#$D9#$00);
|
||||
CipherText: RawByteString(#$80#$00#$00#$00#$00#$00#$00#$00)),
|
||||
(Cipher: ctDES;
|
||||
Mode: cmECB;
|
||||
KeyBits: 64;
|
||||
Key: RawByteString(#$7C#$A1#$10#$45#$4A#$1A#$6E#$57);
|
||||
PlainText: RawByteString(#$01#$A1#$D6#$D0#$39#$77#$67#$42);
|
||||
CipherText: RawByteString(#$69#$0F#$5B#$0D#$9A#$26#$93#$9B)),
|
||||
(Cipher: ctDES;
|
||||
Mode: cmECB;
|
||||
KeyBits: 64;
|
||||
Key: RawByteString(#$80#$01#$01#$01#$01#$01#$01#$01);
|
||||
PlainText: RawByteString(#$00#$00#$00#$00#$00#$00#$00#$00);
|
||||
CipherText: RawByteString(#$95#$A8#$D7#$28#$13#$DA#$A9#$4D)),
|
||||
// DES test vectors from http://tero.co.uk/des/show.php
|
||||
(Cipher: ctDES;
|
||||
Mode: cmECB;
|
||||
KeyBits: 64;
|
||||
Key: '12345678';
|
||||
PlainText: 'This is the message to encrypt!!';
|
||||
CipherText: RawByteString(#$05#$c9#$c4#$ca#$fb#$99#$37#$d9#$5b#$bf#$be#$df#$c5#$d7#$7f#$19 +
|
||||
#$a6#$cd#$5a#$5d#$ab#$18#$8a#$33#$df#$d8#$97#$9f#$c4#$b7#$b2#$be)),
|
||||
(Cipher: ctDES;
|
||||
Mode: cmCBC;
|
||||
KeyBits: 64;
|
||||
Key: '12345678';
|
||||
InitVector: 'abcdefgh';
|
||||
PlainText: 'This is the message to encrypt!!';
|
||||
CipherText: RawByteString(#$6c#$a9#$47#$0c#$84#$9d#$1c#$c1#$a5#$9f#$fc#$14#$8f#$1c#$b5#$e9 +
|
||||
#$cf#$1f#$5c#$03#$28#$a7#$e8#$75#$63#$87#$ff#$4d#$0f#$e4#$60#$50)),
|
||||
(Cipher: ctDES;
|
||||
Mode: cmECB;
|
||||
KeyBits: 64;
|
||||
Key: RawByteString(#$01#$23#$45#$67#$89#$ab#$cd#$ef);
|
||||
PlainText: 'Now is the time for all ';
|
||||
CipherText: RawByteString(#$3f#$a4#$0e#$8a#$98#$4d#$48#$15#$6a#$27#$17#$87#$ab#$88#$83#$f9 +
|
||||
#$89#$3d#$51#$ec#$4b#$56#$3b#$53)),
|
||||
// DES test vectors from http://www.herongyang.com/crypto/des_php_implementation_mcrypt_2.html
|
||||
(Cipher: ctDES;
|
||||
Mode: cmCBC;
|
||||
KeyBits: 64;
|
||||
Key: RawByteString(#$01#$23#$45#$67#$89#$ab#$cd#$ef);
|
||||
InitVector: RawByteString(#$12#$34#$56#$78#$90#$ab#$cd#$ef);
|
||||
PlainText: RawByteString(#$4e#$6f#$77#$20#$69#$73#$20#$74#$68#$65#$20#$74#$69#$6d#$65#$20 +
|
||||
#$66#$6f#$72#$20#$61#$6c#$6c#$20);
|
||||
CipherText: RawByteString(#$e5#$c7#$cd#$de#$87#$2b#$f2#$7c#$43#$e9#$34#$00#$8c#$38#$9c#$0f +
|
||||
#$68#$37#$88#$49#$9a#$7c#$05#$f6)),
|
||||
(Cipher: ctDES;
|
||||
Mode: cmCFB;
|
||||
KeyBits: 64;
|
||||
Key: RawByteString(#$01#$23#$45#$67#$89#$ab#$cd#$ef);
|
||||
InitVector: RawByteString(#$12#$34#$56#$78#$90#$ab#$cd#$ef);
|
||||
PlainText: RawByteString(#$4e#$6f#$77#$20#$69#$73#$20#$74#$68#$65#$20#$74#$69#$6d#$65#$20 +
|
||||
#$66#$6f#$72#$20#$61#$6c#$6c#$20);
|
||||
CipherText: RawByteString(#$f3#$1f#$da#$07#$01#$14#$62#$ee#$18#$7f#$43#$d8#$0a#$7c#$d9#$b5 +
|
||||
#$b0#$d2#$90#$da#$6e#$5b#$9a#$87)),
|
||||
(Cipher: ctDES;
|
||||
Mode: cmOFB;
|
||||
KeyBits: 64;
|
||||
Key: RawByteString(#$01#$23#$45#$67#$89#$ab#$cd#$ef);
|
||||
InitVector: RawByteString(#$12#$34#$56#$78#$90#$ab#$cd#$ef);
|
||||
PlainText: RawByteString(#$4e#$6f#$77#$20#$69#$73#$20#$74#$68#$65#$20#$74#$69#$6d#$65#$20 +
|
||||
#$66#$6f#$72#$20#$61#$6c#$6c#$20);
|
||||
CipherText: RawByteString(#$f3#$4a#$28#$50#$c9#$c6#$49#$85#$d6#$84#$ad#$96#$d7#$72#$e2#$f2 +
|
||||
#$43#$ea#$49#$9a#$be#$e8#$ae#$95)),
|
||||
// Triple-DES test vectors generated from online DES calculator at http://www.riscure.com/tech-corner/online-crypto-tools/des.html
|
||||
(Cipher: ctTripleDESEDE;
|
||||
Mode: cmECB;
|
||||
KeyBits: 128;
|
||||
Key: '1234567890123456';
|
||||
PlainText: '1234567890123456';
|
||||
CipherText: RawByteString(#$BC#$57#$08#$BC#$02#$FE#$BF#$2F#$F6#$AD#$24#$D2#$1E#$FB#$70#$3A)),
|
||||
(Cipher: ctTripleDESEDE;
|
||||
Mode: cmECB;
|
||||
KeyBits: 128;
|
||||
Key: RawByteString(#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00);
|
||||
PlainText: '1234567890123456';
|
||||
CipherText: RawByteString(#$62#$DD#$8E#$4A#$61#$4E#$1A#$F9#$BE#$3D#$31#$47#$71#$1F#$A2#$77)),
|
||||
(Cipher: ctTripleDESEDE;
|
||||
Mode: cmCBC;
|
||||
KeyBits: 128;
|
||||
Key: RawByteString(#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00);
|
||||
InitVector: '12345678';
|
||||
PlainText: '1234567890123456';
|
||||
CipherText: RawByteString(#$8C#$A6#$4D#$E9#$C1#$B1#$23#$A7#$97#$8D#$A5#$4E#$AE#$E5#$7B#$46)),
|
||||
// Triple-DES-3 from https://www.cosic.esat.kuleuven.be/nessie/testvectors/bc/des/Triple-Des-3-Key-192-64.unverified.test-vectors
|
||||
(Cipher: ctTripleDES3EDE;
|
||||
Mode: cmECB;
|
||||
KeyBits: 192;
|
||||
Key: RawByteString(#$F1#$F1#$F1#$F1#$F1#$F1#$F1#$F1#$F1#$F1#$F1#$F1#$F1#$F1#$F1#$F1#$F1#$F1#$F1#$F1#$F1#$F1#$F1#$F1);
|
||||
InitVector: '';
|
||||
PlainText: RawByteString(#$F1#$F1#$F1#$F1#$F1#$F1#$F1#$F1);
|
||||
CipherText: RawByteString(#$5D#$1B#$8F#$AF#$78#$39#$49#$4B)),
|
||||
(Cipher: ctTripleDES3EDE;
|
||||
Mode: cmECB;
|
||||
KeyBits: 192;
|
||||
Key: RawByteString(#$00#$01#$02#$03#$04#$05#$06#$07#$08#$09#$0A#$0B#$0C#$0D#$0E#$0F#$10#$11#$12#$13#$14#$15#$16#$17);
|
||||
InitVector: '';
|
||||
PlainText: RawByteString(#$00#$11#$22#$33#$44#$55#$66#$77);
|
||||
CipherText: RawByteString(#$97#$A2#$5B#$A8#$2B#$56#$4F#$4C)),
|
||||
(Cipher: ctTripleDES3EDE;
|
||||
Mode: cmECB;
|
||||
KeyBits: 192;
|
||||
Key: RawByteString(#$2B#$D6#$45#$9F#$82#$C5#$B3#$00#$95#$2C#$49#$10#$48#$81#$FF#$48#$2B#$D6#$45#$9F#$82#$C5#$B3#$00);
|
||||
InitVector: '';
|
||||
PlainText: RawByteString(#$EA#$02#$47#$14#$AD#$5C#$4D#$84);
|
||||
CipherText: RawByteString(#$C6#$16#$AC#$E8#$43#$95#$82#$47))
|
||||
);
|
||||
|
||||
procedure Test_TestCases;
|
||||
var I : Integer;
|
||||
B : array[0..1023] of AnsiChar;
|
||||
L : Integer;
|
||||
C : RawByteString;
|
||||
M : RawByteString;
|
||||
X : Integer;
|
||||
begin
|
||||
for I := 0 to CipherTestCaseCount - 1 do
|
||||
with CipherTestCases[I] do
|
||||
try
|
||||
if Assigned(GetCipherInfo(Cipher)) then
|
||||
begin
|
||||
M := IntToStringB(I);
|
||||
L := Length(PlainText);
|
||||
Move(Pointer(PlainText)^, B[0], L);
|
||||
L := Encrypt(Cipher, Mode, cpNone, KeyBits, Pointer(Key), Length(Key),
|
||||
@B[0], L, @B[0], Sizeof(B), Pointer(InitVector), Length(InitVector));
|
||||
C := '';
|
||||
SetLength(C, L);
|
||||
Move(B[0], Pointer(C)^, L);
|
||||
if C <> CipherText then
|
||||
begin
|
||||
for X := 1 to L do
|
||||
if C[X] <> CipherText[X] then Writeln(X, '!', Ord(C[X]), '<>', Ord(CipherText[X]), ' L=', L);
|
||||
end;
|
||||
{ Freepascal issue with RawByteString constant conversion }
|
||||
{
|
||||
if I = 13 then
|
||||
begin
|
||||
T := CipherText;
|
||||
for X := 1 to L do
|
||||
Write(IntToHex(Ord(T[X]), 2));
|
||||
Writeln;
|
||||
end;
|
||||
}
|
||||
Assert(C = CipherText, M);
|
||||
L := Decrypt(Cipher, Mode, cpNone, KeyBits, Pointer(Key), Length(Key),
|
||||
@B[0], L, Pointer(InitVector), Length(InitVector));
|
||||
Move(B[0], PByteChar(C)^, L);
|
||||
Assert(C = PlainText, M);
|
||||
Assert(Encrypt(Cipher, Mode, cpNone, KeyBits, Key, PlainText, InitVector) = CipherText, M);
|
||||
Assert(Decrypt(Cipher, Mode, cpNone, KeyBits, Key, CipherText, InitVector) = PlainText, M);
|
||||
end;
|
||||
except
|
||||
on E : Exception do
|
||||
raise Exception.Create('Test case ' + IntToStr(I) + ': ' + E.Message);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure Test_CipherRandom;
|
||||
begin
|
||||
Assert(Length(SecureRandomHexStrB(0)) = 0);
|
||||
Assert(Length(SecureRandomHexStrB(1)) = 1);
|
||||
Assert(Length(SecureRandomHexStrB(511)) = 511);
|
||||
Assert(Length(SecureRandomHexStrB(512)) = 512);
|
||||
Assert(Length(SecureRandomHexStrB(513)) = 513);
|
||||
|
||||
Assert(Length(SecureRandomHexStr(513)) = 513);
|
||||
Assert(Length(SecureRandomHexStrU(513)) = 513);
|
||||
|
||||
Assert(Length(SecureRandomStrA(0)) = 0);
|
||||
Assert(Length(SecureRandomStrA(1)) = 1);
|
||||
Assert(Length(SecureRandomStrA(1023)) = 1023);
|
||||
Assert(Length(SecureRandomStrA(1024)) = 1024);
|
||||
Assert(Length(SecureRandomStrA(1025)) = 1025);
|
||||
end;
|
||||
|
||||
procedure Test;
|
||||
begin
|
||||
Assert(RC2BlockSize = 8);
|
||||
Assert(RC2BlockSize = Sizeof(TRC2Block));
|
||||
Assert(DESBlockSize = 8);
|
||||
Assert(DESBlockSize = Sizeof(TDESBlock));
|
||||
|
||||
flcCipherAES.Test;
|
||||
flcCipherDH.Test;
|
||||
flcCipherRSA.Test;
|
||||
{$IFDEF Cipher_SupportEC}
|
||||
flcCipherEllipticCurve.Test;
|
||||
{$ENDIF}
|
||||
|
||||
flcCipher.Test;
|
||||
|
||||
Test_CipherRandom;
|
||||
Test_TestCases;
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF CIPHER_PROFILE}
|
||||
procedure Profile;
|
||||
begin
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
|
||||
|
||||
end.
|
137
contrib/fundamentals/Cipher/flcCipherUtils.pas
Normal file
137
contrib/fundamentals/Cipher/flcCipherUtils.pas
Normal file
@@ -0,0 +1,137 @@
|
||||
{******************************************************************************}
|
||||
{ }
|
||||
{ Library: Fundamentals 5.00 }
|
||||
{ File name: flcCipherUtils.pas }
|
||||
{ File version: 5.02 }
|
||||
{ Description: Cipher library }
|
||||
{ }
|
||||
{ Copyright: Copyright (c) 2007-2020, David J Butler }
|
||||
{ All rights reserved. }
|
||||
{ This file is licensed under the BSD License. }
|
||||
{ See http://www.opensource.org/licenses/bsd-license.php }
|
||||
{ Redistribution and use in source and binary forms, with }
|
||||
{ or without modification, are permitted provided that }
|
||||
{ the following conditions are met: }
|
||||
{ Redistributions of source code must retain the above }
|
||||
{ copyright notice, this list of conditions and the }
|
||||
{ following disclaimer. }
|
||||
{ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND }
|
||||
{ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED }
|
||||
{ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED }
|
||||
{ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A }
|
||||
{ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL }
|
||||
{ THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, }
|
||||
{ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR }
|
||||
{ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, }
|
||||
{ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF }
|
||||
{ USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) }
|
||||
{ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER }
|
||||
{ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING }
|
||||
{ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE }
|
||||
{ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE }
|
||||
{ POSSIBILITY OF SUCH DAMAGE. }
|
||||
{ }
|
||||
{ Github: https://github.com/fundamentalslib }
|
||||
{ E-mail: fundamentals.library at gmail.com }
|
||||
{ }
|
||||
{ Revision history: }
|
||||
{ }
|
||||
{ 2007/01/05 4.01 Initial version }
|
||||
{ 2016/01/09 5.02 Revised for Fundamentals 5. }
|
||||
{ }
|
||||
{******************************************************************************}
|
||||
|
||||
{$INCLUDE flcCipher.inc}
|
||||
|
||||
unit flcCipherUtils;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
{ System }
|
||||
SysUtils,
|
||||
|
||||
{ Fundamentals }
|
||||
flcStdTypes;
|
||||
|
||||
|
||||
|
||||
{ }
|
||||
{ Cipher errors }
|
||||
{ }
|
||||
const
|
||||
CipherError_InvalidCipher = 1;
|
||||
CipherError_InvalidKeySize = 2;
|
||||
CipherError_InvalidKeyBits = 3;
|
||||
CipherError_InvalidCipherMode = 4;
|
||||
CipherError_InvalidBufferSize = 5;
|
||||
CipherError_InvalidBuffer = 6;
|
||||
CipherError_InvalidData = 7;
|
||||
|
||||
type
|
||||
ECipher = class(Exception)
|
||||
protected
|
||||
FErrorCode : Integer;
|
||||
public
|
||||
constructor Create(const ErrorCode: Integer; const Msg: String);
|
||||
property ErrorCode: Integer read FErrorCode;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{ }
|
||||
{ Secure clear }
|
||||
{ }
|
||||
procedure SecureClear(var Buffer; const BufferSize: Integer);
|
||||
procedure SecureClearBytes(var B: TBytes);
|
||||
procedure SecureClearStr(var S: RawByteString);
|
||||
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
|
||||
{ }
|
||||
{ Cipher errors }
|
||||
{ }
|
||||
constructor ECipher.Create(const ErrorCode: Integer; const Msg: String);
|
||||
begin
|
||||
FErrorCode := ErrorCode;
|
||||
inherited Create(Msg);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{ }
|
||||
{ Secure clear helper function }
|
||||
{ Securely clears a piece of memory before it is released to help prevent }
|
||||
{ sensitive information from being exposed. }
|
||||
{ }
|
||||
procedure SecureClear(var Buffer; const BufferSize: Integer);
|
||||
begin
|
||||
if BufferSize <= 0 then
|
||||
exit;
|
||||
FillChar(Buffer, BufferSize, $00);
|
||||
end;
|
||||
|
||||
procedure SecureClearBytes(var B: TBytes);
|
||||
begin
|
||||
SecureClear(Pointer(B)^, Length(B));
|
||||
B := nil;
|
||||
end;
|
||||
|
||||
procedure SecureClearStr(var S: RawByteString);
|
||||
var L : Integer;
|
||||
begin
|
||||
L := Length(S);
|
||||
if L = 0 then
|
||||
exit;
|
||||
SecureClear(S[1], L);
|
||||
SetLength(S, 0);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
end.
|
||||
|
Reference in New Issue
Block a user