What is MD5 algorithm

MD5 Message Digest Algorithm (English: MD5 Message-Digest Algorithm), a widely used cryptographic hash function, can generate a 128-bit (16-byte) hash value (hash value), used to ensure Information transmission is complete and consistent.

MD5 function

Input information of any length, after processing, the output is 128-bit information (digital fingerprint);
different input results in different results (uniqueness);

MD5 is not an encryption algorithm

Those who think it does not belong because they feel that the original text cannot be obtained from the ciphertext (hash value) in turn, that is, there is no decryption algorithm, so these people think that MD5 can only belong to the algorithm and cannot be called an encryption algorithm
; Because they feel that the original text cannot be seen after MD5 processing, that is, the original text has been encrypted, so they think that MD5 is an encryption algorithm; I personally support the former, just as they think that the BASE64 algorithm can only be regarded as encoding.

Is the MD5 algorithm reversible?

The reason why MD5 is irreversible is that it is a hash function that uses the hash algorithm, and part of the information of the original text is lost during the calculation process.

However, one thing worth pointing out is that theoretically, an MD5 may indeed correspond to an infinite number of original texts, because MD5 has a finite number of original texts and there may be an infinite number of original texts. For example, the MD5 used by the mainstream maps a “byte string of any length into a large 128-bit integer. That is to say, there are 2^128 possibilities in total, which is about 3.4*10^38. This number is limited, but the world There are countless possibilities for the original text that can be used to encrypt.

However, one thing to note is that although this is a theoretical finite versus infinite, the problem is that this infinite is not fully established in real life, because on the one hand, the length of the original text in reality is often limited (take commonly used passwords as For example, most people are within 20), on the other hand, it is very difficult to find that two original texts correspond to the same MD5 value (professionals say this is called hash collision), so in a sense, within a certain range, if you want to construct The one-to-one correspondence between the MD5 value and the original text is entirely possible. Therefore, the most effective way to attack MD5 is the rainbow table. For details, you can learn about it through Google.

MD5 is equivalent to lossy compression.

MD5 purpose

1. To prevent tampering:

1) For example, when sending an electronic document, before sending it, I first get the output result a of MD5. Then, after the other party receives the electronic document, the other party also gets an MD5 output b. If a is the same as b, it means that it has not been tampered with halfway.

2) For example, if I provide file downloads, in order to prevent criminals from adding Trojan horses in the installation program, I can publish the MD5 output results obtained from the installation files on the website.

3) SVN also uses MD5 to detect whether the file has been modified after CheckOut.

2. Prevent direct viewing of plaintext:

Many websites now store the MD5 value of the user’s password when storing the user’s password in the database. In this way, even if criminals obtain the MD5 value of the user password of the database, they cannot know the user’s password. (For example, in the UNIX system, the user’s password is encrypted with MD5 (or other similar algorithms) and stored in the file system. When the user logs in, the system calculates the password entered by the user into an MD5 value, and then saves it Compare the MD5 value in the file system to determine whether the entered password is correct. Through such steps, the system can determine the legitimacy of the user’s login system without knowing the clear code of the user’s password. This can not only prevent users from The password is known by users with system administrator privileges, and it also increases the difficulty of password cracking to a certain extent.)

3. Non-repudiation (digital signature):

This requires a third-party certification authority. For example, A writes a file, and the certification body uses the MD5 algorithm to generate summary information for this file and make a record. If A says that this document was not written by him in the future, the authoritative organization only needs to regenerate the summary information of this document, and then compare it with the summary information recorded in the record. If it is the same, it will be proved that it was written by A. This is called a “digital signature”.

MD5 security

It is generally believed that MD5 is very safe, because the time for brute force cracking is unacceptable to ordinary people. In fact, if the user’s password MD5 is processed and then stored in the database, it is actually very insecure. Because the user’s password is relatively short, and many users’ passwords use birthdays, mobile phone numbers, ID card numbers, phone numbers and so on. Or use some commonly used auspicious numbers, or an English word. If I process the commonly used passwords with MD5 first, store the data, and then match your MD5 results, then I may get the plaintext. Therefore, the password strategy of most websites now is to force users to use a combination of numbers, uppercase and lowercase letters to improve the security of user passwords.

MD5 algorithm process

A brief description of the MD5 algorithm can be as follows: MD5 uses 512-bit groups to process input information, and each group is divided into 16 32-bit sub-groups. After a series of processing, the output of the algorithm consists of four 32-bit sub-groups. A 128-bit hash value will be generated after concatenating these four 32-bit groups.

The first step, filling: If the length (bit) of the input information is not equal to 448 for the remainder of 512, it needs to be filled so that the result of the remainder of 512 is equal to 448. The filling method is to fill a 1 and n 0s. After filling, the length of the information is N*512+448(bit);

The second step is to record the information length: use 64 bits to store the information length before filling. These 64 bits are added to the result of the first step, so that the information length becomes N*512+448+64=(N+1)*512 bits.

The third step is to load the standard magic number (four integers): the standard magic number (physical order) is (A=(01234567)16, B=(89ABCDEF)16, C=(FEDCBA98)16, D=( 76543210) 16). If it is defined in the program, it should be:
(A=0X67452301L, B=0XEFCDAB89L, C=0X98BADCFEL, D=0X10325476L). I’m a little dizzy, but I understand it after thinking about it.

The fourth step, four rounds of loop operation: the number of loops is the number of groups (N+1)

1) Subdivide each 512 bytes into 16 groups, each with 64 bits (8 bytes)

2) First recognize four linear functions (& is and, | is or, ~ is not, ^ is exclusive or)

1
2
3
4
F(X,Y,Z)=(X&Y)|((~X)&Z)
G(X,Y,Z)=(X&Z)|(Y&(~Z))
H(X,Y,Z)=X^Y^Z
I(X,Y,Z)=Y^(X|(~Z))

3) Let Mj represent the jth subgroup of the message (from 0 to 15), <<

1
2
3
4
FF(a,b,c,d,Mj,s,ti) equals to a=b+((a+F(b,c,d)+Mj+ti)<<<s)
GG(a,b,c,d,Mj,s,ti) equals to a=b+((a+G(b,c,d)+Mj+ti)<<<s)
HH(a,b,c,d,Mj,s,ti) equals to a=b+((a+H(b,c,d)+Mj+ti)<<<s)
II(a,b,c,d,Mj,s,ti) equals to a=b+((a+I(b,c,d)+Mj+ti)<<<s)

4) Four-wheel operation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// Round one
a=FF(a,b,c,d,M0,7,0xd76aa478)
b=FF(d,a,b,c,M1,12,0xe8c7b756)
c=FF(c,d,a,b,M2,17,0x242070db)
d=FF(b,c,d,a,M3,22,0xc1bdceee)
a=FF(a,b,c,d,M4,7,0xf57c0faf)
b=FF(d,a,b,c,M5,12,0x4787c62a)
c=FF(c,d,a,b,M6,17,0xa8304613)
d=FF(b,c,d,a,M7,22,0xfd469501)
a=FF(a,b,c,d,M8,7,0x698098d8)
b=FF(d,a,b,c,M9,12,0x8b44f7af)
c=FF(c,d,a,b,M10,17,0xffff5bb1)
d=FF(b,c,d,a,M11,22,0x895cd7be)
a=FF(a,b,c,d,M12,7,0x6b901122)
b=FF(d,a,b,c,M13,12,0xfd987193)
c=FF(c,d,a,b,M14,17,0xa679438e)
d=FF(b,c,d,a,M15,22,0x49b40821)

// Round two
a=GG(a,b,c,d,M1,5,0xf61e2562)
b=GG(d,a,b,c,M6,9,0xc040b340)
c=GG(c,d,a,b,M11,14,0x265e5a51)
d=GG(b,c,d,a,M0,20,0xe9b6c7aa)
a=GG(a,b,c,d,M5,5,0xd62f105d)
b=GG(d,a,b,c,M10,9,0x02441453)
c=GG(c,d,a,b,M15,14,0xd8a1e681)
d=GG(b,c,d,a,M4,20,0xe7d3fbc8)
a=GG(a,b,c,d,M9,5,0x21e1cde6)
b=GG(d,a,b,c,M14,9,0xc33707d6)
c=GG(c,d,a,b,M3,14,0xf4d50d87)
d=GG(b,c,d,a,M8,20,0x455a14ed)
a=GG(a,b,c,d,M13,5,0xa9e3e905)
b=GG(d,a,b,c,M2,9,0xfcefa3f8)
c=GG(c,d,a,b,M7,14,0x676f02d9)
d=GG(b,c,d,a,M12,20,0x8d2a4c8a)

// Round three
a=HH(a,b,c,d,M5,4,0xfffa3942)
b=HH(d,a,b,c,M8,11,0x8771f681)
c=HH(c,d,a,b,M11,16,0x6d9d6122)
d=HH(b,c,d,a,M14,23,0xfde5380c)
a=HH(a,b,c,d,M1,4,0xa4beea44)
b=HH(d,a,b,c,M4,11,0x4bdecfa9)
c=HH(c,d,a,b,M7,16,0xf6bb4b60)
d=HH(b,c,d,a,M10,23,0xbebfbc70)
a=HH(a,b,c,d,M13,4,0x289b7ec6)
b=HH(d,a,b,c,M0,11,0xeaa127fa)
c=HH(c,d,a,b,M3,16,0xd4ef3085)
d=HH(b,c,d,a,M6,23,0x04881d05)
a=HH(a,b,c,d,M9,4,0xd9d4d039)
b=HH(d,a,b,c,M12,11,0xe6db99e5)
c=HH(c,d,a,b,M15,16,0x1fa27cf8)
d=HH(b,c,d,a,M2,23,0xc4ac5665)

// Round four
a=II(a,b,c,d,M0,6,0xf4292244)
b=II(d,a,b,c,M7,10,0x432aff97)
c=II(c,d,a,b,M14,15,0xab9423a7)
d=II(b,c,d,a,M5,21,0xfc93a039)
a=II(a,b,c,d,M12,6,0x655b59c3)
b=II(d,a,b,c,M3,10,0x8f0ccc92)
c=II(c,d,a,b,M10,15,0xffeff47d)
d=II(b,c,d,a,M1,21,0x85845dd1)
a=II(a,b,c,d,M8,6,0x6fa87e4f)
b=II(d,a,b,c,M15,10,0xfe2ce6e0)
c=II(c,d,a,b,M6,15,0xa3014314)
d=II(b,c,d,a,M13,21,0x4e0811a1)
a=II(a,b,c,d,M4,6,0xf7537e82)
b=II(d,a,b,c,M11,10,0xbd3af235)
c=II(c,d,a,b,M2,15,0x2ad7d2bb)
d=II(b,c,d,a,M9,21,0xeb86d391)

5) After each cycle, add a, b, c, d to A, B, C, D respectively, and then enter the next cycle.

If the above process is implemented with JAVA code, the code is as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
public class MD5 {

static final String hexs[]={"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
// Standard fantasy
private static final long A=0x67452301L;
private static final long B=0xefcdab89L;
private static final long C=0x98badcfeL;
private static final long D=0x10325476L;


// The following S11-S44 is actually a 4*4 matrix, which is used in the four-wheel loop operation
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;

// Java does not support unsigned basic data (UNSIGNED)
private long [] result={A,B,C,D};// Storage of Hash results, 4 × 32 = 128 bits, the initialization value is (phantom level couplet)

public static void main(String []args){
MD5 md=new MD5();
System.out.println("md5(abc)="+md.digest("abc"));
}

private String digest(String inputStr){
byte [] inputBytes=inputStr.getBytes();
int byteLen=inputBytes.length;// Length (byte)
int groupCount=0;// The number of complete groups
groupCount=byteLen/64;// 512 bits per group (64 bytes)
long []groups=null;// The 16 groups (4 bytes) after each group (64 bytes) are subdivided into subdivision (4 bytes)

// Treatment each complete group
for(int step=0;step<groupCount;step++){
groups=divGroup(inputBytes,step*64);
trans(groups);// Processing group, core algorithm
}

// Tail after processing the full group
int rest=byteLen%64;// The remaining number after 512 groups
byte [] tempBytes=new byte[64];
if(rest<=56){
for(int i=0;i<rest;i++)
tempBytes[i]=inputBytes[byteLen-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)(byteLen<<3);
for(int i=0;i<8;i++){
tempBytes[56+i]=(byte)(len&0xFFL);
len=len>>8;
}
groups=divGroup(tempBytes,0);
trans(groups);// Processing group
}else{
for(int i=0;i<rest;i++)
tempBytes[i]=inputBytes[byteLen-rest+i];
tempBytes[rest]=(byte)(1<<7);
for(int i=rest+1;i<64;i++)
tempBytes[i]=0;
groups=divGroup(tempBytes,0);
trans(groups);// Processing group

for(int i=0;i<56;i++)
tempBytes[i]=0;
long len=(long)(byteLen<<3);
for(int i=0;i<8;i++){
tempBytes[56+i]=(byte)(len&0xFFL);
len=len>>8;
}
groups=divGroup(tempBytes,0);
trans(groups);// Processing group
}

// Convert the hash value into 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;
}

/**
* Start with 512 bits from the index of InputBytes as a new group
* Divide each 512 -bit group into 16 groups, 64 -bit (8 bytes) per group (8 bytes) per group
* @param inputBytes
* @param index
* @return
*/
private static long[] divGroup(byte[] inputBytes,int index){
long [] temp=new long[16];
for(int i=0;i<16;i++){
temp[i]=b2iu(inputBytes[4*i+index])|
(b2iu(inputBytes[4*i+1+index]))<<8|
(b2iu(inputBytes[4*i+2+index]))<<16|
(b2iu(inputBytes[4*i+3+index]))<<24;
}
return temp;
}

/**
* At this time, there is no symbolic bit (symbolic storage is no longer a positive and negative), so you need to deal with it
* @param b
* @return
*/
public static long b2iu(byte b){
return b < 0 ? b & 0x7F + 128 : b;
}

/**
* The main operation, the four -wheel loop
* @param groups[]--Each group 512 -bit (64 bytes)
*/
private void trans(long[] groups) {
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); /* 1 */
d = FF(d, a, b, c, groups[1], S12, 0xe8c7b756L); /* 2 */
c = FF(c, d, a, b, groups[2], S13, 0x242070dbL); /* 3 */
b = FF(b, c, d, a, groups[3], S14, 0xc1bdceeeL); /* 4 */
a = FF(a, b, c, d, groups[4], S11, 0xf57c0fafL); /* 5 */
d = FF(d, a, b, c, groups[5], S12, 0x4787c62aL); /* 6 */
c = FF(c, d, a, b, groups[6], S13, 0xa8304613L); /* 7 */
b = FF(b, c, d, a, groups[7], S14, 0xfd469501L); /* 8 */
a = FF(a, b, c, d, groups[8], S11, 0x698098d8L); /* 9 */
d = FF(d, a, b, c, groups[9], S12, 0x8b44f7afL); /* 10 */
c = FF(c, d, a, b, groups[10], S13, 0xffff5bb1L); /* 11 */
b = FF(b, c, d, a, groups[11], S14, 0x895cd7beL); /* 12 */
a = FF(a, b, c, d, groups[12], S11, 0x6b901122L); /* 13 */
d = FF(d, a, b, c, groups[13], S12, 0xfd987193L); /* 14 */
c = FF(c, d, a, b, groups[14], S13, 0xa679438eL); /* 15 */
b = FF(b, c, d, a, groups[15], S14, 0x49b40821L); /* 16 */

/*second round*/
a = GG(a, b, c, d, groups[1], S21, 0xf61e2562L); /* 17 */
d = GG(d, a, b, c, groups[6], S22, 0xc040b340L); /* 18 */
c = GG(c, d, a, b, groups[11], S23, 0x265e5a51L); /* 19 */
b = GG(b, c, d, a, groups[0], S24, 0xe9b6c7aaL); /* 20 */
a = GG(a, b, c, d, groups[5], S21, 0xd62f105dL); /* 21 */
d = GG(d, a, b, c, groups[10], S22, 0x2441453L); /* 22 */
c = GG(c, d, a, b, groups[15], S23, 0xd8a1e681L); /* 23 */
b = GG(b, c, d, a, groups[4], S24, 0xe7d3fbc8L); /* 24 */
a = GG(a, b, c, d, groups[9], S21, 0x21e1cde6L); /* 25 */
d = GG(d, a, b, c, groups[14], S22, 0xc33707d6L); /* 26 */
c = GG(c, d, a, b, groups[3], S23, 0xf4d50d87L); /* 27 */
b = GG(b, c, d, a, groups[8], S24, 0x455a14edL); /* 28 */
a = GG(a, b, c, d, groups[13], S21, 0xa9e3e905L); /* 29 */
d = GG(d, a, b, c, groups[2], S22, 0xfcefa3f8L); /* 30 */
c = GG(c, d, a, b, groups[7], S23, 0x676f02d9L); /* 31 */
b = GG(b, c, d, a, groups[12], S24, 0x8d2a4c8aL); /* 32 */

/*Third round*/
a = HH(a, b, c, d, groups[5], S31, 0xfffa3942L); /* 33 */
d = HH(d, a, b, c, groups[8], S32, 0x8771f681L); /* 34 */
c = HH(c, d, a, b, groups[11], S33, 0x6d9d6122L); /* 35 */
b = HH(b, c, d, a, groups[14], S34, 0xfde5380cL); /* 36 */
a = HH(a, b, c, d, groups[1], S31, 0xa4beea44L); /* 37 */
d = HH(d, a, b, c, groups[4], S32, 0x4bdecfa9L); /* 38 */
c = HH(c, d, a, b, groups[7], S33, 0xf6bb4b60L); /* 39 */
b = HH(b, c, d, a, groups[10], S34, 0xbebfbc70L); /* 40 */
a = HH(a, b, c, d, groups[13], S31, 0x289b7ec6L); /* 41 */
d = HH(d, a, b, c, groups[0], S32, 0xeaa127faL); /* 42 */
c = HH(c, d, a, b, groups[3], S33, 0xd4ef3085L); /* 43 */
b = HH(b, c, d, a, groups[6], S34, 0x4881d05L); /* 44 */
a = HH(a, b, c, d, groups[9], S31, 0xd9d4d039L); /* 45 */
d = HH(d, a, b, c, groups[12], S32, 0xe6db99e5L); /* 46 */
c = HH(c, d, a, b, groups[15], S33, 0x1fa27cf8L); /* 47 */
b = HH(b, c, d, a, groups[2], S34, 0xc4ac5665L); /* 48 */

/*Fourth round*/
a = II(a, b, c, d, groups[0], S41, 0xf4292244L); /* 49 */
d = II(d, a, b, c, groups[7], S42, 0x432aff97L); /* 50 */
c = II(c, d, a, b, groups[14], S43, 0xab9423a7L); /* 51 */
b = II(b, c, d, a, groups[5], S44, 0xfc93a039L); /* 52 */
a = II(a, b, c, d, groups[12], S41, 0x655b59c3L); /* 53 */
d = II(d, a, b, c, groups[3], S42, 0x8f0ccc92L); /* 54 */
c = II(c, d, a, b, groups[10], S43, 0xffeff47dL); /* 55 */
b = II(b, c, d, a, groups[1], S44, 0x85845dd1L); /* 56 */
a = II(a, b, c, d, groups[8], S41, 0x6fa87e4fL); /* 57 */
d = II(d, a, b, c, groups[15], S42, 0xfe2ce6e0L); /* 58 */
c = II(c, d, a, b, groups[6], S43, 0xa3014314L); /* 59 */
b = II(b, c, d, a, groups[13], S44, 0x4e0811a1L); /* 60 */
a = II(a, b, c, d, groups[4], S41, 0xf7537e82L); /* 61 */
d = II(d, a, b, c, groups[11], S42, 0xbd3af235L); /* 62 */
c = II(c, d, a, b, groups[2], S43, 0x2ad7d2bbL); /* 63 */
b = II(b, c, d, a, groups[9], S44, 0xeb86d391L); /* 64 */

/*Add to the results of the previous calculations*/
result[0] += a;
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;
}

/**
* The following is a linear function to be used
*/
private static long F(long x, long y, long z) {
return (x & y) | ((~x) & z);
}

private static 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 static long I(long x, long y, long z) {
return y ^ (x | (~z));
}

private static 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 static 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 static 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 static 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);
}
}

JAVA implements MD5

It is very simple to implement MD5 in java. There is a class MessageDigest in the package java.security. The official document is as follows.
The MessageDigest class provides the application with the function of message digest algorithm, such as MD5 or SHA algorithm. A message digest is a secure one-way hash function that accepts data of any size and outputs a fixed-length hash value.

The MessageDigest object is initially initialized. This object manipulates the data by using the update method. The digest can be reset at any time by calling the reset method. Once all the data that needs to be updated has been updated, one of the digest methods should be called to complete the hash calculation.

The digest method can only be called once for a given amount of updated data. After digest is called, the MessageDigest object is reset to its initial state.

The JAVA code is as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import java.security.MessageDigest;

public class MyMD5 {

static char[] hex = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
public static void main(String[] args) {
try{
MessageDigest md5 = MessageDigest.getInstance("MD5");// Illustne of the use of the MD5 algorithm
md5.update("a".getBytes());//
System.out.println("md5(a)="+byte2str(md5.digest()));
md5.update("a".getBytes());
md5.update("bc".getBytes());
System.out.println("md5(abc)="+byte2str(md5.digest()));
}catch(Exception e){
e.printStackTrace();
}
}

/**
* Convert byte array to hexadecimal string
* @param bytes
* @return
*/
private static String byte2str(byte []bytes){
int len = bytes.length;
StringBuffer result = new StringBuffer();
for (int i = 0; i < len; i++) {
byte byte0 = bytes[i];
result.append(hex[byte0 >>> 4 & 0xf]);
result.append(hex[byte0 & 0xf]);
}
return result.toString();
}
}