MD5 电子签名

MD5 算法

假设我们有 b - bits 的数据,需要计算他的电子签名 , 对于任意的 b ( 甚至可以是 0 , 但是必须是 8 的倍数) 。

追加对齐bit数据。

让数据对齐成 模512 byte 剩余448 byte 的长度。 追加数据一定要进行,哪怕数据本来就是模512 byte 剩余448 byte, 也得追加512个byte来对对齐。 追加数据的方式是第一个bit是1 。 其余的bit全部是 0 。

追加长度

对于追加了对齐数据后的数据,将原始数据的长度 ( in bits)( 64 bit 数据表示, 小32位在前 )追加到数据后面。这样最终得到512 byte 的倍数的数据。

初始化 4 byte 长度的电子签名

先低 byte :
word A: 01 23 45 67
word B: 89 ab cd ef
word C: fe dc ba 98
word D: 76 54 32 10

每 16 bytes 走下面的流程 :

。。。 各种扭曲平移。。。

将ABCD一次从小的byte 到大依次输出为MD5电子签名

代码

#include <math.h>
#include <string.h>
#include "md5.h"

static const MD5_word A_init = 0x67452301;
static const MD5_word B_init = 0xefcdab89;
static const MD5_word C_init = 0x98badcfe;
static const MD5_word D_init = 0x10325476;

static const MD5_word T[65] = {
    /*   4294967296 * abs( sin ( i ) )  */
        0 ,
3614090360,      3905402710,    606105819,   3250441966,
4118548399,      1200080426,    2821735955,  4249261313,
1770035416,      2336552879,    4294925233,  2304563134,
1804603682,      4254626195,    2792965006,  1236535329,
4129170786,      3225465664,    643717713,   3921069994,
3593408605,      38016083,      3634488961,  3889429448,
568446438,       3275163606,    4107603335,  1163531501,
2850285829,      4243563512,    1735328473,  2368359562,
4294588738,      2272392833,    1839030562,  4259657740,
2763975236,      1272893353,    4139469664,  3200236656,
681279174,       3936430074,    3572445317,  76029189,
3654602809,      3873151461,    530742520,   3299628645,
4096336452,      1126891415,    2878612391,  4237533241,
1700485571,      2399980690,    4293915773,  2240044497,
1873313359,      4264355552,    2734768916,  1309151649,
4149444226,      3174756917,    718787259,   3951481745 };

// XY       ==> X&Y
// not (X)  ==> ~X
// X v Y    ==> X | Y
// X xor Y  ==> X ^ Y
// X <<< s  ==> ( X << s )  | ( X >> (32 -s ) ) 

//F(X,Y,Z) = XY v not(X) Z
inline MD5_word F(MD5_word X , MD5_word Y , MD5_word Z) {
    return  X & Y | ~X & Z ;
}

//G(X,Y,Z) = XZ v Y not(Z)
inline MD5_word G(MD5_word X , MD5_word Y , MD5_word Z) {
    return X & Z ^ Y & ~Z ;
}

//H(X,Y,Z) = X xor Y xor Z
inline MD5_word H(MD5_word X , MD5_word Y , MD5_word Z) {
    return X ^ Y ^ Z ;    
}

//I(X,Y,Z) = Y xor (X v not(Z))
inline MD5_word I(MD5_word X , MD5_word Y , MD5_word Z) {
    return Y ^ ( X | ~ Z ) ;    
}

/* Round 1. */
/* Let [abcd k s i] denote the operation
   a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */

#define ROUND1(a,b,c,d,k,s,i)  \
     a = a + F(b,c,d) + X[k] + T[i] ; \
     a = ( a << s | a>>(32 - s) ) + b;


/* Round 2. */
/* Let [abcd k s i] denote the operation
   a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */

#define ROUND2(a,b,c,d,k,s,i) \
     a = a + G(b,c,d) + X[k] + T[i] ; \
     a = ( a << s | a>>(32 - s) ) + b;

/* Round 3. */
/* Let [abcd k s t] denote the operation
   a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */

#define ROUND3(a,b,c,d,k,s,i) \
     a = a + H(b,c,d) + X[k] + T[i] ; \
     a = ( a << s | a>>(32 - s) ) + b;

/* Round 4. */
/* Let [abcd k s t] denote the operation
   a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
#define ROUND4(a,b,c,d,k,s,i) \
        a = a + I(b,c,d) + X[k] + T[i] ; \
        a = ( a << s | a>>(32 - s) ) + b;

void MD5_16Word(const MD5_word X[16] ,struct MD5Content * content) {

    register MD5_word AA = content->A;
    register MD5_word BB = content->B;
    register MD5_word CC = content->C;
    register MD5_word DD = content->D;

    ROUND1(AA, BB, CC, DD, 0, 7, 1)  
    ROUND1(DD, AA, BB, CC, 1, 12, 2)
    ROUND1(CC, DD, AA, BB, 2, 17, 3)
    ROUND1(BB, CC, DD, AA, 3, 22, 4)
    ROUND1(AA,BB,CC,DD, 4  , 7, 5 );
    ROUND1(DD,AA,BB,CC, 5 , 12, 6);
    ROUND1(CC,DD,AA,BB, 6  , 17, 7);
    ROUND1(BB,CC,DD,AA, 7  , 22, 8);  
    ROUND1(AA,BB,CC,DD, 8  , 7, 9 );
    ROUND1(DD,AA,BB,CC, 9 , 12, 10);
    ROUND1(CC,DD,AA,BB, 10 , 17, 11);
    ROUND1(BB,CC,DD,AA, 11 , 22, 12);  
    ROUND1(AA,BB,CC,DD, 12 , 7, 13 );
    ROUND1(DD,AA,BB,CC, 13 , 12, 14);
    ROUND1(CC,DD,AA,BB, 14 , 17, 15);
    ROUND1(BB,CC,DD,AA, 15 , 22, 16);  

    ROUND2(AA,BB,CC,DD, 1  , 5, 17 );
    ROUND2(DD,AA,BB,CC, 6  , 9, 18);
    ROUND2(CC,DD,AA,BB, 11 , 14, 19);
    ROUND2(BB,CC,DD,AA, 0  , 20, 20);  
    ROUND2(AA,BB,CC,DD, 5  , 5, 21 );
    ROUND2(DD,AA,BB,CC, 10 , 9, 22);
    ROUND2(CC,DD,AA,BB, 15 , 14, 23);
    ROUND2(BB,CC,DD,AA, 4  , 20, 24);  
    ROUND2(AA,BB,CC,DD, 9  , 5, 25 );
    ROUND2(DD,AA,BB,CC, 14 , 9, 26);
    ROUND2(CC,DD,AA,BB, 3  , 14, 27);
    ROUND2(BB,CC,DD,AA, 8  , 20, 28);  
    ROUND2(AA,BB,CC,DD, 13 , 5, 29 );
    ROUND2(DD,AA,BB,CC, 2  , 9, 30);
    ROUND2(CC,DD,AA,BB, 7  , 14, 31);
    ROUND2(BB,CC,DD,AA, 12 , 20, 32);  

    ROUND3(AA,BB,CC,DD,  5,  4, 33);
    ROUND3(DD,AA,BB,CC,  8, 11, 34);
    ROUND3(CC,DD,AA,BB, 11, 16, 35);
    ROUND3(BB,CC,DD,AA, 14, 23, 36);
    ROUND3(AA,BB,CC,DD,  1,  4, 37);
    ROUND3(DD,AA,BB,CC,  4, 11, 38);
    ROUND3(CC,DD,AA,BB,  7, 16, 39);
    ROUND3(BB,CC,DD,AA, 10, 23, 40);
    ROUND3(AA,BB,CC,DD, 13,  4, 41);
    ROUND3(DD,AA,BB,CC,  0, 11, 42);
    ROUND3(CC,DD,AA,BB,  3, 16, 43);
    ROUND3(BB,CC,DD,AA,  6, 23, 44);
    ROUND3(AA,BB,CC,DD,  9,  4, 45);
    ROUND3(DD,AA,BB,CC, 12, 11, 46);
    ROUND3(CC,DD,AA,BB, 15, 16, 47);
    ROUND3(BB,CC,DD,AA,  2, 23, 48);


    ROUND4(AA,BB,CC,DD,  0,  6, 49);
    ROUND4(DD,AA,BB,CC,  7, 10, 50);
    ROUND4(CC,DD,AA,BB, 14, 15, 51);
    ROUND4(BB,CC,DD,AA,  5, 21, 52);
    ROUND4(AA,BB,CC,DD, 12,  6, 53);
    ROUND4(DD,AA,BB,CC,  3, 10, 54);
    ROUND4(CC,DD,AA,BB, 10, 15, 55);
    ROUND4(BB,CC,DD,AA,  1, 21, 56);
    ROUND4(AA,BB,CC,DD,  8,  6, 57);
    ROUND4(DD,AA,BB,CC, 15, 10, 58);
    ROUND4(CC,DD,AA,BB,  6, 15, 59);
    ROUND4(BB,CC,DD,AA, 13, 21, 60);
    ROUND4(AA,BB,CC,DD,  4,  6, 61);
    ROUND4(DD,AA,BB,CC, 11, 10, 62);
    ROUND4(CC,DD,AA,BB,  2, 15, 63);
    ROUND4(BB,CC,DD,AA,  9, 21, 64);

    content->A += AA;
    content->B += BB;
    content->C += CC;
    content->D += DD;
}   

union MD5Buff {
    MD5_word words[16];
    struct append_buff{
        unsigned char chars[56];
        MD5_word size[2];
    } append;
};

void byteSwap(MD5_word *buf, unsigned words){
#ifdef BIG_ENDIAN
   unsigned char *p = (unsigned char *)buf;
    do {
        *buf++ = (MD5_word) ( ((unsigned)p[3] )| ((unsigned) p[2] <<8)   
                              | ((unsigned)p[1] << 16 ) | ((unsigned p[0]) << 24 ) );
        p += 4;
    } while (--words);
#endif
}

struct MD5Content MD5(const unsigned char  * buff_ , MD5_uint64 size_ ) { 

    MD5Content content;
    content.A = A_init;
    content.B = B_init;
    content.C = C_init;
    content.D = D_init; 

    MD5_uint64 left_size = size_ ;
    const unsigned char * next = buff_;

    MD5Buff buff;
    while( left_size >= 64 ) {
        memcpy(buff.words,next,64);
        byteSwap(buff.words , 16) ;
        MD5_16Word(buff.words,&content);
        next += 64 ;
        left_size -= 64 ;
    }

    memset(buff.words , 0 , 64 );

    if(left_size > 0 ){
        memcpy(buff.append.chars,next,left_size);
    }
    buff.append.chars[left_size] = 0x80;
    if( left_size < 55 ) {
        buff.append.size[1] = (MD5_word)(((size_<<3) & ( 0xffff0000ULL) ) >> 32 ) ;
        buff.append.size[0] = (MD5_word)(((size_<<3) & ( 0x0000ffffULL) ) ) ;
    }
    byteSwap(buff.words , 16) ;
    MD5_16Word(buff.words,&content);
    if( left_size > 55) {
        memset(buff.words , 0 , 64 );
        buff.append.size[1] = (MD5_word)((size_<<3 & ( 0xffff0000ULL) ) >> 32 ) ;
        buff.append.size[0] = (MD5_word)((size_<<3 & ( 0x0000ffffULL) ) ) ;
        byteSwap(buff.words , 16) ;
        MD5_16Word(buff.words,&content);
    }

    return content;
}

inline std::string GetMD5(unsigned char *buf, size_t len) {
    auto content = MD5((unsigned char *)buf, (unsigned long long ) len );
    MD5Result ret;
    ret.content = content;
    std::ostringstream ost;
    for( int i = 0 ; i < 16 ; i ++ ) {
        ost.width(2);
        ost.fill('0');
        ost<<std::hex<<short(ret.buff[i]);
    }
    return ost.str();
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值