-
-
Notifications
You must be signed in to change notification settings - Fork 72
Expand file tree
/
Copy pathCipherExample.pas
More file actions
159 lines (142 loc) · 5.37 KB
/
CipherExample.pas
File metadata and controls
159 lines (142 loc) · 5.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
{ *********************************************************************************** }
{ * CryptoLib Library * }
{ * Author - Ugochukwu Mmaduekwe * }
{ * Github Repository <https://github.com/Xor-el> * }
{ * * }
{ * Distributed under the MIT software license, see the accompanying file LICENSE * }
{ * or visit http://www.opensource.org/licenses/mit-license.php. * }
{ * * }
{ * Acknowledgements: * }
{ * * }
{ * Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring * }
{ * the development of this library * }
{ * ******************************************************************************* * }
(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
unit CipherExample;
interface
{$IFDEF FPC}
{$MODE DELPHI}
{$HINTS OFF}
{$WARNINGS OFF}
{$ENDIF FPC}
uses
SysUtils,
Math,
ClpIBufferedCipher,
ClpCipherUtilities,
ClpParameterUtilities,
ClpParametersWithIV,
ClpConverters,
ClpSecureRandom,
ClpISecureRandom,
ClpArrayUtilities,
ClpCryptoLibTypes,
ClpICipherParameters,
ExampleBase;
type
TCipherExample = class(TExampleBase)
private
function GetKeyAlgorithmName(const ACipherAlgorithm: string): string;
function GetAesKeySizeLabel(AKeySizeBytes: Int32): string;
function ProcessIncrementally(const ACipher: IBufferedCipher;
const AInput: TBytes): TBytes;
procedure RunCipherEncryptDecrypt(const ACipherAlgorithm: string;
const AParams: ICipherParameters);
procedure RunAesEncryptDecrypt(const ACipherAlgorithm: string;
AKeySizeBytes: Int32);
public
procedure Run; override;
end;
implementation
function TCipherExample.GetKeyAlgorithmName(const ACipherAlgorithm: string): string;
var
LSlash: Int32;
begin
LSlash := Pos('/', ACipherAlgorithm);
if LSlash > 0 then
Result := Copy(ACipherAlgorithm, 1, LSlash - 1)
else
Result := ACipherAlgorithm;
end;
function TCipherExample.GetAesKeySizeLabel(AKeySizeBytes: Int32): string;
begin
case AKeySizeBytes of
16: Result := 'AES-128';
24: Result := 'AES-192';
32: Result := 'AES-256';
else
raise EArgumentException.Create(Format('Invalid AES key size: %d bytes. Valid sizes are 16, 24, 32.', [AKeySizeBytes]));
end;
end;
function TCipherExample.ProcessIncrementally(const ACipher: IBufferedCipher;
const AInput: TBytes): TBytes;
const
BufferSize = 1024;
var
LInOff, LOutOff, LChunk, LCount, LInputLen: Int32;
begin
LInputLen := System.Length(AInput);
System.SetLength(Result, ACipher.GetOutputSize(LInputLen));
LInOff := 0;
LOutOff := 0;
while LInOff < LInputLen do
begin
LChunk := Min(BufferSize, LInputLen - LInOff);
LCount := ACipher.ProcessBytes(AInput, LInOff, LChunk, Result, LOutOff);
System.Inc(LOutOff, LCount);
System.Inc(LInOff, LChunk);
end;
LCount := ACipher.DoFinal(Result, LOutOff);
System.Inc(LOutOff, LCount);
System.SetLength(Result, LOutOff);
end;
procedure TCipherExample.RunCipherEncryptDecrypt(const ACipherAlgorithm: string;
const AParams: ICipherParameters);
var
LCipher: IBufferedCipher;
LPlain, LCipherText, LDecrypted: TBytes;
begin
Logger.LogInformation('Cipher: {0}', [ACipherAlgorithm]);
LCipher := TCipherUtilities.GetCipher(ACipherAlgorithm);
if LCipher = nil then
begin
Logger.LogWarning('Cipher "{0}" not available.', [ACipherAlgorithm]);
Exit;
end;
LPlain := TConverters.ConvertStringToBytes('Secret message', TEncoding.UTF8);
LCipher.Init(True, AParams);
LCipherText := ProcessIncrementally(LCipher, LPlain);
Logger.LogInformation('{0} encrypted length: {1}', [ACipherAlgorithm, IntToStr(System.Length(LCipherText))]);
LCipher.Init(False, AParams);
LDecrypted := ProcessIncrementally(LCipher, LCipherText);
if TArrayUtilities.AreEqual(LPlain, LDecrypted) then
Logger.LogInformation('{0} decrypt match: success.', [ACipherAlgorithm])
else
Logger.LogError('{0} decrypt match: failed.', [ACipherAlgorithm]);
end;
procedure TCipherExample.RunAesEncryptDecrypt(const ACipherAlgorithm: string;
AKeySizeBytes: Int32);
var
LKey, LIV: TBytes;
LSecureRandom: ISecureRandom;
LParams: ICipherParameters;
LKeyAlg: string;
begin
Logger.LogInformation('{0} {1} ({2}-byte key)', [GetAesKeySizeLabel(AKeySizeBytes), ACipherAlgorithm, IntToStr(AKeySizeBytes)]);
LSecureRandom := TSecureRandom.Create();
System.SetLength(LKey, AKeySizeBytes);
System.SetLength(LIV, 16);
LSecureRandom.NextBytes(LKey);
LSecureRandom.NextBytes(LIV);
LKeyAlg := GetKeyAlgorithmName(ACipherAlgorithm);
LParams := TParametersWithIV.Create(TParameterUtilities.CreateKeyParameter(LKeyAlg, LKey), LIV) as ICipherParameters;
RunCipherEncryptDecrypt(ACipherAlgorithm, LParams);
end;
procedure TCipherExample.Run;
begin
LogWithLineBreak('--- Cipher example: encrypt/decrypt ---');
RunAesEncryptDecrypt('AES/CBC/PKCS7PADDING', 16);
RunAesEncryptDecrypt('AES/CBC/PKCS7PADDING', 24);
RunAesEncryptDecrypt('AES/CBC/PKCS7PADDING', 32);
end;
end.