forked from donbowman/mautic-gmail-add-on
-
Notifications
You must be signed in to change notification settings - Fork 0
/
phpcrypt.js
188 lines (157 loc) · 5.29 KB
/
phpcrypt.js
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
(function () {
// Shortcuts
var C = CryptoJS;
var C_lib = C.lib;
var Base = C_lib.Base;
var WordArray = C_lib.WordArray;
var C_algo = C.algo;
var MD5 = C_algo.MD5;
var Utf8 = C.enc.Utf8;
// Constants
var SALT_MAXLEN = 8;
var MD5_MAGIC = "$1$";
var PHP_CRYPT_MD5 = C_algo.PHP_CRYPT_MD5 = Base.extend({
/**
* Initializes a newly created Password hashing function.
*
* @example
*
* var md5crypt = CryptoJS.algo.PHP_CRYPT_MD5.create();
*/
init: function () {
},
/**
* Computes the the PHP MD5 based crypt hash
*
* @param {WordArray|string} password The password.
* @param {string} salt A salt (this can be the output of the crypt
* function).
*
* @return {string} The password hash
*
* @example
*
* var hash = kdf.compute(password, salt);
*/
compute: function (password, salt) {
if (typeof password == 'string') {
password = Utf8.parse(password);
}
var saltStart = 0;
if(salt.indexOf(MD5_MAGIC) === 0) {
saltStart += MD5_MAGIC.length;
}
var saltEnd = Math.min(SALT_MAXLEN+MD5_MAGIC.length,
salt.indexOf("$", saltStart));
if(saltEnd < 0) {
saltEnd = SALT_MAXLEN + MD5_MAGIC.length;
}
var realSalt = salt.substring(saltStart, saltEnd);
var ctx = MD5.create();
ctx.update(password);
ctx.update(realSalt);
ctx.update(password);
var fin = ctx.finalize();
ctx.reset();
ctx.update(password);
ctx.update(MD5_MAGIC);
ctx.update(realSalt);
for(var pl = password.sigBytes; pl > 0; pl -= 16) {
var words = WordArray.create(
fin.words, Math.min(pl, 16)
);
ctx.update(words);
}
var empty = WordArray.create([0], 1);
var pwc1 = WordArray.create(password.words, 1);
for(var i = password.sigBytes; i !== 0; i >>>= 1) {
if((i & 1) !== 0) {
ctx.update(empty);
} else {
ctx.update(pwc1);
}
}
fin = ctx.finalize();
for(i = 0; i < 1000; ++i) {
ctx.reset();
if((i & 1) !== 0) {
ctx.update(password);
} else {
ctx.update(fin);
}
if((i % 3) !== 0) {
ctx.update(realSalt);
}
if((i % 7) !== 0) {
ctx.update(password);
}
if((i & 1) !== 0) {
ctx.update(fin);
} else {
ctx.update(password);
}
fin = ctx.finalize();
}
var finb = this.wordArrayToByteArray(fin);
var result = MD5_MAGIC + realSalt + "$" +
this.to64((finb[ 0] << 16) | (finb[ 6] << 8) | finb[12], 4) +
this.to64((finb[ 1] << 16) | (finb[ 7] << 8) | finb[13], 4) +
this.to64((finb[ 2] << 16) | (finb[ 8] << 8) | finb[14], 4) +
this.to64((finb[ 3] << 16) | (finb[ 9] << 8) | finb[15], 4) +
this.to64((finb[ 4] << 16) | (finb[10] << 8) | finb[ 5], 4) +
this.to64( finb[11], 2);
return result;
},
/**
* Converts a WordArray-object to an array of bytes. I'm surprised that
* this is not part of the CryptoJS library.
*
* @param {WordArray} wa The numeric value to be converted
*
* @return {array} The bytes contained in the WordArray object
*/
wordArrayToByteArray: function(wa) {
var bytes = [], words = wa.words;
for(var i = 0; i < wa.sigBytes; ++i) {
var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
bytes.push(bite);
}
return bytes;
},
/**
* Implements the to64-function used by the php_md5_crypt_r function.
*
* @param {number} v The numeric value to be converted
* @param {number} n The number of digits to return
*
* @return {string} The base64 digits.
*/
to64: function(v, n) {
var itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
"abcdefghijklmnopqrstuvwxyz";
var result = "";
while(--n >= 0) {
result += itoa64.charAt(v & 0x3f);
v >>= 6;
}
return result;
}
});
/**
* Computes the the PHP MD5 based crypt hash
*
* @param {WordArray|string} password The password.
* @param {string} salt A salt.
*
* @return {string} The password hash
*
* @static
*
* @example
*
* var hash = CryptoJS.PHP_CRYPT_MD5(password, salt);
*/
C.PHP_CRYPT_MD5 = function (password, salt) {
return PHP_CRYPT_MD5.create().compute(password, salt);
};
}());