-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.js
100 lines (93 loc) · 2.82 KB
/
app.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
// Define constants
const NUMBERS = "0123456789"
const UPPERCASED = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
const LOWERCASED = "abcdefghijklmnopqrstuvwxyz"
const SPECIALS = "!$-+,.#@"
const STANDARD_CHARSET = `${NUMBERS}${UPPERCASED}${LOWERCASED}`
const EXTENDED_CHARSET = `${STANDARD_CHARSET}${SPECIALS}`
const pickChar = charset => code => charset[code % charset.length]
// Hashing algorithm
const pw3 = (service_, salt_, pwLength, special) => {
const pwChar = pickChar(special ? EXTENDED_CHARSET : STANDARD_CHARSET)
let service = service_.toString()
if (service.length === 1) {
service += pwChar(service.charCodeAt())
}
let salt = salt_.toString()
if (
!((salt.length + 1) % service.length && service.length % (salt.length + 1))
) {
salt += pwChar(salt.length + service.length)
}
let sum = 0
for (let j = 0; j < service.length; j++) {
sum += service.charCodeAt(j)
}
for (let k = 0; k < salt.length; k++) {
sum += salt.charCodeAt(k)
}
const jOffset = sum % service.length
const kOffset = sum % (salt.length + 1)
const pwArr = []
for (
let i = 0;
!(i >= pwLength && i >= service.length && i >= salt.length + 1);
i++
) {
const innerSalt = salt + pwChar(i)
// Service & salt offsets:
const j = (i + jOffset) % service.length
const k = (i + kOffset) % innerSalt.length
// eslint-disable-next-line max-len
pwArr[i % pwLength] =
(pwArr[i % pwLength] || 0) +
i +
service.charCodeAt(j) ** 2 +
innerSalt.charCodeAt(k) ** 2
}
const password = pwArr.reduce((prev, item) => prev + pwChar(item), "")
return password
}
const testFor = char => charsArray => (charsArray.indexOf(char) === -1 ? 0 : 1)
// Rehashing password to match needed conditions
export const getRecurrPw = (
{service = "", salt = "", pwLength = 0, special = false},
callback
) => {
const password = pw3(service, salt, pwLength, special)
let upperCasedCount = 0
let lowerCasedCount = 0
let numbersCount = 0
let specialsCount = 0
for (let index = 0; index < password.length; index++) {
const testIn = testFor(password[index])
numbersCount += testIn(NUMBERS)
upperCasedCount += testIn(UPPERCASED)
lowerCasedCount += testIn(LOWERCASED)
specialsCount += testIn(SPECIALS)
}
const goodPassword =
numbersCount >= 2 &&
upperCasedCount >= 1 &&
lowerCasedCount >= 1 &&
(!special || specialsCount >= 1)
return goodPassword
? callback(password)
: getRecurrPw(
{
service: password,
salt,
pwLength,
special,
},
callback
)
}
export const inputAdapter = target => ({
pwLength: +target.passwordlength.value,
service: target.casesensitive.checked
? target.service.value
: target.service.value.toLowerCase(),
salt: target.masterpassword.value,
special: target.special.checked,
})