MD5 algorithm experiment report (XDU Internet of things security)

Posted by j0sh on Mon, 03 Jan 2022 23:49:14 +0100

MD5 algorithm experiment

1, Experimental purpose

Programming MD5 algorithm, in-depth understanding of MD5 encryption and decryption principle

2, Instruments used in the experiment (or experimental environment)

The experimental center of the school of computer science and technology can access 44 desktop computers on the Internet.

3, Basic principle and requirements of experiment

1. Experimental principle

Step 1: add padding bits. If the length (bit) of the input plaintext is not equal to 448, it needs to be padded so that the result of 512 is equal to 448. The filling method is to fill a 1 and N 0. After filling, the length of the information is N*512+448(bit)

Step 2: fill in the length. Fill in the length of the original message after the result of the first step. The available storage length is 64 bits. If the message length is greater than 2 ^ 64, only its lower 64 bit value is used, that is (the message length is modulo 2 ^ 64). After this step, the final message length is N x 512+448+64=(N+1) x 512.

The third step is to initialize the buffer. A 128bit buffer can be used to save the intermediate and final results of the hash function. It can be expressed as four 32 bit registers (A,B,C,D) Where A=(01234567)16, B=(89ABCDEF)16, C=(FEDCBA98)16, D=(76543210)16. If defined in the program, it should be A=0X67452301L, B=0XEFCDAB89L, C=0X98BADCFEL, D=0X10325476L

Step 4: cycle data processing

Each round of operation as

The fifth step, cascade output, gives the encrypted ciphertext of MD5 algorithm.

2. Experimental requirements

Plaintext customization (for example, it can be an English famous saying). It is encrypted by MD5 algorithm, and the experimental process and encryption results are given.

4, Experimental steps and experimental data records: (text description and necessary screenshots)

1. Algorithm description

MD5 processes the input information in 512 bit packets, and each packet is divided into 16 32-bit sub packets. After a series of processing, the output of the algorithm consists of four 32-bit packets. After cascading the four 32-bit packets, a 128 bit hash value will be generated.

2. Code structure

3. Specific implementation steps

(1) The first step we need to do is fill. If the length (bit) of the input information is not equal to 448 for 512, we need to fill so that the result of 512 is equal to 448. The filling method is to fill a 1 and N 0. After filling, the length of the information is N*512+448(bit); The code is shown in the figure below:

(2) The original length b(bit) of the input information is expressed as a 64 bit number and added to the result of the previous step (on a 32-bit machine, the 64 bits will be represented by 2 words and the low order will be in the front). When b is greater than 2 ^ 64, the high bit of b is truncated and only the low 64 bit of b is used. After the above two steps, the data is filled in a multiple of 512(bit). That is, the data length at this time is an integer multiple of 16 words (32 bytes). The code is shown in the figure below:

(3) Load the standard magic number (four integers) and use a four word buffer (A,B,C,D) to calculate the message summary. A, B, C and D are 32-bit registers respectively. The number in hexadecimal is used for initialization. Note that the low byte is first:

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

(4) Four round cycle operation: the number of cycles is the number of groups (N+1)

① Four auxiliary functions are defined. The input of each function is three 32-bit words and the output is a 32-bit word: (& yes and, | yes or, ~ Yes or, ^ is XOR). The code is shown in the following figure:

​ F(X,Y,Z)=(X&Y)|((~X)&Z)
​ G(X,Y,Z)=(X&Z)|(Y&(~Z))
​ H(X,Y,Z)=XYZ
​ I(X,Y,Z)=Y^(X|(~Z))

② Let Mj represent the j-th sub group of the message (from 0 to 15): the code is shown in the following figure:

FF(a,b,c,d,Mj,s,ti) means a = B + ((a + F (B, C, d) + MJ + Ti) < < s)
GG(a,b,c,d,Mj,s,ti) means a = B + ((a + G (B, C, d) + MJ + Ti) < < s)
HH(a,b,c,d,Mj,s,ti) means a = B + ((a + H (B, C, d) + MJ + Ti) < < s)
II(a,b,c,d,Mj,s,ti) means a = B + ((a + I (B, C, d) + MJ + Ti) < < s)

(5) After each cycle, add a, B, C and D respectively, and then enter the next cycle

5, Analysis of experimental results

1. Experimental results

At the beginning, the string we passed in is: "inspire the glorious MES that you are", and the final MD5 value is "ADE90D3E14F9114D0EF4626971DE0BD0".

2. Experimental summary

After any message is processed by the hash function, A unique hash value will be generated. This hash value can be used to verify the integrity of the message. MD5 also makes use of this feature. Through the study and experiment of the principle of MD5 algorithm, I have A deeper understanding of the compressibility, easy calculation and anti modification of the hash function, Basically, the verification of MD5 algorithm can only be carried out with the help of computer, because the amount of calculation of MD5 algorithm is relatively complex. Through the computer, we can carry out summation operation very simply. When the grouping operation of the last plaintext is completed, the values in A, B, C and D are the final results (i.e. hash function values).

6, Source code

class MD5{
    //Initialize MD5 parameters
    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;
    //Defining standard magic numbers
    private static final long A=0x67452301L;
    private static final long B=0xefcdab89L;
    private static final long C=0x98badcfeL;
    private static final long D=0x10325476L;
    
    private long [] result={A,B,C,D};  //Store results
    static final String hexs[]={"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
    private String str;

    public MD5(String str) {
        this.str=str;
        String result=Main_process();
        System.out.println("| MD5---<"+str+">"+" | \nResult: "+result);
    }
    
    private String Main_process() {
        byte [] inputBytes=str.getBytes();
        int str_length=inputBytes.length;   //String byte length
        int group_number=0;                 //Number of packets, 512 bits per group (64 bytes)
        group_number=str_length/64;         //Byte length / 64 bytes
        long []groups=null;                 //Each group is subdivided by 4 bytes

        for(int i=0;i<group_number;i++){  //Processing packet, cyclic operation, number of cyclic sub digit packets
            groups=Create_NewGroup(inputBytes,i*64);
            Transform(groups);                     //Processing grouping, core algorithm
        }

        int rest=str_length%64;            //Remainder after processing 512 bit packets
        byte [] tempBytes=new byte[64];
        if(rest<=56){
            for(int i=0;i<rest;i++)
                tempBytes[i]=inputBytes[str_length-rest+i];
            if(rest<56){
                tempBytes[rest]=(byte)(1<<7);
                for(int i=1;i<56-rest;i++)
                    tempBytes[rest+i]=0;
            }
            long len=(long)(str_length<<3);
            for(int i=0;i<8;i++){
                tempBytes[56+i]=(byte)(len&0xFFL);
                len=len>>8;
            }
            groups=Create_NewGroup(tempBytes,0);
            Transform(groups);
        }else{
            for(int i=0;i<rest;i++)
                tempBytes[i]=inputBytes[str_length-rest+i];
            tempBytes[rest]=(byte)(1<<7);
            for(int i=rest+1;i<64;i++)
                tempBytes[i]=0;
            groups=Create_NewGroup(tempBytes,0);
            Transform(groups);

            for(int i=0;i<56;i++)
                tempBytes[i]=0;
            long len=(long)(str_length<<3);
            for(int i=0;i<8;i++){
                tempBytes[56+i]=(byte)(len&0xFFL);
                len=len>>8;
            }
            groups=Create_NewGroup(tempBytes,0);
            Transform(groups);
        }
        return ToHexString();
    }

    private String ToHexString(){  //The Hash value is converted to a hexadecimal string
        String resStr="";
        long temp=0;
        for(int i=0;i<4;i++){
            for(int j=0;j<4;j++){
                temp=result[i]&0x0FL;
                String a=hexs[(int)(temp)];
                result[i]=result[i]>>4;
                temp=result[i]&0x0FL;
                resStr+=hexs[(int)(temp)]+a;
                result[i]=result[i]>>4;
            }
        }
        return resStr;
    }
    private void Transform(long[] groups) {  //Packets are processed, 64 bytes per packet
        long a = result[0], b = result[1], c = result[2], d = result[3];
        //first round
        a = FF(a, b, c, d, groups[0], S11, 0xd76aa478L);
        d = FF(d, a, b, c, groups[1], S12, 0xe8c7b756L);
        c = FF(c, d, a, b, groups[2], S13, 0x242070dbL);
        b = FF(b, c, d, a, groups[3], S14, 0xc1bdceeeL);
        a = FF(a, b, c, d, groups[4], S11, 0xf57c0fafL);
        d = FF(d, a, b, c, groups[5], S12, 0x4787c62aL);
        c = FF(c, d, a, b, groups[6], S13, 0xa8304613L);
        b = FF(b, c, d, a, groups[7], S14, 0xfd469501L);
        a = FF(a, b, c, d, groups[8], S11, 0x698098d8L);
        d = FF(d, a, b, c, groups[9], S12, 0x8b44f7afL);
        c = FF(c, d, a, b, groups[10], S13, 0xffff5bb1L);
        b = FF(b, c, d, a, groups[11], S14, 0x895cd7beL);
        a = FF(a, b, c, d, groups[12], S11, 0x6b901122L);
        d = FF(d, a, b, c, groups[13], S12, 0xfd987193L);
        c = FF(c, d, a, b, groups[14], S13, 0xa679438eL);
        b = FF(b, c, d, a, groups[15], S14, 0x49b40821L);
        //Second round
        a = GG(a, b, c, d, groups[1], S21, 0xf61e2562L);
        d = GG(d, a, b, c, groups[6], S22, 0xc040b340L);
        c = GG(c, d, a, b, groups[11], S23, 0x265e5a51L);
        b = GG(b, c, d, a, groups[0], S24, 0xe9b6c7aaL);
        a = GG(a, b, c, d, groups[5], S21, 0xd62f105dL);
        d = GG(d, a, b, c, groups[10], S22, 0x2441453L);
        c = GG(c, d, a, b, groups[15], S23, 0xd8a1e681L);
        b = GG(b, c, d, a, groups[4], S24, 0xe7d3fbc8L);
        a = GG(a, b, c, d, groups[9], S21, 0x21e1cde6L);
        d = GG(d, a, b, c, groups[14], S22, 0xc33707d6L);
        c = GG(c, d, a, b, groups[3], S23, 0xf4d50d87L);
        b = GG(b, c, d, a, groups[8], S24, 0x455a14edL);
        a = GG(a, b, c, d, groups[13], S21, 0xa9e3e905L);
        d = GG(d, a, b, c, groups[2], S22, 0xfcefa3f8L);
        c = GG(c, d, a, b, groups[7], S23, 0x676f02d9L);
        b = GG(b, c, d, a, groups[12], S24, 0x8d2a4c8aL);
        //Third round
        a = HH(a, b, c, d, groups[5], S31, 0xfffa3942L);
        d = HH(d, a, b, c, groups[8], S32, 0x8771f681L);
        c = HH(c, d, a, b, groups[11], S33, 0x6d9d6122L);
        b = HH(b, c, d, a, groups[14], S34, 0xfde5380cL);
        a = HH(a, b, c, d, groups[1], S31, 0xa4beea44L);
        d = HH(d, a, b, c, groups[4], S32, 0x4bdecfa9L);
        c = HH(c, d, a, b, groups[7], S33, 0xf6bb4b60L);
        b = HH(b, c, d, a, groups[10], S34, 0xbebfbc70L);
        a = HH(a, b, c, d, groups[13], S31, 0x289b7ec6L);
        d = HH(d, a, b, c, groups[0], S32, 0xeaa127faL);
        c = HH(c, d, a, b, groups[3], S33, 0xd4ef3085L);
        b = HH(b, c, d, a, groups[6], S34, 0x4881d05L);
        a = HH(a, b, c, d, groups[9], S31, 0xd9d4d039L);
        d = HH(d, a, b, c, groups[12], S32, 0xe6db99e5L);
        c = HH(c, d, a, b, groups[15], S33, 0x1fa27cf8L);
        b = HH(b, c, d, a, groups[2], S34, 0xc4ac5665L);
        //Fourth round
        a = II(a, b, c, d, groups[0], S41, 0xf4292244L);
        d = II(d, a, b, c, groups[7], S42, 0x432aff97L);
        c = II(c, d, a, b, groups[14], S43, 0xab9423a7L);
        b = II(b, c, d, a, groups[5], S44, 0xfc93a039L);
        a = II(a, b, c, d, groups[12], S41, 0x655b59c3L);
        d = II(d, a, b, c, groups[3], S42, 0x8f0ccc92L);
        c = II(c, d, a, b, groups[10], S43, 0xffeff47dL);
        b = II(b, c, d, a, groups[1], S44, 0x85845dd1L);
        a = II(a, b, c, d, groups[8], S41, 0x6fa87e4fL);
        d = II(d, a, b, c, groups[15], S42, 0xfe2ce6e0L);
        c = II(c, d, a, b, groups[6], S43, 0xa3014314L);
        b = II(b, c, d, a, groups[13], S44, 0x4e0811a1L);
        a = II(a, b, c, d, groups[4], S41, 0xf7537e82L);
        d = II(d, a, b, c, groups[11], S42, 0xbd3af235L);
        c = II(c, d, a, b, groups[2], S43, 0x2ad7d2bbL);
        b = II(b, c, d, a, groups[9], S44, 0xeb86d391L);

        result[0] += a; //Added to previous calculations
        result[1] += b;
        result[2] += c;
        result[3] += d;
        result[0]=result[0]&0xFFFFFFFFL;
        result[1]=result[1]&0xFFFFFFFFL;
        result[2]=result[2]&0xFFFFFFFFL;
        result[3]=result[3]&0xFFFFFFFFL;
    }
    private long DealHi(byte b){                   //Symbol bits need to be processed
        return b < 0 ? b & 0x7F + 128 : b;
    }
    private long[] Create_NewGroup(byte[] inputBytes,int index){
        long [] temp=new long[16];                 //Each 512 bit packet is subdivided into 16 groups, with 64 bits (8 bytes) per group
        for(int i=0;i<16;i++){
            temp[i]=DealHi(inputBytes[4*i+index])|
                    (DealHi(inputBytes[4*i+1+index]))<<8|
                    (DealHi(inputBytes[4*i+2+index]))<<16|
                    (DealHi(inputBytes[4*i+3+index]))<<24;
        }
        return temp;
    }
    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 static 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));
    }
    private long FF(long a, long b, long c, long d, long x, long s,
                           long ac) {
        a += (F(b, c, d)&0xFFFFFFFFL) + x + ac;
        a = ((a&0xFFFFFFFFL)<< s) | ((a&0xFFFFFFFFL) >>> (32 - s));
        a += b;
        return (a&0xFFFFFFFFL);
    }
    private long GG(long a, long b, long c, long d, long x, long s,
                           long ac) {
        a += (G(b, c, d)&0xFFFFFFFFL) + x + ac;
        a = ((a&0xFFFFFFFFL) << s) | ((a&0xFFFFFFFFL) >>> (32 - s));
        a += b;
        return (a&0xFFFFFFFFL);
    }
    private long HH(long a, long b, long c, long d, long x, long s,
                           long ac) {
        a += (H(b, c, d)&0xFFFFFFFFL) + x + ac;
        a = ((a&0xFFFFFFFFL) << s) | ((a&0xFFFFFFFFL) >>> (32 - s));
        a += b;
        return (a&0xFFFFFFFFL);
    }
    private long II(long a, long b, long c, long d, long x, long s,
                           long ac) {
        a += (I(b, c, d)&0xFFFFFFFFL) + x + ac;
        a = ((a&0xFFFFFFFFL) << s) | ((a&0xFFFFFFFFL) >>> (32 - s));
        a += b;
        return (a&0xFFFFFFFFL);
    }
}
public class IOT_md5 {
    public static void main(String []args){
        String str="Embrace the glorious mess that you are";
        MD5 md=new MD5(str);
    }
}

Topics: Java md5