gPass

gPass Git Source Tree

Root/chrome_addon/lib/misc.js

1/*
2 Copyright (C) 2013-2017 Grégory Soutadé
3
4 This file is part of gPass.
5
6 gPass is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 gPass is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with gPass. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20var default_preferences = {"pbkdf2_level": 1000,
21 "account_url": "https://gpass-demo.soutade.fr/demo",
22 "crypto_v1_compatible": true};
23
24var browser = browser || chrome;
25var crypto = crypto || window.crypto;
26
27function notify(text, data)
28{
29 browser.runtime.sendMessage({type: "notification", options:{"message":text}});
30}
31
32function block_url(url)
33{
34 debug("Block URL " + url);
35 browser.runtime.sendMessage({type: "block_url", options:{"url":url}});
36}
37
38// https://stackoverflow.com/questions/6965107/converting-between-strings-and-arraybuffers
39function ab2str(buf) {
40 return String.fromCharCode.apply(null, new Uint8Array(buf));
41}
42
43// https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
44function str2ab2(str) {
45 var chars = []
46 for (var i=0, strLen=str.length; i < strLen; i++) {
47chars.push(str.charCodeAt(i));
48 }
49 return new Uint8Array(chars);
50}
51
52function str2ab(str) {
53 var buf = new ArrayBuffer(str.length);
54 // var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
55 var bufView = new Uint8Array(buf);
56 for (var i=0, strLen=str.length; i < strLen; i++) {
57bufView[i] = str.charCodeAt(i);
58 }
59 return bufView;
60}
61
62function crypto_pbkdf2(mkey, salt, level)
63{
64 AESCBC = {
65 name: "AES-CBC",
66 length: 256,
67 }
68
69 var key = str2ab(mkey);
70 return crypto.subtle.importKey("raw", key, {name: "PBKDF2"}, false, ["deriveBits", "deriveKey"])
71.then(function(key){
72 //sha-256
73 return crypto.subtle.deriveKey({
74name: "PBKDF2",
75salt: str2ab(salt),
76iterations: level,
77hash: "SHA-256",
78 }, key, AESCBC, false, ["encrypt", "decrypt", "unwrapKey", "wrapKey"])
79.then(function(key) {
80 return key;
81})
82.catch(function(err){
83 debug("Error derive key " + err);
84});
85})
86.catch(function(err) {
87 debug("Error import key" + err);
88});
89}
90
91function simple_pbkdf2(mkey, salt, level)
92{
93 AESCBC = {
94 name: "AES-CBC",
95 length: 256,
96 }
97
98 var key = str2ab(mkey);
99 return crypto.subtle.importKey("raw", key, {name: "PBKDF2"}, false, ["deriveBits", "deriveKey"])
100.then(function(key){
101 //sha-256
102 return crypto.subtle.deriveKey({
103name: "PBKDF2",
104salt: str2ab(salt),
105iterations: level,
106hash: "SHA-256",
107 }, key, AESCBC, true, ["unwrapKey", "wrapKey"])
108.then(function(key) {
109 return crypto.subtle.exportKey("raw", key)
110.then(function (key) {
111 return ab2str(key);
112});
113})
114.catch(function(err){
115 debug("Error derive key " + err);
116});
117})
118.catch(function(err) {
119 debug("Error import key" + err);
120});
121}
122
123function _encrypt(mkey, iv, data)
124{
125 while ((data.length % 16))
126data += "\0";
127
128 data = str2ab(data);
129
130 promise = mkey.then(function(mkey){
131 return crypto.subtle.encrypt({
132 name: "AES-CBC",
133 iv: iv
134 }, mkey, data)})
135 .then(function(encrypted) {
136 return ab2str(encrypted);
137 })
138 .catch(function(encryption) {
139 debug("Encryption rejected " + encryption);
140 });
141
142 return promise;
143}
144
145async function _decrypt(mkey, iv, data)
146{
147 while ((data.length % 16))
148data += "\0";
149
150 nulliv = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
151 pkcs7_padding = new Uint8Array([16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16]);
152 pkcs7_padding = await _encrypt(mkey, nulliv, ab2str(pkcs7_padding));
153
154 data = str2ab(data + pkcs7_padding);
155
156 nulliv = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
157
158 promise = mkey.then(function(mkey){
159 return crypto.subtle.decrypt({
160 name: "AES-CBC",
161 iv: iv
162 }, mkey, data)})
163 .then(function(decrypted) {
164 return ab2str(decrypted);
165 })
166 .catch(function(decryption) {
167 debug("Decryption rejected " + decryption);
168 });
169
170 return promise;
171}
172
173async function encrypt_ecb(mkey, data)
174{
175 var result = "";
176
177 debug("Encrypt ECB " + data);
178
179 nulliv = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
180
181 while (data.length > 16)
182 {
183res = await _encrypt(mkey, nulliv, data.slice(0, 16));
184// Remove PKCS7 padding
185result += res.slice(0, 16);
186data = data.slice(16);
187 }
188 res = await _encrypt(mkey, nulliv, data);
189 result += res.slice(0, 16);
190
191 return result;
192}
193
194async function decrypt_ecb(mkey, data)
195{
196 var result = "";
197
198 debug("Decrypt ECB " + data);
199
200 nulliv = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
201
202 while (data.length > 16)
203 {
204res = await _decrypt(mkey, nulliv, data.slice(0, 16));
205// Remove PKCS7 padding
206result += res.slice(0, 16);
207data = data.slice(16);
208 }
209 res = await _decrypt(mkey, nulliv, data);
210 result += res.slice(0, 16);
211
212 return result;
213}
214
215async function encrypt_cbc(mkey, iv, data)
216{
217 debug("Encrypt CBC " + data);
218
219 var result = await _encrypt(mkey, str2ab(iv), data);
220
221 // Remove PKCS7 padding
222 return result.slice(0, result.length-16);
223}
224
225async function decrypt_cbc(mkey, iv, data)
226{
227 debug("Decrypt CBC " + data);
228
229 var result = await _decrypt(mkey, str2ab(iv), data);
230
231 // Remove PKCS7 padding
232 return result.slice(0, result.length-16);
233}
234
235async function digest(data)
236{
237 return crypto.subtle.digest("SHA-256", str2ab(data)).then(function (hash) {
238return ab2str(hash);
239 });
240}

Archive Download this file