You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi 10.4加密密码存入Firebird后字符异常的技术求助

问题排查与解决方案

核心原因:你加密后的结果本质是二进制字节流,而非合法的文本字符,当用字符串类型存储时,Delphi的Unicode字符串与Firebird的字符集编码映射过程中,无效或无法映射的字节被替换成了其他字符(比如¥变成Y)。

解决方法(按推荐优先级排序)

1. 转Base64存储(最稳妥的文本方式)

加密后的二进制数据转成Base64编码的字符串,所有字符都是可打印的安全字符,不会出现编码转换问题:

修改加密/解密函数

uses System.NetEncoding;

// 加密:输入字符串,返回加密后的字节数组
function Titkositas(Jelszo: string; Code: LongInt): TBytes;
var
  Ciklus: Integer;
  JelszoBytes: TBytes;
begin
  RandSeed := Code;
  // 先把输入密码转成UTF-8字节(避免Unicode字符丢失)
  JelszoBytes := TEncoding.UTF8.GetBytes(Jelszo);
  SetLength(Result, Length(JelszoBytes));
  for Ciklus := 0 to High(JelszoBytes) do
    Result[Ciklus] := JelszoBytes[Ciklus] xor Random(256);
end;

// 解密:输入加密后的字节数组,返回原始密码字符串
function Dekodolas(EncryptedBytes: TBytes; Code: LongInt): string;
var
  Ciklus: Integer;
  DecryptedBytes: TBytes;
begin
  RandSeed := Code;
  SetLength(DecryptedBytes, Length(EncryptedBytes));
  for Ciklus := 0 to High(EncryptedBytes) do
    DecryptedBytes[Ciklus] := EncryptedBytes[Ciklus] xor Random(256);
  Result := TEncoding.UTF8.GetString(DecryptedBytes);
end;

存储与验证代码

// 存储时转Base64
ParamByName('PASSWD').AsString := TBase64Encoding.EncodeBytesToString(Titkositas(Trim(Edit4.Text), 123456));

// 验证时解码Base64再解密
var
  EncryptedBase64: string;
  EncryptedBytes: TBytes;
begin
  // 从数据库读取PASSWD字段值
  EncryptedBase64 := Query1.FieldByName('PASSWD').AsString;
  EncryptedBytes := TBase64Encoding.DecodeStringToBytes(EncryptedBase64);
  if Dekodolas(EncryptedBytes, 123456) = Trim(EditLoginPassword.Text) then
    ShowMessage('登录成功')
  else
    ShowMessage('密码错误');
end;

2. 用二进制字段存储(最直接的方式)

将Firebird表的PASSWD字段类型改为BLOB SUB_TYPE BINARY,直接存储加密后的字节数组,跳过编码转换:

存储与验证代码

// 存储时直接存字节
ParamByName('PASSWD').AsBytes := Titkositas(Trim(Edit4.Text), 123456);

// 验证时直接读字节解密
var
  EncryptedBytes: TBytes;
begin
  EncryptedBytes := Query1.FieldByName('PASSWD').AsBytes;
  if Dekodolas(EncryptedBytes, 123456) = Trim(EditLoginPassword.Text) then
    ShowMessage('登录成功');
end;

3. 强制编码一致性(不推荐,仍有风险)

如果坚持用字符串字段,需确保两端编码完全匹配:

  • Firebird表的PASSWD字段设为VARCHAR(n) CHARACTER SET UTF8,n要足够大
  • Delphi端用AsWideString传递参数,避免编码转换:
    ParamByName('PASSWD').AsWideString := Titkositas(Trim(Edit4.Text), 123456);
    

注意:这种方式仍可能因为某些字节序列不是合法UTF-8字符而被替换,导致数据损坏,仅作为临时过渡方案。

内容的提问来源于stack exchange,提问作者Hexa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 13:10:25