`
mmk12333
  • 浏览: 35319 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

MD5加密算法详解

阅读更多

注:MD5不是绝对的安全,有俩md5解决

 

/*******************************************************************************
 * keyBean 类实现了RSA Data Security, Inc.在提交给IETF 的RFC1321中的keyBean message-digest
 * 算法。
 ******************************************************************************/
public class MD5keyBean {
    /*
     * 下面这些S11-S44实际上是一个4*4的矩阵,在原始的C实现中是用#define 实现的, 这里把它们实现成为static
     * final是表示了只读,切能在同一个进程空间内的多个 Instance间共享
     */
    static final int S11 = 7;
    static final int S12 = 12;
    static final int S13 = 17;
    static final int S14 = 22;
    static final int S21 = 5;
    static final int S22 = 9;
    static final int S23 = 14;
    static final int S24 = 20;
    static final int S31 = 4;
    static final int S32 = 11;
    static final int S33 = 16;
    static final int S34 = 23;
    static final int S41 = 6;
    static final int S42 = 10;
    static final int S43 = 15;
    static final int S44 = 21;
    static final byte[] PADDING = { -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0 };
    /*
     * 下面的三个成员是keyBean计算过程中用到的3个核心数据,在原始的C实现中 被定义到keyBean_CTX结构中
     */
    private long[] state = new long[4]; // state (ABCD)
    private long[] count = new long[2]; // number of bits, modulo 2^64 (lsb
                                        // first)
    private byte[] buffer = new byte[64]; // input buffer
    /*
     * digestHexStr是keyBean的唯一一个公共成员,是最新一次计算结果的 16进制ASCII表示.
     */

    public String digestHexStr;
    /*
     * digest,是最新一次计算结果的2进制内部表示,表示128bit的keyBean值.
     */
    private byte[] digest = new byte[16];

    /*
     * getkeyBeanofStr是类keyBean最主要的公共方法,入口参数是你想要进行keyBean变换的字符串
     * 返回的是变换完的结果,这个结果是从公共成员digestHexStr取得的.
     */
    public String getkeyBeanofStr(String inbuf) {
        keyBeanInit();
        keyBeanUpdate(inbuf.getBytes(), inbuf.length());
        keyBeanFinal();
        digestHexStr = "";
        for (int i = 0; i < 16; i++) {
            digestHexStr += byteHEX(digest[i]);
        }
        return digestHexStr;
    }

    // 这是keyBean这个类的标准构造函数,JavaBean要求有一个public的并且没有参数的构造函数
    public MD5keyBean() {
        keyBeanInit();
        return;
    }

    /* keyBeanInit是一个初始化函数,初始化核心变量,装入标准的幻数 */
    private void keyBeanInit() {
        count[0] = 0L;
        count[1] = 0L;
        // /* Load magic initialization constants.
        state[0] = 0x67452301L;
        state[1] = 0xefcdab89L;
        state[2] = 0x98badcfeL;
        state[3] = 0x10325476L;
        return;
    }

    /*
     * F, G, H ,I 是4个基本的keyBean函数,在原始的keyBean的C实现中,由于它们是
     * 简单的位运算,可能出于效率的考虑把它们实现成了宏,在java中,我们把它们 实现成了private方法,名字保持了原来C中的。
     */
    private long F(long x, long y, long z) {
        return (x & y) | ((~x) & z);
    }

    private long G(long x, long y, long z) {
        return (x & z) | (y & (~z));
    }

    private long H(long x, long y, long z) {
        return x ^ y ^ z;
    }

    private long I(long x, long y, long z) {
        return y ^ (x | (~z));
    }

    /*
     * FF,GG,HH和II将调用F,G,H,I进行近一步变换 FF, GG, HH, and II transformations for
     * rounds 1, 2, 3, and 4. Rotation is separate from addition to prevent
     * recomputation.
     */
    private long FF(long a, long b, long c, long d, long x, long s, long ac) {
        a += F(b, c, d) + x + ac;
        a = ((int) a << s) | ((int) a >>> (32 - s));
        a += b;
        return a;
    }

    private long GG(long a, long b, long c, long d, long x, long s, long ac) {
        a += G(b, c, d) + x + ac;
        a = ((int) a << s) | ((int) a >>> (32 - s));
        a += b;
        return a;
    }

    private long HH(long a, long b, long c, long d, long x, long s, long ac) {
        a += H(b, c, d) + x + ac;
        a = ((int) a << s) | ((int) a >>> (32 - s));
        a += b;
        return a;
    }

    private long II(long a, long b, long c, long d, long x, long s, long ac) {
        a += I(b, c, d) + x + ac;
        a = ((int) a << s) | ((int) a >>> (32 - s));
        a += b;
        return a;
    }

    /*
     * keyBeanUpdate是keyBean的主计算过程,inbuf是要变换的字节串,inputlen是长度,这个
     * 函数由getkeyBeanofStr调用,调用之前需要调用keyBeaninit,因此把它设计成private的
     */
    private void keyBeanUpdate(byte[] inbuf, int inputLen) {
        int i, index, partLen;
        byte[] block = new byte[64];
        index = (int) (count[0] >>> 3) & 0x3F;
        // /* Update number of bits */
        if ((count[0] += (inputLen << 3)) < (inputLen << 3))
            count[1]++;
        count[1] += (inputLen >>> 29);
        partLen = 64 - index;
        // Transform as many times as possible.
        if (inputLen >= partLen) {
            keyBeanMemcpy(buffer, inbuf, index, 0, partLen);
            keyBeanTransform(buffer);
            for (i = partLen; i + 63 < inputLen; i += 64) {
                keyBeanMemcpy(block, inbuf, 0, i, 64);
                keyBeanTransform(block);
            }
            index = 0;
        } else
            i = 0;
        // /* Buffer remaining input */
        keyBeanMemcpy(buffer, inbuf, index, i, inputLen - i);
    }

    /*
     * keyBeanFinal整理和填写输出结果
     */
    private void keyBeanFinal() {
        byte[] bits = new byte[8];
        int index, padLen;
        // /* Save number of bits */
        Encode(bits, count, 8);
        // /* Pad out to 56 mod 64.
        index = (int) (count[0] >>> 3) & 0x3f;
        padLen = (index < 56) ? (56 - index) : (120 - index);
        keyBeanUpdate(PADDING, padLen);
        // /* Append length (before padding) */
        keyBeanUpdate(bits, 8);
        // /* Store state in digest */
        Encode(digest, state, 16);
    }

    /*
     * keyBeanMemcpy是一个内部使用的byte数组的块拷贝函数,从input的inpos开始把len长度的
     * 字节拷贝到output的outpos位置开始
     */
    private void keyBeanMemcpy(byte[] output, byte[] input, int outpos,
            int inpos, int len) {
        int i;
        for (i = 0; i < len; i++)
            output[outpos + i] = input[inpos + i];
    }

    /*
     * keyBeanTransform是keyBean核心变换程序,有keyBeanUpdate调用,block是分块的原始字节
     */
    private void keyBeanTransform(byte block[]) {
        long a = state[0], b = state[1], c = state[2], d = state[3];
        long[] x = new long[16];
        Decode(x, block, 64);
        /* Round 1 */
        a = FF(a, b, c, d, x[0], S11, 0xd76aa478L); /* 1 */
        d = FF(d, a, b, c, x[1], S12, 0xe8c7b756L); /* 2 */
        c = FF(c, d, a, b, x[2], S13, 0x242070dbL); /* 3 */
        b = FF(b, c, d, a, x[3], S14, 0xc1bdceeeL); /* 4 */
        a = FF(a, b, c, d, x[4], S11, 0xf57c0fafL); /* 5 */
        d = FF(d, a, b, c, x[5], S12, 0x4787c62aL); /* 6 */
        c = FF(c, d, a, b, x[6], S13, 0xa8304613L); /* 7 */
        b = FF(b, c, d, a, x[7], S14, 0xfd469501L); /* 8 */
        a = FF(a, b, c, d, x[8], S11, 0x698098d8L); /* 9 */
        d = FF(d, a, b, c, x[9], S12, 0x8b44f7afL); /* 10 */
        c = FF(c, d, a, b, x[10], S13, 0xffff5bb1L); /* 11 */
        b = FF(b, c, d, a, x[11], S14, 0x895cd7beL); /* 12 */
        a = FF(a, b, c, d, x[12], S11, 0x6b901122L); /* 13 */
        d = FF(d, a, b, c, x[13], S12, 0xfd987193L); /* 14 */
        c = FF(c, d, a, b, x[14], S13, 0xa679438eL); /* 15 */
        b = FF(b, c, d, a, x[15], S14, 0x49b40821L); /* 16 */
        /* Round 2 */
        a = GG(a, b, c, d, x[1], S21, 0xf61e2562L); /* 17 */
        d = GG(d, a, b, c, x[6], S22, 0xc040b340L); /* 18 */
        c = GG(c, d, a, b, x[11], S23, 0x265e5a51L); /* 19 */
        b = GG(b, c, d, a, x[0], S24, 0xe9b6c7aaL); /* 20 */
        a = GG(a, b, c, d, x[5], S21, 0xd62f105dL); /* 21 */
        d = GG(d, a, b, c, x[10], S22, 0x2441453L); /* 22 */
        c = GG(c, d, a, b, x[15], S23, 0xd8a1e681L); /* 23 */
        b = GG(b, c, d, a, x[4], S24, 0xe7d3fbc8L); /* 24 */
        a = GG(a, b, c, d, x[9], S21, 0x21e1cde6L); /* 25 */
        d = GG(d, a, b, c, x[14], S22, 0xc33707d6L); /* 26 */
        c = GG(c, d, a, b, x[3], S23, 0xf4d50d87L); /* 27 */
        b = GG(b, c, d, a, x[8], S24, 0x455a14edL); /* 28 */
        a = GG(a, b, c, d, x[13], S21, 0xa9e3e905L); /* 29 */
        d = GG(d, a, b, c, x[2], S22, 0xfcefa3f8L); /* 30 */
        c = GG(c, d, a, b, x[7], S23, 0x676f02d9L); /* 31 */
        b = GG(b, c, d, a, x[12], S24, 0x8d2a4c8aL); /* 32 */
        /* Round 3 */
        a = HH(a, b, c, d, x[5], S31, 0xfffa3942L); /* 33 */
        d = HH(d, a, b, c, x[8], S32, 0x8771f681L); /* 34 */
        c = HH(c, d, a, b, x[11], S33, 0x6d9d6122L); /* 35 */
        b = HH(b, c, d, a, x[14], S34, 0xfde5380cL); /* 36 */
        a = HH(a, b, c, d, x[1], S31, 0xa4beea44L); /* 37 */
        d = HH(d, a, b, c, x[4], S32, 0x4bdecfa9L); /* 38 */
        c = HH(c, d, a, b, x[7], S33, 0xf6bb4b60L); /* 39 */
        b = HH(b, c, d, a, x[10], S34, 0xbebfbc70L); /* 40 */
        a = HH(a, b, c, d, x[13], S31, 0x289b7ec6L); /* 41 */
        d = HH(d, a, b, c, x[0], S32, 0xeaa127faL); /* 42 */
        c = HH(c, d, a, b, x[3], S33, 0xd4ef3085L); /* 43 */
        b = HH(b, c, d, a, x[6], S34, 0x4881d05L); /* 44 */
        a = HH(a, b, c, d, x[9], S31, 0xd9d4d039L); /* 45 */
        d = HH(d, a, b, c, x[12], S32, 0xe6db99e5L); /* 46 */
        c = HH(c, d, a, b, x[15], S33, 0x1fa27cf8L); /* 47 */
        b = HH(b, c, d, a, x[2], S34, 0xc4ac5665L); /* 48 */
        /* Round 4 */
        a = II(a, b, c, d, x[0], S41, 0xf4292244L); /* 49 */
        d = II(d, a, b, c, x[7], S42, 0x432aff97L); /* 50 */
        c = II(c, d, a, b, x[14], S43, 0xab9423a7L); /* 51 */
        b = II(b, c, d, a, x[5], S44, 0xfc93a039L); /* 52 */
        a = II(a, b, c, d, x[12], S41, 0x655b59c3L); /* 53 */
        d = II(d, a, b, c, x[3], S42, 0x8f0ccc92L); /* 54 */
        c = II(c, d, a, b, x[10], S43, 0xffeff47dL); /* 55 */
        b = II(b, c, d, a, x[1], S44, 0x85845dd1L); /* 56 */
        a = II(a, b, c, d, x[8], S41, 0x6fa87e4fL); /* 57 */
        d = II(d, a, b, c, x[15], S42, 0xfe2ce6e0L); /* 58 */
        c = II(c, d, a, b, x[6], S43, 0xa3014314L); /* 59 */
        b = II(b, c, d, a, x[13], S44, 0x4e0811a1L); /* 60 */
        a = II(a, b, c, d, x[4], S41, 0xf7537e82L); /* 61 */
        d = II(d, a, b, c, x[11], S42, 0xbd3af235L); /* 62 */
        c = II(c, d, a, b, x[2], S43, 0x2ad7d2bbL); /* 63 */
        b = II(b, c, d, a, x[9], S44, 0xeb86d391L); /* 64 */
        state[0] += a;
        state[1] += b;
        state[2] += c;
        state[3] += d;
    }

    /*
     * Encode把long数组按顺序拆成byte数组,因为java的long类型是64bit的, 只拆低32bit,以适应原始C实现的用途
     */
    private void Encode(byte[] output, long[] input, int len) {
        int i, j;
        for (i = 0, j = 0; j < len; i++, j += 4) {
            output[j] = (byte) (input[i] & 0xffL);
            output[j + 1] = (byte) ((input[i] >>> 8) & 0xffL);
            output[j + 2] = (byte) ((input[i] >>> 16) & 0xffL);
            output[j + 3] = (byte) ((input[i] >>> 24) & 0xffL);
        }
    }

    /*
     * Decode把byte数组按顺序合成成long数组,因为java的long类型是64bit的,
     * 只合成低32bit,高32bit清零,以适应原始C实现的用途
     */
    private void Decode(long[] output, byte[] input, int len) {
        int i, j;

        for (i = 0, j = 0; j < len; i++, j += 4)
            output[i] = b2iu(input[j]) | (b2iu(input[j + 1]) << 8)
                    | (b2iu(input[j + 2]) << 16) | (b2iu(input[j + 3]) << 24);
        return;
    }

    /*
     * b2iu是我写的一个把byte按照不考虑正负号的原则的"升位"程序,因为java没有unsigned运算
     */
    public static long b2iu(byte b) {
        return b < 0 ? b & 0x7F + 128 : b;
    }

    /*
     * byteHEX(),用来把一个byte类型的数转换成十六进制的ASCII表示,
     * 因为java中的byte的toString无法实现这一点,我们又没有C语言中的 sprintf(outbuf,"%02X",ib)
     */
    public static String byteHEX(byte ib) {
        char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
                'B', 'C', 'D', 'E', 'F' };
        char[] ob = new char[2];
        ob[0] = Digit[(ib >>> 4) & 0X0F];
        ob[1] = Digit[ib & 0X0F];
        String s = new String(ob);
        return s;
    }

    /**
     * 测试类
     * @param args
     */
    public static void main(String args[]) {
        MD5keyBean m = new MD5keyBean();
        String md5 = m.getkeyBeanofStr("123456");
        System.out.println(md5);
    }
}

分享到:
评论

相关推荐

    MD5加密算法详解(标题写的更详细,容易让他人下载)

    MD5加密算法详解 MD5加密算法是一种常用的散列函数,可以将任意长度的消息压缩成固定长度的消息摘要。MD5的主要特点是快速、不可逆和碰撞-resistant。 MD5算法的工作过程可以分为以下几个步骤: 1. 初始化处理:...

    md5加密算法详解md5加密算法详解md5加密算法详解md5加密算法详解

    在Java中实现MD5加密算法,通常会涉及以下几个关键步骤: 1. **初始化**: - 初始化函数`md5Init()`负责设置MD5的核心变量,如`state`数组(保存中间计算状态),`count`数组(记录处理了多少位数据),以及`...

    MD5加密 算法 详解

    尽管MD5在当时被认为是一种安全的算法,但随着时间的推移,其安全性逐渐降低,现在已经不建议用于安全性要求高的场景。 MD5的工作原理是将任意长度的消息转换成固定长度的摘要。这个过程通过四个不同的阶段完成:...

    md5加密算法

    ### MD5加密算法详解 #### 一、MD5算法简介 MD5(Message-Digest Algorithm 5)是一种广泛使用的散列函数,它能够接收任意长度的信息,并产生一个128位(16字节)的散列值。该算法由Ron Rivest在1991年设计,作为...

    md5中使用MD5加密算法进行加密

    ### MD5加密算法详解 #### 一、MD5算法简介 MD5(Message-Digest Algorithm 5)是一种广泛使用的散列函数(哈希函数),它能够接收任意长度的数据输入,并生成一个固定长度(通常为128位)的十六进制数值作为输出...

    MD5加密算法

    ### MD5加密算法详解 #### 一、基本简介 MD5(Message-Digest Algorithm 5,信息摘要算法5)是一种广泛应用于计算机领域的散列算法,主要用于确保信息传输过程中的完整性和一致性。它由MD2、MD3和MD4发展而来,自...

    VB写的MD5加密算法

    ### VB编写的MD5加密算法详解 #### 基础常量定义 - `BITS_TO_A_BYTE`: 指定每个字节包含的比特数,即8。 - `BYTES_TO_A_WORD`: 定义一个字包含的字节数,为4。 - `BITS_TO_A_WORD`: 表示一个字包含的比特数,是32...

    MD5加密的算法详解

    ### MD5加密算法详解 #### 一、引言 在信息安全领域,数据加密技术是保护信息不被非法窃取和篡改的重要手段之一。MD5(Message-Digest Algorithm 5)作为常用的一种散列函数,因其高效且相对安全的特点,在实际...

    MD5 RAS DES 加密算法详解

    ### MD5 RAS DES 加密算法详解 #### MD5算法:信息安全的守护者 MD5,全称为Message-Digest Algorithm 5,是由MIT的计算机科学实验室与RSA Data Security Inc.共同研发的一种散列函数,其设计目的是为了保障信息的...

    MD5加密以及MD5算法流程详解-c++

    MD5(Message-Digest ...在提供的压缩包文件中,"MD5算法流程.pdf"可能详细介绍了MD5的步骤和工作原理,而"md5(1).rar"可能包含了一个C++实现MD5加密的示例代码,你可以参考这两个文件来学习和理解MD5加密的完整过程。

    matlab实现md5算法,md5算法详解,matlab

    总结来说,MATLAB实现MD5算法涉及的主要知识点包括:MD5算法的背景和用途,哈希函数的基本概念,MD5算法的四轮循环结构,FF、GG、HH、II四个非线性函数的作用,以及MATLAB中位运算和数组操作的应用。通过学习这个...

    MD5 算法详解以及代码

    MD5 算法详解及 Java 实现 在信息安全领域中,MD5 算法是一种常用的摘要算法,用于生成信息的数字指纹。MD5 全称为 Message-Digest Algorithm 5,即信息-摘要算法 5。它可以将任意长度的信息转换为一个固定长度的...

    md5加密算法-c语

    ### MD5加密算法-C语言实现详解 #### 一、引言 MD5(Message-Digest Algorithm 5)是一种广泛使用的密码散列函数,能够产生一个128位(16字节)的散列值,用于确保信息传输的完整性和一致性。在网络安全领域,MD5...

    DELPHI MD5文本加密算法

    ### DELPHI MD5文本加密算法详解 在IT领域,数据安全与隐私保护的重要性日益凸显,其中加密技术作为保障信息安全的关键手段之一,被广泛应用。MD5(Message-Digest Algorithm 5)是一种常用的散列函数,它能将任意...

    网易云音乐登录信息加密算法详解1

    网易云音乐登录信息加密算法详解 网易云音乐登录信息加密算法是网易云音乐平台上的一种加密算法,用于保护用户登录信息的安全。本算法的核心过程包括两部分:AES 加密和 RSA 加密。 AES 加密 AES 加密是网易云...

    MD5算法详细流程(pdf)

    ### MD5算法详解 #### 一、MD5算法概述 MD5(Message-Digest Algorithm 5)是一种广泛使用的散列函数,它可以将任意长度的消息转换成一个固定长度的散列值,通常用来验证数据的完整性。MD5算法的核心在于它能够快速...

    md5算法流程图

    ### MD5算法详解 #### 一、概述 MD5(Message-Digest Algorithm 5)是一种广泛使用的散列函数,能够将任意长度的消息压缩成一个固定长度(128位)的散列值,通常用于数据完整性的校验、密码存储等场景。MD5算法的...

    MD5加密,简单易懂

    ### MD5加密算法详解 #### 一、简介 MD5(Message-Digest Algorithm 5)是一种广泛使用的散列函数,可以将任意长度的数据转换为一个固定长度(通常是128位)的十六进制字符串。这种转换过程是不可逆的,也就是说...

Global site tag (gtag.js) - Google Analytics