虽然Delphi有这自己独特的语言优势,但是跟其他语言加解密互通时,处理显得尤为麻烦。比如3DES加解密,网上下载的一些加解密方法加密的字符使用java无法解密,或者java加密的文本,无法用D解密。
无奈之下使用其他语言封装加解密部分,再用D来调用。前一篇博客中说到的是使用c++封装dll的方式,但是有非常大的问题,加密串的长度有限制,且使用静态数组分配内存,占用了不少的内存空间。经过多次调整改用动态数组失败后,决定改用C#封装dll的方式来加解密。
将C#封装的DLL注册未COM组件,外部参数定义为:
//加密
function GetDes3EncryptedText_Ex(const key: WideString; const data: WideString): PSafeArray; safecall;
//解密
function GetDes3EncryptedText(key: PSafeArray; data: PSafeArray): PSafeArray; safecall;
麻烦来了,在Delphi中使用的时候需要实现PSafeArray与TBytes的相互转化。不过不要担心,笔者已经完美解决了这个问题,并且在项目中使用了。详见下面的代码段:
/// <summary>
/// 将TBytes转为pSafeArray
/// </summary>
function ArrayToSafeArray(DataArray: TBytes): PSafeArray;
var
Bound: TSafeArrayBound;
psa: PSafeArray;
i, ret: Integer;
begin
Bound.cElements := Length(DataArray);
Bound.lLbound := 0;
psa := SafeArrayCreate(VT_UI1, 1, PSafeArrayBound(@Bound));
for i := Low(DataArray) to High(DataArray) do
begin
ret := SafeArrayPutElement(psa, &i, &DataArray[i]);
end;
Result := psa;
end;
/// <summary>
/// 将pSafeArray转为TBytes
/// <param name="pArray">源pSafeArray</param>
/// <param name="ABytes">目标TBytes</param>
/// </summary>
function SafeArrayToBytes(pArray: PSafeArray; out ABytes: TBytes): Boolean;
var
RVarData: TVarData;
RBound: TVarArrayBound;
j, UCount: Integer;
aValue: Byte;
begin
VarResultCheck((SafeArrayGetLBound(pArray, 1, RBound.LowBound)));
VarResultCheck(SafeArrayGetUBound(pArray, 1, UCount));
RBound.ElementCount := UCount - RBound.LowBound;
SetLength(ABytes, RBound.ElementCount+2);
for j := RBound.LowBound to RBound.ElementCount do
begin
VarResultCheck(SafeArrayGetElement(pArray, j, aValue));
ABytes[j] := aValue;
end;