mirror of
https://github.com/darkwire/darkwire.io.git
synced 2025-07-19 19:14:53 +00:00
Fix audio class, moving crypto functions
This commit is contained in:
parent
316db0cfc5
commit
f008a7db93
@ -1,6 +1,6 @@
|
|||||||
export default class AudoHandler {
|
export default class AudoHandler {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.beep = new Audio('beep.mp3');
|
this._beep = window.Audio && new window.Audio('beep.mp3') || false;
|
||||||
this._soundEnabled = true;
|
this._soundEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9,13 +9,14 @@ export default class AudoHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set soundEnabled(state) {
|
set soundEnabled(state) {
|
||||||
if (state) {
|
|
||||||
this._soundEnabled = state;
|
this._soundEnabled = state;
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
play() {
|
play() {
|
||||||
this.beep.play();
|
if (this._beep && this.soundEnabled) {
|
||||||
|
this._beep.play();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
237
src/js/crypto.js
Normal file
237
src/js/crypto.js
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
export default class CryptoUtil {
|
||||||
|
constructor() {
|
||||||
|
this._crypto = window.crypto || false;
|
||||||
|
|
||||||
|
if (!this._crypto || (!this._crypto.subtle && !this._crypto.webkitSubtle)) {
|
||||||
|
$('#no-crypto').modal({
|
||||||
|
backdrop: 'static',
|
||||||
|
show: false,
|
||||||
|
keyboard: false
|
||||||
|
})
|
||||||
|
$('#no-crypto').modal('show');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
get crypto() {
|
||||||
|
return this._crypto;
|
||||||
|
}
|
||||||
|
|
||||||
|
convertStringToArrayBufferView(str) {
|
||||||
|
let bytes = new Uint8Array(str.length);
|
||||||
|
for (let i = 0; i < str.length; i++) {
|
||||||
|
bytes[i] = str.charCodeAt(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
convertArrayBufferViewToString(buffer) {
|
||||||
|
let str = "";
|
||||||
|
for (let i = 0; i < buffer.byteLength; i++) {
|
||||||
|
str += String.fromCharCode(buffer[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
createSigningKey() {
|
||||||
|
return this._crypto.subtle.generateKey(
|
||||||
|
{
|
||||||
|
name: "HMAC",
|
||||||
|
hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
|
||||||
|
//length: 256, //optional, if you want your key length to differ from the hash function's block length
|
||||||
|
},
|
||||||
|
true, //whether the key is extractable (i.e. can be used in exportKey)
|
||||||
|
["sign", "verify"] //can be any combination of "sign" and "verify"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
createPrimaryKeys() {
|
||||||
|
return this._crypto.subtle.generateKey(
|
||||||
|
{
|
||||||
|
name: "RSA-OAEP",
|
||||||
|
modulusLength: 2048, //can be 1024, 2048, or 4096
|
||||||
|
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
||||||
|
hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
|
||||||
|
},
|
||||||
|
true, //whether the key is extractable (i.e. can be used in exportKey)
|
||||||
|
["encrypt", "decrypt"] //must be ["encrypt", "decrypt"] or ["wrapKey", "unwrapKey"]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
createSecretKey() {
|
||||||
|
return this._crypto.subtle.generateKey(
|
||||||
|
{
|
||||||
|
name: "AES-CBC",
|
||||||
|
length: 256, //can be 128, 192, or 256
|
||||||
|
},
|
||||||
|
true, //whether the key is extractable (i.e. can be used in exportKey)
|
||||||
|
["encrypt", "decrypt"] //can be "encrypt", "decrypt", "wrapKey", or "unwrapKey"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
encryptSecretKey(data, secretKey) {
|
||||||
|
// Secret key will be recipient's public key
|
||||||
|
return this._crypto.subtle.encrypt(
|
||||||
|
{
|
||||||
|
name: "RSA-OAEP",
|
||||||
|
modulusLength: 2048,
|
||||||
|
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
||||||
|
hash: {name: "SHA-256"}
|
||||||
|
},
|
||||||
|
secretKey,
|
||||||
|
data //ArrayBuffer of data you want to encrypt
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
decryptSecretKey(data, key) {
|
||||||
|
// key will be my private key
|
||||||
|
return this._crypto.subtle.decrypt(
|
||||||
|
{
|
||||||
|
name: "RSA-OAEP",
|
||||||
|
modulusLength: 2048,
|
||||||
|
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
||||||
|
hash: {name: "SHA-256"}
|
||||||
|
//label: Uint8Array([...]) //optional
|
||||||
|
},
|
||||||
|
key,
|
||||||
|
data //ArrayBuffer of the data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
encryptSigningKey(data, signingKey) {
|
||||||
|
// Secret key will be recipient's public key
|
||||||
|
return this._crypto.subtle.encrypt(
|
||||||
|
{
|
||||||
|
name: "RSA-OAEP",
|
||||||
|
modulusLength: 2048,
|
||||||
|
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
||||||
|
hash: {name: "SHA-256"}
|
||||||
|
},
|
||||||
|
signingKey,
|
||||||
|
data //ArrayBuffer of data you want to encrypt
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
decryptSigningKey(data, key) {
|
||||||
|
// key will be my private key
|
||||||
|
return this._crypto.subtle.decrypt(
|
||||||
|
{
|
||||||
|
name: "RSA-OAEP",
|
||||||
|
modulusLength: 2048,
|
||||||
|
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
||||||
|
hash: {name: "SHA-256"}
|
||||||
|
//label: Uint8Array([...]) //optional
|
||||||
|
},
|
||||||
|
key,
|
||||||
|
data //ArrayBuffer of the data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
encryptMessage(data, secretKey, iv) {
|
||||||
|
return this._crypto.subtle.encrypt(
|
||||||
|
{
|
||||||
|
name: "AES-CBC",
|
||||||
|
//Don't re-use initialization vectors!
|
||||||
|
//Always generate a new iv every time your encrypt!
|
||||||
|
iv: iv,
|
||||||
|
},
|
||||||
|
secretKey, //from generateKey or importKey above
|
||||||
|
data //ArrayBuffer of data you want to encrypt
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
decryptMessage(data, secretKey, iv) {
|
||||||
|
return this._crypto.subtle.decrypt(
|
||||||
|
{
|
||||||
|
name: "AES-CBC",
|
||||||
|
iv: iv, //The initialization vector you used to encrypt
|
||||||
|
},
|
||||||
|
secretKey, //from generateKey or importKey above
|
||||||
|
data //ArrayBuffer of the data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
importSecretKey(jwkData, format) {
|
||||||
|
return this._crypto.subtle.importKey(
|
||||||
|
format || "jwk", //can be "jwk" or "raw"
|
||||||
|
//this is an example jwk key, "raw" would be an ArrayBuffer
|
||||||
|
jwkData,
|
||||||
|
{ //this is the algorithm options
|
||||||
|
name: "AES-CBC",
|
||||||
|
},
|
||||||
|
true, //whether the key is extractable (i.e. can be used in exportKey)
|
||||||
|
["encrypt", "decrypt"] //can be "encrypt", "decrypt", "wrapKey", or "unwrapKey"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
importPrimaryKey(jwkData, format) {
|
||||||
|
// Will be someone's public key
|
||||||
|
let hashObj = {
|
||||||
|
name: "RSA-OAEP"
|
||||||
|
};
|
||||||
|
if (!this._crypto.webkitSubtle) {
|
||||||
|
hashObj.hash = {name: "SHA-256"};
|
||||||
|
}
|
||||||
|
return this._crypto.subtle.importKey(
|
||||||
|
format || "jwk", //can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only)
|
||||||
|
jwkData,
|
||||||
|
hashObj,
|
||||||
|
true, //whether the key is extractable (i.e. can be used in exportKey)
|
||||||
|
["encrypt"] //"encrypt" or "wrapKey" for public key import or
|
||||||
|
//"decrypt" or "unwrapKey" for private key imports
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
exportKey(key, format) {
|
||||||
|
// Will be public primary key or public signing key
|
||||||
|
return this._crypto.subtle.exportKey(
|
||||||
|
format || "jwk", //can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only)
|
||||||
|
key //can be a publicKey or privateKey, as long as extractable was true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
importSigningKey(jwkData) {
|
||||||
|
return this._crypto.subtle.importKey(
|
||||||
|
"raw", //can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only)
|
||||||
|
//this is an example jwk key, other key types are Uint8Array objects
|
||||||
|
jwkData,
|
||||||
|
{ //these are the algorithm options
|
||||||
|
name: "HMAC",
|
||||||
|
hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
|
||||||
|
//length: 256, //optional, if you want your key length to differ from the hash function's block length
|
||||||
|
},
|
||||||
|
true, //whether the key is extractable (i.e. can be used in exportKey)
|
||||||
|
["verify"] //"verify" for public key import, "sign" for private key imports
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
signKey(data, keyToSignWith) {
|
||||||
|
// Will use my private key
|
||||||
|
return this._crypto.subtle.sign(
|
||||||
|
{
|
||||||
|
name: "HMAC",
|
||||||
|
hash: {name: "SHA-256"}
|
||||||
|
},
|
||||||
|
keyToSignWith, //from generateKey or importKey above
|
||||||
|
data //ArrayBuffer of data you want to sign
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
verifyKey(signature, data, keyToVerifyWith) {
|
||||||
|
// Will verify with sender's public key
|
||||||
|
return this._crypto.subtle.verify(
|
||||||
|
{
|
||||||
|
name: "HMAC",
|
||||||
|
hash: {name: "SHA-256"}
|
||||||
|
},
|
||||||
|
keyToVerifyWith, //from generateKey or importKey above
|
||||||
|
signature, //ArrayBuffer of the signature
|
||||||
|
data //ArrayBuffer of the data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
295
src/js/main.js
295
src/js/main.js
@ -1,4 +1,5 @@
|
|||||||
import AudioHandler from './audio';
|
import AudioHandler from './audio';
|
||||||
|
import CryptoUtil from './crypto';
|
||||||
|
|
||||||
let fs = window.RequestFileSystem || window.webkitRequestFileSystem;
|
let fs = window.RequestFileSystem || window.webkitRequestFileSystem;
|
||||||
|
|
||||||
@ -9,6 +10,7 @@ window.favicon = new Favico({
|
|||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
const audio = new AudioHandler();
|
const audio = new AudioHandler();
|
||||||
|
const cryptoUtil = new CryptoUtil();
|
||||||
|
|
||||||
let isActive = false;
|
let isActive = false;
|
||||||
let newMessages = 0;
|
let newMessages = 0;
|
||||||
@ -45,16 +47,6 @@ $(function() {
|
|||||||
|
|
||||||
if (!roomId) return;
|
if (!roomId) return;
|
||||||
|
|
||||||
if (!window.crypto || (!window.crypto.subtle && !window.crypto.webkitSubtle)) {
|
|
||||||
$('#no-crypto').modal({
|
|
||||||
backdrop: 'static',
|
|
||||||
show: false,
|
|
||||||
keyboard: false
|
|
||||||
})
|
|
||||||
$('#no-crypto').modal('show');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$('input.share-text').val("https://darkwire.io" + roomId);
|
$('input.share-text').val("https://darkwire.io" + roomId);
|
||||||
|
|
||||||
$('input.share-text').click(function() {
|
$('input.share-text').click(function() {
|
||||||
@ -92,7 +84,7 @@ $(function() {
|
|||||||
$inputMessage.focus();
|
$inputMessage.focus();
|
||||||
|
|
||||||
Promise.all([
|
Promise.all([
|
||||||
createPrimaryKeys()
|
cryptoUtil.createPrimaryKeys()
|
||||||
])
|
])
|
||||||
.then(function(data) {
|
.then(function(data) {
|
||||||
keys = {
|
keys = {
|
||||||
@ -100,7 +92,7 @@ $(function() {
|
|||||||
private: data[0].privateKey
|
private: data[0].privateKey
|
||||||
};
|
};
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
exportKey(data[0].publicKey, "spki")
|
cryptoUtil.exportKey(data[0].publicKey, "spki")
|
||||||
]);
|
]);
|
||||||
})
|
})
|
||||||
.then(function(exportedKeys) {
|
.then(function(exportedKeys) {
|
||||||
@ -301,7 +293,7 @@ $(function() {
|
|||||||
let promise = new Promise(function(resolve, reject) {
|
let promise = new Promise(function(resolve, reject) {
|
||||||
let currentUser = user;
|
let currentUser = user;
|
||||||
Promise.all([
|
Promise.all([
|
||||||
importPrimaryKey(currentUser.publicKey, "spki")
|
cryptoUtil.importPrimaryKey(currentUser.publicKey, "spki")
|
||||||
])
|
])
|
||||||
.then(function(keys) {
|
.then(function(keys) {
|
||||||
users.push({
|
users.push({
|
||||||
@ -352,7 +344,7 @@ $(function() {
|
|||||||
username: username,
|
username: username,
|
||||||
message: message
|
message: message
|
||||||
});
|
});
|
||||||
let vector = crypto.getRandomValues(new Uint8Array(16));
|
let vector = cryptoUtil.crypto.getRandomValues(new Uint8Array(16));
|
||||||
|
|
||||||
let secretKey;
|
let secretKey;
|
||||||
let secretKeys;
|
let secretKeys;
|
||||||
@ -362,10 +354,10 @@ $(function() {
|
|||||||
let encryptedMessageData;
|
let encryptedMessageData;
|
||||||
|
|
||||||
// Generate new secret key and vector for each message
|
// Generate new secret key and vector for each message
|
||||||
createSecretKey()
|
cryptoUtil.createSecretKey()
|
||||||
.then(function(key) {
|
.then(function(key) {
|
||||||
secretKey = key;
|
secretKey = key;
|
||||||
return createSigningKey();
|
return cryptoUtil.createSigningKey();
|
||||||
})
|
})
|
||||||
.then(function(key) {
|
.then(function(key) {
|
||||||
signingKey = key;
|
signingKey = key;
|
||||||
@ -380,23 +372,23 @@ $(function() {
|
|||||||
let secretKeyStr;
|
let secretKeyStr;
|
||||||
|
|
||||||
// Export secret key
|
// Export secret key
|
||||||
exportKey(secretKey, "raw")
|
cryptoUtil.exportKey(secretKey, "raw")
|
||||||
.then(function(data) {
|
.then(function(data) {
|
||||||
return encryptSecretKey(data, thisUser.publicKey);
|
return cryptoUtil.encryptSecretKey(data, thisUser.publicKey);
|
||||||
})
|
})
|
||||||
.then(function(encryptedSecretKey) {
|
.then(function(encryptedSecretKey) {
|
||||||
let encData = new Uint8Array(encryptedSecretKey);
|
let encData = new Uint8Array(encryptedSecretKey);
|
||||||
secretKeyStr = convertArrayBufferViewToString(encData);
|
secretKeyStr = cryptoUtil.convertArrayBufferViewToString(encData);
|
||||||
// Export HMAC signing key
|
// Export HMAC signing key
|
||||||
return exportKey(signingKey, "raw");
|
return cryptoUtil.exportKey(signingKey, "raw");
|
||||||
})
|
})
|
||||||
.then(function(data) {
|
.then(function(data) {
|
||||||
// Encrypt signing key with user's public key
|
// Encrypt signing key with user's public key
|
||||||
return encryptSigningKey(data, thisUser.publicKey);
|
return cryptoUtil.encryptSigningKey(data, thisUser.publicKey);
|
||||||
})
|
})
|
||||||
.then(function(encryptedSigningKey) {
|
.then(function(encryptedSigningKey) {
|
||||||
let encData = new Uint8Array(encryptedSigningKey);
|
let encData = new Uint8Array(encryptedSigningKey);
|
||||||
var str = convertArrayBufferViewToString(encData);
|
var str = cryptoUtil.convertArrayBufferViewToString(encData);
|
||||||
resolve({
|
resolve({
|
||||||
id: thisUser.id,
|
id: thisUser.id,
|
||||||
secretKey: secretKeyStr,
|
secretKey: secretKeyStr,
|
||||||
@ -411,18 +403,18 @@ $(function() {
|
|||||||
})
|
})
|
||||||
.then(function(data) {
|
.then(function(data) {
|
||||||
secretKeys = data;
|
secretKeys = data;
|
||||||
messageData = convertStringToArrayBufferView(message);
|
messageData = cryptoUtil.convertStringToArrayBufferView(message);
|
||||||
return signKey(messageData, signingKey);
|
return cryptoUtil.signKey(messageData, signingKey);
|
||||||
})
|
})
|
||||||
.then(function(data) {
|
.then(function(data) {
|
||||||
signature = data;
|
signature = data;
|
||||||
return encryptMessage(messageData, secretKey, vector);
|
return cryptoUtil.encryptMessage(messageData, secretKey, vector);
|
||||||
})
|
})
|
||||||
.then(function(data) {
|
.then(function(data) {
|
||||||
encryptedMessageData = data;
|
encryptedMessageData = data;
|
||||||
let msg = convertArrayBufferViewToString(new Uint8Array(encryptedMessageData));
|
let msg = cryptoUtil.convertArrayBufferViewToString(new Uint8Array(encryptedMessageData));
|
||||||
let vct = convertArrayBufferViewToString(new Uint8Array(vector));
|
let vct = cryptoUtil.convertArrayBufferViewToString(new Uint8Array(vector));
|
||||||
let sig = convertArrayBufferViewToString(new Uint8Array(signature));
|
let sig = cryptoUtil.convertArrayBufferViewToString(new Uint8Array(signature));
|
||||||
socket.emit('new message', {
|
socket.emit('new message', {
|
||||||
message: msg,
|
message: msg,
|
||||||
vector: vct,
|
vector: vct,
|
||||||
@ -439,17 +431,15 @@ $(function() {
|
|||||||
if (!isActive) {
|
if (!isActive) {
|
||||||
newMessages++;
|
newMessages++;
|
||||||
favicon.badge(newMessages);
|
favicon.badge(newMessages);
|
||||||
if (audio.soundEnabled && beep) {
|
|
||||||
audio.play();
|
audio.play();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let message = data.message;
|
let message = data.message;
|
||||||
let messageData = convertStringToArrayBufferView(message);
|
let messageData = cryptoUtil.convertStringToArrayBufferView(message);
|
||||||
let username = data.username;
|
let username = data.username;
|
||||||
let senderId = data.id
|
let senderId = data.id
|
||||||
let vector = data.vector;
|
let vector = data.vector;
|
||||||
let vectorData = convertStringToArrayBufferView(vector);
|
let vectorData = cryptoUtil.convertStringToArrayBufferView(vector);
|
||||||
let secretKeys = data.secretKeys;
|
let secretKeys = data.secretKeys;
|
||||||
let decryptedMessageData;
|
let decryptedMessageData;
|
||||||
let decryptedMessage;
|
let decryptedMessage;
|
||||||
@ -458,29 +448,29 @@ $(function() {
|
|||||||
return key.id === myUserId;
|
return key.id === myUserId;
|
||||||
});
|
});
|
||||||
let signature = data.signature;
|
let signature = data.signature;
|
||||||
let signatureData = convertStringToArrayBufferView(signature);
|
let signatureData = cryptoUtil.convertStringToArrayBufferView(signature);
|
||||||
let secretKeyArrayBuffer = convertStringToArrayBufferView(mySecretKey.secretKey);
|
let secretKeyArrayBuffer = cryptoUtil.convertStringToArrayBufferView(mySecretKey.secretKey);
|
||||||
let signingKeyArrayBuffer = convertStringToArrayBufferView(mySecretKey.encryptedSigningKey);
|
let signingKeyArrayBuffer = cryptoUtil.convertStringToArrayBufferView(mySecretKey.encryptedSigningKey);
|
||||||
|
|
||||||
decryptSecretKey(secretKeyArrayBuffer, keys.private)
|
cryptoUtil.decryptSecretKey(secretKeyArrayBuffer, keys.private)
|
||||||
.then(function(data) {
|
.then(function(data) {
|
||||||
return importSecretKey(new Uint8Array(data), "raw");
|
return cryptoUtil.importSecretKey(new Uint8Array(data), "raw");
|
||||||
})
|
})
|
||||||
.then(function(data) {
|
.then(function(data) {
|
||||||
let secretKey = data;
|
let secretKey = data;
|
||||||
return decryptMessage(messageData, secretKey, vectorData);
|
return cryptoUtil.decryptMessage(messageData, secretKey, vectorData);
|
||||||
})
|
})
|
||||||
.then(function(data) {
|
.then(function(data) {
|
||||||
decryptedMessageData = data;
|
decryptedMessageData = data;
|
||||||
decryptedMessage = convertArrayBufferViewToString(new Uint8Array(data))
|
decryptedMessage = cryptoUtil.convertArrayBufferViewToString(new Uint8Array(data))
|
||||||
return decryptSigningKey(signingKeyArrayBuffer, keys.private)
|
return cryptoUtil.decryptSigningKey(signingKeyArrayBuffer, keys.private)
|
||||||
})
|
})
|
||||||
.then(function(data) {
|
.then(function(data) {
|
||||||
return importSigningKey(new Uint8Array(data), "raw");
|
return cryptoUtil.importSigningKey(new Uint8Array(data), "raw");
|
||||||
})
|
})
|
||||||
.then(function(data) {
|
.then(function(data) {
|
||||||
let signingKey = data;
|
let signingKey = data;
|
||||||
return verifyKey(signatureData, decryptedMessageData, signingKey);
|
return cryptoUtil.verifyKey(signatureData, decryptedMessageData, signingKey);
|
||||||
})
|
})
|
||||||
.then(function(bool) {
|
.then(function(bool) {
|
||||||
if (bool) {
|
if (bool) {
|
||||||
@ -566,225 +556,10 @@ $(function() {
|
|||||||
$('.navbar-toggle:visible').click();
|
$('.navbar-toggle:visible').click();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('input.bs-switch').bootstrapSwitch();
|
let audioSwitch = $('input.bs-switch').bootstrapSwitch();
|
||||||
|
|
||||||
$('input.bs-switch').on('switchChange.bootstrapSwitch', function(event, state) {
|
audioSwitch.on('switchChange.bootstrapSwitch', function(event, state) {
|
||||||
audio.setSoundEnabled(state);
|
audio.soundEnabled = state;
|
||||||
});
|
});
|
||||||
|
|
||||||
function convertStringToArrayBufferView(str) {
|
|
||||||
var bytes = new Uint8Array(str.length);
|
|
||||||
for (var i = 0; i < str.length; i++) {
|
|
||||||
bytes[i] = str.charCodeAt(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
function convertArrayBufferViewToString(buffer) {
|
|
||||||
var str = "";
|
|
||||||
for (var i = 0; i < buffer.byteLength; i++) {
|
|
||||||
str += String.fromCharCode(buffer[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
function createSigningKey() {
|
|
||||||
return window.crypto.subtle.generateKey(
|
|
||||||
{
|
|
||||||
name: "HMAC",
|
|
||||||
hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
|
|
||||||
//length: 256, //optional, if you want your key length to differ from the hash function's block length
|
|
||||||
},
|
|
||||||
true, //whether the key is extractable (i.e. can be used in exportKey)
|
|
||||||
["sign", "verify"] //can be any combination of "sign" and "verify"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function createPrimaryKeys() {
|
|
||||||
return window.crypto.subtle.generateKey(
|
|
||||||
{
|
|
||||||
name: "RSA-OAEP",
|
|
||||||
modulusLength: 2048, //can be 1024, 2048, or 4096
|
|
||||||
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
|
||||||
hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
|
|
||||||
},
|
|
||||||
true, //whether the key is extractable (i.e. can be used in exportKey)
|
|
||||||
["encrypt", "decrypt"] //must be ["encrypt", "decrypt"] or ["wrapKey", "unwrapKey"]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function createSecretKey() {
|
|
||||||
return window.crypto.subtle.generateKey(
|
|
||||||
{
|
|
||||||
name: "AES-CBC",
|
|
||||||
length: 256, //can be 128, 192, or 256
|
|
||||||
},
|
|
||||||
true, //whether the key is extractable (i.e. can be used in exportKey)
|
|
||||||
["encrypt", "decrypt"] //can be "encrypt", "decrypt", "wrapKey", or "unwrapKey"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function encryptSecretKey(data, secretKey) {
|
|
||||||
// Secret key will be recipient's public key
|
|
||||||
return window.crypto.subtle.encrypt(
|
|
||||||
{
|
|
||||||
name: "RSA-OAEP",
|
|
||||||
modulusLength: 2048,
|
|
||||||
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
|
||||||
hash: {name: "SHA-256"}
|
|
||||||
},
|
|
||||||
secretKey,
|
|
||||||
data //ArrayBuffer of data you want to encrypt
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function decryptSecretKey(data, key) {
|
|
||||||
// key will be my private key
|
|
||||||
return window.crypto.subtle.decrypt(
|
|
||||||
{
|
|
||||||
name: "RSA-OAEP",
|
|
||||||
modulusLength: 2048,
|
|
||||||
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
|
||||||
hash: {name: "SHA-256"}
|
|
||||||
//label: Uint8Array([...]) //optional
|
|
||||||
},
|
|
||||||
key,
|
|
||||||
data //ArrayBuffer of the data
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function encryptSigningKey(data, signingKey) {
|
|
||||||
// Secret key will be recipient's public key
|
|
||||||
return window.crypto.subtle.encrypt(
|
|
||||||
{
|
|
||||||
name: "RSA-OAEP",
|
|
||||||
modulusLength: 2048,
|
|
||||||
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
|
||||||
hash: {name: "SHA-256"}
|
|
||||||
},
|
|
||||||
signingKey,
|
|
||||||
data //ArrayBuffer of data you want to encrypt
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function decryptSigningKey(data, key) {
|
|
||||||
// key will be my private key
|
|
||||||
return window.crypto.subtle.decrypt(
|
|
||||||
{
|
|
||||||
name: "RSA-OAEP",
|
|
||||||
modulusLength: 2048,
|
|
||||||
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
|
||||||
hash: {name: "SHA-256"}
|
|
||||||
//label: Uint8Array([...]) //optional
|
|
||||||
},
|
|
||||||
key,
|
|
||||||
data //ArrayBuffer of the data
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function encryptMessage(data, secretKey, iv) {
|
|
||||||
return window.crypto.subtle.encrypt(
|
|
||||||
{
|
|
||||||
name: "AES-CBC",
|
|
||||||
//Don't re-use initialization vectors!
|
|
||||||
//Always generate a new iv every time your encrypt!
|
|
||||||
iv: iv,
|
|
||||||
},
|
|
||||||
secretKey, //from generateKey or importKey above
|
|
||||||
data //ArrayBuffer of data you want to encrypt
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function decryptMessage(data, secretKey, iv) {
|
|
||||||
return window.crypto.subtle.decrypt(
|
|
||||||
{
|
|
||||||
name: "AES-CBC",
|
|
||||||
iv: iv, //The initialization vector you used to encrypt
|
|
||||||
},
|
|
||||||
secretKey, //from generateKey or importKey above
|
|
||||||
data //ArrayBuffer of the data
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function importSecretKey(jwkData, format) {
|
|
||||||
return window.crypto.subtle.importKey(
|
|
||||||
format || "jwk", //can be "jwk" or "raw"
|
|
||||||
//this is an example jwk key, "raw" would be an ArrayBuffer
|
|
||||||
jwkData,
|
|
||||||
{ //this is the algorithm options
|
|
||||||
name: "AES-CBC",
|
|
||||||
},
|
|
||||||
true, //whether the key is extractable (i.e. can be used in exportKey)
|
|
||||||
["encrypt", "decrypt"] //can be "encrypt", "decrypt", "wrapKey", or "unwrapKey"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function importPrimaryKey(jwkData, format) {
|
|
||||||
// Will be someone's public key
|
|
||||||
let hashObj = {
|
|
||||||
name: "RSA-OAEP"
|
|
||||||
};
|
|
||||||
if (!window.crypto.webkitSubtle) {
|
|
||||||
hashObj.hash = {name: "SHA-256"};
|
|
||||||
}
|
|
||||||
return window.crypto.subtle.importKey(
|
|
||||||
format || "jwk", //can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only)
|
|
||||||
jwkData,
|
|
||||||
hashObj,
|
|
||||||
true, //whether the key is extractable (i.e. can be used in exportKey)
|
|
||||||
["encrypt"] //"encrypt" or "wrapKey" for public key import or
|
|
||||||
//"decrypt" or "unwrapKey" for private key imports
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function exportKey(key, format) {
|
|
||||||
// Will be public primary key or public signing key
|
|
||||||
return window.crypto.subtle.exportKey(
|
|
||||||
format || "jwk", //can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only)
|
|
||||||
key //can be a publicKey or privateKey, as long as extractable was true
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function importSigningKey(jwkData) {
|
|
||||||
return window.crypto.subtle.importKey(
|
|
||||||
"raw", //can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only)
|
|
||||||
//this is an example jwk key, other key types are Uint8Array objects
|
|
||||||
jwkData,
|
|
||||||
{ //these are the algorithm options
|
|
||||||
name: "HMAC",
|
|
||||||
hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
|
|
||||||
//length: 256, //optional, if you want your key length to differ from the hash function's block length
|
|
||||||
},
|
|
||||||
true, //whether the key is extractable (i.e. can be used in exportKey)
|
|
||||||
["verify"] //"verify" for public key import, "sign" for private key imports
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function signKey(data, keyToSignWith) {
|
|
||||||
// Will use my private key
|
|
||||||
return window.crypto.subtle.sign(
|
|
||||||
{
|
|
||||||
name: "HMAC",
|
|
||||||
hash: {name: "SHA-256"}
|
|
||||||
},
|
|
||||||
keyToSignWith, //from generateKey or importKey above
|
|
||||||
data //ArrayBuffer of data you want to sign
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function verifyKey(signature, data, keyToVerifyWith) {
|
|
||||||
// Will verify with sender's public key
|
|
||||||
return window.crypto.subtle.verify(
|
|
||||||
{
|
|
||||||
name: "HMAC",
|
|
||||||
hash: {name: "SHA-256"}
|
|
||||||
},
|
|
||||||
keyToVerifyWith, //from generateKey or importKey above
|
|
||||||
signature, //ArrayBuffer of the signature
|
|
||||||
data //ArrayBuffer of the data
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user