From 09de4b663b0d8b8f31e7ec3a88f8c6ee62529b07 Mon Sep 17 00:00:00 2001 From: C-3PO Date: Thu, 5 Jul 2018 03:30:13 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=20Rewrite=20decryptChunk?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ssn/decryption/decryptChunk.ts | 33 +++++++++++++++++++++++++++++- src/ssn/streams/decryptStream.ts | 15 +++----------- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/ssn/decryption/decryptChunk.ts b/src/ssn/decryption/decryptChunk.ts index c6f1c17..3d194b3 100644 --- a/src/ssn/decryption/decryptChunk.ts +++ b/src/ssn/decryption/decryptChunk.ts @@ -1,6 +1,6 @@ import updateKeys from './lib/updateKeys'; -export default function decryptChunk(encryptedChunk: Buffer, [key0, key1, key2]: [number, number, number]): {decryptedChunk: Buffer, keys: [number, number, number]} { +/*export default function decryptChunk(encryptedChunk: Buffer, [key0, key1, key2]: [number, number, number]): {decryptedChunk: Buffer, keys: [number, number, number]} { const decryptedChunk = Buffer.alloc(encryptedChunk.length); const dvOut = new DataView(decryptedChunk.buffer); @@ -17,4 +17,35 @@ export default function decryptChunk(encryptedChunk: Buffer, [key0, key1, key2]: } return { decryptedChunk, keys: [key0, key1, key2] }; +}*/ + +export default function getDecryptor([key0, key1, key2]: [number, number, number]) { + let position = 0; + + return (encryptedChunk: Buffer) => { + const decryptedChunk = Buffer.alloc(encryptedChunk.length); + const dvOut = new DataView(decryptedChunk.buffer); + + for (let i = 0; i < encryptedChunk.length; i += 1) { + //read and decrypt byte + let curChar = encryptedChunk.readUInt8(i); + const keyPart = (key2 | 2) & 0xFFFF; + const decryptedByte = (keyPart * (keyPart ^ 1)) >>> 8; + curChar ^= decryptedByte & 0xFF; + if (position + i < 12) { + //do nothing + } else if (position + i >= 12 && position < 12) { + dvOut.setUint8(position + i - 12, curChar); + } else { + dvOut.setUint8(i, curChar); + } + + //update keys + [key0, key1, key2] = updateKeys([key0, key1, key2], curChar); + } + + position += encryptedChunk.length; + + return decryptedChunk; + }; } diff --git a/src/ssn/streams/decryptStream.ts b/src/ssn/streams/decryptStream.ts index 6f65b69..3343e10 100644 --- a/src/ssn/streams/decryptStream.ts +++ b/src/ssn/streams/decryptStream.ts @@ -1,27 +1,18 @@ import * as stream from 'stream'; -import decryptChunk from '../decryption/decryptChunk'; +import getDecryptor from '../decryption/decryptChunk'; export default function decryptStream(inputStream: stream.Readable, [key0, key1, key2]: [number, number, number]): stream.Readable { - let skippedRandomHeader = false; + const decryptor = getDecryptor([key0, key1, key2]); const outStream = new stream.Readable({ read(size) { - //There are 12 random bytes at the beginning, we need to use them to initialize the decryption keys, but we can ignore the decrypted bytes. - if (!skippedRandomHeader) { - const encryptedHeader: Buffer = inputStream.read(12); - const { keys } = decryptChunk(encryptedHeader, [key0, key1, key2]); - [key0, key1, key2] = keys; - skippedRandomHeader = true; - } - //Decrypt chunk const encryptedChunk: Buffer = inputStream.read(size); if (encryptedChunk === null) { //If end has been reached, stop this.push(null); } else { - const { decryptedChunk, keys } = decryptChunk(encryptedChunk, [key0, key1, key2]); - [key0, key1, key2] = keys; + const decryptedChunk = decryptor(encryptedChunk); this.push(decryptedChunk); } },