зеркало из https://github.com/mozilla/watchdog.git
popups in visualizer, started similar password detection
This commit is contained in:
Родитель
1ea8a08b49
Коммит
735002ebae
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -0,0 +1,42 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Secure Hash Algorithm (SHA1)
|
||||||
|
* http://www.webtoolkit.info/
|
||||||
|
*
|
||||||
|
* minified, obviously.
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
function SHA1(msg){function rotate_left(n,s){var t4=(n<<s)|(n>>>(32-s));
|
||||||
|
return t4;};function lsb_hex(val){var str="";var i;var vh;var vl;for(i=0;i<=6;
|
||||||
|
i+=2){vh=(val>>>(i*4+4))&0x0f;vl=(val>>>(i*4))&0x0f;str+=vh.toString(16)+
|
||||||
|
vl.toString(16);}return str;};function cvt_hex(val){var str="";var i;var v;
|
||||||
|
for(i=7;i>=0;i--){v=(val>>>(i*4))&0x0f;str+=v.toString(16);}return str;};
|
||||||
|
function Utf8Encode(string){string=string.replace(/\r\n/g,"\n");var utftext="";
|
||||||
|
for(var n=0;n<string.length;n++){var c=string.charCodeAt(n);if(c<128){utftext
|
||||||
|
+=String.fromCharCode(c);}else if((c>127)&&(c<2048)){utftext+=
|
||||||
|
String.fromCharCode((c>>6)|192);utftext+=String.fromCharCode((c&63)|128);
|
||||||
|
}else{utftext+=String.fromCharCode((c>>12)|224);utftext+=String.fromCharCode(
|
||||||
|
((c>>6)&63)|128);utftext+=String.fromCharCode((c&63)|128);}}return utftext;};
|
||||||
|
var blockstart;var i,j;var W=new Array(80);var H0=0x67452301;var H1=0xEFCDAB89;
|
||||||
|
var H2=0x98BADCFE;var H3=0x10325476;var H4=0xC3D2E1F0;var A,B,C,D,E;var temp;
|
||||||
|
msg=Utf8Encode(msg);var msg_len=msg.length;var word_array=new Array();for(i=0;
|
||||||
|
i<msg_len-3;i+=4){j=msg.charCodeAt(i)<<24|msg.charCodeAt(i+1)<<16|
|
||||||
|
msg.charCodeAt(i+2)<<8|msg.charCodeAt(i+3);word_array.push(j);}
|
||||||
|
switch(msg_len%4){case 0:i=0x080000000;break;case 1:i=msg.charCodeAt(
|
||||||
|
msg_len-1)<<24|0x0800000;break;case 2:i=msg.charCodeAt(msg_len-2)<<24|
|
||||||
|
msg.charCodeAt(msg_len-1)<<16|0x08000;break;case 3:i=msg.charCodeAt(msg_len
|
||||||
|
-3)<<24|msg.charCodeAt(msg_len-2)<<16|msg.charCodeAt(msg_len-1)<<8|0x80;break;}
|
||||||
|
word_array.push(i);while((word_array.length%16)!=14)word_array.push(0);
|
||||||
|
word_array.push(msg_len>>>29);word_array.push((msg_len<<3)&0x0ffffffff);
|
||||||
|
for(blockstart=0;blockstart<word_array.length;blockstart+=16){for(i=0;i<16;i++)W[i]=word_array[blockstart+i];for(i=16;i<=79;i++)
|
||||||
|
W[i]=rotate_left(W[i-3]^W[i-8]^W[i-14]^W[i-16],1);A=H0;B=H1;C=H2;D=H3;E=H4;
|
||||||
|
for(i=0;i<=19;i++){temp=(rotate_left(A,5)+((B&C)|(~B&D))+E+W[i]+0x5A827999)
|
||||||
|
&0x0ffffffff;E=D;D=C;C=rotate_left(B,30);B=A;A=temp;}for(i=20;i<=39;i++)
|
||||||
|
{temp=(rotate_left(A,5)+(B^C^D)+E+W[i]+0x6ED9EBA1)&0x0ffffffff;E=D;D=C;C=
|
||||||
|
rotate_left(B,30);B=A;A=temp;}for(i=40;i<=59;i++){temp=(rotate_left(A,5)+
|
||||||
|
((B&C)|(B&D)|(C&D))+E+W[i]+0x8F1BBCDC)&0x0ffffffff;E=D;D=C;C=rotate_left(B,
|
||||||
|
30);B=A;A=temp;}for(i=60;i<=79;i++){temp=(rotate_left(A,5)+(B^C^D)+E+W[i]
|
||||||
|
+0xCA62C1D6)&0x0ffffffff;E=D;D=C;C=rotate_left(B,30);B=A;A=temp;}H0=(H0+A)
|
||||||
|
&0x0ffffffff;H1=(H1+B)&0x0ffffffff;H2=(H2+C)&0x0ffffffff;H3=(H3+D)&0x0ffffffff;
|
||||||
|
H4=(H4+E)&0x0ffffffff;}temp=cvt_hex(H0)+cvt_hex(H1)+cvt_hex(H2)+cvt_hex(
|
||||||
|
H3)+cvt_hex(H4);return temp.toLowerCase();}
|
|
@ -16,7 +16,7 @@ function init() {
|
||||||
|
|
||||||
function startViz() {
|
function startViz() {
|
||||||
var force = d3.layout.force()
|
var force = d3.layout.force()
|
||||||
.charge(-60)
|
.charge(-100)
|
||||||
.nodes(loginData.nodes)
|
.nodes(loginData.nodes)
|
||||||
.links(loginData.links)
|
.links(loginData.links)
|
||||||
.size([800, 600])
|
.size([800, 600])
|
||||||
|
@ -38,15 +38,25 @@ function startViz() {
|
||||||
.attr("class", "node")
|
.attr("class", "node")
|
||||||
.attr("cx", function(d) { return d.x; })
|
.attr("cx", function(d) { return d.x; })
|
||||||
.attr("cy", function(d) { return d.y; })
|
.attr("cy", function(d) { return d.y; })
|
||||||
.attr("r", 5)
|
.attr("r", function(n) {
|
||||||
|
if (n.group == 1)
|
||||||
|
return 5;
|
||||||
|
return 7;
|
||||||
|
})
|
||||||
.style("fill", function(d) { return fill(d.group); })
|
.style("fill", function(d) { return fill(d.group); })
|
||||||
.call(force.drag);
|
.call(force.drag);
|
||||||
|
|
||||||
|
|
||||||
|
node.on("mouseover", mouseOver);
|
||||||
|
|
||||||
|
node.on("mouseout", function(e) {
|
||||||
|
$('.infoPopup').hide();
|
||||||
|
});
|
||||||
|
|
||||||
node.append("svg:text").text(function(d) { return "hey"; });
|
// node.append("svg:text").text(function(d) { return "hey"; });
|
||||||
|
//
|
||||||
node.append("svg:title")
|
// node.append("svg:title")
|
||||||
.text(function(d) { return d.name; });
|
// .text(function(d) { return d.name; });
|
||||||
|
|
||||||
vis.style("opacity", 1e-6)
|
vis.style("opacity", 1e-6)
|
||||||
.transition()
|
.transition()
|
||||||
|
@ -62,6 +72,85 @@ function startViz() {
|
||||||
node.attr("cx", function(d) { return d.x; })
|
node.attr("cx", function(d) { return d.x; })
|
||||||
.attr("cy", function(d) { return d.y; });
|
.attr("cy", function(d) { return d.y; });
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawPasswordHash(canvas,password) {
|
||||||
|
var hashedPassword = SHA1(password);
|
||||||
|
|
||||||
|
var ctx = canvas.getContext('2d');
|
||||||
|
clearCanvas(canvas);
|
||||||
|
|
||||||
|
for (var bandX = 0; bandX < 6; bandX++) {
|
||||||
|
ctx.fillStyle = '#' + hashedPassword.substr(bandX*6,6);
|
||||||
|
ctx.fillRect(canvas.width/6*bandX,0,canvas.width/6,canvas.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function mouseOver(e) {
|
||||||
|
$('.infoPopup').css('left',e.x + 20);
|
||||||
|
$('.infoPopup').css('top',e.y);
|
||||||
|
|
||||||
|
if (e.group == 0) {
|
||||||
|
$('#obfuscatePassword').html(obfuscatePassword(e.name));
|
||||||
|
// $('#passwordStrength').html(passwordStrength(e.name).score);
|
||||||
|
$('#passwordInfo').show();
|
||||||
|
drawPasswordStrength($('#passwordStrengthCanvas').get()[0],passwordStrength(e.name));
|
||||||
|
drawPasswordHash($('#passwordHashCanvas').get()[0],e.name);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('#siteInfo').html(e.name).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearCanvas(canvas) {
|
||||||
|
var canvasCtx = canvas.getContext('2d');
|
||||||
|
canvasCtx.fillStyle="#ffffff";
|
||||||
|
canvasCtx.lineStyle="#ffffff";
|
||||||
|
canvasCtx.fillRect(0,0,canvas.width,canvas.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawPasswordStrength(canvas,strength) {
|
||||||
|
var ctx = canvas.getContext('2d');
|
||||||
|
clearCanvas(canvas);
|
||||||
|
ctx.lineStyle="#000000";
|
||||||
|
for (var boxX = 0; boxX < strength.max; boxX++) {
|
||||||
|
if (boxX < strength.score)
|
||||||
|
ctx.fillStyle="#ff0000";
|
||||||
|
else
|
||||||
|
ctx.fillStyle="#ffffff";
|
||||||
|
ctx.fillRect(boxX/strength.max*canvas.width,0,canvas.width/strength.max,canvas.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function passwordStrength(password) {
|
||||||
|
var securityRating = 1;
|
||||||
|
// Over 6 characters?
|
||||||
|
if (password.length > 6)
|
||||||
|
securityRating += 1;
|
||||||
|
// Over 10 characters?
|
||||||
|
if (password.length > 10)
|
||||||
|
securityRating += 1;
|
||||||
|
// Mixed case?
|
||||||
|
if (password.toLowerCase() != password)
|
||||||
|
securityRating += 1;
|
||||||
|
// Numeric characters?
|
||||||
|
for (var passwordCharIdx in password) {
|
||||||
|
if (parseFloat(password[passwordCharIdx]) != NaN) {
|
||||||
|
securityRating += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
score: securityRating,
|
||||||
|
max: 5
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function obfuscatePassword(password) {
|
||||||
|
var obfuscatePassword = password[0];
|
||||||
|
for (var x = 0; x < password.length-2; x++)
|
||||||
|
obfuscatePassword += '*';
|
||||||
|
obfuscatePassword += password[password.length-1];
|
||||||
|
return obfuscatePassword;
|
||||||
}
|
}
|
|
@ -1,18 +1,55 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<style>
|
<style>
|
||||||
|
body {
|
||||||
|
/* background-color:#000000;*/
|
||||||
|
}
|
||||||
#paper {
|
#paper {
|
||||||
width:100%;
|
width:100%;
|
||||||
height:100%;
|
height:100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#passwordStrengthContainer {
|
||||||
|
border:1px solid;
|
||||||
|
height:10px;
|
||||||
|
}
|
||||||
|
#passwordStrengthCanvas {
|
||||||
|
width:60px;
|
||||||
|
height:10px;
|
||||||
|
}
|
||||||
|
#passwordHashCanvas {
|
||||||
|
width:200px;
|
||||||
|
height:15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infoPopup {
|
||||||
|
display:none;
|
||||||
|
position:absolute;
|
||||||
|
background-color:#ffffff;
|
||||||
|
border:2px dashed;
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<script src="js/d3.min.js" type="text/javascript"></script>
|
<script src="js/d3.min.js" type="text/javascript"></script>
|
||||||
<script src="js/d3.geom.min.js" type="text/javascript"></script>
|
<script src="js/d3.geom.min.js" type="text/javascript"></script>
|
||||||
<script src="js/d3.layout.min.js" type="text/javascript"></script>
|
<script src="js/d3.layout.min.js" type="text/javascript"></script>
|
||||||
|
<script src="js/jquery-1.6.2.min.js" type="text/javascript"></script>
|
||||||
|
<script src="js/sha1.js" type="text/javascript"></script>
|
||||||
|
|
||||||
<script src="js/view_passwords.js" type="text/javascript"></script>
|
<script src="js/view_passwords.js" type="text/javascript"></script>
|
||||||
</head>
|
</head>
|
||||||
<body onload="init();">
|
<body onload="init();">
|
||||||
<div id="chart">
|
<div id="chart">
|
||||||
</div>
|
</div>
|
||||||
|
<div id="siteInfo" class="infoPopup"></div>
|
||||||
|
<div id="passwordInfo" class="infoPopup">
|
||||||
|
<div id="passwordHash">
|
||||||
|
<canvas id="passwordHashCanvas"></canvas>
|
||||||
|
</div>
|
||||||
|
<div id="obfuscatePassword"></div>
|
||||||
|
<div id="passwordStrength">
|
||||||
|
Strength: <span id="passwordStrengthContainer"><canvas id="passwordStrengthCanvas"></canvas></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
84
lib/main.js
84
lib/main.js
|
@ -11,7 +11,7 @@ var widget = widgets.Widget({
|
||||||
label: "Mozilla website",
|
label: "Mozilla website",
|
||||||
contentURL: dataDir.url("lock_blue.png"),
|
contentURL: dataDir.url("lock_blue.png"),
|
||||||
onClick: function() {
|
onClick: function() {
|
||||||
tabs.open(dataDir.url("view_passwords.html"));
|
openPasswordVisualizer();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -25,6 +25,13 @@ require("page-mod").PageMod({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function openPasswordVisualizer() {
|
||||||
|
tabs.open(dataDir.url("view_passwords.html"));
|
||||||
|
}
|
||||||
|
|
||||||
|
openPasswordVisualizer();
|
||||||
|
console.log(detectSimilarPasswords(getLoginsTable()));
|
||||||
|
|
||||||
function getLoginsTable() {
|
function getLoginsTable() {
|
||||||
var logins = loginManager.getAllLogins();
|
var logins = loginManager.getAllLogins();
|
||||||
var loginsTable = {};
|
var loginsTable = {};
|
||||||
|
@ -34,27 +41,30 @@ function getLoginsTable() {
|
||||||
loginsTable[loginInfo.password] = [];
|
loginsTable[loginInfo.password] = [];
|
||||||
loginsTable[loginInfo.password].push(loginInfo.hostname);
|
loginsTable[loginInfo.password].push(loginInfo.hostname);
|
||||||
}
|
}
|
||||||
|
return loginsTable; //obfuscateLoginsTable(loginsTable);
|
||||||
|
|
||||||
return fubarLoginsTable(loginsTable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function fubarLoginsTable(loginsTable) {
|
function obfuscateLoginsTable(loginsTable) {
|
||||||
var fubarTable = {};
|
var obfuscateTable = {};
|
||||||
|
|
||||||
// Fubar passwords
|
// obfuscate passwords
|
||||||
for (var password in loginsTable) {
|
for (var password in loginsTable) {
|
||||||
var fubarPassword = password[0];
|
var obfuscatedPassword = obfuscatePassword(loginsTable[password]);
|
||||||
for (var x = 0; x < password.length-2; x++)
|
|
||||||
fubarPassword += '*';
|
|
||||||
fubarPassword += password[password.length-1];
|
|
||||||
// Resolve any collisions by taking on *'s
|
// Resolve any collisions by taking on *'s
|
||||||
while (fubarTable[fubarPassword])
|
while (obfuscateTable[obfuscatedPassword])
|
||||||
fubarPassword += '*'
|
obfuscatedPassword += '*'
|
||||||
fubarTable[fubarPassword] = loginsTable[password];
|
obfuscateTable[obfuscatedPassword] = loginsTable[password];
|
||||||
}
|
}
|
||||||
|
|
||||||
return fubarTable;
|
return obfuscateTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
function obfuscatePassword(password) {
|
||||||
|
var obfuscatePassword = password[0];
|
||||||
|
for (var x = 0; x < password.length-2; x++)
|
||||||
|
obfuscatePassword += '*';
|
||||||
|
obfuscatePassword += password[password.length-1];
|
||||||
|
return obfuscatePassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getLoginsJSON() {
|
function getLoginsJSON() {
|
||||||
|
@ -85,5 +95,49 @@ function getLoginsJSON() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function detectSimilarPasswords(loginsTable) {
|
||||||
|
var passwordsChecked = [];
|
||||||
|
var similarPasswordPairs = [];
|
||||||
|
|
||||||
|
for (var password1 in loginsTable) {
|
||||||
|
for (var password2 in loginsTable) {
|
||||||
|
if (password1 == password2)
|
||||||
|
continue;
|
||||||
|
if (passwordsChecked.indexOf(password2) != -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (levenshtein(password1,password2) < Math.max(password1.length,password2.length)/2)
|
||||||
|
similarPasswordPairs.push([password1,password2]);
|
||||||
|
}
|
||||||
|
passwordsChecked.push(password1);
|
||||||
|
}
|
||||||
|
return similarPasswordPairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Thanks, http://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#JavaScript
|
||||||
|
function levenshtein(str1, str2) {
|
||||||
|
var l1 = str1.length, l2 = str2.length;
|
||||||
|
if (Math.min(l1, l2) === 0) {
|
||||||
|
return Math.max(l1, l2);
|
||||||
|
}
|
||||||
|
var i = 0, j = 0, d = [];
|
||||||
|
for (i = 0 ; i <= l1 ; i++) {
|
||||||
|
d[i] = [];
|
||||||
|
d[i][0] = i;
|
||||||
|
}
|
||||||
|
for (j = 0 ; j <= l2 ; j++) {
|
||||||
|
d[0][j] = j;
|
||||||
|
}
|
||||||
|
for (i = 1 ; i <= l1 ; i++) {
|
||||||
|
for (j = 1 ; j <= l2 ; j++) {
|
||||||
|
d[i][j] = Math.min(
|
||||||
|
d[i - 1][j] + 1,
|
||||||
|
d[i][j - 1] + 1,
|
||||||
|
d[i - 1][j - 1] + (str1.charAt(i - 1) === str2.charAt(j - 1) ? 0 : 1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return d[l1][l2];
|
||||||
|
}
|
||||||
|
|
||||||
console.log("The add-on is running.");
|
console.log("The add-on is running.");
|
Загрузка…
Ссылка в новой задаче