Add Firefox WebExtension
This commit is contained in:
		
							
								
								
									
										17
									
								
								firefox_webextension/background.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								firefox_webextension/background.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | browser.runtime.onMessage.addListener( | ||||||
|  |     function(request) { | ||||||
|  |  | ||||||
|  | 	if (request.type == "notification") | ||||||
|  | 	{ | ||||||
|  | 	    options = { | ||||||
|  | 		type: "basic", | ||||||
|  | 		title : "gPass", | ||||||
|  | 		message : request.options.message, | ||||||
|  | 		iconUrl:browser.extension.getURL("gpass_icon_64.png") | ||||||
|  | 	    }; | ||||||
|  |  | ||||||
|  | 	    browser.notifications.create("gPass", options); | ||||||
|  |  | ||||||
|  | 	    window.setTimeout(function() {browser.notifications.clear("gPass")}, 2000); | ||||||
|  | 	} | ||||||
|  |     }); | ||||||
							
								
								
									
										220
									
								
								firefox_webextension/compat.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										220
									
								
								firefox_webextension/compat.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,220 @@ | |||||||
|  | /* | ||||||
|  |   Copyright (C) 2013-2016 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 <http://www.gnu.org/licenses/>. | ||||||
|  | */ | ||||||
|  |  | ||||||
|  | var default_preferences = {"pbkdf2_level": 1000, | ||||||
|  | 			   "account_url": "https://gpass-demo.soutade.fr/demo"}; | ||||||
|  |  | ||||||
|  | function notify(text, data) | ||||||
|  | { | ||||||
|  |     browser.runtime.sendMessage({type: "notification", options:{"message":text}}); | ||||||
|  | } | ||||||
|  | // https://stackoverflow.com/questions/6965107/converting-between-strings-and-arraybuffers | ||||||
|  | function ab2str(buf) { | ||||||
|  |     return String.fromCharCode.apply(null, new Uint8Array(buf)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String | ||||||
|  | function str2ab2(str) { | ||||||
|  |     var chars = [] | ||||||
|  |     for (var i=0, strLen=str.length; i < strLen; i++) { | ||||||
|  | 	chars.push(str.charCodeAt(i)); | ||||||
|  |     } | ||||||
|  |     return new Uint8Array(chars); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function str2ab(str) { | ||||||
|  |     var buf = new ArrayBuffer(str.length); // 2 bytes for each char | ||||||
|  |     // var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char | ||||||
|  |     var bufView = new Uint8Array(buf); | ||||||
|  |     for (var i=0, strLen=str.length; i < strLen; i++) { | ||||||
|  | 	bufView[i] = str.charCodeAt(i); | ||||||
|  |     } | ||||||
|  |     return bufView; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function returnResult(result) { return result;} | ||||||
|  | function onError(error) { console.error(error); } | ||||||
|  |  | ||||||
|  | function pbkdf2(mkey, salt, level) | ||||||
|  | { | ||||||
|  |     debug("Process pbkdf2 with " + mkey); | ||||||
|  |  | ||||||
|  |     AESCBC = { | ||||||
|  |         name: "AES-CBC", | ||||||
|  |         length: 256, | ||||||
|  |     } | ||||||
|  |     level=1000; | ||||||
|  |  | ||||||
|  |     var key = str2ab(mkey); | ||||||
|  |     return window.crypto.subtle.importKey("raw", key, {name: "PBKDF2"}, false, ["deriveBits", "deriveKey"]) | ||||||
|  | 	.then(function(key){ | ||||||
|  |             //sha-256 | ||||||
|  |             return window.crypto.subtle.deriveKey({ | ||||||
|  | 		name: "PBKDF2", | ||||||
|  | 		salt: str2ab(salt), | ||||||
|  | 		iterations: level, | ||||||
|  | 		hash: "SHA-256", | ||||||
|  |             }, key, AESCBC, false, ["encrypt", "decrypt", "unwrapKey", "wrapKey"]) | ||||||
|  | 		.then(function(key) { | ||||||
|  | 		    return key; | ||||||
|  | 		}) | ||||||
|  | 		.catch(function(err){ | ||||||
|  | 		    console.log("Error derive key " + err); | ||||||
|  | 		}); | ||||||
|  | 	}) | ||||||
|  | 	.catch(function(err) { | ||||||
|  | 	    console.log("Error import key" + err); | ||||||
|  | 	}); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function _encrypt(mkey, data) | ||||||
|  | { | ||||||
|  |     while ((data.length % 16)) | ||||||
|  | 	data += "\0"; | ||||||
|  |      | ||||||
|  |     debug("Encrypt " + data); | ||||||
|  |  | ||||||
|  |     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 window.crypto.subtle.encrypt({ | ||||||
|  |             name: "AES-CBC", | ||||||
|  |             iv: nulliv | ||||||
|  |     	}, mkey, data)}) | ||||||
|  |     	.then(function(encrypted) { | ||||||
|  |     	    return ab2str(encrypted); | ||||||
|  |     	}) | ||||||
|  |     	.catch(function(encryption) { | ||||||
|  |     	    console.log("Encryption rejected " + encryption); | ||||||
|  |     	}); | ||||||
|  |  | ||||||
|  |     return promise; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | async function _decrypt(mkey, data) | ||||||
|  | { | ||||||
|  |     while ((data.length % 16)) | ||||||
|  | 	data += "\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)); | ||||||
|  |  | ||||||
|  |     debug("Decrypt " + data); | ||||||
|  |  | ||||||
|  |     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 window.crypto.subtle.decrypt({ | ||||||
|  |             name: "AES-CBC", | ||||||
|  |             iv: nulliv | ||||||
|  |     	}, mkey, data)}) | ||||||
|  |     	.then(function(decrypted) { | ||||||
|  |     	    return ab2str(decrypted); | ||||||
|  |     	}) | ||||||
|  |     	.catch(function(decryption) { | ||||||
|  |     	    console.log("Decryption rejected " + decryption); | ||||||
|  |     	}); | ||||||
|  |  | ||||||
|  |     return promise; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | async function encrypt(mkey, data) | ||||||
|  | { | ||||||
|  |     var result = ""; | ||||||
|  |      | ||||||
|  |     while (data.length > 16) | ||||||
|  |     { | ||||||
|  | 	res = await _encrypt(mkey, data.slice(0, 16)); | ||||||
|  | 	// Remove PKCS7 padding | ||||||
|  | 	result += res.slice(0, 16); | ||||||
|  | 	data = data.slice(16); | ||||||
|  |     } | ||||||
|  |     res = await _encrypt(mkey, data); | ||||||
|  |     result += res.slice(0, 16); | ||||||
|  |  | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | async function decrypt(mkey, data) | ||||||
|  | { | ||||||
|  |     var result = ""; | ||||||
|  |      | ||||||
|  |     while (data.length > 16) | ||||||
|  |     { | ||||||
|  | 	res = await _decrypt(mkey, data.slice(0, 16)); | ||||||
|  | 	// Remove PKCS7 padding | ||||||
|  | 	result += res.slice(0, 16); | ||||||
|  | 	data = data.slice(16); | ||||||
|  |     } | ||||||
|  |     res = await _decrypt(mkey, data); | ||||||
|  |     result += res.slice(0, 16); | ||||||
|  |  | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function getPref(key) | ||||||
|  | { | ||||||
|  |     return browser.storage.local.get(key) | ||||||
|  | 	.then( | ||||||
|  | 	    function (pref) { | ||||||
|  | 		if (!pref.hasOwnProperty(key)) | ||||||
|  | 		    return default_preferences[key]; | ||||||
|  | 		return pref[key]; | ||||||
|  | 	    } | ||||||
|  | 	    , | ||||||
|  | 	    function (err) { | ||||||
|  | 		console.log("Error getting preference " + err); | ||||||
|  | 	    } | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function setPref(key, value) | ||||||
|  | { | ||||||
|  |     browser.storage.local.set({key:value}); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // function getPref(key) | ||||||
|  | // { | ||||||
|  | //     res = localStorage.getItem(key); | ||||||
|  | //     if (res == null) | ||||||
|  | // 	return default_preferences[key]; | ||||||
|  | //     return res; | ||||||
|  | // } | ||||||
|  |  | ||||||
|  | // function setPref(key, value) | ||||||
|  | // { | ||||||
|  | //     localStorage.setItem(key, value); | ||||||
|  | // } | ||||||
|  |  | ||||||
|  | // function load_preferences() | ||||||
|  | // { | ||||||
|  | //     preferences = {}; | ||||||
|  |  | ||||||
|  | //     for (var i = 0; i < localStorage.length; i++) | ||||||
|  | //     { | ||||||
|  | // 	k = localStorage.key(i); | ||||||
|  | // 	preferences[k] = getPref[k]; | ||||||
|  | //     } | ||||||
|  |  | ||||||
|  | //     return preferences; | ||||||
|  | // } | ||||||
							
								
								
									
										1
									
								
								firefox_webextension/gpass_icon_128.png
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								firefox_webextension/gpass_icon_128.png
									
									
									
									
									
										Symbolic link
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | ../resources/gpass_icon_128.png | ||||||
							
								
								
									
										1
									
								
								firefox_webextension/gpass_icon_16.png
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								firefox_webextension/gpass_icon_16.png
									
									
									
									
									
										Symbolic link
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | ../resources/gpass_icon_16.png | ||||||
							
								
								
									
										1
									
								
								firefox_webextension/gpass_icon_32.png
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								firefox_webextension/gpass_icon_32.png
									
									
									
									
									
										Symbolic link
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | ../resources/gpass_icon_32.png | ||||||
							
								
								
									
										1
									
								
								firefox_webextension/gpass_icon_64.png
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								firefox_webextension/gpass_icon_64.png
									
									
									
									
									
										Symbolic link
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | ../resources/gpass_icon_64.png | ||||||
							
								
								
									
										1
									
								
								firefox_webextension/lib
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								firefox_webextension/lib
									
									
									
									
									
										Symbolic link
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | ../chrome_addon/lib/ | ||||||
							
								
								
									
										35
									
								
								firefox_webextension/manifest.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								firefox_webextension/manifest.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | |||||||
|  | { | ||||||
|  |     "manifest_version": 2, | ||||||
|  |  | ||||||
|  |     "name": "gPass", | ||||||
|  |     "short_name": "gPass", | ||||||
|  |     "version": "0.8", | ||||||
|  |     "description": "gPass : global password manager", | ||||||
|  |     "icons" : {"16":"gpass_icon_16.png", "32":"gpass_icon_32.png", "64":"gpass_icon_64.png", "128":"gpass_icon_128.png"}, | ||||||
|  |     "author" : "Grégory Soutadé", | ||||||
|  |     "homepage_url" : "http://indefero.soutade.fr/p/gpass", | ||||||
|  |      | ||||||
|  |     "content_scripts": [ | ||||||
|  | 	{ | ||||||
|  | 	    "matches": ["https://*/*", "http://*/*"], | ||||||
|  | 	    "js": ["lib/parseuri.js", "compat.js", "lib/main.js"], | ||||||
|  | 	    "run_at" : "document_idle", | ||||||
|  | 	    "all_frames" : true | ||||||
|  | 	} | ||||||
|  |     ], | ||||||
|  |  | ||||||
|  |     "background": { | ||||||
|  | 	"persistent": false, | ||||||
|  | 	"scripts": ["background.js"] | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     "options_ui": { "page":"options.html" }, | ||||||
|  |  | ||||||
|  |     "permissions": [ | ||||||
|  | 	"https://*/", | ||||||
|  | 	"http://*/", | ||||||
|  | 	"notifications", | ||||||
|  | 	"storage", | ||||||
|  | 	"activeTab" | ||||||
|  |     ] | ||||||
|  | } | ||||||
							
								
								
									
										1
									
								
								firefox_webextension/options.html
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								firefox_webextension/options.html
									
									
									
									
									
										Symbolic link
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | ../chrome_addon/options.html | ||||||
							
								
								
									
										35
									
								
								firefox_webextension/options.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								firefox_webextension/options.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | |||||||
|  | var default_preferences = {"pbkdf2_level": 1000, | ||||||
|  | 			   "account_url": "https://gpass-demo.soutade.fr/demo"}; | ||||||
|  |  | ||||||
|  | function save() { | ||||||
|  |     var account_url = document.getElementById('account_url').value; | ||||||
|  |     var pbkdf2 = document.getElementById('pbkdf2').value; | ||||||
|  |  | ||||||
|  |     browser.storage.local.set({ | ||||||
|  | 	"account_url":account_url, | ||||||
|  | 	"pbkdf2_level":pbkdf2 | ||||||
|  |     }) | ||||||
|  | 	.then(function ok() { alert("Saved"); }, | ||||||
|  | 	      function err() { alert("Cannot save your preferences");} | ||||||
|  | 	     ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function restoreOptions() | ||||||
|  | { | ||||||
|  |     document.getElementById('account_url').value = default_preferences['account_url']; | ||||||
|  |     document.getElementById('pbkdf2').value = default_preferences['pbkdf2_level']; | ||||||
|  |  | ||||||
|  |     browser.storage.local.get().then( | ||||||
|  | 	function(prefs) | ||||||
|  | 	{ | ||||||
|  | 	    if (prefs.hasOwnProperty("account_url")) | ||||||
|  | 		document.getElementById('account_url').value = prefs["account_url"]; | ||||||
|  |  | ||||||
|  | 	    if (prefs.hasOwnProperty("pbkdf2_level")) | ||||||
|  | 		document.getElementById('pbkdf2').value = prefs["pbkdf2_level"]; | ||||||
|  | 	} | ||||||
|  |     ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | document.getElementById('save').addEventListener("click", save); | ||||||
|  | document.addEventListener("DOMContentLoaded", restoreOptions); | ||||||
		Reference in New Issue
	
	Block a user