问题描述
我已将 Delphi 7.1 应用程序移植到 Delphi 10.3。 我有一些简单的加密/解密功能。 如果我加密字符串值并加密它们,一切都很好:
var
test,encrypted,decrypted : string;
begin
test := 'XXXXXXXX'; // hidden message
encrypted := _common.encrypt(test);
decrypted := _common.decrypt(encrypted );
end;
在这种情况下,一切都按预期工作,即使使用特殊字符,加密也会是:'y'#$0080'vn'
但是如果值是 string[25],它会以不同的方式处理特殊字符:
var
test,decrypted : string;
encrypted : string[25]
begin
test := 'XXXXXXXX'; // hidden message
encrypted := _common.encrypt(test);
decrypted := _common.decrypt(encrypted);
end;
在这种情况下,除非加密字符串包含特殊字符,否则在本例中 res1 将是:'y?vn'
我在记录中使用 string[],当向磁盘写入数据/从磁盘读取数据时
我该如何解决这个问题?
我可以为记录类型使用不同的字符串类型吗?
/弗莱明
解决方法
从 Delphi 7 开始,string
类型已从一字节 ANSI 字符更改为两字节 Unicode 字符。但是,固定长度的 string[n]
仍然是一个一字节的 ANSI 字符串。因此,您正在混合不同的字符串类型。最简单的解决方法可能是将您声明为 string
的变量切换为 AnsiString
的声明。
在两个代码示例中您没有得到相同结果的原因是第一个代码示例完全依赖于使用默认字符串类型,在 Delphi 10.3 中为 WideString(每个字符两个字节)。
但在您的第二个代码示例中,您将结果声明为 string[25]
,这是一种短字符串类型。现在不像普通的字符串类型,ShortString 类型只能包含单字节字符,或者说只支持 AnsiString 类型,这是 Delphi 7 中默认的字符串类型。
因此,当您混合两种不同的字符串类型时,您不会得到相同的结果。
处理加密和解密时的一般规则是根本不使用字符串,而是使用原始二进制数据。为什么?
在 Delphi 7 的时候字符串已经受到当前使用的字符串编码的影响。因此,如果您在使用一种字符串编码的计算机上加密某个字符串并在使用另一种字符串编码的计算机上解密,您将得到错误的结果。
现在在使用带有 Unicode 编码的 WideString 的现代 Delphi 版本上,这不再造成这样的问题,但还有另一个潜在的问题,因为在 Windows 上字符串是基于 1(字符串中第一个字符的索引是 1)而在移动平台上字符串是 0基于(第一个字符的索引为 0)。
所以我强烈建议你重新设计你的加密/解密例程来处理原始二进制数据。