之前写过一篇文章《Delphi实现SM4国密算法》,使用的是网上找到的代码,修复了几个BUG;这次准备使用CnPack的算法库来实现一下;算法库比较全,日常中需要使用的算法基本都有,但调用有点复杂,所以一般都需要根据自己的需求来简单封装一下;代码比较简单,直接贴了~需要使用高版本Delphi编译器
文件的加密方式为CTR,原因是CBC不能并行计算,对于大文件来说,效率比较低;
unit uSM4_LG;
{
使用CnPack的CnSM4及CnPemUtils单元进行封装;
实现字符串加密(CBC)、文件加密(CTR);
字符串填充均采用PKCS5
}
interface
uses
System.SysUtils, system.Classes, CnSM4, CnPemUtils;
// SM4/CBC/PKCS5 字符串加密
function SM4Encrypt(sInput, sKey, sIV :string):string;
// SM4/CTR/PKCS5 文件加密
function SM4EncryptFile(sSrcFile:string; sDesFile:string; sKey, sIV:string):Boolean;
implementation
function SM4Encrypt(sInput, sKey, sIV :string):string;
var
_sStr:string;
_BytesIn, _BytesKey, _BytesIV, _BytesOut : TBytes;
_Len: Integer;
begin
try
try
Result := '';
//均按照UTF8进行解析
with TEncoding.UTF8 do
begin
_BytesIn := GetBytes(sInput);
_BytesKey := GetBytes(sKey);
_BytesIV := GetBytes(sIV);
end;
//PKCS5填充
BytesAddPKCS5Padding(_BytesIn);
//SM4加密
_BytesOut := SM4EncryptCbcBytes(_BytesKey, _BytesIV, _BytesIn);
//输出16进制格式字符串
_Len := System.Length(_BytesOut);
SetLength(Result, 2*_Len);
BinToHex(@_BytesOut[0], PWideChar(Result), _Len);
except
on E:Exception do
begin
//
end;
end;
finally
SetLength(_BytesIn, 0);
SetLength(_BytesKey, 0);
SetLength(_BytesIV, 0);
SetLength(_BytesOut, 0);
end;
end;
function SM4EncryptFile(sSrcFile:string; sDesFile:string; sKey, sIV:string):Boolean;
var
_FileStream: TFileStream;
_BytesIn, _BytesKey, _BytesIV, _BytesOut : TBytes;
begin
try
try
Result := False;
//将文件读取到Tbytes _BytesIn中
_FileStream := TFileStream.Create(sSrcFile, fmOpenRead);
try
SetLength(_BytesIn, _FileStream.Size);
_FileStream.Read(_BytesIn, _FileStream.Size);
finally
_FileStream.Free;
end;
//均按照UTF8进行解析
with TEncoding.UTF8 do
begin
_BytesKey := GetBytes(sKey);
_BytesIV := GetBytes(sIV);
end;
//PKCS5填充
BytesAddPKCS5Padding(_BytesIn);
//SM4加密
_BytesOut := SM4EncryptCtrBytes(_BytesKey, _BytesIV, _BytesIn);
//将Tbytes _BytesOut中的数据写入文件中
_FileStream := TFileStream.Create(sDesFile, fmCreate);
try
_FileStream.Write(_BytesOut, System.Length(_BytesOut));
finally
_FileStream.Free;
end;
Result := True;
except
on E:Exception do
begin
//
end;
end;
finally
if Assigned(_FileStream) then _FileStream.Free;
SetLength(_BytesIn, 0);
SetLength(_BytesKey, 0);
SetLength(_BytesIV, 0);
SetLength(_BytesOut, 0);
end;
end;
end.
Pascal