diff --git a/server/_user b/server/_user
index ec1f3d5..10a1288 100644
--- a/server/_user
+++ b/server/_user
@@ -44,7 +44,7 @@ function load_database()
// Brute force ??
$db->close();
return null;
- }
+ }
$db->query("UPDATE conf SET last_access_time=$usec");
$db->close();
$db = new SQLite3("./gpass.bdd", SQLITE3_OPEN_READONLY);
@@ -79,6 +79,7 @@ for ($i=0; $i<$MAX_PASSWORDS_PER_REQUEST && isset($_POST["k$i"]); $i++)
$result->finalize();
if (isset($row["password"]))
{
+ echo "matched_key=" . $i . "\n";
echo "pass=" . $row["password"] . "\n";
break;
}
diff --git a/server/conf.php b/server/conf.php
index cd8a9d4..ba7e75d 100644
--- a/server/conf.php
+++ b/server/conf.php
@@ -80,4 +80,11 @@ $REQUESTS_MIN_DELAY=1000;
Clear master keys and reset passwords after 15 minutes of inactivity
*/
$CLEAR_TIME=15*60*1000;
+
+/*
+ The first crypto schema use an AES-ECB process to encrypt logins.
+ It's used until version 0.7.
+ Since version 0.8, we use AES-CBC + SHA256.
+ */
+$CRYPTO_V1_COMPATIBLE=1;
?>
\ No newline at end of file
diff --git a/server/functions.php b/server/functions.php
index dfab88c..bff0b03 100755
--- a/server/functions.php
+++ b/server/functions.php
@@ -20,11 +20,13 @@
/*
login is stored as :
- @@url;login
+ url;login + 16 bytes padding * \0 + sha256(url;login + padding)[8:24]
Password is salted (3 random characters) and encrypted
- All is encrypted with AES256 and key : PKDBF2(hmac_sha256, master key, url, 1000)
+ All is encrypted with AES256-CBC and key PBKDF2(hmac_sha256, master key, server url, 1000)
+ level is server configurable
+ iv is PBKDF2(hmac_sha256, server url, master key, 1000)[0:16]
*/
$MAX_ENTRY_LEN = 512;
$USERS_PATH = "./users/";
diff --git a/server/index.php b/server/index.php
index abd4d83..d94dafd 100644
--- a/server/index.php
+++ b/server/index.php
@@ -79,6 +79,7 @@ else
diff --git a/server/resources/gpass.js b/server/resources/gpass.js
index 271958b..c3b6ea4 100755
--- a/server/resources/gpass.js
+++ b/server/resources/gpass.js
@@ -119,16 +119,18 @@ function a2hex(str) {
return hex;
}
-function derive_mkey(user, mkey)
+async function derive_mkey(user, mkey)
{
url = url_domain(document.URL) + "/" + user;
- return pbkdf2(mkey, url, pbkdf2_level, 256/8);
+ global_iv = simple_pbkdf2(url, mkey, pbkdf2_level);
+ return crypto_pbkdf2(mkey, url, pbkdf2_level);
}
var passwords;
var current_user = "";
var current_mkey = "";
var clearTimer = null;
+var global_iv = null;
function PasswordEntry (ciphered_login, ciphered_password, salt, shadow_login) {
this.ciphered_login = ciphered_login;
@@ -165,13 +167,19 @@ function PasswordEntry (ciphered_login, ciphered_password, salt, shadow_login) {
if (masterkey == null || this.clear_url == "" || this.clear_login == "")
return false;
- ciphered_login = "@@" + this.clear_url + ";" + this.clear_login;
+ var ciphered_login = this.clear_url + ";" + this.clear_login;
+ while ((ciphered_login.length % 16))
+ ciphered_login += "\0";
+ var computed_hash = await digest(ciphered_login);
+ ciphered_login += computed_hash.slice(8, 24);
+ var iv = await global_iv;
+ iv = iv.slice(0, 16);
// Add salt
- ciphered_password = this.clear_password + generate_random(3, false);
+ var ciphered_password = generate_random(3, false) + this.clear_password ;
- this.ciphered_login = a2hex(await encrypt(masterkey, ciphered_login));
- this.ciphered_password = a2hex(await encrypt(masterkey, ciphered_password));
+ this.ciphered_login = a2hex(await encrypt_cbc(masterkey, iv, ciphered_login));
+ this.ciphered_password = a2hex(await encrypt_cbc(masterkey, iv, ciphered_password));
this.unciphered = true;
this.masterkey = masterkey;
@@ -188,25 +196,53 @@ function PasswordEntry (ciphered_login, ciphered_password, salt, shadow_login) {
if (masterkey == this.masterkey)
return (this.unciphered == true);
- login = await decrypt(masterkey, hex2a(this.ciphered_login));
- login = login.replace(/\0*$/, "");
- if (login.indexOf("@@") != 0)
+ var old = false;
+ var iv = await global_iv;
+ iv = iv.slice(0, 16);
+ var login = await decrypt_cbc(masterkey, iv, hex2a(this.ciphered_login));
+
+ var computed_digest = await digest(login.slice(0, login.length-16))
+ computed_digest = computed_digest.slice(8, 24);
+
+ if (login.indexOf(computed_digest) == login.length-16)
{
- return false;
+ login = login.slice(0, login.length-16).replace(/\0*$/, "");
}
- // Remove @@
- login = login.substring(2);
+ else if (CRYPTO_V1_COMPATIBLE)
+ {
+ login = await decrypt_ecb(masterkey, hex2a(this.ciphered_login));
+ if (login.indexOf("@@") != 0)
+ {
+ return false;
+ }
+ login = login.replace(/\0*$/, "");
+ // Remove @@
+ login = login.substring(2);
+ old = true;
+ }
+ else
+ return false;
+
infos = login.split(";");
this.clear_url = infos[0];
this.clear_login = infos[1];
- this.clear_password = await decrypt(masterkey, hex2a(this.ciphered_password));
+ if (old)
+ {
+ this.clear_password = await decrypt_ecb(masterkey, hex2a(this.ciphered_password));
+ // Remove salt
+ this.clear_password = this.clear_password.replace(/\0*$/, "");
+ this.clear_password = this.clear_password.substr(0, this.clear_password.length-3);
+ }
+ else
+ {
+ this.clear_password = await decrypt_cbc(masterkey, iv, hex2a(this.ciphered_password));
+ // Remove salt
+ this.clear_password = this.clear_password.replace(/\0*$/, "");
+ this.clear_password = this.clear_password.substr(3, this.clear_password.length);
+ }
this.unciphered = true;
this.masterkey = masterkey;
- // Remove salt
- this.clear_password = this.clear_password.replace(/\0*$/, "");
- this.clear_password = this.clear_password.substr(0, this.clear_password.length-3);
-
return true;
}
@@ -222,7 +258,7 @@ function PasswordEntry (ciphered_login, ciphered_password, salt, shadow_login) {
this.shadow_login_to_access_token = async function(masterkey)
{
- this.access_token = await encrypt(masterkey, hex2a(this.shadow_login));
+ this.access_token = await encrypt_ecb(masterkey, hex2a(this.shadow_login));
this.access_token = a2hex(this.access_token);
}
@@ -857,11 +893,14 @@ async function update_masterkey()
return;
oldmkey = derive_mkey(current_user, oldmkey);
+ old_global_iv = global_iv;
current_mkey = derive_mkey(current_user, newmkey);
+ new_global_iv = global_iv;
var found = 0;
for(i=0; i.
-*/
-
-function hmac256(key, message) {
- var ipad = "";
- var opad = "";
-
- if (key.length > 512/8)
- {
- key = digest256(key);
- }
-
- for(i=0; i<512/8; i++)
- {
- if (i >= key.length)
- {
- ipad += String.fromCharCode(0x36);
- opad += String.fromCharCode(0x5c);
- }
- else
- {
- ipad += String.fromCharCode(key.charCodeAt(i) ^ 0x36);
- opad += String.fromCharCode(key.charCodeAt(i) ^ 0x5c);
- }
- }
-
- result = digest256(opad + digest256(ipad + message));
-
- return result;
-}
diff --git a/server/resources/jsaes.js b/server/resources/jsaes.js
deleted file mode 100644
index e340a81..0000000
--- a/server/resources/jsaes.js
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * 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;i16){
- var data='';
- for(var i=0;i
-*
-* NOTE: This version is not tested thoroughly!
-*
-* Copyright (c) 2003, Christoph Bichlmeier
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-* 3. Neither the name of the copyright holder nor the names of contributors
-* may be used to endorse or promote products derived from this software
-* without specific prior written permission.
-*
-* ======================================================================
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
-* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
-* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
-* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* SHA256 logical functions */
-function rotateRight(n,x) {
- return ((x >>> n) | (x << (32 - n)));
-}
-function choice(x,y,z) {
- return ((x & y) ^ (~x & z));
-}
-function majority(x,y,z) {
- return ((x & y) ^ (x & z) ^ (y & z));
-}
-function sha256_Sigma0(x) {
- return (rotateRight(2, x) ^ rotateRight(13, x) ^ rotateRight(22, x));
-}
-function sha256_Sigma1(x) {
- return (rotateRight(6, x) ^ rotateRight(11, x) ^ rotateRight(25, x));
-}
-function sha256_sigma0(x) {
- return (rotateRight(7, x) ^ rotateRight(18, x) ^ (x >>> 3));
-}
-function sha256_sigma1(x) {
- return (rotateRight(17, x) ^ rotateRight(19, x) ^ (x >>> 10));
-}
-function sha256_expand(W, j) {
- return (W[j&0x0f] += sha256_sigma1(W[(j+14)&0x0f]) + W[(j+9)&0x0f] +
-sha256_sigma0(W[(j+1)&0x0f]));
-}
-
-/* Hash constant words K: */
-var K256 = new Array(
- 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
- 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
- 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
- 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
- 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
- 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
- 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
- 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
- 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
- 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
- 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
- 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
- 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
- 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
- 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
- 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
-);
-
-/* global arrays */
-var ihash, count, buffer;
-var sha256_hex_digits = "0123456789abcdef";
-
-/* Add 32-bit integers with 16-bit operations (bug in some JS-interpreters:
-overflow) */
-function safe_add(x, y)
-{
- var lsw = (x & 0xffff) + (y & 0xffff);
- var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
- return (msw << 16) | (lsw & 0xffff);
-}
-
-/* Initialise the SHA256 computation */
-function sha256_init() {
- ihash = new Array(8);
- count = new Array(2);
- buffer = new Array(64);
- count[0] = count[1] = 0;
- ihash[0] = 0x6a09e667;
- ihash[1] = 0xbb67ae85;
- ihash[2] = 0x3c6ef372;
- ihash[3] = 0xa54ff53a;
- ihash[4] = 0x510e527f;
- ihash[5] = 0x9b05688c;
- ihash[6] = 0x1f83d9ab;
- ihash[7] = 0x5be0cd19;
-}
-
-/* Transform a 512-bit message block */
-function sha256_transform() {
- var a, b, c, d, e, f, g, h, T1, T2;
- var W = new Array(16);
-
- /* Initialize registers with the previous intermediate value */
- a = ihash[0];
- b = ihash[1];
- c = ihash[2];
- d = ihash[3];
- e = ihash[4];
- f = ihash[5];
- g = ihash[6];
- h = ihash[7];
-
- /* make 32-bit words */
- for(var i=0; i<16; i++)
- W[i] = ((buffer[(i<<2)+3]) | (buffer[(i<<2)+2] << 8) | (buffer[(i<<2)+1]
-<< 16) | (buffer[i<<2] << 24));
-
- for(var j=0; j<64; j++) {
- T1 = h + sha256_Sigma1(e) + choice(e, f, g) + K256[j];
- if(j < 16) T1 += W[j];
- else T1 += sha256_expand(W, j);
- T2 = sha256_Sigma0(a) + majority(a, b, c);
- h = g;
- g = f;
- f = e;
- e = safe_add(d, T1);
- d = c;
- c = b;
- b = a;
- a = safe_add(T1, T2);
- }
-
- /* Compute the current intermediate hash value */
- ihash[0] += a;
- ihash[1] += b;
- ihash[2] += c;
- ihash[3] += d;
- ihash[4] += e;
- ihash[5] += f;
- ihash[6] += g;
- ihash[7] += h;
-}
-
-/* Read the next chunk of data and update the SHA256 computation */
-function sha256_update(data, inputLen) {
- var i, index, curpos = 0;
- /* Compute number of bytes mod 64 */
- index = ((count[0] >> 3) & 0x3f);
- var remainder = (inputLen & 0x3f);
-
- /* Update number of bits */
- if ((count[0] += (inputLen << 3)) < (inputLen << 3)) count[1]++;
- count[1] += (inputLen >> 29);
-
- /* Transform as many times as possible */
- for(i=0; i+63> 3) & 0x3f);
- buffer[index++] = 0x80;
- if(index <= 56) {
- for(var i=index; i<56; i++)
- buffer[i] = 0;
- } else {
- for(var i=index; i<64; i++)
- buffer[i] = 0;
- sha256_transform();
- for(var i=0; i<56; i++)
- buffer[i] = 0;
- }
- buffer[56] = (count[1] >>> 24) & 0xff;
- buffer[57] = (count[1] >>> 16) & 0xff;
- buffer[58] = (count[1] >>> 8) & 0xff;
- buffer[59] = count[1] & 0xff;
- buffer[60] = (count[0] >>> 24) & 0xff;
- buffer[61] = (count[0] >>> 16) & 0xff;
- buffer[62] = (count[0] >>> 8) & 0xff;
- buffer[63] = count[0] & 0xff;
- sha256_transform();
-}
-
-/* Split the internal hash values into an array of bytes */
-function sha256_encode_bytes() {
- var j=0;
- var output = new Array(32);
- for(var i=0; i<8; i++) {
- output[j++] = ((ihash[i] >>> 24) & 0xff);
- output[j++] = ((ihash[i] >>> 16) & 0xff);
- output[j++] = ((ihash[i] >>> 8) & 0xff);
- output[j++] = (ihash[i] & 0xff);
- }
- return output;
-}
-
-/* Get the internal hash as a hex string */
-function sha256_encode_hex() {
- var output = new String();
- for(var i=0; i<8; i++) {
- for(var j=28; j>=0; j-=4)
- output += sha256_hex_digits.charAt((ihash[i] >>> j) & 0x0f);
- }
- return output;
-}
-
-/* Get the internal hash as string */
-function sha256_encode() {
- var output = new String();
- for(var i=0; i<8; i++) {
- for(var j=3; j>=0; j--)
- output += String.fromCharCode((ihash[i] >>> j*8) & 0xff);
- }
- return output;
-}
-
-/* Main function: returns a hex string representing the SHA256 value of the
- given data */
-function digest256 (data) {
- sha256_init();
- sha256_update(data, data.length);
- sha256_final();
- return sha256_encode();
- // return sha256_encode_hex();
-}
-
-/* test if the JS-interpreter is working properly */
-function sha256_self_test()
-{
- return sha256_digest("message digest") ==
-"f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650";
-}
-
-
diff --git a/server/resources/misc.js b/server/resources/misc.js
index 65310b1..866d2b6 100644
--- a/server/resources/misc.js
+++ b/server/resources/misc.js
@@ -47,7 +47,7 @@ function str2ab(str) {
return bufView;
}
-function pbkdf2(mkey, salt, level)
+function crypto_pbkdf2(mkey, salt, level)
{
AESCBC = {
name: "AES-CBC",
@@ -76,19 +76,49 @@ function pbkdf2(mkey, salt, level)
});
}
-function _encrypt(mkey, data)
+function simple_pbkdf2(mkey, salt, level)
+{
+ AESCBC = {
+ name: "AES-CBC",
+ length: 256,
+ }
+
+ var key = str2ab(mkey);
+ return crypto.subtle.importKey("raw", key, {name: "PBKDF2"}, false, ["deriveBits", "deriveKey"])
+ .then(function(key){
+ //sha-256
+ return crypto.subtle.deriveKey({
+ name: "PBKDF2",
+ salt: str2ab(salt),
+ iterations: level,
+ hash: "SHA-256",
+ }, key, AESCBC, true, ["unwrapKey", "wrapKey"])
+ .then(function(key) {
+ return crypto.subtle.exportKey("raw", key)
+ .then(function (key) {
+ return ab2str(key);
+ });
+ })
+ .catch(function(err){
+ console.log("Error derive key " + err);
+ });
+ })
+ .catch(function(err) {
+ console.log("Error import key" + err);
+ });
+}
+
+function _encrypt(mkey, iv, data)
{
while ((data.length % 16))
data += "\0";
data = str2ab(data);
- nulliv = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
-
promise = mkey.then(function(mkey){
return crypto.subtle.encrypt({
name: "AES-CBC",
- iv: nulliv
+ iv: iv
}, mkey, data)})
.then(function(encrypted) {
return ab2str(encrypted);
@@ -100,22 +130,21 @@ function _encrypt(mkey, data)
return promise;
}
-async function _decrypt(mkey, data)
+async function _decrypt(mkey, iv, data)
{
while ((data.length % 16))
data += "\0";
+ nulliv = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
pkcs7_padding = new Uint8Array([16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16]);
- pkcs7_padding = await _encrypt(mkey, ab2str(pkcs7_padding));
+ pkcs7_padding = await _encrypt(mkey, nulliv, ab2str(pkcs7_padding));
data = str2ab(data + pkcs7_padding);
- nulliv = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
-
promise = mkey.then(function(mkey){
return crypto.subtle.decrypt({
name: "AES-CBC",
- iv: nulliv
+ iv: iv
}, mkey, data)})
.then(function(decrypted) {
return ab2str(decrypted);
@@ -127,36 +156,63 @@ async function _decrypt(mkey, data)
return promise;
}
-async function encrypt(mkey, data)
+async function encrypt_ecb(mkey, data)
{
var result = "";
+ nulliv = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
+
while (data.length > 16)
{
- res = await _encrypt(mkey, data.slice(0, 16));
+ res = await _encrypt(mkey, nulliv, data.slice(0, 16));
// Remove PKCS7 padding
result += res.slice(0, 16);
data = data.slice(16);
}
- res = await _encrypt(mkey, data);
+ res = await _encrypt(mkey, nulliv, data);
result += res.slice(0, 16);
return result;
}
-async function decrypt(mkey, data)
+async function decrypt_ecb(mkey, data)
{
var result = "";
+ nulliv = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
+
while (data.length > 16)
{
- res = await _decrypt(mkey, data.slice(0, 16));
+ res = await _decrypt(mkey, nulliv, data.slice(0, 16));
// Remove PKCS7 padding
result += res.slice(0, 16);
data = data.slice(16);
}
- res = await _decrypt(mkey, data);
+ res = await _decrypt(mkey, nulliv, data);
result += res.slice(0, 16);
return result;
}
+
+async function encrypt_cbc(mkey, iv, data)
+{
+ var result = await _encrypt(mkey, str2ab(iv), data);
+
+ // Remove PKCS7 padding
+ return result.slice(0, result.length-16);
+}
+
+async function decrypt_cbc(mkey, iv, data)
+{
+ var result = await _decrypt(mkey, str2ab(iv), data);
+
+ // Remove PKCS7 padding
+ return result.slice(0, result.length-16);
+}
+
+async function digest(data)
+{
+ return crypto.subtle.digest("SHA-256", str2ab(data)).then(function (hash) {
+ return ab2str(hash);
+ });
+}
diff --git a/server/resources/pkdbf2.js b/server/resources/pkdbf2.js
deleted file mode 100644
index 278c4d2..0000000
--- a/server/resources/pkdbf2.js
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- Copyright (C) 2013 Grégory Soutadé
-
- This file is part of gPass.
-
- gPass 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 3 of the License, or
- (at your option) any later version.
-
- gPass 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 gPass. If not, see .
-*/
-
-function pkdbf2 (password, salt, iterations, outlen) {
- var result = "";
- var temp = "";
- var temp2 = "";
- var temp_res = "";
- var temp_res2 = "";
-
- for (i=1; result.length < outlen; i++)
- {
- temp = hmac256(password, salt +
- String.fromCharCode((i & 0xff000000) >> 24) +
- String.fromCharCode((i & 0x00ff0000) >> 16) +
- String.fromCharCode((i & 0x0000ff00) >> 8) +
- String.fromCharCode((i & 0x000000ff) >> 0)
- );
- temp_res = temp;
-
- for(a=1; a