-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathencrypt-storage.js
More file actions
143 lines (138 loc) · 4.36 KB
/
encrypt-storage.js
File metadata and controls
143 lines (138 loc) · 4.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* Encryption API using JavaScript native crypto.js and indexeDB for storing private keys */
const encrypt_storage_version = "1.1.15";
async function encryptMessage(message,publicKey) {
let encoded = new TextEncoder().encode(message);
let ciphertext = await window.crypto.subtle.encrypt(
{
name: "RSA-OAEP"
},
publicKey,
encoded
);
return ciphertext;
}
async function decryptMessage(ciphertext,privateKey) {
let decrypted = await window.crypto.subtle.decrypt(
{
name: "RSA-OAEP"
},
privateKey,
ciphertext
);
let dec = new TextDecoder();
return dec.decode(decrypted);
}
async function arrayBuffertoURI(arrayBuffer) {
let blob = new Blob([arrayBuffer]);
return new Promise((resolve) => {
let reader = new FileReader()
reader.onloadend = function() {
resolve(reader.result);
};
reader.readAsDataURL(blob);
});
}
function URItoarrayBuffer(URI) {
var byteString = atob(URI.split(',')[1]);
var arrayBuffer = new ArrayBuffer(byteString.length);
var _ia = new Uint8Array(arrayBuffer);
for (var i = 0; i < byteString.length; i++) {
_ia[i] = byteString.charCodeAt(i);
}
return arrayBuffer;
}
async function sha256sum(msg) {
let enc = new TextEncoder().encode(msg);
const buff = await crypto.subtle.digest('SHA-256', enc);
const barray = Array.from(new Uint8Array(buff));
let hex = barray.map(function(b) {
return b.toString(16).padStart(2, '0');
}).join('');
return hex;
};
function dbManager(user,key,sum) {
return new Promise(function(resolve, reject) {
var indexedDB = window.indexedDB || window.mozIndexedDB
|| window.webkitIndexedDB || window.msIndexedDB
|| window.shimIndexedDB;
var open = indexedDB.open("cve-services.apikeyStore", 1);
open.onupgradeneeded = function() {
var db = open.result;
if (!db.objectStoreNames.contains("keyStore")) {
var store = db.createObjectStore("keyStore",
{keyPath: "user"});
var index = store.createIndex("sigIndex", ["sum.sha256"]);
}
};
open.onsuccess = function() {
var db = open.result;
var tx = db.transaction("keyStore", "readwrite");
var store = tx.objectStore("keyStore");
if(key) {
store.put({user: user, key: key, sum: sum});
} else {
if(user) {
var getUser = store.get(user);
getUser.onsuccess = function(q) {
resolve(q);
};
} else if(sum.sha256) {
var index = store.index("sigIndex");
var getSum = index.get([sum.sha256]);
getSum.onsuccess = function(q) {
resolve(q);
};
} else {
reject("A user or a checksum is required");
}
};
tx.oncomplete = function() {
db.close();
};
}
});
}
async function save_key(user,key) {
let fpb = await window.crypto.subtle.exportKey("jwk", key.publicKey);
let fpr = await window.crypto.subtle.exportKey("jwk", key.privateKey);
/* Re-import private key as non-extractable to prevent JWK extraction */
let safePrivateKey = await window.crypto.subtle.importKey("jwk",fpr,
{name:"RSA-OAEP", hash: {name: "SHA-256"}},false,["decrypt"]);
let exportKey = {epr: safePrivateKey, epb: fpb};
let sum = {sha256: await sha256sum(fpb.n)};
dbManager(user,exportKey,sum);
return exportKey;
}
async function import_key({epr,epb}) {
/* epr may be a CryptoKey (new) or JWK object (legacy) */
let prkey = (epr instanceof CryptoKey) ? epr :
await window.crypto.subtle.importKey("jwk",epr,{name:"RSA-OAEP", hash: {name: "SHA-256"}},false,["decrypt"]);
let pbkey = await window.crypto.subtle.importKey("jwk",epb,{name:"RSA-OAEP", hash: {name: "SHA-256"}},false,["encrypt"]);
return { privateKey: prkey, publicKey: pbkey };
}
async function check_create_key(user) {
let dbKey = await dbManager(user);
if(('target' in dbKey) && (dbKey.target.result) &&
(dbKey.target.result.user == user)) {
return import_key(dbKey.target.result.key);
}
return window.crypto.subtle.generateKey(
{
name: "RSA-OAEP",
modulusLength: 4096,
publicExponent: new Uint8Array([1, 0, 1]),
hash: "SHA-256",
},
true,
["encrypt", "decrypt"]
).then(function(key) {
save_key(user,key);
return key;
});
}
/* Node.js / test environment exports */
if (typeof module !== "undefined" && module.exports) {
module.exports = { encryptMessage, decryptMessage, arrayBuffertoURI,
URItoarrayBuffer, sha256sum, dbManager, save_key, import_key,
check_create_key };
}