feat(frontend): mob file decryption
This commit is contained in:
parent
a73828fb43
commit
6955cd3e93
3 changed files with 38 additions and 5 deletions
|
|
@ -28,6 +28,7 @@ import AssistManager from './managers/AssistManager';
|
|||
|
||||
import MFileReader from './messages/MFileReader';
|
||||
import { loadFiles, requestEFSDom, requestEFSDevtools } from './network/loadFiles';
|
||||
import { decryptSessionBytes } from './network/crypto';
|
||||
|
||||
import { INITIAL_STATE as SUPER_INITIAL_STATE, State as SuperState } from './StatedScreen/StatedScreen';
|
||||
import { INITIAL_STATE as ASSIST_INITIAL_STATE, State as AssistState } from './managers/AssistManager';
|
||||
|
|
@ -215,14 +216,17 @@ export default class MessageDistributor extends StatedScreen {
|
|||
}
|
||||
|
||||
private loadMessages() {
|
||||
const createNewParser = () => {
|
||||
const createNewParser = (shouldDecrypt=true) => {
|
||||
const decrypt = shouldDecrypt && this.session.fileKey
|
||||
? (b: Uint8Array) => decryptSessionBytes(b, this.session.fileKey)
|
||||
: (b: Uint8Array) => Promise.resolve(b)
|
||||
// Each time called - new fileReader created
|
||||
const fileReader = new MFileReader(new Uint8Array(), this.sessionStart)
|
||||
return (b: Uint8Array) => {
|
||||
return (b: Uint8Array) => decrypt(b).then(b => {
|
||||
fileReader.append(b)
|
||||
this.parseAndDistributeMessages(fileReader)
|
||||
this.setMessagesLoading(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
this.setMessagesLoading(true)
|
||||
this.waitingForFiles = true
|
||||
|
|
@ -230,7 +234,7 @@ export default class MessageDistributor extends StatedScreen {
|
|||
loadFiles(this.session.domURL, createNewParser())
|
||||
.catch(() => // do if only the first file missing (404) (?)
|
||||
requestEFSDom(this.session.sessionId)
|
||||
.then(createNewParser())
|
||||
.then(createNewParser(false))
|
||||
// Fallback to back Compatability with mobsUrl
|
||||
.catch(e =>
|
||||
loadFiles(this.session.mobsUrl, createNewParser())
|
||||
|
|
@ -245,7 +249,7 @@ export default class MessageDistributor extends StatedScreen {
|
|||
loadFiles(this.session.devtoolsURL, createNewParser())
|
||||
.catch(() =>
|
||||
requestEFSDevtools(this.session.sessionId)
|
||||
.then(createNewParser())
|
||||
.then(createNewParser(false))
|
||||
)
|
||||
//.catch() // not able to download the devtools file
|
||||
.finally(() => update({ devtoolsLoading: false }))
|
||||
|
|
|
|||
28
frontend/app/player/MessageDistributor/network/crypto.ts
Normal file
28
frontend/app/player/MessageDistributor/network/crypto.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
|
||||
const u8aFromHex = (hexString:string) =>
|
||||
Uint8Array.from(hexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)))
|
||||
|
||||
const is16BitHex = (maybeHex: string | undefined) =>
|
||||
maybeHex && maybeHex.length % 2 === 0 && !/[^a-fA-F0-9]/u.test(maybeHex)
|
||||
|
||||
|
||||
function truncPadding(padded: Uint8Array): Uint8Array {
|
||||
let i = padded.length - 1
|
||||
for (; !padded[i] ;i--) {}
|
||||
return padded.subarray(0, i)
|
||||
}
|
||||
|
||||
export function decryptSessionBytes(cypher: Uint8Array, keyString: string): Promise<Uint8Array> {
|
||||
const [hexKey, hexIV] = keyString.split(",")
|
||||
if (!is16BitHex(hexIV) || !is16BitHex(hexKey)) {
|
||||
return Promise.reject("Wrong key/iv pair")
|
||||
}
|
||||
const iv = u8aFromHex(hexIV)
|
||||
const byteKey = u8aFromHex(hexKey)
|
||||
return crypto.subtle.importKey("raw",byteKey, { name: "AES-CBC" }, false, ["decrypt"])
|
||||
.then(key => crypto.subtle.decrypt({ name: "AES-CBC", iv: iv}, key, cypher))
|
||||
.then(truncPadding)
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -83,6 +83,7 @@ export default Record({
|
|||
agentToken: '',
|
||||
notes: [],
|
||||
notesWithEvents: [],
|
||||
fileKey: '',
|
||||
}, {
|
||||
fromJS:({
|
||||
startTs=0,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue