mirror of
https://github.com/darkwire/darkwire.io.git
synced 2025-07-19 02:59:57 +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 {
|
||||
constructor() {
|
||||
this.beep = new Audio('beep.mp3');
|
||||
this._beep = window.Audio && new window.Audio('beep.mp3') || false;
|
||||
this._soundEnabled = true;
|
||||
}
|
||||
|
||||
@ -9,13 +9,14 @@ export default class AudoHandler {
|
||||
}
|
||||
|
||||
set soundEnabled(state) {
|
||||
if (state) {
|
||||
this._soundEnabled = state;
|
||||
}
|
||||
this._soundEnabled = state;
|
||||
return this;
|
||||
}
|
||||
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
297
src/js/main.js
297
src/js/main.js
@ -1,4 +1,5 @@
|
||||
import AudioHandler from './audio';
|
||||
import CryptoUtil from './crypto';
|
||||
|
||||
let fs = window.RequestFileSystem || window.webkitRequestFileSystem;
|
||||
|
||||
@ -9,6 +10,7 @@ window.favicon = new Favico({
|
||||
|
||||
$(function() {
|
||||
const audio = new AudioHandler();
|
||||
const cryptoUtil = new CryptoUtil();
|
||||
|
||||
let isActive = false;
|
||||
let newMessages = 0;
|
||||
@ -45,16 +47,6 @@ $(function() {
|
||||
|
||||
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').click(function() {
|
||||
@ -92,7 +84,7 @@ $(function() {
|
||||
$inputMessage.focus();
|
||||
|
||||
Promise.all([
|
||||
createPrimaryKeys()
|
||||
cryptoUtil.createPrimaryKeys()
|
||||
])
|
||||
.then(function(data) {
|
||||
keys = {
|
||||
@ -100,7 +92,7 @@ $(function() {
|
||||
private: data[0].privateKey
|
||||
};
|
||||
return Promise.all([
|
||||
exportKey(data[0].publicKey, "spki")
|
||||
cryptoUtil.exportKey(data[0].publicKey, "spki")
|
||||
]);
|
||||
})
|
||||
.then(function(exportedKeys) {
|
||||
@ -301,7 +293,7 @@ $(function() {
|
||||
let promise = new Promise(function(resolve, reject) {
|
||||
let currentUser = user;
|
||||
Promise.all([
|
||||
importPrimaryKey(currentUser.publicKey, "spki")
|
||||
cryptoUtil.importPrimaryKey(currentUser.publicKey, "spki")
|
||||
])
|
||||
.then(function(keys) {
|
||||
users.push({
|
||||
@ -352,7 +344,7 @@ $(function() {
|
||||
username: username,
|
||||
message: message
|
||||
});
|
||||
let vector = crypto.getRandomValues(new Uint8Array(16));
|
||||
let vector = cryptoUtil.crypto.getRandomValues(new Uint8Array(16));
|
||||
|
||||
let secretKey;
|
||||
let secretKeys;
|
||||
@ -362,10 +354,10 @@ $(function() {
|
||||
let encryptedMessageData;
|
||||
|
||||
// Generate new secret key and vector for each message
|
||||
createSecretKey()
|
||||
cryptoUtil.createSecretKey()
|
||||
.then(function(key) {
|
||||
secretKey = key;
|
||||
return createSigningKey();
|
||||
return cryptoUtil.createSigningKey();
|
||||
})
|
||||
.then(function(key) {
|
||||
signingKey = key;
|
||||
@ -380,23 +372,23 @@ $(function() {
|
||||
let secretKeyStr;
|
||||
|
||||
// Export secret key
|
||||
exportKey(secretKey, "raw")
|
||||
cryptoUtil.exportKey(secretKey, "raw")
|
||||
.then(function(data) {
|
||||
return encryptSecretKey(data, thisUser.publicKey);
|
||||
return cryptoUtil.encryptSecretKey(data, thisUser.publicKey);
|
||||
})
|
||||
.then(function(encryptedSecretKey) {
|
||||
let encData = new Uint8Array(encryptedSecretKey);
|
||||
secretKeyStr = convertArrayBufferViewToString(encData);
|
||||
secretKeyStr = cryptoUtil.convertArrayBufferViewToString(encData);
|
||||
// Export HMAC signing key
|
||||
return exportKey(signingKey, "raw");
|
||||
return cryptoUtil.exportKey(signingKey, "raw");
|
||||
})
|
||||
.then(function(data) {
|
||||
// Encrypt signing key with user's public key
|
||||
return encryptSigningKey(data, thisUser.publicKey);
|
||||
return cryptoUtil.encryptSigningKey(data, thisUser.publicKey);
|
||||
})
|
||||
.then(function(encryptedSigningKey) {
|
||||
let encData = new Uint8Array(encryptedSigningKey);
|
||||
var str = convertArrayBufferViewToString(encData);
|
||||
var str = cryptoUtil.convertArrayBufferViewToString(encData);
|
||||
resolve({
|
||||
id: thisUser.id,
|
||||
secretKey: secretKeyStr,
|
||||
@ -411,18 +403,18 @@ $(function() {
|
||||
})
|
||||
.then(function(data) {
|
||||
secretKeys = data;
|
||||
messageData = convertStringToArrayBufferView(message);
|
||||
return signKey(messageData, signingKey);
|
||||
messageData = cryptoUtil.convertStringToArrayBufferView(message);
|
||||
return cryptoUtil.signKey(messageData, signingKey);
|
||||
})
|
||||
.then(function(data) {
|
||||
signature = data;
|
||||
return encryptMessage(messageData, secretKey, vector);
|
||||
return cryptoUtil.encryptMessage(messageData, secretKey, vector);
|
||||
})
|
||||
.then(function(data) {
|
||||
encryptedMessageData = data;
|
||||
let msg = convertArrayBufferViewToString(new Uint8Array(encryptedMessageData));
|
||||
let vct = convertArrayBufferViewToString(new Uint8Array(vector));
|
||||
let sig = convertArrayBufferViewToString(new Uint8Array(signature));
|
||||
let msg = cryptoUtil.convertArrayBufferViewToString(new Uint8Array(encryptedMessageData));
|
||||
let vct = cryptoUtil.convertArrayBufferViewToString(new Uint8Array(vector));
|
||||
let sig = cryptoUtil.convertArrayBufferViewToString(new Uint8Array(signature));
|
||||
socket.emit('new message', {
|
||||
message: msg,
|
||||
vector: vct,
|
||||
@ -439,17 +431,15 @@ $(function() {
|
||||
if (!isActive) {
|
||||
newMessages++;
|
||||
favicon.badge(newMessages);
|
||||
if (audio.soundEnabled && beep) {
|
||||
audio.play();
|
||||
}
|
||||
audio.play();
|
||||
}
|
||||
|
||||
let message = data.message;
|
||||
let messageData = convertStringToArrayBufferView(message);
|
||||
let messageData = cryptoUtil.convertStringToArrayBufferView(message);
|
||||
let username = data.username;
|
||||
let senderId = data.id
|
||||
let vector = data.vector;
|
||||
let vectorData = convertStringToArrayBufferView(vector);
|
||||
let vectorData = cryptoUtil.convertStringToArrayBufferView(vector);
|
||||
let secretKeys = data.secretKeys;
|
||||
let decryptedMessageData;
|
||||
let decryptedMessage;
|
||||
@ -458,29 +448,29 @@ $(function() {
|
||||
return key.id === myUserId;
|
||||
});
|
||||
let signature = data.signature;
|
||||
let signatureData = convertStringToArrayBufferView(signature);
|
||||
let secretKeyArrayBuffer = convertStringToArrayBufferView(mySecretKey.secretKey);
|
||||
let signingKeyArrayBuffer = convertStringToArrayBufferView(mySecretKey.encryptedSigningKey);
|
||||
let signatureData = cryptoUtil.convertStringToArrayBufferView(signature);
|
||||
let secretKeyArrayBuffer = cryptoUtil.convertStringToArrayBufferView(mySecretKey.secretKey);
|
||||
let signingKeyArrayBuffer = cryptoUtil.convertStringToArrayBufferView(mySecretKey.encryptedSigningKey);
|
||||
|
||||
decryptSecretKey(secretKeyArrayBuffer, keys.private)
|
||||
cryptoUtil.decryptSecretKey(secretKeyArrayBuffer, keys.private)
|
||||
.then(function(data) {
|
||||
return importSecretKey(new Uint8Array(data), "raw");
|
||||
return cryptoUtil.importSecretKey(new Uint8Array(data), "raw");
|
||||
})
|
||||
.then(function(data) {
|
||||
let secretKey = data;
|
||||
return decryptMessage(messageData, secretKey, vectorData);
|
||||
return cryptoUtil.decryptMessage(messageData, secretKey, vectorData);
|
||||
})
|
||||
.then(function(data) {
|
||||
decryptedMessageData = data;
|
||||
decryptedMessage = convertArrayBufferViewToString(new Uint8Array(data))
|
||||
return decryptSigningKey(signingKeyArrayBuffer, keys.private)
|
||||
decryptedMessage = cryptoUtil.convertArrayBufferViewToString(new Uint8Array(data))
|
||||
return cryptoUtil.decryptSigningKey(signingKeyArrayBuffer, keys.private)
|
||||
})
|
||||
.then(function(data) {
|
||||
return importSigningKey(new Uint8Array(data), "raw");
|
||||
return cryptoUtil.importSigningKey(new Uint8Array(data), "raw");
|
||||
})
|
||||
.then(function(data) {
|
||||
let signingKey = data;
|
||||
return verifyKey(signatureData, decryptedMessageData, signingKey);
|
||||
return cryptoUtil.verifyKey(signatureData, decryptedMessageData, signingKey);
|
||||
})
|
||||
.then(function(bool) {
|
||||
if (bool) {
|
||||
@ -566,225 +556,10 @@ $(function() {
|
||||
$('.navbar-toggle:visible').click();
|
||||
});
|
||||
|
||||
$('input.bs-switch').bootstrapSwitch();
|
||||
let audioSwitch = $('input.bs-switch').bootstrapSwitch();
|
||||
|
||||
$('input.bs-switch').on('switchChange.bootstrapSwitch', function(event, state) {
|
||||
audio.setSoundEnabled(state);
|
||||
audioSwitch.on('switchChange.bootstrapSwitch', function(event, 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