首页 | 乐园 | 淘宝店 | 社区 | 电驴 | 网页游戏 | 网址大全

VeryCD / 社区 / 电驴软件开发

资源管理小组

相关主题

主题: 从easyMule源代码中提取的HASH函数HASH出来的值和eMule中的不一样

相关分类: 请教

icedream_linxi (楼主) 2008/12/14 20:03:20 顶楼 举报

我从easyMule源代码中提取的HASH函数HASH出来的值和eMule中的不一样 不知道哪里没弄对 请高手帮我看一下 哪里还需要改一下 代码提取于CKnownFile

代码
#include "stdafx.h"
#include <io.h>
#include "MD4.h"
#include "otherfunctions.h"

void CreateHash(CFile* pFile, uint64 Length, uchar* pMd4HashOut)
{
    ASSERT( pFile != NULL );
    ASSERT( pMd4HashOut != NULL );

    uint64  Required = Length;
    uchar   X[64*128];
    CMD4 md4;

    while (Required >= 64)
    {
        uint32 len;
        if ((Required / 64) > sizeof(X)/(64 * sizeof(X[0])))
            len = sizeof(X)/(64 * sizeof(X[0]));
        else
            len = (uint32)Required / 64;
        pFile->Read(&X, len*64);

        if (pMd4HashOut != NULL)
        {
            md4.Add(X, len*64);
        }
        Required -= len*64;
    }

    Required = Length % 64;

    if (pMd4HashOut != NULL)
    {
        md4.Add(X, (uint32)Required);
        md4.Finish();
        md4cpy(pMd4HashOut, md4.GetHash());
    }
}

bool CreateHash(FILE* fp, uint64 uSize, uchar* pucHash)
{
    bool bResult = false;
    CStdioFile file(fp);
    try
    {
        CreateHash(&file, uSize, pucHash);
        bResult = true;
    }
    catch (CFileException* ex)
    {
        ex->Delete();
    }
    return bResult;
}

bool CreateHash(const uchar* pucData, uint32 uSize, uchar* pucHash)
{
    bool bResult = false;
    CMemFile file(const_cast<uchar*>(pucData), uSize);
    try
    {
        CreateHash(&file, uSize, pucHash);
        bResult = true;
    }
    catch (CFileException* ex)
    {
        ex->Delete();
    }
    return bResult;
}

bool CreateFromFile(LPCTSTR in_directory, LPCTSTR in_filename, uchar fileHash[16])
{
    // open file
    CString strFilePath;
    _tmakepathlimit(strFilePath.GetBuffer(MAX_PATH), NULL, in_directory, in_filename, NULL);
    strFilePath.ReleaseBuffer();
    FILE* file = _tfsopen(strFilePath, _T("rbS"), _SH_DENYNO); // can not use _SH_DENYWR because we may access a completing part file
    if (!file){
        tcout << _T("文件") << strFilePath << _T("打开失败! CodeDesc = ") << _tcserror(errno) << std::endl;
        return false;
    }

    // set filesize
    if (_filelengthi64(file->_file) > MAX_EMULE_FILE_SIZE)
    {
        fclose(file);
        return false; // not supported by network
    }

    uint64 nFileSize = (uint64)_filelengthi64(file->_file);

    // we are reading the file data later in 8K blocks, adjust the internal file stream buffer accordingly
    setvbuf(file, NULL, _IOFBF, 1024*8*2);

    CArray<uchar*, uchar*>    hashlist;

    // create hashset
    uint64 togo = nFileSize;
    UINT hashcount;
    for (hashcount = 0; togo >= PARTSIZE; )
    {
        uchar* newhash = new uchar[16];
        if (!CreateHash(file, PARTSIZE, newhash))
        {
            tcout << _T("Hash文件") << strFilePath << _T("失败! CodeDesc = ") << _tcserror(errno) << std::endl;
            fclose(file);
            delete[] newhash;
            return false;
        }

        hashlist.Add(newhash);
        togo -= PARTSIZE;
        hashcount++;
    }

    uchar* lasthash = new uchar[16];
    md4clr(lasthash);
    if (!CreateHash(file, togo, lasthash))
    {
        tcout << _T("Hash文件") << strFilePath << _T("失败! CodeDesc = ") << _tcserror(errno) << std::endl;
        fclose(file);
        delete[] lasthash;
        return false;
    }

    if (!hashcount)
    {
        md4cpy(fileHash, lasthash);
        delete[] lasthash;
    }
    else
    {
        hashlist.Add(lasthash);
        uchar* buffer = new uchar[hashlist.GetCount()*16];
        for (int i = 0; i < hashlist.GetCount(); i++)
            md4cpy(buffer+(i*16), hashlist[i]);
        CreateHash(buffer, hashlist.GetCount()*16, fileHash);
        delete[] buffer;
    }
    fclose(file);
    file = NULL;
    return true;
}

int main(void)
{
    using namespace std;
    string filePath;
    while(getline(cin, filePath))
    {
        string::size_type pathEnd = filePath.find_last_of(_T('\\'));
        string strDir = filePath.substr(0, pathEnd);
        string strFile = filePath.substr(pathEnd + 1, string::npos);
        uchar fileHash[16];
        if(CreateFromFile(strDir.c_str(), strFile.c_str(), fileHash))
            cout << "Hash = " << md4str(fileHash) << endl;
    }
    return 0;
}

分享到开心网  分享到校内  收藏到QQ书签    订阅本主題RSS更新  美味书签

jiangliwei 2008/12/15 18:10:14 2楼 举报

先声明,我不是高手,只是喜欢研究代码而已。
既然楼主有勇气把代码贴出来,说明楼主也是个好学之人,那我就不客气的说了。

首先,楼主的代码我没有细看,我只看了头文件包含的部分和main的部分,我可以确认的第一件事就是楼主肯定没写过cpp代码,或者说是比较规范的cpp代码。很多部分带有浓厚的c风格,使用标准库方面也明显是在生搬硬套。关于这方面我不想多说,如果想拥有专业水准,请自行看书学习,推荐《c++ primer》4th。

然后,楼主没有在帖子里详细说明这段代码的目的到底是什么,根据标题,我猜测是想写一段测试emule中hash函数的代码,换句话说也就是做个简单的单元测试。我为了省事起见,直接将楼主的代码与emule源码比较,发现确实是摘自其中一部分,只是省略了不少东西,已是残缺不全。

在假设楼主是想写单元测试的前提下,建议不要修改源代码,先在原来的emule工程里搜索一下,看看原有的使用方法,弄清楚参数、返回值、依赖关系等等。然后设计好测试用例(也就是说准备好一套输入参数),执行之,看看是否吻合期待值(以标题来看,就是看看得到的hash值跟emule是否一致)。

还有一种情况,楼主只是想模仿源代码,摘抄出部分功能以实现其他目的。我不想对楼主摘抄的部分做过多评价,只是建议你用类的方式来实现会比较好(当然,前提是你在写cpp代码),毕竟在emule源代码中这部分功能是属于CKnownFile类的。

其余的部分请自行研究吧,这本来就不是什么复杂的功能,在有源代码的情况下,只要细心些就应该很轻松的实现出来。如果还是不行,那么请楼主放弃吧,eMule源代码还不适合你看,先补习一下基础再看吧,否则只会事倍功半徒劳无获。

最后,像这种只贴了一堆代码的半吊子帖子,很明显就是根本没有认真思考过,发现问题就直接贴出来了。像这样是不会有人肯回答你的问题的,这只是在利用别人,是不劳而获。如果是真的不会的话,请先复习一下《提问的智慧》然后再发贴。


[+2] [0] [回复]

godLaugh (组长) 2008/12/17 10:16:13 3楼 举报

eMule 中的hash 是按 9.28M 分段计算,然后再算 HashList 的 总hash 值即为文件的hash值。


[0] [0] [回复]

icedream_linxi (楼主) 2008/12/17 12:58:47 4楼 举报

to jiangliwei
您还真不客气!
1,说我的代码不规范,不知道您遵循的是那套规范。
2,说有浓厚的C风格,我想说@#¥%……&*
3,说生搬硬套,这么点代码您也能看出来,汗。。。
4,您根本没明白我问什么,更没看我写的是什么,后面对我的和我的代码的评价和建议我就不多说什么了


to godLaugh
我是这么做的
我只是把电驴源代码中做Hash部分代码中有关AICHHash部分去掉了,MD4Hash可以说是和源代码一模一样


[0] [-1] [回复]

jiangliwei 2008/12/17 23:16:28 5楼 举报

写的时候比较匆忙,写着写着就跑题了,请无视吧。。。。
我只是用最简单的办法,beyonndcompare比较了一下你的代码和ckonwfile的源码。而且我确实不明白你想问什么,也没看明白你写的是什么,算了,请无视吧。。。飘走


[+2] [0] [回复]

godLaugh (组长) 2009/01/05 14:43:49 6楼 举报

@icedream_linxi
在 emule-project.net 官方有一个 LinkCreater工具,提供了源代码(和你一样提取了Hash计算的相关代码),你可以再参考比较一下
http://www.emule-project.net/home/perl/gen...download
具体还是你多细心的调试分析对比一下,肯定就找到原因了...


[+3] [0] [回复]

icedream_linxi (楼主) 2009/04/25 20:14:44 7楼 举报

郁闷 漏了几行代码sleep.gif!
只要改成下面的函数就可以了

代码
void CreateHash(CFile* pFile, uint64 Length, uchar* pMd4HashOut)
{
    ASSERT( pFile != NULL );
    ASSERT( pMd4HashOut != NULL );

    uint64  Required = Length;
    uchar   X[64*128];
    CMD4 md4;

    while (Required >= 64)
    {
        uint32 len;
        if ((Required / 64) > sizeof(X)/(64 * sizeof(X[0])))
            len = sizeof(X)/(64 * sizeof(X[0]));
        else
            len = (uint32)Required / 64;
        pFile->Read(&X, len*64);

        if (pMd4HashOut != NULL)
        {
            md4.Add(X, len*64);
        }
        Required -= len*64;
    }

    Required = Length % 64;
    // 就这里少写了 郁闷sleep.gif!
    if (Required != 0)
    {
        pFile->Read(&X, (uint32)Required);
    }

    if (pMd4HashOut != NULL)
    {
        md4.Add(X, (uint32)Required);
        md4.Finish();
        md4cpy(pMd4HashOut, md4.GetHash());
    }
}


[0] [0] [回复]

kernel1983 2009/05/01 08:07:54 8楼 举报

http://code.google.com/p/edkgen/


[0] [0] [回复]

9-11楼已被删除

1899acmilan1999 2009/06/22 18:47:41 12楼 举报

引用(jiangliwei @ 2008-12-15, 06:10 PM) *
先声明,我不是高手,只是喜欢研究代码而已。
既然楼主有勇气把代码贴出来,说明楼主也是个好学之人,那我就不客气的说了。

首先,楼主的代码我没有细看,我只看了头文件包含的部分和main的部分,我可以确认的第一件事就是楼主肯定没写过cpp代码,或者说是比较规范的cpp代码。很多部分带有浓厚的c风格,使用标准库方面也明显是在生搬硬套。关于这方面我不想多说,如果想拥有专业水准,请自行看书学习,推荐《c++ primer》4th。

然后,楼主没有在帖子里详细说明这段代码的目的到底是什么,根据标题,我猜测是想写一段测试emule中hash函数的代码,换句话说也就是做个简单的单元测试。我为了省事起见,直接将楼主的代码与emule源码比较,发现确实是摘自其中一部分,只是省略了不少东西,已是残缺不全。

在假设楼主是想写单元测试的前提下,建议不要修改源代码,先在原来的emule工程里搜索一下,看看原有的使用方法,弄清楚参数、返回值、依赖关系等等。然后设计好测试用例(也就是说准备好一套输入参数),执行之,看看是否吻合期待值(以标题来看,就是看看得到的hash值跟emule是否一致)。

还有一种情况,楼主只是想模仿源代码,摘抄出部分功能以实现其他目的。我不想对楼主摘抄的部分做过多评价,只是建议你用类的方式来实现会比较好(当然,前提是你在写cpp代码),毕竟在emule源代码中这部分功能是属于CKnownFile类的。

其余的部分请自行研究吧,这本来就不是什么复杂的功能,在有源代码的情况下,只要细心些就应该很轻松的实现出来。如果还是不行,那么请楼主放弃吧,eMule源代码还不适合你看,先补习一下基础再看吧,否则只会事倍功半徒劳无获。

最后,像这种只贴了一堆代码的半吊子帖子,很明显就是根本没有认真思考过,发现问题就直接贴出来了。像这样是不会有人肯回答你的问题的,这只是在利用别人,是不劳而获。如果是真的不会的话,请先复习一下《提问的智慧》然后再发贴。




你写的好多啊 厉害


[0] [0] [回复]

patricxu 2009/08/25 16:31:12 13楼 举报

引用(icedream_linxi @ 2009-04-25, 08:14 PM) *
郁闷 漏了几行代码sleep.gif!
只要改成下面的函数就可以了
代码
void CreateHash(CFile* pFile, uint64 Length, uchar* pMd4HashOut)
{
    ASSERT( pFile != NULL );
    ASSERT( pMd4HashOut != NULL );

    uint64  Required = Length;
    uchar   X[64*128];
    CMD4 md4;

    while (Required >= 64)
    {
        uint32 len;
        if ((Required / 64) > sizeof(X)/(64 * sizeof(X[0])))
            len = sizeof(X)/(64 * sizeof(X[0]));
        else
            len = (uint32)Required / 64;
        pFile->Read(&X, len*64);

        if (pMd4HashOut != NULL)
        {
            md4.Add(X, len*64);
        }
        Required -= len*64;
    }

    Required = Length % 64;
    // 就这里少写了 郁闷sleep.gif!
    if (Required != 0)
    {
        pFile->Read(&X, (uint32)Required);
    }

    if (pMd4HashOut != NULL)
    {
        md4.Add(X, (uint32)Required);
        md4.Finish();
        md4cpy(pMd4HashOut, md4.GetHash());
    }
}

我也提取了MD4的算法,以同样的关键字作为参数,得出的结果和EMLUE的搜索关键字时的值不一样,大家交流一下?


[0] [0] [回复]

patricxu 2009/08/26 14:05:28 14楼 举报

今天调试出来的结果和emule的输出结果一致了


[0] [0] [回复]


返回组首页

快速回复

(?) 附件上传

关于我们 | 诚聘英才 | 著作权声明 | 合作信息 | 广告事务
沪ICP备05001009号
©2003 - 2009 VeryCD.com Some Rights Reserved.