зеркало из 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() {
|
||||
var force = d3.layout.force()
|
||||
.charge(-60)
|
||||
.charge(-100)
|
||||
.nodes(loginData.nodes)
|
||||
.links(loginData.links)
|
||||
.size([800, 600])
|
||||
|
@ -38,15 +38,25 @@ function startViz() {
|
|||
.attr("class", "node")
|
||||
.attr("cx", function(d) { return d.x; })
|
||||
.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); })
|
||||
.call(force.drag);
|
||||
|
||||
|
||||
node.append("svg:text").text(function(d) { return "hey"; });
|
||||
node.on("mouseover", mouseOver);
|
||||
|
||||
node.append("svg:title")
|
||||
.text(function(d) { return d.name; });
|
||||
node.on("mouseout", function(e) {
|
||||
$('.infoPopup').hide();
|
||||
});
|
||||
|
||||
// node.append("svg:text").text(function(d) { return "hey"; });
|
||||
//
|
||||
// node.append("svg:title")
|
||||
// .text(function(d) { return d.name; });
|
||||
|
||||
vis.style("opacity", 1e-6)
|
||||
.transition()
|
||||
|
@ -62,6 +72,85 @@ function startViz() {
|
|||
node.attr("cx", function(d) { return d.x; })
|
||||
.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>
|
||||
<head>
|
||||
<style>
|
||||
body {
|
||||
/* background-color:#000000;*/
|
||||
}
|
||||
#paper {
|
||||
width: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>
|
||||
<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.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>
|
||||
</head>
|
||||
<body onload="init();">
|
||||
<div id="chart">
|
||||
</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>
|
||||
</html>
|
84
lib/main.js
84
lib/main.js
|
@ -11,7 +11,7 @@ var widget = widgets.Widget({
|
|||
label: "Mozilla website",
|
||||
contentURL: dataDir.url("lock_blue.png"),
|
||||
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() {
|
||||
var logins = loginManager.getAllLogins();
|
||||
var loginsTable = {};
|
||||
|
@ -34,27 +41,30 @@ function getLoginsTable() {
|
|||
loginsTable[loginInfo.password] = [];
|
||||
loginsTable[loginInfo.password].push(loginInfo.hostname);
|
||||
}
|
||||
|
||||
|
||||
return fubarLoginsTable(loginsTable);
|
||||
return loginsTable; //obfuscateLoginsTable(loginsTable);
|
||||
}
|
||||
|
||||
function fubarLoginsTable(loginsTable) {
|
||||
var fubarTable = {};
|
||||
function obfuscateLoginsTable(loginsTable) {
|
||||
var obfuscateTable = {};
|
||||
|
||||
// Fubar passwords
|
||||
// obfuscate passwords
|
||||
for (var password in loginsTable) {
|
||||
var fubarPassword = password[0];
|
||||
for (var x = 0; x < password.length-2; x++)
|
||||
fubarPassword += '*';
|
||||
fubarPassword += password[password.length-1];
|
||||
var obfuscatedPassword = obfuscatePassword(loginsTable[password]);
|
||||
// Resolve any collisions by taking on *'s
|
||||
while (fubarTable[fubarPassword])
|
||||
fubarPassword += '*'
|
||||
fubarTable[fubarPassword] = loginsTable[password];
|
||||
while (obfuscateTable[obfuscatedPassword])
|
||||
obfuscatedPassword += '*'
|
||||
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() {
|
||||
|
@ -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.");
|
Загрузка…
Ссылка в новой задаче