Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit889d9c3

Browse files
feat: Added MD5 hashing algorithm (TheAlgorithms#1519)
* feat: Added MD5 hashing algorithm* Added wiki link* Remove spam?* Fix extend towards end* Return Uint32Array in MD5 function* Preprocess function now works on uint arrays* chunkify U32Array instead of string* Remove all string related functions* Replace typed arrays with named variables* Fix "Replace typed arrays with named variables"* Return Uint8 Array in MD5 functionThe MD5 function now returns a uint8 array with the correct endianness.* Add tests* Fix docstrings* Introduce hexMD5 function* Change test string* Format test file
1 parentaebd52f commit889d9c3

File tree

2 files changed

+243
-0
lines changed

2 files changed

+243
-0
lines changed

‎Hashes/MD5.js

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
// Module that replicates the MD5 Cryptographic Hash
2+
// function in Javascript.
3+
4+
// main variables
5+
constS=[
6+
7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22,5,9,14,20,5,
7+
9,14,20,5,9,14,20,5,9,14,20,4,11,16,23,4,11,16,23,4,11,
8+
16,23,4,11,16,23,6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,
9+
21
10+
]
11+
12+
constK=[
13+
0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,0xf57c0faf,0x4787c62a,
14+
0xa8304613,0xfd469501,0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be,
15+
0x6b901122,0xfd987193,0xa679438e,0x49b40821,0xf61e2562,0xc040b340,
16+
0x265e5a51,0xe9b6c7aa,0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,
17+
0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,0xa9e3e905,0xfcefa3f8,
18+
0x676f02d9,0x8d2a4c8a,0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c,
19+
0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70,0x289b7ec6,0xeaa127fa,
20+
0xd4ef3085,0x04881d05,0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,
21+
0xf4292244,0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,
22+
0xffeff47d,0x85845dd1,0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1,
23+
0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391
24+
]
25+
26+
/**
27+
* Separates an array into equal sized chunks
28+
*
29+
*@param {Array|string} array - array or string to separate into chunks
30+
*@param {number} size - number of elements wanted in each chunk
31+
*@return {Array} - array of original array split into chunks
32+
*
33+
*@example
34+
* chunkify("this is a test", 2)
35+
*/
36+
functionchunkify(array,size){
37+
constchunks=[]
38+
for(leti=0;i<array.length;i+=size){
39+
chunks.push(array.slice(i,i+size))
40+
}
41+
returnchunks
42+
}
43+
44+
/**
45+
* Rotates the bits to the left
46+
*
47+
*@param {number} bits - 32 bit number
48+
*@param {number} turns - number of rotations to make
49+
*@return {number} - number after bits rotation
50+
*
51+
*@example
52+
* rotateLeft(0b1011, 3); // 0b1011000
53+
*/
54+
functionrotateLeft(bits,turns){
55+
return(bits<<turns)|(bits>>>(32-turns))
56+
}
57+
58+
/**
59+
* Converts Uint8Array to Uint32Array
60+
*
61+
*@param {Uint8Array} u8Array Uint8Array to convert
62+
*@returns {Uint32Array} - Required Uint32Array
63+
*/
64+
functionu8ToU32(u8Array){
65+
constuint32Array=newUint32Array(u8Array.length/4)
66+
67+
for(leti=0;i<u8Array.length;i+=4){
68+
uint32Array[i/4]=
69+
(u8Array[i]|
70+
(u8Array[i+1]<<8)|
71+
(u8Array[i+2]<<16)|
72+
(u8Array[i+3]<<24))>>>
73+
0
74+
}
75+
76+
returnuint32Array
77+
}
78+
79+
/**
80+
* Converts Uint32Array to Uint8Array
81+
*
82+
*@param {Uint32Array} u32Array Uint32Array to convert
83+
*@returns {Uint8Array} - Required Uint8Array
84+
*/
85+
functionu32ToU8(u32Array){
86+
constuint8Array=newUint8Array(u32Array.length*4)
87+
88+
for(leti=0;i<u32Array.length;i++){
89+
uint8Array[i*4]=u32Array[i]&0xff
90+
uint8Array[i*4+1]=(u32Array[i]>>8)&0xff
91+
uint8Array[i*4+2]=(u32Array[i]>>16)&0xff
92+
uint8Array[i*4+3]=(u32Array[i]>>24)&0xff
93+
}
94+
95+
returnuint8Array
96+
}
97+
98+
/**
99+
* Adds padding to the end of the given array
100+
*
101+
*@param {Uint8Array} u8Array Array to pad
102+
*@param {number} size Resulting size of the array
103+
*/
104+
functionpadEnd(u8Array,size){
105+
constresult=newUint8Array(size)
106+
result.set(u8Array)
107+
result.fill(0,u8Array.length)
108+
109+
returnresult
110+
}
111+
112+
/**
113+
* Pre-processes message to feed the algorithm loop
114+
*
115+
*@param {Uint8Array} message - message to pre-process
116+
*@return {Uint32Array} - processed message
117+
*/
118+
functionpreProcess(message){
119+
// Extend message by adding '0'
120+
//
121+
// message.length + 1 is for adding '1' bit
122+
// 56 - (length % 64) is for padding with '0's
123+
// 8 is for appending 64 bit message length
124+
letm=padEnd(
125+
message,
126+
message.length+1+(56-((message.length+1)%64))+8
127+
)
128+
129+
// Add '1' bit at the end of the message
130+
m[message.length]=1<<7
131+
132+
// convert message to 32 bit uint array
133+
m=u8ToU32(m)
134+
135+
// Append the length of the message to the end
136+
// (ml / 0x100000000) | 0 is equivalent to (ml >> 32) & 0xffffffff) in other languages
137+
letml=message.length*8
138+
m[m.length-2]=ml&0xffffffff
139+
m[m.length-1]=(ml/0x100000000)|0
140+
141+
returnm
142+
}
143+
144+
/**
145+
* Hashes message using MD5 Cryptographic Hash Function
146+
*
147+
*@see
148+
* For more info: https://en.wikipedia.org/wiki/MD5
149+
*
150+
*@param {Uint8Array} message - message to hash
151+
*@return {Uint8Array} - message digest (hash value)
152+
*/
153+
functionMD5(message){
154+
// Initialize variables:
155+
let[a0,b0,c0,d0]=[
156+
0x67452301>>>0,
157+
0xefcdab89>>>0,
158+
0x98badcfe>>>0,
159+
0x10325476>>>0
160+
]
161+
162+
// pre-process message and split into 512 bit chunks
163+
constwords=Array.from(preProcess(message))
164+
constchunks=chunkify(words,16)
165+
166+
chunks.forEach(function(chunk,_){
167+
// initialize variables for this chunk
168+
let[A,B,C,D]=[a0,b0,c0,d0]
169+
170+
for(leti=0;i<64;i++){
171+
let[F,g]=[0,0]
172+
173+
if(i<=15){
174+
F=(B&C)|(~B&D)
175+
g=i
176+
}elseif(i<=31){
177+
F=(D&B)|(~D&C)
178+
g=(5*i+1)%16
179+
}elseif(i<=47){
180+
F=B^C^D
181+
g=(3*i+5)%16
182+
}else{
183+
F=C^(B|~D)
184+
g=(7*i)%16
185+
}
186+
187+
F=(F+A+K[i]+chunk[g])>>>0
188+
A=D
189+
D=C
190+
C=B
191+
B=((B+rotateLeft(F,S[i]))&0xffffffff)>>>0
192+
}
193+
194+
// add values for this chunk to main hash variables (unsigned)
195+
a0=(a0+A)>>>0
196+
b0=(b0+B)>>>0
197+
c0=(c0+C)>>>0
198+
d0=(d0+D)>>>0
199+
})
200+
201+
returnu32ToU8([a0,b0,c0,d0])
202+
}
203+
204+
// export MD5 function
205+
export{MD5}

‎Hashes/tests/MD5.test.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import{MD5}from'../MD5'
2+
3+
/**
4+
* Returns the MD5 hash of the given message as a hexadecimal string
5+
*
6+
*@param {Uint8Array} message - message to hash
7+
*@return {string} - hash as a hexadecimal string
8+
*/
9+
functionhexMD5(message){
10+
returnArray.from(MD5(message),(byte)=>
11+
byte.toString(16).padStart(2,'0')
12+
).join('')
13+
}
14+
15+
describe('Testing MD5 function',()=>{
16+
it('should return the correct hash for "The quick brown fox jumps over the lazy dog"',()=>{
17+
constinput=newTextEncoder().encode(
18+
'The quick brown fox jumps over the lazy dog'
19+
)
20+
consthash=hexMD5(input)
21+
22+
expect(hash).toBe('9e107d9d372bb6826bd81d3542a419d6')
23+
})
24+
25+
it('should return the correct hash for "JavaScript!"',()=>{
26+
constinput=newTextEncoder().encode('JavaScript!')
27+
consthash=hexMD5(input)
28+
29+
expect(hash).toBe('209eddd6b61af0643907a8e069a08fb8')
30+
})
31+
32+
it('should correctly hash an empty string',()=>{
33+
constinput=newTextEncoder().encode('')
34+
consthash=hexMD5(input)
35+
36+
expect(hash).toBe('d41d8cd98f00b204e9800998ecf8427e')
37+
})
38+
})

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp