Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 09c8d6bcba | |||
| 07c64a44a0 | |||
|
|
0a233a42c0 | ||
| 81385fbf88 | |||
| 4cb4b44690 | |||
| 2f12a09a1b | |||
|
|
b216ec9928 | ||
|
|
da4a99a6ef | ||
| f98cc4a863 | |||
| 5a1d6c7390 |
68
ChangeLog
Normal file
68
ChangeLog
Normal file
@@ -0,0 +1,68 @@
|
||||
**v0.8.2 :**
|
||||
Server
|
||||
|
||||
Addon
|
||||
|
||||
* Error in wildcard domain generation
|
||||
* Forgot some console.log in code (replace it with debug function)
|
||||
|
||||
CLI
|
||||
|
||||
**v0.8.1 :**
|
||||
|
||||
Server
|
||||
|
||||
* Scroll to page bottom when user adds a new password
|
||||
|
||||
Addon
|
||||
|
||||
* Add Privacy Policy information
|
||||
* Run a simpler algorithm for wildcard domains
|
||||
|
||||
CLI
|
||||
|
||||
* Run a simpler algorithm for wildcard domains
|
||||
|
||||
**v0.8 :**
|
||||
|
||||
Server
|
||||
|
||||
* Clear master keys and reset passwords after 15 minutes of inactivity
|
||||
* Set USE_SHADOW_LOGINS by default
|
||||
* New crypto scheme (Use CBC chaining and fix a security problem with salt) and protocol v4. not backward compatible with v3
|
||||
* Add QUnit tests
|
||||
* New password form is now on top of the page
|
||||
* Add a button to go to the top of the page when scrolling
|
||||
* Add simple password button
|
||||
* Rework password generation for most user friendly passwords (less special characters, more letters)
|
||||
|
||||
Addon
|
||||
|
||||
* New webextension for Firefox is provided. It shares most of code with Chrome extension and use native crypto API
|
||||
* Block connection when masterkey is sent in clear (password replacement failed). **Doesn't work with Firefox**
|
||||
|
||||
CLI
|
||||
|
||||
* Add command line interface (CLI)
|
||||
|
||||
**v0.7 :**
|
||||
|
||||
Server
|
||||
|
||||
* Fix a bug for Chrome browser (doesn't support default parameters)
|
||||
* Display an error message when a query fails
|
||||
* You can now export clear password database (only unciphered passwords)
|
||||
* New database version : 2
|
||||
* Add two new protections : REQUESTS_MIN_DELAY and MAX_PASSWORDS_PER_REQUEST (see conf.php)
|
||||
* Remove '\' character from password generation
|
||||
|
||||
Addon
|
||||
|
||||
* Addon is now compatible with more websites
|
||||
* Use jpm building tool instead of cfx for Firefox Addon
|
||||
|
||||
**v0.6 : **
|
||||
|
||||
Addon
|
||||
|
||||
* Add support for "@_masterkey" input
|
||||
47
PrivacyPolicy.md
Normal file
47
PrivacyPolicy.md
Normal file
@@ -0,0 +1,47 @@
|
||||
gPass web browser extension Privacy Policy
|
||||
------------------------------------------
|
||||
|
||||
|
||||
## Information we collect ##
|
||||
|
||||
The gPass extension collect three information once invoked :
|
||||
* Site address URL
|
||||
* Login name
|
||||
* Master key
|
||||
|
||||
|
||||
## How we use information we collect ##
|
||||
|
||||
Once collected, site address and login name are crypted by a derived version of your master key.
|
||||
It's then sent to the server you configured in extension configuration page for comparison.
|
||||
|
||||
This server has been set up by the user himself (recommended) or by a provider he trust in.
|
||||
|
||||
The database that the server access to do comparisons only contains the crypted
|
||||
version of your information. They are never decrypted in the server side.
|
||||
|
||||
If a comparison match, the real password is sent back to your extension were
|
||||
it's unencrypted using the same key.
|
||||
|
||||
Finally, the application context is cleared and nothing is retained in memory
|
||||
nor written anywhere.
|
||||
|
||||
|
||||
## Accessing and updating your personal information ##
|
||||
|
||||
As a user, you can add, edit and delete your crypted information through
|
||||
the web interface of the configuration defined server.
|
||||
|
||||
During these operations, no clear information is sent to the server.
|
||||
|
||||
|
||||
## Information we share ##
|
||||
|
||||
Nothing is shared with anyone. Nor on extension side nor on server side.
|
||||
|
||||
|
||||
## Information security ##
|
||||
|
||||
Information transmitted to the server are done through an HTTPS AJAX request.
|
||||
Data are crypted using AES 256 CBC algorithm and the master key is prior
|
||||
derived using PKBDF2 algorithm.
|
||||
7
README
7
README
@@ -1,7 +0,0 @@
|
||||
gPass : global Password.
|
||||
|
||||
Copyright (C) 2013-2014 Grégory Soutadé
|
||||
|
||||
Licence : GPL v3
|
||||
|
||||
See http://indefero.soutade.fr/p/gpass/ for further information
|
||||
91
README.md
Normal file
91
README.md
Normal file
@@ -0,0 +1,91 @@
|
||||
gPass : global Password for Firefox and Chrome
|
||||
==============================================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Everyday we have a lot of passwords to manage corresponding to a lot of accounts we use. It's hard to remain all of these, moreover if we don't use it often. So, what most people do is to generate only a subset of passwords easy to remain. This implies two common errors :
|
||||
|
||||
* Password are not very strong
|
||||
* We use them for multiple accounts
|
||||
|
||||
The best way to avoid these errors is to have a unique strong password for each account. gPass helps to reach this goal : you keep a subset of passwords (called masterkey) and for each login/password tuple you chose, gPass returns the real password by querying a password server.
|
||||
|
||||
To have a high level of security, all information is stored encrypted (server side). Nothing is stored on client. The decryption is done on the fly when it's needed and only with user input. So, a hacker can get your password database, it will not be able to see any information (except if it brute force your masterkey) ! So it's important to choose to strong masterkey !
|
||||
|
||||
This addon is like [last pass](https://lastpass.com/) one, but I wanted it to be open source and self hostable (be careful on server down !). Moreover, with gPass, you can have multiple master keys !
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The first thing to do is to populate your database (from your/a password server) with website/login/password/master key values. You can use "*" character to access to all sub domains of a specific website. If you want to make strong password, there is a password generator. After that, configure your addon in "tools -> addons -> gPass -> preferences" in Firefox or "addons -> gPass -> options" in Chrome to point to your password server (+ username). Be careful, login and password are case sensitive.
|
||||
|
||||
When you're in a login form and you want to use gPass, type your login (case sensitive !) and fill "@@masterkey" in password field. Then submit and password will automatically be replaced by the one in the database (after addon decrypt it).
|
||||
|
||||
**You can also type "@_masterkey" to only replace your password without submitting and manually submit. This allows to support more websites.**
|
||||
|
||||
Technical details
|
||||
-----------------
|
||||
|
||||
The two columns in database are "login" and "password".
|
||||
login is compounded by "domain;login" is salted and encrypted with AES 256-CBC
|
||||
|
||||
The key that encrypt these fields is PBKDF2 (hmac-sha256, masterkey, password_server_url, 1000, 256), IV is PBKDF2 (hmac-sha256, password_server_url, masterkey, 1000, 256)
|
||||
|
||||
PBKDF2 level can be changed by user
|
||||
|
||||
Server side is written in PHP (with SQLite3 for database component).
|
||||
|
||||
|
||||
Server
|
||||
------
|
||||
|
||||
To host a password server, you need a webserver. Just copy server files in a directory read/write for web server user (www-data). A sample apache2 configuration file is available in resources. Since v0.8 and the use of Crypto API, it's manadatory to have an HTTPS access to the server. Without that, the decryption will fails.
|
||||
|
||||
Configuration parameters are in conf.php
|
||||
|
||||
A demonstration server is available [here](https://gpass-demo.soutade.fr). It may not works with HTTPS content because it uses a self-signed SSL certificate. If so, explicitly add the certificate to your browser. It's the default server of package (user demo).
|
||||
|
||||
**Warning** The master key derivation is partially based on account URL. So it's linked to your current server information. You can't move databases from servers with different URLs, you need to export them and import again.
|
||||
|
||||
**Server side is available [here](http://indefero.soutade.fr/p/gpass/downloads)**
|
||||
|
||||
Version 0.6 introduces shadow logins. It's a protection again illegal database dump and purge but requires high cpu bandwidth. Database update is transparent.
|
||||
|
||||
The principle is to generate a random value (shadow login) that must be encrypted with the masterkey to get an access token. This access token allows to get the true (but encrypted) login/password couple. It's a kind of challenge : if I can encrypt the shadow login, I know the masterkey ! For security reason, the derivation of masterkey for deciphering passwords is different than for encrypting shadow logins (it uses its own salt).
|
||||
|
||||
Client
|
||||
------
|
||||
|
||||
Just install the package. You can have debug information by setting DEBUG in main.js.
|
||||
|
||||
Command line interface
|
||||
----------------------
|
||||
|
||||
A command line interface is also available with the following usage :
|
||||
|
||||
Usage: ./gpass_cli [-f config_file] [-p server_port] [-c CA_certificate_path] [-l PBKDF2_level] [-s gpass_server] [-v] -d domain -u username
|
||||
|
||||
You can save recurrent parameters into a configuration file. Default config file is found at $HOME/.local/share/gpass/gpass.ini
|
||||
|
||||
The dependencies are libcurl and OpenSSL (-dev packages : ie _libcurl4-openssl-dev_ and _libssl-dev_)
|
||||
|
||||
A sample configuration file is available _gpass.ini.sample_
|
||||
|
||||
Version Information
|
||||
-------------------
|
||||
|
||||
Current version is 0.8.2 **(not compatible with 0.7)**
|
||||
|
||||
Firefox will remove support for addons, so the gPass addon code is not supported since v0.8, please migrate to webextension.
|
||||
|
||||
Transition from v0.7 to v0.8 : **Please update your masterkey (even with the same one) to gain a security level of your passwords's wallet.**
|
||||
|
||||
**This version is incompatible from 0.1**. Please use [this script](http://soutade.fr/files/gpass_migrate_0_1.php) to migrate.
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
All the code is licensed under GPL v3. Source code is available [here](http://indefero.soutade.fr/p/gpass).
|
||||
@@ -288,21 +288,18 @@ function wildcard_domain(domain)
|
||||
{
|
||||
var parts = domain.split(".");
|
||||
|
||||
if (parts.length >= 3)
|
||||
// Standard root domain (zzz.xxx.com) or more
|
||||
if (parts.length > 2)
|
||||
{
|
||||
// Seems to be a two level root domain (ie zzz.xxx.co.uk ...)
|
||||
if (parts[parts.length-2].lenght <= 3)
|
||||
{
|
||||
if (parts.length > 3)
|
||||
return "*" + "." + parts[parts.length-3] + "." + parts[parts.length-2] + "." + parts[parts.length-1];
|
||||
}
|
||||
// Standard root domain (zzz.xxx.com)
|
||||
else
|
||||
return "*" + "." + parts[parts.length-2] + "." + parts[parts.length-1];
|
||||
res = "*.";
|
||||
for (i=1; i<parts.length; i++)
|
||||
res += parts[i] + ".";
|
||||
// Remove last "."
|
||||
return res.substr(0, res.length-1);
|
||||
}
|
||||
// Simple xxx.com
|
||||
else if (parts.length == 2)
|
||||
return "*" + "." + parts[0] + "." + parts[1];
|
||||
return "*." + domain;
|
||||
|
||||
return "";
|
||||
}
|
||||
@@ -463,4 +460,8 @@ async function self_test()
|
||||
console.log("Self test OK !");
|
||||
}
|
||||
|
||||
console.log("Welcome to gPass web extension v0.8.2 !");
|
||||
console.log("Privacy Policy can be found at http://indefero.soutade.fr/p/gpass/source/tree/master/PrivacyPolicy.md");
|
||||
console.log("");
|
||||
|
||||
//self_test();
|
||||
|
||||
@@ -80,11 +80,11 @@ function crypto_pbkdf2(mkey, salt, level)
|
||||
return key;
|
||||
})
|
||||
.catch(function(err){
|
||||
console.log("Error derive key " + err);
|
||||
debug("Error derive key " + err);
|
||||
});
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.log("Error import key" + err);
|
||||
debug("Error import key" + err);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -112,11 +112,11 @@ function simple_pbkdf2(mkey, salt, level)
|
||||
});
|
||||
})
|
||||
.catch(function(err){
|
||||
console.log("Error derive key " + err);
|
||||
debug("Error derive key " + err);
|
||||
});
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.log("Error import key" + err);
|
||||
debug("Error import key" + err);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ function _encrypt(mkey, iv, data)
|
||||
return ab2str(encrypted);
|
||||
})
|
||||
.catch(function(encryption) {
|
||||
console.log("Encryption rejected " + encryption);
|
||||
debug("Encryption rejected " + encryption);
|
||||
});
|
||||
|
||||
return promise;
|
||||
@@ -164,7 +164,7 @@ async function _decrypt(mkey, iv, data)
|
||||
return ab2str(decrypted);
|
||||
})
|
||||
.catch(function(decryption) {
|
||||
console.log("Decryption rejected " + decryption);
|
||||
debug("Decryption rejected " + decryption);
|
||||
});
|
||||
|
||||
return promise;
|
||||
@@ -174,7 +174,7 @@ async function encrypt_ecb(mkey, data)
|
||||
{
|
||||
var result = "";
|
||||
|
||||
console.log("Encrypt ECB " + data);
|
||||
debug("Encrypt ECB " + data);
|
||||
|
||||
nulliv = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
@@ -195,7 +195,7 @@ async function decrypt_ecb(mkey, data)
|
||||
{
|
||||
var result = "";
|
||||
|
||||
console.log("Decrypt ECB " + data);
|
||||
debug("Decrypt ECB " + data);
|
||||
|
||||
nulliv = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
@@ -214,7 +214,7 @@ async function decrypt_ecb(mkey, data)
|
||||
|
||||
async function encrypt_cbc(mkey, iv, data)
|
||||
{
|
||||
console.log("Encrypt CBC " + data);
|
||||
debug("Encrypt CBC " + data);
|
||||
|
||||
var result = await _encrypt(mkey, str2ab(iv), data);
|
||||
|
||||
@@ -224,7 +224,7 @@ async function encrypt_cbc(mkey, iv, data)
|
||||
|
||||
async function decrypt_cbc(mkey, iv, data)
|
||||
{
|
||||
console.log("Decrypt CBC " + data);
|
||||
debug("Decrypt CBC " + data);
|
||||
|
||||
var result = await _decrypt(mkey, str2ab(iv), data);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
"name": "gPass",
|
||||
"short_name": "gPass",
|
||||
"version": "0.8",
|
||||
"version": "0.8.2",
|
||||
"description": "gPass : global password manager",
|
||||
"icons" : {"16":"icons/gpass_icon_16.png", "32":"icons/gpass_icon_32.png", "64":"icons/gpass_icon_64.png", "128":"icons/gpass_icon_128.png"},
|
||||
"author" : "Grégory Soutadé",
|
||||
|
||||
15
cli/main.c
15
cli/main.c
@@ -297,20 +297,13 @@ static char* wildcard_domain(char* domain)
|
||||
}
|
||||
|
||||
// Final level
|
||||
level_length[cur_level] = tmp - level_ptr[cur_level-1];
|
||||
level_length[cur_level-1] = tmp - level_ptr[cur_level-1];
|
||||
|
||||
tmp = NULL;
|
||||
if (cur_level >= 3)
|
||||
if (cur_level > 2)
|
||||
{
|
||||
// Seems to be a two level root domain (ie zzz.xxx.co.uk ...)
|
||||
if (level_length[cur_level-2] <= 3)
|
||||
{
|
||||
if (cur_level > 3)
|
||||
tmp = level_ptr[cur_level-3];
|
||||
}
|
||||
else
|
||||
// Standard root domain (zzz.xxx.com)
|
||||
tmp = level_ptr[cur_level-2];
|
||||
// Standard root domain (zzz.xxx.com) or more
|
||||
tmp = level_ptr[1];
|
||||
}
|
||||
// Simple xxx.com
|
||||
else if (cur_level == 2)
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
gPass : global Password
|
||||
=======================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Everyday we have a lot of passwords to manage corresponding to a lot of accounts we use. It's hard to remain all of these, moreover if we don't use it often. So, what most people do is to generate only a subset of passwords easy to remain. This implies two common errors :
|
||||
|
||||
* Password are not very strong
|
||||
* We use them for multiple accounts
|
||||
|
||||
The best way to avoid these errors is to have a unique strong password for each account. gPass helps to reach this goal : you keep a subset of passwords (called master key) and for each login/password tuple you chose, gPass returns the real password by querying a password server.
|
||||
|
||||
To have a high level of security, all stored information (server side) is encrypted. Nothing is stored on client. The decryption is done on the fly when it's needed and only with user input. So, a hacker can get your password database, it will not be able to see any information (except if it bruteforce your masterkey) ! So it's important to choose to strong masterkey !
|
||||
|
||||
This addon is like [last pass](https://lastpass.com/) one, but I wanted it to be open source and home hostable (be careful on server down !). Moreover, with gPass, you can have multiple master keys !
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The first thing to do is to populate your database (from your/a password server) with website/login/password/master key values. You can use * character to access to all subdomains of a specific website. If you want to make strong password, there is a password generator. After that, configure your addon in "tools -> addons -> gPass -> preferences" to point to your password server (+ username). Be careful, login and password are case sensitive.
|
||||
|
||||
When you're in a login form and you want to use gPass, type your login and fill "@@masterkey" in password field. Then submit and password will automatically be replaced by the one in the database (after addon decrypt it).
|
||||
|
||||
You can also type "@_masterkey" to only replace your password without submiting and manually submit. This allows to support more websites.
|
||||
|
||||
|
||||
Technical details
|
||||
-----------------
|
||||
|
||||
The two columns in database are "login" and "password".
|
||||
login is compounded by "@@domain;login" encrypted with AES 256
|
||||
password is salted and encrypted with AES 256
|
||||
|
||||
The key that encrypt these fields is PBKDF2(hmac-sha256, masterkey, password_server_url, 1000, 256)
|
||||
|
||||
For now, the only addons made is for firefox. Server side is written in PHP (with SQLite3 for database component).
|
||||
|
||||
|
||||
Server
|
||||
------
|
||||
|
||||
To host a password server, you need a webserver. Just copy server files in a directory read/write for web server user (www-data). A sample apache2 configuration file is available in ressources. For enhanced security, it's better to put the password server under https and add authentication to admin panel. Server side is written in PHP (with SQLite3 for database component).
|
||||
|
||||
Configuration parameters are in conf.php
|
||||
|
||||
A demonstration server is available [here](http://gpass-demo.soutade.fr). It's the default server of XPI package (user demo).
|
||||
|
||||
**Warning** The master key derivation is partially based on account URL. So it's linked to your server information. Currently there is no simple way to export/import a full gPass database.
|
||||
|
||||
Client
|
||||
------
|
||||
|
||||
Just install xpi package. You can have debug information by setting DEBUG in main.js (use it with firefox addon sdk).
|
||||
|
||||
|
||||
Licence
|
||||
-------
|
||||
|
||||
All the code is licenced under GPL v3. Source code is available [here](http://indefero.soutade.fr/p/gpass).
|
||||
1
firefox_addon/README.md
Symbolic link
1
firefox_addon/README.md
Symbolic link
@@ -0,0 +1 @@
|
||||
../README.md
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
"name": "gPass",
|
||||
"short_name": "gPass",
|
||||
"version": "0.8",
|
||||
"version": "0.8.2",
|
||||
"description": "gPass : global password manager",
|
||||
"icons" : {"16":"icons/gpass_icon_16.png", "32":"icons/gpass_icon_32.png", "64":"icons/gpass_icon_64.png", "128":"icons/gpass_icon_128.png"},
|
||||
"author" : "Grégory Soutadé",
|
||||
|
||||
@@ -761,6 +761,8 @@ function add_password()
|
||||
startClearTimer();
|
||||
});
|
||||
|
||||
window.scrollTo(0,document.body.scrollHeight);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user