Full JS : first pass, all seems to work execpt add/delete/update
This commit is contained in:
@@ -31,9 +31,11 @@ body {
|
||||
border-color:green;
|
||||
padding : 15px;
|
||||
margin : 15px;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
#user input {
|
||||
margin-left : 15px;
|
||||
margin-right : 30px;
|
||||
margin-top : 10px;
|
||||
margin-bottom : 10px;
|
||||
|
@@ -72,20 +72,219 @@ function a2hex(str) {
|
||||
return hex;
|
||||
}
|
||||
|
||||
function derive_mkey(user, mkey_target)
|
||||
function derive_mkey(user, mkey)
|
||||
{
|
||||
mkey_target = document.getElementById(mkey_target) ;
|
||||
mkey = mkey_target.value;
|
||||
|
||||
if (mkey.length == 0)
|
||||
{
|
||||
alert('Empty master key');
|
||||
return false;
|
||||
}
|
||||
|
||||
url = url_domain(document.URL) + "/" + user;
|
||||
mkey = a2hex(pkdbf2(mkey, url, 1000, 256/8));
|
||||
mkey_target.value = mkey;
|
||||
|
||||
return true;
|
||||
return mkey;
|
||||
}
|
||||
|
||||
var passwords;
|
||||
var current_user = "";
|
||||
var current_mkey = "";
|
||||
|
||||
function PasswordEntry (ciphered_login="", ciphered_password="") {
|
||||
this.ciphered_login = ciphered_login;
|
||||
this.ciphered_password = ciphered_password;
|
||||
this.unciphered = false;
|
||||
this.clear_url = "";
|
||||
this.clear_login = "";
|
||||
this.clear_password = "";
|
||||
this.masterkey = "";
|
||||
|
||||
this.decrypt = function(masterkey)
|
||||
{
|
||||
if (masterkey == this.masterkey && this.unciphered == true)
|
||||
return true;
|
||||
|
||||
if (masterkey == "" || this.unciphered == true)
|
||||
return false;
|
||||
|
||||
aes = new AES();
|
||||
a_masterkey = aes.init(hex2a(masterkey));
|
||||
login = aes.decryptLongString(hex2a(this.ciphered_login), a_masterkey);
|
||||
if (login.indexOf("@@") != 0)
|
||||
{
|
||||
aes.finish();
|
||||
return false;
|
||||
}
|
||||
// Remove @@
|
||||
login = login.substring(2);
|
||||
infos = login.split(";");
|
||||
this.clear_url = infos[0];
|
||||
this.clear_login = infos[1];
|
||||
this.clear_password = aes.decryptLongString(hex2a(this.ciphered_password), a_masterkey);
|
||||
this.unciphered = true;
|
||||
this.masterkey = masterkey;
|
||||
aes.finish();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
this.isUnciphered = function(masterkey)
|
||||
{
|
||||
return (this.unciphered == true && masterkey == this.masterkey && masterkey != "")
|
||||
}
|
||||
}
|
||||
|
||||
function list_all_entries(user)
|
||||
{
|
||||
passwords = new Array();
|
||||
|
||||
req = new XMLHttpRequest();
|
||||
req.addEventListener("load", function(evt) {
|
||||
entries = this.responseText.split("\n");
|
||||
for(i=0; i<entries.length; i++)
|
||||
{
|
||||
if (entries[i] == "") continue;
|
||||
entry = entries[i].split(";");
|
||||
passwords.push(new PasswordEntry(entry[0], entry[1]));
|
||||
}
|
||||
}, false);
|
||||
req.open("GET", document.documentURI + "?get_passwords=1&user=" + user, false);
|
||||
req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
|
||||
req.send(null);
|
||||
}
|
||||
|
||||
function change_master_key()
|
||||
{
|
||||
nb_ciphered_passwords = 0;
|
||||
nb_unciphered_passwords = 0;
|
||||
|
||||
for(i=0; i<passwords.length; i++)
|
||||
{
|
||||
ret = passwords[i].decrypt(current_mkey);
|
||||
if (ret)
|
||||
nb_unciphered_passwords++;
|
||||
else
|
||||
nb_ciphered_passwords++;
|
||||
}
|
||||
|
||||
password_div = document.getElementById("passwords");
|
||||
while (password_div.hasChildNodes())
|
||||
password_div.removeChild(password_div.childNodes[0]);
|
||||
|
||||
text = document.createElement("b");
|
||||
text.appendChild(document.createTextNode(nb_unciphered_passwords + " unciphered password(s)"));
|
||||
password_div.appendChild(text);
|
||||
password_div.appendChild(document.createElement("br"));
|
||||
password_div.appendChild(document.createElement("br"));
|
||||
|
||||
for(i=0; i<passwords.length; i++)
|
||||
{
|
||||
if (passwords[i].isUnciphered(current_mkey))
|
||||
{
|
||||
div = document.createElement("div");
|
||||
div.setAttribute("id", i);
|
||||
div.setAttribute("class", "password");
|
||||
|
||||
div.appendChild(document.createTextNode("URL"));
|
||||
url = document.createElement("input");
|
||||
url.setAttribute("type", "text");
|
||||
url.setAttribute("name", "URL");
|
||||
url.setAttribute("value", passwords[i].clear_url);
|
||||
div.appendChild(url);
|
||||
|
||||
div.appendChild(document.createTextNode("login"));
|
||||
login = document.createElement("input");
|
||||
login.setAttribute("type", "text");
|
||||
login.setAttribute("name", "login");
|
||||
login.setAttribute("value", passwords[i].clear_login);
|
||||
div.appendChild(login);
|
||||
|
||||
div.appendChild(document.createTextNode("password"));
|
||||
password = document.createElement("input");
|
||||
password.setAttribute("type", "text");
|
||||
password.setAttribute("name", "password");
|
||||
password.setAttribute("value", passwords[i].clear_password);
|
||||
div.appendChild(password);
|
||||
|
||||
delete_button = document.createElement("input");
|
||||
delete_button.setAttribute("type", "button");
|
||||
delete_button.setAttribute("value", "Delete");
|
||||
div.appendChild(delete_button);
|
||||
|
||||
update_button = document.createElement("input");
|
||||
update_button.setAttribute("type", "button");
|
||||
update_button.setAttribute("value", "Update");
|
||||
div.appendChild(update_button);
|
||||
|
||||
password_div.appendChild(div);
|
||||
}
|
||||
}
|
||||
|
||||
text = document.createElement("b");
|
||||
text.appendChild(document.createTextNode(nb_ciphered_passwords + " ciphered password(s)"));
|
||||
password_div.appendChild(document.createElement("br"));
|
||||
password_div.appendChild(document.createElement("br"));
|
||||
password_div.appendChild(text);
|
||||
password_div.appendChild(document.createElement("br"));
|
||||
password_div.appendChild(document.createElement("br"));
|
||||
|
||||
for(i=0; i<passwords.length; i++)
|
||||
{
|
||||
if (!passwords[i].isUnciphered(current_mkey))
|
||||
{
|
||||
div = document.createElement("div");
|
||||
div.setAttribute("id", i);
|
||||
div.setAttribute("class", "password");
|
||||
|
||||
div.appendChild(document.createTextNode("URL"));
|
||||
url = document.createElement("input");
|
||||
url.setAttribute("class", "hash");
|
||||
url.setAttribute("type", "text");
|
||||
url.setAttribute("name", "URL");
|
||||
url.setAttribute("value", passwords[i].ciphered_login);
|
||||
div.appendChild(url);
|
||||
|
||||
div.appendChild(document.createTextNode("password"));
|
||||
password = document.createElement("input");
|
||||
password.setAttribute("class", "hash");
|
||||
password.setAttribute("type", "text");
|
||||
password.setAttribute("name", "password");
|
||||
password.setAttribute("value", passwords[i].ciphered_password);
|
||||
div.appendChild(password);
|
||||
|
||||
delete_button = document.createElement("input");
|
||||
delete_button.setAttribute("type", "button");
|
||||
delete_button.setAttribute("value", "Delete");
|
||||
div.appendChild(delete_button);
|
||||
|
||||
password_div.appendChild(div);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function update_master_key()
|
||||
{
|
||||
user = select_widget.options[select_widget.selectedIndex].value;
|
||||
|
||||
if (user != current_user)
|
||||
{
|
||||
current_user = user;
|
||||
document.title = "gPass : global Password - " + current_user;
|
||||
passwords = new Array();
|
||||
list_all_entries(current_user);
|
||||
|
||||
addon_address = document.getElementById("addon_address");
|
||||
addon_address.removeChild(addon_address.childNodes[0]);
|
||||
addon_address.appendChild(document.createTextNode("Current addon address is : " + document.documentURI + current_user));
|
||||
}
|
||||
|
||||
current_mkey = document.getElementById("master_key").value;
|
||||
|
||||
if (current_mkey != "")
|
||||
current_mkey = derive_mkey(current_user, current_mkey);
|
||||
|
||||
change_master_key();
|
||||
}
|
||||
|
||||
function start()
|
||||
{
|
||||
select_widget = document.getElementById('selected_user') ;
|
||||
|
||||
if (select_widget == null) return;
|
||||
|
||||
return update_master_key();
|
||||
}
|
291
server/ressources/jsaes.js
Normal file
291
server/ressources/jsaes.js
Normal file
@@ -0,0 +1,291 @@
|
||||
/*
|
||||
* jsaes version 0.1 - Copyright 2006 B. Poettering
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* http://point-at-infinity.org/jsaes/
|
||||
*
|
||||
* This is a javascript implementation of the AES block cipher. Key lengths
|
||||
* of 128, 192 and 256 bits are supported.
|
||||
*
|
||||
* The well-functioning of the encryption/decryption routines has been
|
||||
* verified for different key lengths with the test vectors given in
|
||||
* FIPS-197, Appendix C.
|
||||
*
|
||||
* The following code example enciphers the plaintext block '00 11 22 .. EE FF'
|
||||
* with the 256 bit key '00 01 02 .. 1E 1F'.
|
||||
*
|
||||
* AES_Init();
|
||||
*
|
||||
* var block = new Array(16);
|
||||
* for(var i = 0; i < 16; i++)
|
||||
* block[i] = 0x11 * i;
|
||||
*
|
||||
* var key = new Array(32);
|
||||
* for(var i = 0; i < 32; i++)
|
||||
* key[i] = i;
|
||||
*
|
||||
* AES_ExpandKey(key);
|
||||
* AES_Encrypt(block, key);
|
||||
*
|
||||
* AES_Done();
|
||||
*
|
||||
* Report bugs to: jsaes AT point-at-infinity.org
|
||||
*
|
||||
*/
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/*
|
||||
AES_Init: initialize the tables needed at runtime. Call this function
|
||||
before the (first) key expansion.
|
||||
*/
|
||||
|
||||
function AES_Init() {
|
||||
AES_Sbox_Inv = new Array(256);
|
||||
for(var i = 0; i < 256; i++)
|
||||
AES_Sbox_Inv[AES_Sbox[i]] = i;
|
||||
|
||||
AES_ShiftRowTab_Inv = new Array(16);
|
||||
for(var i = 0; i < 16; i++)
|
||||
AES_ShiftRowTab_Inv[AES_ShiftRowTab[i]] = i;
|
||||
|
||||
AES_xtime = new Array(256);
|
||||
for(var i = 0; i < 128; i++) {
|
||||
AES_xtime[i] = i << 1;
|
||||
AES_xtime[128 + i] = (i << 1) ^ 0x1b;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
AES_Done: release memory reserved by AES_Init. Call this function after
|
||||
the last encryption/decryption operation.
|
||||
*/
|
||||
|
||||
function AES_Done() {
|
||||
delete AES_Sbox_Inv;
|
||||
delete AES_ShiftRowTab_Inv;
|
||||
delete AES_xtime;
|
||||
}
|
||||
|
||||
/*
|
||||
AES_ExpandKey: expand a cipher key. Depending on the desired encryption
|
||||
strength of 128, 192 or 256 bits 'key' has to be a byte array of length
|
||||
16, 24 or 32, respectively. The key expansion is done "in place", meaning
|
||||
that the array 'key' is modified.
|
||||
*/
|
||||
|
||||
function AES_ExpandKey(key) {
|
||||
var kl = key.length, ks, Rcon = 1;
|
||||
switch (kl) {
|
||||
case 16: ks = 16 * (10 + 1); break;
|
||||
case 24: ks = 16 * (12 + 1); break;
|
||||
case 32: ks = 16 * (14 + 1); break;
|
||||
default:
|
||||
alert("AES_ExpandKey: Only key lengths of 16, 24 or 32 bytes allowed!");
|
||||
}
|
||||
for(var i = kl; i < ks; i += 4) {
|
||||
var temp = key.slice(i - 4, i);
|
||||
if (i % kl == 0) {
|
||||
temp = new Array(AES_Sbox[temp[1]] ^ Rcon, AES_Sbox[temp[2]],
|
||||
AES_Sbox[temp[3]], AES_Sbox[temp[0]]);
|
||||
if ((Rcon <<= 1) >= 256)
|
||||
Rcon ^= 0x11b;
|
||||
}
|
||||
else if ((kl > 24) && (i % kl == 16))
|
||||
temp = new Array(AES_Sbox[temp[0]], AES_Sbox[temp[1]],
|
||||
AES_Sbox[temp[2]], AES_Sbox[temp[3]]);
|
||||
for(var j = 0; j < 4; j++)
|
||||
key[i + j] = key[i + j - kl] ^ temp[j];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
AES_Encrypt: encrypt the 16 byte array 'block' with the previously
|
||||
expanded key 'key'.
|
||||
*/
|
||||
|
||||
function AES_Encrypt(block, key) {
|
||||
var l = key.length;
|
||||
AES_AddRoundKey(block, key.slice(0, 16));
|
||||
for(var i = 16; i < l - 16; i += 16) {
|
||||
AES_SubBytes(block, AES_Sbox);
|
||||
AES_ShiftRows(block, AES_ShiftRowTab);
|
||||
AES_MixColumns(block);
|
||||
AES_AddRoundKey(block, key.slice(i, i + 16));
|
||||
}
|
||||
AES_SubBytes(block, AES_Sbox);
|
||||
AES_ShiftRows(block, AES_ShiftRowTab);
|
||||
AES_AddRoundKey(block, key.slice(i, l));
|
||||
}
|
||||
|
||||
/*
|
||||
AES_Decrypt: decrypt the 16 byte array 'block' with the previously
|
||||
expanded key 'key'.
|
||||
*/
|
||||
|
||||
function AES_Decrypt(block, key) {
|
||||
var l = key.length;
|
||||
AES_AddRoundKey(block, key.slice(l - 16, l));
|
||||
AES_ShiftRows(block, AES_ShiftRowTab_Inv);
|
||||
AES_SubBytes(block, AES_Sbox_Inv);
|
||||
for(var i = l - 32; i >= 16; i -= 16) {
|
||||
AES_AddRoundKey(block, key.slice(i, i + 16));
|
||||
AES_MixColumns_Inv(block);
|
||||
AES_ShiftRows(block, AES_ShiftRowTab_Inv);
|
||||
AES_SubBytes(block, AES_Sbox_Inv);
|
||||
}
|
||||
AES_AddRoundKey(block, key.slice(0, 16));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/* The following lookup tables and functions are for internal use only! */
|
||||
|
||||
AES_Sbox = new Array(99,124,119,123,242,107,111,197,48,1,103,43,254,215,171,
|
||||
118,202,130,201,125,250,89,71,240,173,212,162,175,156,164,114,192,183,253,
|
||||
147,38,54,63,247,204,52,165,229,241,113,216,49,21,4,199,35,195,24,150,5,154,
|
||||
7,18,128,226,235,39,178,117,9,131,44,26,27,110,90,160,82,59,214,179,41,227,
|
||||
47,132,83,209,0,237,32,252,177,91,106,203,190,57,74,76,88,207,208,239,170,
|
||||
251,67,77,51,133,69,249,2,127,80,60,159,168,81,163,64,143,146,157,56,245,
|
||||
188,182,218,33,16,255,243,210,205,12,19,236,95,151,68,23,196,167,126,61,
|
||||
100,93,25,115,96,129,79,220,34,42,144,136,70,238,184,20,222,94,11,219,224,
|
||||
50,58,10,73,6,36,92,194,211,172,98,145,149,228,121,231,200,55,109,141,213,
|
||||
78,169,108,86,244,234,101,122,174,8,186,120,37,46,28,166,180,198,232,221,
|
||||
116,31,75,189,139,138,112,62,181,102,72,3,246,14,97,53,87,185,134,193,29,
|
||||
158,225,248,152,17,105,217,142,148,155,30,135,233,206,85,40,223,140,161,
|
||||
137,13,191,230,66,104,65,153,45,15,176,84,187,22);
|
||||
|
||||
AES_ShiftRowTab = new Array(0,5,10,15,4,9,14,3,8,13,2,7,12,1,6,11);
|
||||
|
||||
function AES_SubBytes(state, sbox) {
|
||||
for(var i = 0; i < 16; i++)
|
||||
state[i] = sbox[state[i]];
|
||||
}
|
||||
|
||||
function AES_AddRoundKey(state, rkey) {
|
||||
for(var i = 0; i < 16; i++)
|
||||
state[i] ^= rkey[i];
|
||||
}
|
||||
|
||||
function AES_ShiftRows(state, shifttab) {
|
||||
var h = new Array().concat(state);
|
||||
for(var i = 0; i < 16; i++)
|
||||
state[i] = h[shifttab[i]];
|
||||
}
|
||||
|
||||
function AES_MixColumns(state) {
|
||||
for(var i = 0; i < 16; i += 4) {
|
||||
var s0 = state[i + 0], s1 = state[i + 1];
|
||||
var s2 = state[i + 2], s3 = state[i + 3];
|
||||
var h = s0 ^ s1 ^ s2 ^ s3;
|
||||
state[i + 0] ^= h ^ AES_xtime[s0 ^ s1];
|
||||
state[i + 1] ^= h ^ AES_xtime[s1 ^ s2];
|
||||
state[i + 2] ^= h ^ AES_xtime[s2 ^ s3];
|
||||
state[i + 3] ^= h ^ AES_xtime[s3 ^ s0];
|
||||
}
|
||||
}
|
||||
|
||||
function AES_MixColumns_Inv(state) {
|
||||
for(var i = 0; i < 16; i += 4) {
|
||||
var s0 = state[i + 0], s1 = state[i + 1];
|
||||
var s2 = state[i + 2], s3 = state[i + 3];
|
||||
var h = s0 ^ s1 ^ s2 ^ s3;
|
||||
var xh = AES_xtime[h];
|
||||
var h1 = AES_xtime[AES_xtime[xh ^ s0 ^ s2]] ^ h;
|
||||
var h2 = AES_xtime[AES_xtime[xh ^ s1 ^ s3]] ^ h;
|
||||
state[i + 0] ^= h1 ^ AES_xtime[s0 ^ s1];
|
||||
state[i + 1] ^= h2 ^ AES_xtime[s1 ^ s2];
|
||||
state[i + 2] ^= h1 ^ AES_xtime[s2 ^ s3];
|
||||
state[i + 3] ^= h2 ^ AES_xtime[s3 ^ s0];
|
||||
}
|
||||
}
|
||||
|
||||
function bin2String (array) {
|
||||
var result = "";
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
result += String.fromCharCode(parseInt(array[i], 2));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function string2Bin (str) {
|
||||
var result = [];
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
result.push(str.charCodeAt(i));
|
||||
}
|
||||
while ((result.length % 16))
|
||||
result.push(0);
|
||||
return result;
|
||||
}
|
||||
|
||||
function bin2String (array) {
|
||||
return String.fromCharCode.apply(String, array);
|
||||
}
|
||||
|
||||
// http://osama-oransa.blogspot.fr/2012/03/using-aes-encrypting-in-java-script.html
|
||||
function AES(a) {
|
||||
this.init = function (myKey){
|
||||
AES_Init();
|
||||
var key = string2Bin(myKey);
|
||||
AES_ExpandKey(key);
|
||||
return key;
|
||||
}
|
||||
|
||||
this.encrypt = function ( inputStr,key ) {
|
||||
var block = string2Bin(inputStr);
|
||||
AES_Encrypt(block, key);
|
||||
var data=bin2String(block);
|
||||
return data;
|
||||
}
|
||||
|
||||
this.decrypt = function ( inputStr,key ) {
|
||||
block = string2Bin(inputStr);
|
||||
AES_Decrypt(block, key);
|
||||
var data=bin2String(block);
|
||||
return data;
|
||||
}
|
||||
|
||||
this.encryptLongString = function( myString,key ) {
|
||||
if(myString.length>16){
|
||||
var data='';
|
||||
for(var i=0;i<myString.length;i=i+16){
|
||||
data+=this.encrypt(myString.substr(i,16),key);
|
||||
}
|
||||
return data;
|
||||
}else{
|
||||
return this.encrypt(myString,key);
|
||||
}
|
||||
}
|
||||
|
||||
this.decryptLongString = function ( myString,key ) {
|
||||
if(myString.length>16){
|
||||
var data='';
|
||||
for(var i=0;i<myString.length;i=i+16){
|
||||
data+=this.decrypt(myString.substr(i,16),key);
|
||||
}
|
||||
return data;
|
||||
}else{
|
||||
return this.decrypt(myString,key);
|
||||
}
|
||||
}
|
||||
|
||||
this.finish = function(){
|
||||
AES_Done();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user