Delphi,如何使用BEncode得到info_hash?
Delphi, How to use BEncode to get info_hash?
我想使用 Delphi 获取 info_hash 个 *.torrent 文件。
已尝试 this BEncode decorder。
但是它在解码时会给出疯狂的字符。
Delphi 中还有其他可用的 BEncode 解码器吗?或者我做错了什么?
这是我的代码:
procedure TForm.Button1Click(Sender: TObject);
var
be: TBEncoded;
fs: tfilestream;
op: string;
begin
fs := tfilestream.Create('xx.torrent', fmOpenReadWrite);
be := TBEncoded.Create(fs);
be.Encode(be.ListData.Items[0].Data, op);
showmessage(op);
be.Encode(be.ListData.FindElement('info'), op);
showmessage(op);
end;
我刚试过这个解码器,它工作正常。您不需要使用 Encode 过程,它的目的(如名称所示)是将元素编码回 BEncode。这是在 TMemo 中显示种子信息的测试程序:
procedure ShowDecoded(be: TBEncoded; indent: string='');
var i: Integer;
begin
with form1.Memo1.Lines do
case be.Format of
befstring: Add(indent+be.StringData);
befInteger: Add(indent+IntToStr(be.IntegerData));
befList: begin
Add(indent+'list');
for i:=0 to be.ListData.Count-1 do
ShowDecoded(be.ListData.Items[i].Data as TBEncoded,indent+' ');
Add(indent+'end of list');
end;
befDictionary: begin
Add(indent+'dict');
for i:=0 to be.ListData.Count-1 do begin
Add(indent+' '+be.ListData.Items[i].Header+'=');
ShowDecoded(be.listData.Items[i].Data as TBEncoded,indent+' ');
end;
Add(indent+'end of dict');
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var fs: TFileStream;
be: TBEncoded;
i: Integer;
begin
if OpenDialog1.Execute then begin
fs:=TFileStream.Create(OpenDialog1.FileName,fmOpenRead);
try
be:=TBEncoded.Create(fs);
ShowDecoded(be);
be.Free;
finally
fs.Free;
end;
end;
end;
这是测试结果:
dict
created by=
uTorrent/3.4.3
creation date=
1439626950
encoding=
UTF-8
info=
dict
length=
1345178
name=
Алябьев А., Лист Ф. - Соловей - 1987.pdf
piece length=
16384
pieces=
)Lo.Î ’üXí»IÙçsáôt£ˆb›hŒˆ*Ð誺š¤/N7’`0âÓ†nË5&T€:V•Ìפ¯9¤Ý:¦J©Ï|Œ•A¥,¼R¯þ:H:X&…¢<¸º"2îV-vÀÖˆD†¨¬ß‰ƒ,ümjà?éÛoe¬r£{¨¾]•4òØžhô†›¼AØBeJÕÌ4³·Œ‹¶ËAG— f„\pa
end of dict
end of dict
我将对 BEncode 单元进行一些更改,其中有一些混乱:引发空异常、不安全转换:TBEncoded(object) 而不是 "object as TBEncoded",
在 object.free 之前检查 nil 对象,这是重言式,但通常它有效。
更新 1
获取字段之一的简单代码,'pieces' 并以十六进制显示。
procedure FindAndShowHash(be: TBEncoded);
var i: Integer;
s: string;
infoChunk, piecesChunk: TBencoded;
begin
s:='';
infoChunk:=be.ListData.FindElement('info') as TBencoded;
piecesChunk:=infoChunk.ListData.FindElement('pieces') as TBencoded;
for i:=1 to Length(piecesChunk.StringData) do
s:=s+IntToHex(Byte(piecesChunk.StringData[i]),2);
form1.Memo1.Lines.Add('Hash function:');
form1.Memo1.Lines.Add(s);
end;
如您所见,我们按字符访问 StringData 并将其转换为字节。我只是用十六进制显示的,当然你可以用这些字节做进一步的处理。
注意:您将获得 LOADS 个十六进制值,这不是 MD5 散列或任何其他整个 torrent 的散列,它是每个数据块的散列函数序列,通常是 1 或 2 MB 的块。
更新 2
这个单元可以在较新版本的Delphi中使用,您需要做的就是将其中的所有字符串变量从'string'替换为'ANSIstring',只需Ctrl+ R - ':string' 替换为 ':ANSIstring'。
更新 3
好的,我终于明白了。这是计算 info_hash 并以十六进制显示它的过程,这需要更新版本的 Delphi。此外,将 IdGlobal 和 IdHashSHA 添加到 'uses' 部分。
procedure makeInfoHash(be: TBEncoded);
var SHA1: TIdHashSHA1;
s: string;
infoChunk: TBencoded;
infoEncoded: ANSIString;
bytes: TIdBytes;
begin
infoChunk:=be.ListData.FindElement('info') as TBencoded;
TBencoded.Encode(infoChunk,infoEncoded);
bytes:=RawToBytes(infoEncoded[1],Length(infoEncoded));
SHA1:=TIdHashSHA1.Create;
try
s:=SHA1.HashBytesAsHex(bytes);
finally
SHA1.Free;
end;
Form1.Memo1.Lines.Add(s);
end;
它给出正确的 info_hash,与 uTorrent 中显示的相同,如下所示:
7D0487D3D99D9C27A7C09CDCBB2F2A8034D4F9BF
您必须将 BENcode.pas 中的所有字符串替换为 ANSIstring,如更新 2 中所述。享受!
我想使用 Delphi 获取 info_hash 个 *.torrent 文件。 已尝试 this BEncode decorder。 但是它在解码时会给出疯狂的字符。 Delphi 中还有其他可用的 BEncode 解码器吗?或者我做错了什么? 这是我的代码:
procedure TForm.Button1Click(Sender: TObject);
var
be: TBEncoded;
fs: tfilestream;
op: string;
begin
fs := tfilestream.Create('xx.torrent', fmOpenReadWrite);
be := TBEncoded.Create(fs);
be.Encode(be.ListData.Items[0].Data, op);
showmessage(op);
be.Encode(be.ListData.FindElement('info'), op);
showmessage(op);
end;
我刚试过这个解码器,它工作正常。您不需要使用 Encode 过程,它的目的(如名称所示)是将元素编码回 BEncode。这是在 TMemo 中显示种子信息的测试程序:
procedure ShowDecoded(be: TBEncoded; indent: string='');
var i: Integer;
begin
with form1.Memo1.Lines do
case be.Format of
befstring: Add(indent+be.StringData);
befInteger: Add(indent+IntToStr(be.IntegerData));
befList: begin
Add(indent+'list');
for i:=0 to be.ListData.Count-1 do
ShowDecoded(be.ListData.Items[i].Data as TBEncoded,indent+' ');
Add(indent+'end of list');
end;
befDictionary: begin
Add(indent+'dict');
for i:=0 to be.ListData.Count-1 do begin
Add(indent+' '+be.ListData.Items[i].Header+'=');
ShowDecoded(be.listData.Items[i].Data as TBEncoded,indent+' ');
end;
Add(indent+'end of dict');
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var fs: TFileStream;
be: TBEncoded;
i: Integer;
begin
if OpenDialog1.Execute then begin
fs:=TFileStream.Create(OpenDialog1.FileName,fmOpenRead);
try
be:=TBEncoded.Create(fs);
ShowDecoded(be);
be.Free;
finally
fs.Free;
end;
end;
end;
这是测试结果:
dict
created by=
uTorrent/3.4.3
creation date=
1439626950
encoding=
UTF-8
info=
dict
length=
1345178
name=
Алябьев А., Лист Ф. - Соловей - 1987.pdf
piece length=
16384
pieces=
)Lo.Î ’üXí»IÙçsáôt£ˆb›hŒˆ*Ð誺š¤/N7’`0âÓ†nË5&T€:V•Ìפ¯9¤Ý:¦J©Ï|Œ•A¥,¼R¯þ:H:X&…¢<¸º"2îV-vÀÖˆD†¨¬ß‰ƒ,ümjà?éÛoe¬r£{¨¾]•4òØžhô†›¼AØBeJÕÌ4³·Œ‹¶ËAG— f„\pa
end of dict
end of dict
我将对 BEncode 单元进行一些更改,其中有一些混乱:引发空异常、不安全转换:TBEncoded(object) 而不是 "object as TBEncoded", 在 object.free 之前检查 nil 对象,这是重言式,但通常它有效。
更新 1 获取字段之一的简单代码,'pieces' 并以十六进制显示。
procedure FindAndShowHash(be: TBEncoded);
var i: Integer;
s: string;
infoChunk, piecesChunk: TBencoded;
begin
s:='';
infoChunk:=be.ListData.FindElement('info') as TBencoded;
piecesChunk:=infoChunk.ListData.FindElement('pieces') as TBencoded;
for i:=1 to Length(piecesChunk.StringData) do
s:=s+IntToHex(Byte(piecesChunk.StringData[i]),2);
form1.Memo1.Lines.Add('Hash function:');
form1.Memo1.Lines.Add(s);
end;
如您所见,我们按字符访问 StringData 并将其转换为字节。我只是用十六进制显示的,当然你可以用这些字节做进一步的处理。
注意:您将获得 LOADS 个十六进制值,这不是 MD5 散列或任何其他整个 torrent 的散列,它是每个数据块的散列函数序列,通常是 1 或 2 MB 的块。
更新 2
这个单元可以在较新版本的Delphi中使用,您需要做的就是将其中的所有字符串变量从'string'替换为'ANSIstring',只需Ctrl+ R - ':string' 替换为 ':ANSIstring'。
更新 3
好的,我终于明白了。这是计算 info_hash 并以十六进制显示它的过程,这需要更新版本的 Delphi。此外,将 IdGlobal 和 IdHashSHA 添加到 'uses' 部分。
procedure makeInfoHash(be: TBEncoded);
var SHA1: TIdHashSHA1;
s: string;
infoChunk: TBencoded;
infoEncoded: ANSIString;
bytes: TIdBytes;
begin
infoChunk:=be.ListData.FindElement('info') as TBencoded;
TBencoded.Encode(infoChunk,infoEncoded);
bytes:=RawToBytes(infoEncoded[1],Length(infoEncoded));
SHA1:=TIdHashSHA1.Create;
try
s:=SHA1.HashBytesAsHex(bytes);
finally
SHA1.Free;
end;
Form1.Memo1.Lines.Add(s);
end;
它给出正确的 info_hash,与 uTorrent 中显示的相同,如下所示:
7D0487D3D99D9C27A7C09CDCBB2F2A8034D4F9BF
您必须将 BENcode.pas 中的所有字符串替换为 ANSIstring,如更新 2 中所述。享受!