zoukankan      html  css  js  c++  java
  • 借用gcc源码中的sha1.c进行SHA1计算

    起初打算用sha1校验进行密码比对,然后想找个能算SHA1校验码的C语言函数,想到这个算法很可能在开源代码中能找到,于是在gcc-4.9.2的源码中找到了一个名叫"sha1.c"的文件,在源码树的gcc-4.9.2libiberty目录下,就拿来用用看.

    把该文件拷出来,拿到VC6下打开编译,自动建立了一个工程,但是第26行有个严重错误:

    #include <config.h>

    找不到config.h,这是一个很常见的错误,源码树下又搜不到这个文件,于是,要么新建一个空的文件命成这个名字,要么直接删掉这行包含语句.咱不想破坏源码文件,所以新建了一个空的config.h放在了工程目录下,但,重新编译还是提示找不到,大概是因为用尖括号包含的缘故.接下来修改工程配置,在C/C++的预处理路径中添加一个小数点,代表工程文件所在目录,重新编译,这回能找到了,但是出现了新的错误:在第28行:

    #include "sha1.h"

    回到源码树中搜索,在gcc-4.9.2include路径下找到了sha1.h,拷出来放到工程路径下,重新编译,于是在sha1.h的第29行:

    #include "ansidecl.h"

    继续搜,仍然在gcc-4.9.2include路径下,找到了这个ansidecl.h文件,拷出来放到工程路径下,重新编译,终于编译通过了.

    分析下sha1.h文件,可以看出,sha1_buffer函数就是我们要找的计算SHA1的函数


    很好,新建个测试文件,起名叫sha1_test.c,文件内容如下:

    #include <stdio.h>
    #include "sha1.h"
    
    int main()
    {
        char buffer[64] = { 0 };
        unsigned char resblock[20] = "";
        size_t i = 0;
    
        sha1_buffer (buffer, sizeof (buffer), resblock);
        for (i = 0; i < 20; i++)
        {
            printf ("%02X", resblock[i]);
        }
        putchar ('
    ');
        
        return 0;
    }
    
    代码很简单,只是给了一组数据,64个字节的零,计算其SHA1值,将计算结果以字节为单位,用十六进制打印出来,跑一下,结果如下:

    C8D7D0EF0EEDFA82D2EA1AA592845B9A6D4B02B7

    看起来挺像那么回事的.然后,因为VC6新建工程后,默认为Debug模式,咱把它切换到Release模式下跑跑看,这一跑,坏了,结果不一样了:

    7076B3F1F5B3F7440BB4BFCC04C469EBD9FBC129

    解决办法有两个:其一,修改工程配置,把sha1.c这个文件的优化关掉,重新编译,啊,这回结果变得和Debug下的结果一样了.

    其二,用旧版本的gcc源码,比如gcc-4.7.2的源码,这个版本没有上述问题.


    用文件对比工具(比如SVN)对比下两个版本的源码,发现只有一处差异,第303行,旧版本是

      if (ctx->total[0] < len)
        ++ctx->total[1];
    新版本是

      ctx->total[1] += ((len >> 31) >> 1) + (ctx->total[0] < len);
    果然新版本是把((len >> 31) >> 1)优化错了,据我猜测,新版本这么个改法,是为了在64位程序上,当内存中申请了超过2的32次方大小的内存后,对这块内存求SHA1校验码,((len >> 31) >> 1)才有意义.32位程序由于不存在如此大的buf所以旧版本的没有加.

    手头没有条件测试这个情况,但是根据猜测,旧版本不加((len >> 31) >> 1),会导致对超过2的32次方大小的内存直接计算校验码出现错误吧.新版本之所以要加上这么个量,想必是为了防止这样的错误.但是禁止优化这种事情,很容易忘记,所以,最好的办法是利用config.h文件,在这个文件中加上这么一行:

    #pragma optimize("",off)
    
    强制关掉优化(仅在VC6下试过能用,其他编译环境请自行试验),OK了,有新版咱还是用新版比较安心什么的


    PS:在源码树的gcc-4.9.2libiberty目录下,还能看到其他很多大概能用上的函数,像是md5.c什么的,拿来用用吧

  • 相关阅读:
    hdu 1754 线段树 注意线段树节点的设计 求什么,设什么
    hdu 4015 概率题
    poj 1950 回溯
    最大上升子序列
    JVM学习博客
    2012
    i am alone at a crossroads
    易知难
    牢骚。。
    something
  • 原文地址:https://www.cnblogs.com/sugar13/p/10216609.html
Copyright © 2011-2022 走看看