Initial commit
This commit is contained in:
207
ewpass.js
Normal file
207
ewpass.js
Normal file
@@ -0,0 +1,207 @@
|
||||
var ewpass = {};
|
||||
|
||||
(function(ns) {
|
||||
const SEED_PREFIX = 'E. W. Password Generator Seed/';
|
||||
const DERIVE_PREFIX = 'Domain Password/';
|
||||
const Storage = window.localStorage;
|
||||
|
||||
const BASIC_MAP = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
||||
const EXTENDED_MAP = BASIC_MAP + '`~!@#$%^&*()-_=+[{]}\\|;:\'",<.>/?';
|
||||
|
||||
var settings = {
|
||||
'checksum': undefined,
|
||||
'DEFAULT': [ 16, 1, true ],
|
||||
'domains': {}
|
||||
};
|
||||
var currentDomain = undefined;
|
||||
var seedValid = false;
|
||||
|
||||
var checkSeedChecksum = () => {
|
||||
const valid = $('#checksum').text() === settings.checksum;
|
||||
|
||||
$('#chkok').html(valid ? '✓' : '✗');
|
||||
$('#chkset').prop('disabled', valid ? 'disabled' : '');
|
||||
|
||||
seedValid = valid;
|
||||
};
|
||||
|
||||
var setDomains = () => {
|
||||
$domainlist = $("#domainlist")
|
||||
|
||||
$domainlist.html('');
|
||||
for (domain in settings.domains) {
|
||||
$domainlist.append($('<option>').attr('value', domain).text(domain));
|
||||
}
|
||||
};
|
||||
|
||||
var calcRounds = l => {
|
||||
var m = 0xffffffff;
|
||||
var n = 0;
|
||||
|
||||
while (m > 0) {
|
||||
m = Math.floor(m / l);
|
||||
n++;
|
||||
}
|
||||
|
||||
return n;
|
||||
};
|
||||
|
||||
ns.resetSeed = () => {
|
||||
$('#seed').val('');
|
||||
$('#seed').prop('disabled', '');
|
||||
$('#checksum').text('-');
|
||||
$('#chkok').text('');
|
||||
$('#chkset').prop('disabled', 'disabled');
|
||||
|
||||
seedValid = false;
|
||||
|
||||
$('#seed').focus();
|
||||
};
|
||||
|
||||
ns.calculateSeed = () => {
|
||||
sha256(SEED_PREFIX + $('#seed').val()).then(hash => {
|
||||
$('#seed').val(hash);
|
||||
$('#seed').prop('disabled', 'disabled');
|
||||
$('#checksum').text(hash.substring(0, 2));
|
||||
checkSeedChecksum();
|
||||
});
|
||||
};
|
||||
|
||||
ns.storeSeedChecksum = () => {
|
||||
settings.checksum = $('#checksum').text();
|
||||
Storage.setItem('checksum', settings.checksum);
|
||||
checkSeedChecksum();
|
||||
};
|
||||
|
||||
ns.checkDomainInputMatchesToOption = () => {
|
||||
var domain = $('#domain').val();
|
||||
if (domain in settings.domains) {
|
||||
ns.loadSettingsForDomain(domain);
|
||||
}
|
||||
};
|
||||
|
||||
ns.loadSettingsForDomain = (domain) => {
|
||||
if (domain === undefined) {
|
||||
ns.loadSettingsForDomain($('#domain').val());
|
||||
return;
|
||||
}
|
||||
|
||||
var _settings;
|
||||
|
||||
if (domain === '') {
|
||||
$('#length').prop('disabled', 'disabled');
|
||||
$('#iteration').prop('disabled', 'disabled');
|
||||
$('#nextiter').prop('disabled', 'disabled');
|
||||
$('#extended').prop('disabled', 'disabled');
|
||||
$('#storedomain').prop('disabled', 'disabled');
|
||||
$('#docopy').prop('disabled', 'disabled');
|
||||
|
||||
_settings = settings.DEFAULT;
|
||||
} else if (domain in settings.domains) {
|
||||
_settings = settings.domains[domain];
|
||||
} else if (!confirm('Add new domain "' + domain + '" ?')) {
|
||||
$('#domain').val('');
|
||||
ns.loadSettingsForDomain('');
|
||||
return;
|
||||
} else {
|
||||
settings.domains[domain] = settings.DEFAULT.slice();
|
||||
setDomains();
|
||||
|
||||
_settings = settings.domains[domain];
|
||||
Storage.setItem('domains', JSON.stringify(settings.domains));
|
||||
}
|
||||
|
||||
$('#length').val(_settings[0]);
|
||||
$('#iteration').val(_settings[1]);
|
||||
$('#extended').prop('checked', _settings[2] ? 'checked' : '');
|
||||
|
||||
if (_settings !== settings.DEFAULT) {
|
||||
$('#length').prop('disabled', '');
|
||||
$('#iteration').prop('disabled', '');
|
||||
$('#nextiter').prop('disabled', '');
|
||||
$('#extended').prop('disabled', '');
|
||||
$('#storedomain').prop('disabled', '');
|
||||
$('#docopy').prop('disabled', '');
|
||||
|
||||
currentDomain = domain;
|
||||
}
|
||||
};
|
||||
|
||||
ns.storeSettingsForDomain = () => {
|
||||
_settings = [
|
||||
parseInt($('#length').val()),
|
||||
parseInt($('#iteration').val()),
|
||||
$('#extended').prop('checked')
|
||||
];
|
||||
|
||||
settings.domains[currentDomain] = _settings;
|
||||
Storage.setItem('domains', JSON.stringify(settings.domains));
|
||||
};
|
||||
|
||||
ns.nextIteration = () => {
|
||||
$('#iteration').val(parseInt($('#iteration').val()) + 1);
|
||||
ns.storeSettingsForDomain();
|
||||
};
|
||||
|
||||
ns.deriveAndCopyToClipboard = () => {
|
||||
if (!seedValid) {
|
||||
alert('Enter master password first!');
|
||||
ns.resetSeed();
|
||||
return;
|
||||
}
|
||||
|
||||
$docopy = $('#docopy');
|
||||
$docopy.prop('disabled', 'disabled');
|
||||
|
||||
sha256(DERIVE_PREFIX + $('#seed').val() + '/' + settings.domains[currentDomain][1] + '/' + currentDomain).then(hash => {
|
||||
const map = settings.domains[currentDomain][2] ? EXTENDED_MAP : BASIC_MAP;
|
||||
|
||||
const rounds = calcRounds(map.length);
|
||||
var pw = '';
|
||||
|
||||
for (var i = 0; i < 8; i++) {
|
||||
var x = parseInt(hash.substring(i * 8, (i+1) * 8), 16);
|
||||
for (var j = 0; j < rounds; j++) {
|
||||
pw += map.substring(x % map.length, x % map.length + 1);
|
||||
x = Math.floor(x / map.length);
|
||||
}
|
||||
}
|
||||
|
||||
pw = pw.substring(0, settings.domains[currentDomain][0]);
|
||||
|
||||
navigator.clipboard.writeText(pw).then(() => {
|
||||
$docopy.val('[ COPIED ]');
|
||||
setInterval(() => {
|
||||
$docopy.val('Copy password');
|
||||
$docopy.prop('disabled', '');
|
||||
}, 1500);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
ns.setup = () => {
|
||||
if (Storage.getItem('checksum') != null) {
|
||||
settings.checksum = Storage.getItem('checksum');
|
||||
}
|
||||
if (Storage.getItem('domains') != null) {
|
||||
settings.domains = JSON.parse(Storage.getItem('domains'));
|
||||
console.debug('Loaded domains:', settings.domains);
|
||||
setDomains();
|
||||
}
|
||||
|
||||
var setupReturnEvent = (o, handler) => {
|
||||
o.keypress((event, value) => {
|
||||
if (event.which === 13) {
|
||||
handler(o.val());
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
setupReturnEvent($('#seed'), ns.calculateSeed);
|
||||
setupReturnEvent($('#domain'), ns.loadSettingsForDomain);
|
||||
|
||||
ns.resetSeed();
|
||||
ns.loadSettingsForDomain();
|
||||
};
|
||||
|
||||
})(ewpass);
|
||||
72
index.html
Normal file
72
index.html
Normal file
@@ -0,0 +1,72 @@
|
||||
<html>
|
||||
<head>
|
||||
<script language="javascript" src="./jquery-3.4.1.min.js"></script>
|
||||
<script language="javascript" src="./sha256.js"></script>
|
||||
<script language="javascript" src="./ewpass.js"></script>
|
||||
</head>
|
||||
<body onload="ewpass.setup();">
|
||||
<center>
|
||||
<table border="0" cellspacing="10">
|
||||
<tr>
|
||||
<th>Master password: </th>
|
||||
<td>
|
||||
<table border="0" cellspacing="5">
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<input type="password" id="seed" size="46" autocomplete="off" /> <input type="button" id="clearseed" value="Clear" onclick="ewpass.resetSeed();" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Checksum: </td>
|
||||
<td><span id="chkok"></span> <span id="checksum"></span></td>
|
||||
<td><input type="button" id="chkset" value="Set" onclick="ewpass.storeSeedChecksum();" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Domain: </th>
|
||||
<td><input id="domain" list="domainlist" autocomplete="off" onchange="ewpass.checkDomainInputMatchesToOption();" /><datalist id="domainlist"></datalist></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Options: </th>
|
||||
<td>
|
||||
<table border="0" cellspacing="2">
|
||||
<tr>
|
||||
<td>Length: </td>
|
||||
<td><input id="length" value="12" size="2" autocomplete="off" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Iteration: </td>
|
||||
<td><input id="iteration" value="1" size="2" autocomplete="off" /> <input type="button" id="nextiter" value="Next" onclick="ewpass.nextIteration();" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<label><input type="checkbox" id="extended" checked="checked" /> Use special characters</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<input type="button" id="storedomain" value="Store" onclick="ewpass.storeSettingsForDomain();" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<center>
|
||||
<input type="button" id="docopy" value="Copy password" onclick="ewpass.deriveAndCopyToClipboard();" />
|
||||
</center>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
</body>
|
||||
</html>
|
||||
2
jquery-3.4.1.min.js
vendored
Normal file
2
jquery-3.4.1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user