かなり以前に某所で教えていただいた簡易暗号化復号化ルーチンを
使って、短い文字列を暗号化したり復号したりしているのですが
特定の文字で、うまく複合化できません。
function Endecode(Str: string): string;
var
P: PChar;
i: Integer;
begin
Result := '';
P := PChar(Str);
for i := 0 to Length(P) - 1 do begin
Result := Result + Chr(Ord(P[i]) xor 23);
end;
end;
Strに、例えば「ド」とか「帯」を入れて暗号化すると
複合化した際に「乏」という字になってしまいます。
なぜこうなるのか関連性がわからなくて、困っています。
よろしくお願いいたします。
そのような現象は再現できないけど。
もし、暗号化と複合化の間で何かやってるとしたら、そこに原因があるかも。
Memo1.Clear;
Memo1.Lines.Add(Endecode('Strに、例えば「ド」とか「帯」を入れて暗号化しても複合化した際に「乏」という字にはならないヨ'));
Memo1.Lines.Add(Endecode(Memo1.Lines[0]));
私は
Memo1.Lines.Clear;
Memo1.Lines.Add(Endecode('ド')) ;
Memo1.Lines.Add(Endecode(Memo1.Lines[0]));
で「乏」になる。
あんましバカなこと書いて恥書きたくないが、2バイト文字向きのコードじゃないと思う。
Delphi2007 WinXP SP3
Delphi7 WinXP SP3 の環境だと「ド」は「ド」に戻りました。
なんとなくUnicodeがらみの問題の気がしますね。
とりあえず基本的なことですが、エンコード前、エンコード後、デコード後それぞれのコードを調べてみればどこでどう化けているか見当がつくのではないでしょうか。
ただ、上でも言われているように、この暗号化方式は2バイト文字には向いていません(少なくとも暗号化結果を文字列で保持するのには不向きです)。
23=$17 なので、ASCIIの印字可能文字の範囲であればエンコード後の文字も印字可能な範囲に収まりますが、2バイト文字ではそのような保証はありません。
実際、MBCSで考えると
ド ($83 $68)→$94 $7F なのでエンコード後は不正なコードになりますし、
帯 ($91 $D1)→$86 $C6 もコードは正当ですが文字の割り当てられていない領域になります。
みなさん試していただいてありがとうございました。
さらに試してみたところ、おっしゃるように2バイト文字での
不具合が多く実用的ではないようです。
別のアプローチを考えて見ます。
Memo.Linesとかに入れないで、Stringで保持しておけばおかしくならない。
procedure TForm1.Button1Click(Sender: TObject);
var
s: String;
begin
Memo1.Clear;
s := Endecode('例えば「ド」とか「帯」が「乏」に');
Memo1.Lines.Add(s);
s := Endecode(s);
Memo1.Lines.Add(s);
end;
暗号化した文字を、Memoに入れ、Memoから取り出した文字を復号化すると
WindowsXP SP3 の環境でも文字化けした。
OSでなんかしてるんじゃない?
解決済みになっているが、BlowFishはどうだろうか?
https://www.petitmonte.com/bbs/answers?question_id=2555
>ofzさん
実はこのスレで簡易暗号化がうまくいかないと判った後で
Blowfishを試してみたのです。
ですが、サンプルのように暗号化と復号化を同じルーチンで行えば
うまく動くのですが、暗号・復号を分けて実装すると暗号化は
OKなのに、復号化はうまくいかないのです。
CryptUtilsの使い方が間違っているのだと思いますが
これについては、もう少し調べて、それでもダメなら新スレを立てます(笑
どうもありがとうございました。
uuencodeライクな処理をしてから上記暗号化を行えば大丈夫だと思います。
要するに、文字列をベタなbit集合とみなして順に6bitづつ取り出し、さらに0x20を加算してそれを1文字とみなす。
こうすることで必ず印字可能なASCIIになります。(値が0x20〜0x5Fに収まる)
また、0x17とXORをとってもかならず0x20〜0x5Fに収まります。
0x17というのがうまい選び方で、これはASCIIを意識してますよね。
複合は逆を行えばOK。末尾がハンパになるのでその場合だけ注意。
※ASCIIコードっていうのは正しくない・・・
ツイート | ![]() |