線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:2185
推到 Plurk!
推到 Facebook!

使用DLL 檔加密字串寫入資料庫後解密異常

答題得分者是:Victor4022
superrakce
一般會員


發表:24
回覆:35
積分:11
註冊:2006-10-09

發送簡訊給我
#1 引用回覆 回覆 發表時間:2011-07-19 10:30:05 IP:114.33.xxx.xxx 訂閱
有一支 加解密用的DLL 檔,因為要給其它語言使用所以他的宣告是如此:
function Encrypt(st: PAnsiChar):PAnsiChar; stdcall;
function Decrypt(ts: PAnsiChar):PAnsiChar; stdcall;

目前測試都很正常,一直到發現某些字串寫到資料庫內,讀出解密卻失敗
若是直接加密>解密,就沒有問題(同樣一組字串)

其中 有個函式Ord(s[i]) (s 是傳入要處理的字串,中英數混合)
會是編碼的問題嗎?該如何解決?
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#2 引用回覆 回覆 發表時間:2011-07-20 02:35:46 IP:118.169.xxx.xxx 未訂閱
因為函式定義的是AnsiChar 結構, 很有可能代入的字串包含 UNICODE(WideChar), 在Byte的認定上有出入的問題, 所以建議先查一下字串的字是否引用了 unicode 字集
===================引 用 superrakce 文 章===================
有一支 加解密用的DLL 檔,因為要給其它語言使用所以他的宣告是如此:
function Encrypt(st: PAnsiChar):PAnsiChar; stdcall;
function Decrypt(ts: PAnsiChar):PAnsiChar; stdcall;

目前測試都很正常,一直到發現某些字串寫到資料庫內,讀出解密卻失敗
若是直接加密>解密,就沒有問題(同樣一組字串)

其中 有個函式Ord(s[i]) (s 是傳入要處理的字串,中英數混合)
會是編碼的問題嗎?該如何解決?
superrakce
一般會員


發表:24
回覆:35
積分:11
註冊:2006-10-09

發送簡訊給我
#3 引用回覆 回覆 發表時間:2011-07-20 14:37:31 IP:114.33.xxx.xxx 訂閱
若有該如何解決?
===================引 用 P.D. 文 章===================
因為函式定義的是AnsiChar 結構, 很有可能代入的字串包含 UNICODE(WideChar), 在Byte的認定上有出入的問題, 所以建議先查一下字串的字是否引用了 unicode 字集
===================引 用 superrakce 文 章===================
有一支 加解密用的DLL 檔,因為要給其它語言使用所以他的宣告是如此:
function Encrypt(st: PAnsiChar):PAnsiChar; stdcall;
function Decrypt(ts: PAnsiChar):PAnsiChar; stdcall;

目前測試都很正常,一直到發現某些字串寫到資料庫內,讀出解密卻失敗
若是直接加密>解密,就沒有問題(同樣一組字串)

其中 有個函式Ord(s[i]) (s 是傳入要處理的字串,中英數混合)
會是編碼的問題嗎?該如何解決?
aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#4 引用回覆 回覆 發表時間:2011-07-20 16:26:37 IP:210.64.xxx.xxx 訂閱
你好,

因明日我要演講,捷康辦的,所以時間不多,待演講完後,找時間看看…

我覺得問題應該在你的db的編碼。

首先,請回一下你用的db是哪種? 比如 mysql ? mssql ? …

第二,可能的話po 部份存入db的那部份的程式碼,還有讀回來的部份程式碼…

第三,我覺得可能可以馬上解決的方式(純猜) : 請使用 blob 的格式存入 db (即在db中開一個blob的欄位)。各db對blob欄位的說法不太一樣。但就是存成二進位的方式的那種… 你試一下,也許就搞定了! (觀念,存入時當二進位,讀出時也二進位,但解密時則在換字串,再解)

===================引 用 superrakce 文 章===================
有一支 加解密用的DLL 檔,因為要給其它語言使用所以他的宣告是如此:
function Encrypt(st: PAnsiChar):PAnsiChar; stdcall;
function Decrypt(ts: PAnsiChar):PAnsiChar; stdcall;

目前測試都很正常,一直到發現某些字串寫到資料庫內,讀出解密卻失敗
若是直接加密>解密,就沒有問題(同樣一組字串)

其中 有個函式Ord(s[i]) (s 是傳入要處理的字串,中英數混合)
會是編碼的問題嗎?該如何解決?
------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
superrakce
一般會員


發表:24
回覆:35
積分:11
註冊:2006-10-09

發送簡訊給我
#5 引用回覆 回覆 發表時間:2011-07-20 16:56:19 IP:114.33.xxx.xxx 訂閱
1.資料庫是mssql
2.

[code delphi]
procedure TForm1.Button4Click(Sender: TObject);
begin
aq.SQL.Text :='INSERT INTO TEST (ad,bd,cd,dd) VALUES (:A,:B,:C,:D)';
aq.Parameters.ParamByName('A').Value := string(Encrypt(PAnsiChar (edit9.Text)));
aq.Parameters.ParamByName('B').Value := string(Encrypt(PAnsiChar (edit9.Text)));
aq.Parameters.ParamByName('C').Value := string(Encrypt(PAnsiChar (edit9.Text)));
aq.Parameters.ParamByName('D').Value := string(Encrypt(PAnsiChar (edit9.Text)));
AQ.ExecSQL;
end;

procedure TForm1.Button5Click(Sender: TObject);
begin
aq.Parameters.Clear;
AQ.SQl.Text := 'SELECT ad,bd,cd,dd FROM TEST WHERE id = :aid';
aq.Parameters.ParamByName('aid').Value := edit13.Text;
aq.Open();
aq.First;
if aq.RecordCount > 0 then begin

edit9.Text := Decrypt(PAnsiChar(aq.Fields.FieldByName('ad').AsString));
edit10.Text := Decrypt(PAnsiChar(aq.Fields.FieldByName('bd').AsString));
edit11.Text := Decrypt(PAnsiChar(aq.Fields.FieldByName('cd').AsString));
edit12.Text := Decrypt(PAnsiChar(aq.Fields.FieldByName('dd').AsString));
end;
end;

[/code]

目前測試欄位的型態:
ad:nvarchar
bd:varchar
cd:nchar
dd:char

結果都一樣
3.所以資料庫型態是要改成binary ?我測試完在回報結果。

===================引 用 aftcast 文 章===================
你好,

因明日我要演講,捷康辦的,所以時間不多,待演講完後,找時間看看…

我覺得問題應該在你的db的編碼。

首先,請回一下你用的db是哪種? 比如 mysql ? mssql ? …

第二,可能的話po 部份存入db的那部份的程式碼,還有讀回來的部份程式碼…

第三,我覺得可能可以馬上解決的方式(純猜) : 請使用 blob 的格式存入 db (即在db中開一個blob的欄位)。各db對blob欄位的說法不太一樣。但就是存成二進位的方式的那種… 你試一下,也許就搞定了! (觀念,存入時當二進位,讀出時也二進位,但解密時則在換字串,再解)

===================引 用 superrakce 文 章===================
有一支 加解密用的DLL 檔,因為要給其它語言使用所以他的宣告是如此:
function Encrypt(st: PAnsiChar):PAnsiChar; stdcall;
function Decrypt(ts: PAnsiChar):PAnsiChar; stdcall;

目前測試都很正常,一直到發現某些字串寫到資料庫內,讀出解密卻失敗
若是直接加密>解密,就沒有問題(同樣一組字串)

其中 有個函式Ord(s[i]) (s 是傳入要處理的字串,中英數混合)
會是編碼的問題嗎?該如何解決?
編輯記錄
superrakce 重新編輯於 2011-07-20 03:14:18, 註解 無‧
superrakce
一般會員


發表:24
回覆:35
積分:11
註冊:2006-10-09

發送簡訊給我
#6 引用回覆 回覆 發表時間:2011-07-21 15:36:05 IP:114.33.xxx.xxx 訂閱
找不到字串轉binary (2進位的)方法
大大能給個提示嗎
Victor4022
中階會員


發表:0
回覆:76
積分:90
註冊:2011-02-20

發送簡訊給我
#7 引用回覆 回覆 發表時間:2011-07-29 23:32:14 IP:122.126.xxx.xxx 訂閱
請問:
1. 您的 Compiler 是?
2. 您提到 "有個函式Ord(s[i])", 指的是 dll export 出來 function 的 其中一個parameter, 還是??
superrakce
一般會員


發表:24
回覆:35
積分:11
註冊:2006-10-09

發送簡訊給我
#8 引用回覆 回覆 發表時間:2011-08-01 09:09:20 IP:114.33.xxx.xxx 訂閱
1.Delphi 
2.Ord(s[i]) 是逐一將字串中的每一個字元轉成相對應的ASCII 碼

作法是將每一個字元分別轉成相對應的ASCII碼然後經過運算
最後用Chr 轉回來成為文字
然後寫入資料庫。

最新測試結果是:某一串中文&數字混合的字串,在加密後寫入資料庫,讀出後不能解密成功
然後嘗試著將「那個字串」尾巴加上3~13個不等的英文或數字,便可反解成功。
有些字串不會有反解失敗的問題
有些字串尾巴加上3個英或數可反解,有些則需要多達13個
===================引 用 Victor4022 文 章===================
請問:
1. 您的 Compiler 是?
2. 您提到 "有個函式Ord(s[i])", 指的是 dll export 出來 function 的 其中一個parameter, 還是??
編輯記錄
superrakce 重新編輯於 2011-07-31 19:12:57, 註解 無‧
Victor4022
中階會員


發表:0
回覆:76
積分:90
註冊:2011-02-20

發送簡訊給我
#9 引用回覆 回覆 發表時間:2011-08-01 18:17:31 IP:114.34.xxx.xxx 訂閱
小弟猜想您的 Delphi 版本是 2009(或之後)的, 然後 Encode/Decode 為 Ansi 版本的程式碼(Delphi 2006 以下開發),  因此:

[code delphi]
procedure TForm1.Button1Click(Sender: TObject);
var
u8 : Utf8String;
begin
u8 := UTF8Encode(edit9.Text);
aq.SQL.Text :='INSERT INTO TEST (ad,bd,cd,dd) VALUES (:A,:B,:C,:D)';
// aq.Parameters.ParamByName('A').Value := string(Encrypt(PAnsiChar (edit9.Text)));
// aq.Parameters.ParamByName('B').Value := string(Encrypt(PAnsiChar (edit9.Text)));
// aq.Parameters.ParamByName('C').Value := string(Encrypt(PAnsiChar (edit9.Text)));
// aq.Parameters.ParamByName('D').Value := string(Encrypt(PAnsiChar (edit9.Text)));
aq.Parameters.ParamByName('A').Value := string(Encrypt(PAnsiChar (u8)));
aq.Parameters.ParamByName('B').Value := string(Encrypt(PAnsiChar (u8)));
aq.Parameters.ParamByName('C').Value := string(Encrypt(PAnsiChar (u8)));
aq.Parameters.ParamByName('D').Value := string(Encrypt(PAnsiChar (u8)));
AQ.ExecSQL;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
u8 : Utf8String;
begin
aq.Parameters.Clear;
AQ.SQl.Text := 'SELECT ad,bd,cd,dd FROM TEST WHERE id = :aid';
aq.Parameters.ParamByName('aid').Value := edit13.Text;
aq.Open();
aq.First;
if aq.RecordCount > 0 then
begin
u8 := Utf8String(aq.Fields.FieldByName('ad').AsString);
edit9.Text := UTF8Decode(u8);
// edit9.Text := Decrypt(PAnsiChar(aq.Fields.FieldByName('ad').AsString));
// edit10.Text := Decrypt(PAnsiChar(aq.Fields.FieldByName('bd').AsString));
// edit11.Text := Decrypt(PAnsiChar(aq.Fields.FieldByName('cd').AsString));
// edit12.Text := Decrypt(PAnsiChar(aq.Fields.FieldByName('dd').AsString));
end;
end;
[/code]


===================引 用 superrakce 文 章===================
1.Delphi
2.Ord(s[i]) 是逐一將字串中的每一個字元轉成相對應的ASCII 碼

作法是將每一個字元分別轉成相對應的ASCII碼然後經過運算
最後用Chr 轉回來成為文字
然後寫入資料庫。

最新測試結果是:某一串中文&數字混合的字串,在加密後寫入資料庫,讀出後不能解密成功
然後嘗試著將「那個字串」尾巴加上3~13個不等的英文或數字,便可反解成功。
有些字串不會有反解失敗的問題
有些字串尾巴加上3個英或數可反解,有些則需要多達13個
===================引 用 Victor4022 文 章===================
請問:
1. 您的 Compiler 是?
2. 您提到 "有個函式Ord(s[i])", 指的是 dll export 出來 function 的 其中一個parameter, 還是??
superrakce
一般會員


發表:24
回覆:35
積分:11
註冊:2006-10-09

發送簡訊給我
#10 引用回覆 回覆 發表時間:2011-08-02 09:15:13 IP:114.33.xxx.xxx 訂閱
加解密的DLL 是delphi 7
然後給C# VisualStudio2008使用
測試中...
===================引 用 Victor4022 文 章===================
小弟猜想您的 Delphi 版本是 2009(或之後)的, 然後 Encode/Decode 為 Ansi版本的程式碼(Delphi 2006 以下開發),因此:

編輯記錄
superrakce 重新編輯於 2011-08-01 19:16:02, 註解 無‧
superrakce
一般會員


發表:24
回覆:35
積分:11
註冊:2006-10-09

發送簡訊給我
#11 引用回覆 回覆 發表時間:2011-08-02 10:18:03 IP:114.33.xxx.xxx 訂閱
測試結果:
加密並寫入資料庫:

[code delphi]
procedure TForm1.Button4Click(Sender: TObject);
var u8 : Utf8String;
begin
aq.SQL.Text :='INSERT INTO TEST (ad,bd,cd,dd) VALUES (:A,:B,:C,:D)';
u8 := UTF8Encode(edit9.Text);
aq.Parameters.ParamByName('A').Value := string(Encrypt(PAnsiChar (u8)));
aq.Parameters.ParamByName('B').Value := string(Encrypt(PAnsiChar (u8)));
aq.Parameters.ParamByName('C').Value := string(Encrypt(PAnsiChar (u8)));
aq.Parameters.ParamByName('D').Value := string(Encrypt(PAnsiChar (u8)));
AQ.ExecSQL;
end;

[/code]
從資料庫取出並解密:

[code delphi]
procedure TForm1.Button5Click(Sender: TObject);
begin
aq.Parameters.Clear;
AQ.SQl.Text := 'SELECT ad,bd,cd,dd FROM TEST WHERE id = :aid';
aq.Parameters.ParamByName('aid').Value := edit13.Text;
aq.Open();
aq.First;
if aq.RecordCount > 0 then begin
edit9.Text := UTF8Decode(string(Decrypt(PAnsiChar(aq.Fields.FieldByName('ad').AsString))));
edit10.Text := UTF8Decode(string(Decrypt(PAnsiChar(aq.Fields.FieldByName('bd').AsString))));
edit11.Text := UTF8Decode(string(Decrypt(PAnsiChar(aq.Fields.FieldByName('cd').AsString))));
edit12.Text := UTF8Decode(string(Decrypt(PAnsiChar(aq.Fields.FieldByName('dd').AsString))));
end;
end;

[/code]

結果,通通都是空白
資料庫使用MSSQL2000
欄位型態分別是:
ad:char
bd:varchar
cd:nchar
dd:nvarchar

最後新增了一個欄位型態是binary
加解密就正常了
但這樣子在資料庫規劃上不是很好
而且這些欄位會被用來搜尋

還是程式的寫法錯了?

編輯記錄
superrakce 重新編輯於 2011-08-01 20:19:28, 註解 無‧
系統時間:2024-07-04 9:06:25
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!