2019-05-13 09:39:17 -04:00

123 lines
3.3 KiB
JavaScript

import Crypto from './crypto'
const crypto = new Crypto()
export const process = (payload, state) => new Promise(async (resolve, reject) => {
const privateKeyJson = state.user.privateKey
const privateKey = await crypto.importEncryptDecryptKey(privateKeyJson, 'jwk', ['decrypt', 'unwrapKey'])
let sessionKey
let signingKey
const iv = await crypto.convertStringToArrayBufferView(payload.iv)
const signature = await crypto.convertStringToArrayBufferView(payload.signature)
const payloadBuffer = await crypto.convertStringToArrayBufferView(payload.payload)
await new Promise((resolvePayload) => {
payload.keys.forEach(async (key) => {
try {
sessionKey = await crypto.unwrapKey(
'jwk',
key.sessionKey,
privateKey,
{
name: 'RSA-OAEP',
hash: { name: 'SHA-1' },
},
{ name: 'AES-CBC' },
true,
['decrypt']
)
signingKey = await crypto.unwrapKey(
'jwk',
key.signingKey,
privateKey,
{
name: 'RSA-OAEP',
hash: { name: 'SHA-1' },
},
{ name: 'HMAC', hash: { name: 'SHA-256' } },
true,
['verify']
)
resolvePayload()
} catch (e) { } // eslint-disable-line
})
})
const verified = await crypto.verifyPayload(
signature,
payloadBuffer,
signingKey
)
if (!verified) {
reject()
return
}
const decryptedPayload = await crypto.decryptMessage(
payloadBuffer,
sessionKey,
iv
)
const payloadJson = JSON.parse(crypto.convertArrayBufferViewToString(new Uint8Array(decryptedPayload)))
resolve(payloadJson)
})
export const prepare = (payload, state) => new Promise(async (resolve) => {
const myUsername = state.user.username
const myId = state.user.id
const sessionKey = await crypto.createSecretKey()
const signingKey = await crypto.createSigningKey()
const iv = await crypto.crypto.getRandomValues(new Uint8Array(16))
const jsonToSend = {
...payload,
payload: {
...payload.payload,
sender: myId,
username: myUsername,
text: encodeURI(payload.payload.text),
},
}
const payloadBuffer = crypto.convertStringToArrayBufferView(JSON.stringify(jsonToSend))
const encryptedPayload = await crypto.encryptMessage(payloadBuffer, sessionKey, iv)
const payloadString = await crypto.convertArrayBufferViewToString(new Uint8Array(encryptedPayload))
const signature = await crypto.signMessage(encryptedPayload, signingKey)
const encryptedKeys = await Promise.all(state.room.members
.map(async (member) => {
const key = await crypto.importEncryptDecryptKey(member.publicKey)
const enc = await Promise.all([
crypto.wrapKey(sessionKey, key),
crypto.wrapKey(signingKey, key),
])
return {
sessionKey: enc[0],
signingKey: enc[1],
}
})
)
const ivString = await crypto.convertArrayBufferViewToString(new Uint8Array(iv))
const signatureString = await crypto.convertArrayBufferViewToString(new Uint8Array(signature))
resolve({
toSend: {
payload: payloadString,
signature: signatureString,
iv: ivString,
keys: encryptedKeys,
},
original: jsonToSend,
})
})