296 lines
8.4 KiB
ObjectPascal
296 lines
8.4 KiB
ObjectPascal
|
(**************************************************)
|
|||
|
(* *)
|
|||
|
(* Advanced Encryption Standard (AES) Extend *)
|
|||
|
(* *)
|
|||
|
(* Copyright (c) 2005-2016 *)
|
|||
|
(* aisino, qiaobu@139.com qiaohaidong@aisino.com *)
|
|||
|
(* *)
|
|||
|
(**************************************************)
|
|||
|
|
|||
|
unit JDAESExtend;
|
|||
|
|
|||
|
interface
|
|||
|
|
|||
|
{$WARN IMPLICIT_STRING_CAST OFF} // <20>رվ<D8B1><D5BE><EFBFBD>
|
|||
|
{$WARN IMPLICIT_STRING_CAST_LOSS OFF}
|
|||
|
|
|||
|
uses
|
|||
|
SysUtils, Classes, Math, ElAES, System.Generics.Collections, Soap.EncdDecd;
|
|||
|
|
|||
|
type
|
|||
|
TPaddingType = (PKCS5Padding { , PKCS7Padding } );
|
|||
|
TKeyBit = (kb128, kb192, kb256);
|
|||
|
TalgoMode = (amECB, amCBC { , amCFB, amOFB, amCTR } );
|
|||
|
TCipherType = (ctBase64, ctHex);
|
|||
|
|
|||
|
TArrayPadding = array of Byte;
|
|||
|
TArrayByte = array of Byte;
|
|||
|
|
|||
|
var
|
|||
|
AESKey128: TAESKey128;
|
|||
|
AESKey192: TAESKey192;
|
|||
|
AESKey256: TAESKey256;
|
|||
|
|
|||
|
InitVector: TAESBuffer;
|
|||
|
|
|||
|
function EncryptString(Value: AnsiString; Key: AnsiString; KeyBit: TKeyBit = kb128; algoMode: TalgoMode = amECB; padding: TPaddingType = PKCS5Padding; sInitVector: AnsiString = '0000000000000000';
|
|||
|
CipherType: TCipherType = ctHex): AnsiString;
|
|||
|
function DecryptString(Value: AnsiString; Key: AnsiString; KeyBit: TKeyBit = kb128; algoMode: TalgoMode = amECB; padding: TPaddingType = PKCS5Padding; sInitVector: AnsiString = '0000000000000000';
|
|||
|
CipherType: TCipherType = ctHex): AnsiString;
|
|||
|
|
|||
|
implementation
|
|||
|
|
|||
|
//<2F>ַ<EFBFBD><D6B7><EFBFBD>ת16<31><36><EFBFBD>ƣ<EFBFBD><C6A3>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
function StrToHex(Value: AnsiString): string;
|
|||
|
var
|
|||
|
i: Integer;
|
|||
|
begin
|
|||
|
Result := '';
|
|||
|
for i := 1 to Length(Value) do
|
|||
|
Result := Result + IntToHex(Ord(Value[i]), 2);
|
|||
|
end;
|
|||
|
//16<31><36><EFBFBD>ƣ<EFBFBD><C6A3>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
|
|||
|
function HexToStr(Value: AnsiString): AnsiString;
|
|||
|
var
|
|||
|
i: Integer;
|
|||
|
begin
|
|||
|
Result := '';
|
|||
|
for i := 1 to Length(Value) do
|
|||
|
begin
|
|||
|
if ((i mod 2) = 1) then
|
|||
|
Result := Result + ansichar(StrToInt('0x' + Copy(Value, i, 2)));
|
|||
|
end;
|
|||
|
end;
|
|||
|
|
|||
|
//PKCS5<53><35><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
function PKCS5_Padding(Value: AnsiString; out arrayValue: TArrayByte): Int64;
|
|||
|
var
|
|||
|
Valueutf8: UTF8String;
|
|||
|
BytesValue: array of Byte;
|
|||
|
intMod: Byte;
|
|||
|
valueLen: Integer;
|
|||
|
i: Integer;
|
|||
|
begin
|
|||
|
Valueutf8 := Value;
|
|||
|
SetLength(BytesValue, Length(Valueutf8));
|
|||
|
Move(Valueutf8[1], BytesValue[0], Length(Valueutf8));
|
|||
|
intMod := 16 - Length(BytesValue) mod 16;
|
|||
|
|
|||
|
valueLen := Length(BytesValue);
|
|||
|
SetLength(BytesValue, valueLen + intMod);
|
|||
|
for i := 0 to intMod - 1 do
|
|||
|
begin
|
|||
|
BytesValue[valueLen + i] := intMod;
|
|||
|
end;
|
|||
|
SetLength(arrayValue, Length(BytesValue));
|
|||
|
Move(BytesValue[0], arrayValue[0], Length(BytesValue));
|
|||
|
Result := Length(BytesValue);
|
|||
|
end;
|
|||
|
|
|||
|
//PKCS5<53><35><EFBFBD><EFBFBD>ȥ<EFBFBD><C8A5><EFBFBD><EFBFBD>
|
|||
|
function PKCS5_DePadding(bytes: TBytes): string;
|
|||
|
var
|
|||
|
Encoding: TEncoding;
|
|||
|
size: Integer;
|
|||
|
paddingByte: Byte;
|
|||
|
tmpBytes: TBytes;
|
|||
|
begin
|
|||
|
paddingByte := bytes[Length(bytes) - 1];
|
|||
|
|
|||
|
SetLength(tmpBytes, Length(bytes) - paddingByte);
|
|||
|
Move(bytes[0], tmpBytes[0], Length(tmpBytes));
|
|||
|
Encoding := TEncoding.UTF8;
|
|||
|
size := TEncoding.GetBufferEncoding(tmpBytes, Encoding);
|
|||
|
Result := Encoding.GetString(tmpBytes, size, Length(tmpBytes) - size)
|
|||
|
end;
|
|||
|
|
|||
|
//<2F><>Կ<EFBFBD><D4BF><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>0<EFBFBD><30><EFBFBD><EFBFBD>
|
|||
|
procedure ZeroPadding(KeyBit: TKeyBit);
|
|||
|
begin
|
|||
|
case KeyBit of
|
|||
|
kb128:
|
|||
|
FillChar(AESKey128, SizeOf(AESKey128), 0);
|
|||
|
kb192:
|
|||
|
FillChar(AESKey192, SizeOf(AESKey192), 0);
|
|||
|
kb256:
|
|||
|
FillChar(AESKey256, SizeOf(AESKey256), 0);
|
|||
|
end;
|
|||
|
end;
|
|||
|
|
|||
|
function EncryptString(Value: AnsiString; Key: AnsiString; KeyBit: TKeyBit = kb128; algoMode: TalgoMode = amECB; padding: TPaddingType = PKCS5Padding; sInitVector: AnsiString = '0000000000000000';
|
|||
|
CipherType: TCipherType = ctHex): AnsiString;
|
|||
|
var
|
|||
|
SS, DS: TMemoryStream;
|
|||
|
str: AnsiString;
|
|||
|
byteContent: TArrayByte;
|
|||
|
begin
|
|||
|
Result := '';
|
|||
|
PKCS5_Padding(Value, byteContent);
|
|||
|
|
|||
|
SS := TMemoryStream.Create;
|
|||
|
SS.WriteBuffer(byteContent[0], Length(byteContent));
|
|||
|
|
|||
|
SS.Position := SS.size;
|
|||
|
DS := TMemoryStream.Create;
|
|||
|
|
|||
|
try
|
|||
|
case KeyBit of
|
|||
|
kb128:
|
|||
|
begin
|
|||
|
ZeroPadding(kb128);
|
|||
|
Move(PAnsiChar(Key)^, AESKey128, Length(Key));
|
|||
|
case algoMode of
|
|||
|
amECB:
|
|||
|
begin
|
|||
|
EncryptAESStreamECB(SS, 0, AESKey128, DS);
|
|||
|
end;
|
|||
|
amCBC:
|
|||
|
begin
|
|||
|
// <20><><EFBFBD><EFBFBD>16λ<36><CEBB>0<EFBFBD><30><EFBFBD><EFBFBD>
|
|||
|
FillChar(InitVector, SizeOf(InitVector), 0);
|
|||
|
Move(PAnsiChar(sInitVector)^, InitVector, Length(sInitVector));
|
|||
|
EncryptAESStreamCBC(SS, 0, AESKey128, InitVector, DS);
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
kb192:
|
|||
|
begin
|
|||
|
ZeroPadding(kb192);
|
|||
|
Move(PAnsiChar(Key)^, AESKey192, Length(Key));
|
|||
|
case algoMode of
|
|||
|
amECB:
|
|||
|
begin
|
|||
|
EncryptAESStreamECB(SS, 0, AESKey192, DS);
|
|||
|
end;
|
|||
|
amCBC:
|
|||
|
begin
|
|||
|
FillChar(InitVector, SizeOf(InitVector), 0);
|
|||
|
Move(PAnsiChar(sInitVector)^, InitVector, Length(sInitVector));
|
|||
|
EncryptAESStreamCBC(SS, 0, AESKey192, InitVector, DS);
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
kb256:
|
|||
|
begin
|
|||
|
ZeroPadding(kb256);
|
|||
|
Move(PAnsiChar(Key)^, AESKey256, Length(Key));
|
|||
|
case algoMode of
|
|||
|
amECB:
|
|||
|
begin
|
|||
|
EncryptAESStreamECB(SS, 0, AESKey256, DS);
|
|||
|
end;
|
|||
|
amCBC:
|
|||
|
begin
|
|||
|
FillChar(InitVector, SizeOf(InitVector), 0);
|
|||
|
Move(PAnsiChar(sInitVector)^, InitVector, Length(sInitVector));
|
|||
|
EncryptAESStreamCBC(SS, 0, AESKey256, InitVector, DS);
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
|
|||
|
SetLength(str, DS.size);
|
|||
|
DS.Position := 0;
|
|||
|
DS.ReadBuffer(PAnsiChar(str)^, DS.size);
|
|||
|
if CipherType = ctHex then
|
|||
|
Result := StrToHex(str)
|
|||
|
else
|
|||
|
Result := EncodeBase64(PChar(str),Length(str));
|
|||
|
finally
|
|||
|
SS.Free;
|
|||
|
DS.Free;
|
|||
|
end;
|
|||
|
end;
|
|||
|
|
|||
|
function DecryptString(Value: AnsiString; Key: AnsiString; KeyBit: TKeyBit = kb128; algoMode: TalgoMode = amECB; padding: TPaddingType = PKCS5Padding; sInitVector: AnsiString = '0000000000000000';
|
|||
|
CipherType: TCipherType = ctHex): AnsiString;
|
|||
|
var
|
|||
|
SS,DS: TMemoryStream;
|
|||
|
str: AnsiString;
|
|||
|
byteContent: TBytes;
|
|||
|
BytesValue: TBytes;
|
|||
|
begin
|
|||
|
Result := '';
|
|||
|
|
|||
|
// pcharValue := pchar(Value);
|
|||
|
if CipherType = ctHex then
|
|||
|
begin
|
|||
|
str := HexToStr(Value);
|
|||
|
SetLength(byteContent, Length(str));
|
|||
|
Move(str[1], byteContent[0], Length(str));
|
|||
|
end
|
|||
|
else
|
|||
|
byteContent:= DecodeBase64(Value);
|
|||
|
|
|||
|
SS := TMemoryStream.Create;
|
|||
|
SS.WriteBuffer(byteContent[0], Length(byteContent));
|
|||
|
|
|||
|
DS := TMemoryStream.Create;
|
|||
|
|
|||
|
try
|
|||
|
case KeyBit of
|
|||
|
kb128:
|
|||
|
begin
|
|||
|
ZeroPadding(kb128);
|
|||
|
Move(PAnsiChar(Key)^, AESKey128, Length(Key));
|
|||
|
case algoMode of
|
|||
|
amECB:
|
|||
|
begin
|
|||
|
DecryptAESStreamECB(SS, 0, AESKey128, DS);
|
|||
|
end;
|
|||
|
amCBC:
|
|||
|
begin
|
|||
|
// <20><><EFBFBD><EFBFBD>16λ<36><CEBB>0<EFBFBD><30><EFBFBD><EFBFBD>
|
|||
|
FillChar(InitVector, SizeOf(InitVector), 0);
|
|||
|
Move(PAnsiChar(sInitVector)^, InitVector, Length(sInitVector));
|
|||
|
DecryptAESStreamCBC(SS, 0, AESKey128, InitVector, DS);
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
kb192:
|
|||
|
begin
|
|||
|
ZeroPadding(kb192);
|
|||
|
Move(PAnsiChar(Key)^, AESKey192, Length(Key));
|
|||
|
case algoMode of
|
|||
|
amECB:
|
|||
|
begin
|
|||
|
DecryptAESStreamECB(SS, 0, AESKey192, DS);
|
|||
|
end;
|
|||
|
amCBC:
|
|||
|
begin
|
|||
|
FillChar(InitVector, SizeOf(InitVector), 0);
|
|||
|
Move(PAnsiChar(sInitVector)^, InitVector, Length(sInitVector));
|
|||
|
DecryptAESStreamCBC(SS, 0, AESKey192, InitVector, DS);
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
kb256:
|
|||
|
begin
|
|||
|
ZeroPadding(kb256);
|
|||
|
Move(PAnsiChar(Key)^, AESKey256, Length(Key));
|
|||
|
case algoMode of
|
|||
|
amECB:
|
|||
|
begin
|
|||
|
DecryptAESStreamECB(SS, 0, AESKey256, DS);
|
|||
|
end;
|
|||
|
amCBC:
|
|||
|
begin
|
|||
|
FillChar(InitVector, SizeOf(InitVector), 0);
|
|||
|
Move(PAnsiChar(sInitVector)^, InitVector, Length(sInitVector));
|
|||
|
DecryptAESStreamCBC(SS, 0, AESKey256, InitVector, DS);
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
DS.Position := 0;
|
|||
|
SetLength(BytesValue, DS.size);
|
|||
|
DS.ReadBuffer(BytesValue[0], DS.size);
|
|||
|
Result := PKCS5_DePadding(BytesValue);
|
|||
|
finally
|
|||
|
SS.Free;
|
|||
|
DS.Free;
|
|||
|
end;
|
|||
|
end;
|
|||
|
|
|||
|
END.
|