MD5&Application In PassWord

来源:互联网 发布:局域网未识别的网络 编辑:程序博客网 时间:2024/06/05 12:16

  • MD5 Program
    • Analysis
    • Code
      • MD5hpp
      • MD5cpp
      • testcpp
    • 实验结果截图
  • MD5 For Password Protection
    • MD5特性
    • MD5在密码中的应用

MD5 Program

根据老师的PPT讲解和RFC1321白皮书,我写了一个可执行的MD5加密程序。

Analysis

具体的思想为:

  1. 先逐个地接收信息字符,然后将每一个字符转化成长度为8位的阿斯克码二进制字符串,然后,加到现有的字符串中,当现有的字符串长度达到512bits时,对它进行处理,然后继续接收下一个512bits长度的字符串,直到最后一个字符输入,然后对最后一段做padding处理,留下最后64位作为长度记录。
  2. padding的时候有三种情况:现在的长度小于448,长度等于448,长度大于448,然后长度小于448的就直接补到448,长度等于或者大于448的就要补到下一个512分组的448位处,才能够把长度填入。
  3. 长度的填入是低位存在前32位,高位存在后32位。
  4. 把每一个512位的分组分成16个32位的无符号整数。之前我们传入的时候是按字符二进制传入的,现在把每四个字符的二进制字符串分为一组,按照小端规则变成16个无符号整数。
  5. 对每一个512位分组,按照下面的规则做4轮FGHI每轮16次迭代,得出这个分组后的结果:
    这里写图片描述
    这里写图片描述

具体的代码和实验结果如下:

Code

MD5.hpp

#ifndef MD5_HPP#define MD5_HPPclass MD5{public:    MD5();    ~MD5();    int SwitchIterationIndex(int i, int j);    unsigned int ShiftLeft(unsigned int in, int b);    void InitVector();    void InitShiftAmount();    void HMD5(unsigned int* in);    void MessageDealing(string s);    void PaddingDealing(string s);    unsigned int add(unsigned int a, unsigned int b);    unsigned int GBCD(int turn, unsigned int b, unsigned int c, unsigned int d);    void Print();    void GetXArray(string s);private:    unsigned int input[4];    int s[64];    unsigned int x[16];    unsigned long  long count;};#endif

MD5.cpp

#include <iostream>#include <iomanip>#include <cmath>#include <cstdlib>#include "MD5.hpp"using namespace std;MD5::MD5() {    count = 0;    InitVector();    InitShiftAmount();}int MD5::SwitchIterationIndex(int i, int j) {    int f;    switch (i) {    case 0:        f = j;        break;    case 1:        f = (1 + 5 * j) % 16;        break;    case 2:        f = (5 + 3 * j) % 16;        break;    case 3:        f = (7 * j) % 16;        break;    }    return f;}unsigned int MD5::ShiftLeft(unsigned int in, int b) {    return (unsigned int)(((unsigned long long)in) << b) | (((unsigned long long)in) >> (32 - b));}void MD5::InitVector() {    input[0] = 0x67452301;    input[1] = 0xEFCDAB89;    input[2] = 0x98BADCFE;    input[3] = 0x10325476;}void MD5::HMD5(unsigned int* in) {    for (int k = 0; k < 4; k++) {        for (int q = 0; q < 16; q++) {            unsigned int tmps = add(GBCD(k, in[1], in[2], in[3]), in[0]);            unsigned int tmp1 = (unsigned int)floor(((unsigned long long)0x100000000)*abs(sin(k * 16 + q+1)));            tmps = add(tmps, x[SwitchIterationIndex(k,k*16+q)]);            tmps = add(tmps, tmp1);            tmp1 = ShiftLeft(tmps, s[k*16+q]);            tmps = tmp1 + in[1];            in[0] = in[3];            in[3] = in[2];            in[2] = in[1];            in[1] = tmps;        }    }    input[0] = input[0] + in[0];    input[1] = input[1] + in[1];    input[2] = input[2] + in[2];    input[3] = input[3] + in[3];}void MD5::GetXArray(string s) {    string tmp1 = "",tmp2 = "",tmp3 = "",tmp4 = "";    for (int k = 0; k < 16; k++) {        tmp1 = s.substr(32 * k, 8);        tmp2 = s.substr(32 * k+8, 8);        tmp3 = s.substr(32 * k+16, 8);        tmp4 = s.substr(32 * k+24, 8);        x[k] = strtol(tmp4.c_str(), NULL, 2) << 24;        x[k] += strtol(tmp3.c_str(), NULL, 2) << 16;        x[k] += strtol(tmp2.c_str(), NULL, 2) << 8;        x[k] += strtol(tmp1.c_str(), NULL, 2);    }}void MD5::MessageDealing(string s) {    count += s.size();    string tmp1 = "",tmp2 = "",tmp3 = "",tmp4 = "", another = "";    if (s.size() < 512) {        int a = s.size() % 512;        if (a == 448) {            s += "1";            for (int i = 1; i < 512; i++) {                s += "0";            }            another = s.substr(512,448);            GetXArray(s);        } else if (a < 448) {            s += "1";            for (int i = 0; i < (447 - a); i++) {                    s += "0";                }                for (int k = 0; k < 14; k++) {                tmp1 = s.substr(32 * k, 8);                tmp2 = s.substr(32 * k+8, 8);                tmp3 = s.substr(32 * k+16, 8);                tmp4 = s.substr(32 * k+24, 8);                x[k] = strtol(tmp4.c_str(), NULL, 2) << 24;                x[k] += strtol(tmp3.c_str(), NULL, 2) << 16;                x[k] += strtol(tmp2.c_str(), NULL, 2) << 8;                x[k] += strtol(tmp1.c_str(), NULL, 2);            }            x[14] =(unsigned int)(count&(unsigned int)0xFFFFFFFF);            x[15] = (count>>32);        } else {            s += "1";            for (int i = 1; i < (960-a); i++) {                s += "0";            }            another = s.substr(512,448);            GetXArray(s);        }    } else {        GetXArray(s);    }    unsigned int temp[4];    for (int k = 0; k < 4; k++) {        temp[k] = input[k];    }    HMD5(temp);    if (s.size() > 512) PaddingDealing(another);}void MD5::PaddingDealing(string s) {    string tmp1 = "",tmp2 = "",tmp3 = "",tmp4 = "";    for (int k = 0; k < 14; k++) {        tmp1 = s.substr(32 * k, 8);        tmp2 = s.substr(32 * k+8, 8);        tmp3 = s.substr(32 * k+16, 8);        tmp4 = s.substr(32 * k+24, 8);        x[k] = strtol(tmp4.c_str(), NULL, 2) << 24;        x[k] += strtol(tmp3.c_str(), NULL, 2) << 16;        x[k] += strtol(tmp2.c_str(), NULL, 2) << 8;        x[k] += strtol(tmp1.c_str(), NULL, 2);    }    x[14] =(unsigned int)(count&(unsigned int)0xFFFFFFFF);    x[15] = (count>>32);    unsigned int temp[4];    for (int k = 0; k < 4; k++) {        temp[k] = input[k];    }    HMD5(temp);}unsigned int MD5::add(unsigned int a, unsigned int b) {    unsigned int c = 0xFFFFFFFF;    return (unsigned int)(((unsigned long)a + (unsigned long)b));}unsigned int MD5::GBCD(int turn, unsigned int b, unsigned int c, unsigned int d) {    unsigned int f;    switch (turn) {    case 0:        f = ((b)&(c)) | ((~b)&(d));        break;    case 1:        f = ((b)&(d)) | ((c)&(~d));        break;    case 2:        f = ((b)^(c) ^ (d));        break;    case 3:        f = ((c)^ ((b) | (~d)));        break;    }    return f;}void MD5::InitShiftAmount() {    s[0] = s[4] = s[8] = s[12] = 7;    s[1] = s[5] = s[9] = s[13] = 12;    s[2] = s[6] = s[10] = s[14] = 17;    s[3] = s[7] = s[11] = s[15] = 22;    s[16] = s[20] = s[24] = s[28] = 5;    s[17] = s[21] = s[25] = s[29] = 9;    s[18] = s[22] = s[26] = s[30] = 14;    s[19] = s[23] = s[27] = s[31] = 20;    s[32] = s[36] = s[40] = s[44] = 4;    s[33] = s[37] = s[41] = s[45] = 11;    s[34] = s[38] = s[42] = s[46] = 16;    s[35] = s[39] = s[43] = s[47] = 23;    s[48] = s[52] = s[56] = s[60] = 6;    s[49] = s[53] = s[57] = s[61] = 10;    s[50] = s[54] = s[58] = s[62] = 15;    s[51] = s[55] = s[59] = s[63] = 21;}void MD5::Print() {    unsigned int a = 0, b = 0, c = 0, d = 0;    for (int k = 0; k < 4; k++) {        a = input[k] & 0xFF;        a = a << 24;        b = input[k] & 0xFF00;        b = b << 8;        c = input[k] & 0xFF0000;        c = c >> 8;        d = input[k] & 0xFF000000;        d = d >> 24;        input[k] = a + b + c + d;        cout<<hex <<setfill('0')<<setw(8)<< input[k];    }    cout << endl;}MD5::~MD5() {}

test.cpp

#include "MD5.hpp"using namespace std;string Encode(char c) {    int num = (int)c;    int temp = 0;    string result =  "";    for (int i = 7; i >= 0; i--) {        temp = num >> i;        if (temp % 2 == 0) {            result += "0";        } else {            result += "1";        }    }    return result;}int main() {    MD5* md = new MD5();    string s = "";    char c;    cout << "Please enter the infomation you want to encode and stop by enter ctrl + Z: " << endl;    int count = 0;    string str = "MD5 for(\"";    while (scanf("%c",&c) != EOF) {        str += c;        if (count == 64) {            count = 1;            md->MessageDealing(s);            s = "" + Encode(c);        } else {            s += Encode(c);            count++;        }    }    if (str.size() != 9) str = str.substr(0,str.size()-1);    s =s.substr(0,s.size()-8);    md->MessageDealing(s);    str += "\"): ";    cout << str;    md->Print();    delete md;    return 0;}

实验结果截图

  1. Case 1
    输入空字符串
    这里写图片描述
    结果为d41d8cd98f00b204e9800998ecf8427e
  2. Case 2
    输入”a”
    这里写图片描述
    结果为:0cc175b9c0f1b6a831c399e269772661
  3. Case 3
    输入”abc”
    这里写图片描述
    结果为:900150983cd24fb0d6963f7d28e17f72
  4. Case 4
    输入”message digest”
    这里写图片描述
    结果为:f96b697d7cb7938d525a2f31aaf161d0
  5. Case 5
    输入”abcdefghijklmnopqrstuvwxyz”
    这里写图片描述
    结果为:c3fcd3d76192e4007dfb496cca67e13b
    6.Case 6
    输入”ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789”
    这里写图片描述
    结果为:d174ab98d277d9f5a5611c2c9f419d9f
    7.Case 7
    输入”12345678901234567890123456789012345678901234567890123456789012345678901234567890”
    这里写图片描述
    结果为:57edf4a22be3c955ac49da2e2107b67a

与RFC321白皮书中提到的example一致:
这里写图片描述

MD5 For Password Protection

MD5特性

  1. 因为MD5是把信息转换成一个固定长度的密文,不管明文的长度是多少,密文的长度固定是128位,这样第一点就可以隐藏密码的具体长度。
  2. 第二个特性就是,MD5是不可逆的,具有单向性,就是说,只有密文,攻击者是无法得知明文的,所以这样来说,密码就比较安全,只有持有者才知道。
  3. 第三个就是,虽然MD5不是足够安全的,但是很难找到真正不同的两个消息,使得他们的MD5值相同。

MD5在密码中的应用

  1. 因为密码是检验密码持有者身份的依据,只要verifier知道这个身份是真是假就可以了。所以,verifier(一个公司、网站或其他服务提供商)在将MD5应用于密码校验的时候只需要将密码持有者送来的待校验密码用MD5算法处理,处理后将得到的MD5值与他们数据库中的存储的MD5值进行对比,如果一致,说明验证成功,如果不一致,说明校验失败。最原始的真正的密码在一开始注册的时候就被以MD5的形式存在数据库中。
  2. 以MD5的形式存在于验证方的数据库中,比裸密码要安全得多,因为攻击者如果得到数据库中的信息,要攻破MD5把原来的密码算出来是很困难的,所以相较之要安全很多。
  3. 一般的密码其实都可以用MD5加密,用户名也是可以的(或者说,也是很有必要的),只有当用户名和密码同时校验成功才算是校验成功。
原创粉丝点击