refactor encryption (support linux api)

This commit is contained in:
Nzix
2018-10-20 13:16:47 +08:00
parent 9be0feccd8
commit 6421a6c9e3
5 changed files with 101 additions and 190 deletions
+24 -57
View File
@@ -1,67 +1,34 @@
// 参考 https://github.com/darknessomi/musicbox/wiki/
'use strict'
const crypto = require('crypto')
const bigInt = require('big-integer')
const modulus =
'00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'
const nonce = '0CoJUm6Qyw8W8jud'
const pubKey = '010001'
const iv = Buffer.from('0102030405060708')
const presetKey = Buffer.from('0CoJUm6Qyw8W8jud')
const linuxapiKey = Buffer.from('rFgB&h#%2?^eDg:Q')
const base62 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
const publicKey = '-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgtQn2JZ34ZC28NWYpAUd98iZ37BUrX/aKzmFbt7clFSs6sXqHauqKWqdtLkF2KexO40H1YTX8z2lSgBBOAxLsvaklV8k4cBFK9snQXE9/DDaFt6Rr7iVZMldczhC0JNgTz+SHXT6CBHuX3e9SdB1Ua44oncaTWz7OBGLbCiK45wIDAQAB\n-----END PUBLIC KEY-----'
String.prototype.hexEncode = function() {
let hex, i
let result = ''
for (i = 0; i < this.length; i++) {
hex = this.charCodeAt(i).toString(16)
result += ('' + hex).slice(-4)
}
return result
const aesEncrypt = (buffer, mode, key, iv) => {
const cipher = crypto.createCipheriv('aes-128-' + mode, key, iv)
return Buffer.concat([cipher.update(buffer),cipher.final()])
}
function createSecretKey(size) {
const keys = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
let key = ''
for (let i = 0; i < size; i++) {
let pos = Math.random() * keys.length
pos = Math.floor(pos)
key = key + keys.charAt(pos)
}
return key
const rsaEncrypt = (buffer, key) => {
buffer = Buffer.concat([Buffer.alloc(128 - buffer.length), buffer])
return crypto.publicEncrypt({key: key, padding: crypto.constants.RSA_NO_PADDING}, buffer)
}
function aesEncrypt(text, secKey) {
const _text = text
const lv = new Buffer('0102030405060708', 'binary')
const _secKey = new Buffer(secKey, 'binary')
const cipher = crypto.createCipheriv('AES-128-CBC', _secKey, lv)
let encrypted = cipher.update(_text, 'utf8', 'base64')
encrypted += cipher.final('base64')
return encrypted
const weapi = (object) => {
const text = JSON.stringify(object)
const secretKey = crypto.randomBytes(16).map(n => (base62.charAt(n % 62).charCodeAt()))
return {
params: aesEncrypt(Buffer.from(aesEncrypt(Buffer.from(text), 'cbc', presetKey, iv).toString('base64')), 'cbc', secretKey, iv).toString('base64'),
encSecKey: rsaEncrypt(secretKey.reverse(), publicKey).toString('hex')
}
}
function zfill(str, size) {
while (str.length < size) str = '0' + str
return str
const linuxapi = (object) => {
const text = JSON.stringify(object)
return {
eparams: aesEncrypt(Buffer.from(text), 'ecb', linuxapiKey, '').toString('hex').toUpperCase()
}
}
function rsaEncrypt(text, pubKey, modulus) {
const _text = text.split('').reverse().join('')
const biText = bigInt(new Buffer(_text).toString('hex'), 16),
biEx = bigInt(pubKey, 16),
biMod = bigInt(modulus, 16),
biRet = biText.modPow(biEx, biMod)
return zfill(biRet.toString(16), 256)
}
function Encrypt(obj) {
const text = JSON.stringify(obj)
const secKey = createSecretKey(16)
const encText = aesEncrypt(aesEncrypt(text, nonce), secKey)
const encSecKey = rsaEncrypt(secKey, pubKey, modulus)
return {
params: encText,
encSecKey: encSecKey
}
}
module.exports = Encrypt
module.exports = {weapi, linuxapi}
-30
View File
@@ -1,30 +0,0 @@
function randomString(pattern, length){
return Array.apply(null, {length: length}).map(() => (pattern[Math.floor(Math.random() * pattern.length)])).join('')
}
function completeCookie(cookie){
let origin = (cookie || '').split(/;\s*/).map(element => (element.split('=')[0])), extra = []
let now = Date.now()
if(!origin.includes('JSESSIONID-WYYY')){
let expire = new Date(now + 1800000) //30 minutes
let jessionid = randomString('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKMNOPQRSTUVWXYZ\\/+',176) + ':' + expire.getTime()
extra.push(['JSESSIONID-WYYY=' + jessionid, 'Expires=' + expire.toGMTString()])
}
if(!origin.includes('_iuqxldmzr_')){
let expire = new Date(now + 157680000000) //5 years
extra.push(['_iuqxldmzr_=32', 'Expires=' + expire.toGMTString()])
}
if((!origin.includes('_ntes_nnid'))||(!origin.includes('_ntes_nuid'))){
let expire = new Date(now + 3153600000000) //100 years
let nnid = randomString('0123456789abcdefghijklmnopqrstuvwxyz',32) + ',' + now
extra.push(['_ntes_nnid=' + nnid, 'Expires=' + expire.toGMTString()])
extra.push(['_ntes_nuid=' + nnid.slice(0,32), 'Expires=' + expire.toGMTString()])
}
return extra
}
module.exports = {
completeCookie
}
+12 -9
View File
@@ -1,10 +1,10 @@
const encrypt = require('./crypto.js')
const encrypt = require('./crypto')
const request = require('request')
const queryString = require('querystring')
// request.debug = false
request.debug = true
function chooseUserAgent(ua) {
function chooseUserAgent(ua){
const userAgentList = [
'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1',
'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1',
@@ -38,7 +38,7 @@ function createRequest(method, url, data, options){
let headers = {'User-Agent': chooseUserAgent(options.ua)}
if(method.toUpperCase() == 'POST') headers['Content-Type'] = 'application/x-www-form-urlencoded'
if(url.indexOf('music.163.com') != -1) headers['Referer'] = 'http://music.163.com'
if(url.includes('music.163.com')) headers['Referer'] = 'http://music.163.com'
// headers['X-Real-IP'] = '118.88.88.88'
if(typeof(options.cookie) === 'object')
@@ -47,9 +47,15 @@ function createRequest(method, url, data, options){
headers['Cookie'] = options.cookie
if(options.crypto == 'weapi'){
const csrfToken = (headers['Cookie'] || '').match(/_csrf=([^(;|$)]+)/)
let csrfToken = (headers['Cookie'] || '').match(/_csrf=([^(;|$)]+)/)
data.csrf_token = (csrfToken ? csrfToken[1] : '')
data = encrypt(data)
data = encrypt.weapi(data)
url = url.replace(/\w*api/,'weapi')
}
else if(options.crypto == 'linuxapi'){
data = encrypt.linuxapi({'method': method, url: url.replace(/\w*api/,'api'), 'params': data})
headers['User-Agent'] = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36'
url = 'http://music.163.com/api/linux/forward'
}
const answer = {status: 500, body: {}, cookie: []}
@@ -66,9 +72,6 @@ function createRequest(method, url, data, options){
try{
answer.body = JSON.parse(body)
answer.status = answer.body.code || res.statusCode
if(answer.body.code=='301'){
answer.body.apiMsg='需要登陆'
}
}
catch(e){
answer.body = body