-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
88 lines (76 loc) · 2.44 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
'use strict'
// Dependencies
const request = require('request-promise')
const crypto = require('crypto')
const xml = require('xml2js')
// Constants
/**
* Key for the decryption
* @type {String}
*/
const KEY = 'cb99b5cbc24db398'
/**
* Initialization vector
* @type {String}
*/
const IV = '9bc24cb995cb8db3'
/**
* JD service for the encrypted key
* @type {String}
*/
const URL = 'http://service.jdownloader.org/dlcrypt/service.php?srcType=dlc&destType=pylo&data='
/**
* The expression for encrypted key from JD.org
* @type {Regex}
*/
const RC_EXPRESSION = /<rc>([\s\S]+)<\/rc>/i
/**
* Decryptes a dlc file containing links
* @access public
* @param {Buffer} file The whole content (as Buffer) of the dlc file
* @returns {Promise} Returns a promise to match ES6 standarts
*/
async function decrypt(file) {
let dlcKey = file.slice(-88) // get the last 88 chars (this is our key)
let dlcData = Buffer.from(file.slice(0, -88).toString(), 'base64') // the rest is the content
try {
let rc = await request(`${URL}${dlcKey}`)
let strippedRc = Buffer.from(rc.match(RC_EXPRESSION)[1], 'base64')
let decryptedKey = await aes_decrypt(strippedRc, KEY, IV, 0)
let decryptedData = await aes_decrypt(dlcData, decryptedKey, decryptedKey, 0)
return await parseXML(Buffer.from(decryptedData, 'base64'))
} catch (e) {
return Promise.reject(e)
}
}
/**
* Decrypts the input data with the key and initializing vector
* @access private
* @param {String} data The string to decrypt
* @param {string} key The key for decrypting
* @param {string} iv The init vector
* @param {Number} padding The padding of decipher defaults to 0
* @return {String} Returns a decrypted string (from binary to utf8)
*/
function aes_decrypt(data, key, iv, padding) {
let decipher = crypto.createDecipheriv('AES-128-CBC', key, iv)
decipher.setAutoPadding(padding || 0)
return Promise.resolve(decipher.update(data, 'binary', 'utf8'))
}
/**
* Parses the XML string of the dlc content and transfroms it into a
* human readable JSON object
* @access private
* @param {Buffer} buf The Buffer containing the string
* @returns {Promise} Returns a promise
*/
function parseXML (buf) {
return new Promise(function(resolve, reject) {
xml.parseString(buf.toString('utf8'), function(err, result) {
if (!err) return resolve(result)
return reject(err)
})
})
}
// export public interface
module.exports = decrypt