popups in visualizer, started similar password detection

This commit is contained in:
Paul Sawaya 2011-08-26 14:13:51 -07:00
Родитель 1ea8a08b49
Коммит 735002ebae
5 изменённых файлов: 262 добавлений и 22 удалений

18
data/js/jquery-1.6.2.min.js поставляемый Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

42
data/js/sha1.js Normal file
Просмотреть файл

@ -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>

Просмотреть файл

@ -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.");