使用更标准的 aes 加密写法, 更换密钥的算法, 限制 data 对象暴露
This commit is contained in:
@@ -1,43 +1,56 @@
|
|||||||
// @ts-types="npm:@types/crypto-js"
|
import crypto from 'node:crypto'
|
||||||
import * as CryptoJS from 'crypto-js'
|
|
||||||
|
|
||||||
const dataIsEmpty = !localStorage.tws_data || localStorage.tws_data == ''
|
const dataIsEmpty = !localStorage.tws_data || localStorage.tws_data == ''
|
||||||
|
|
||||||
const aes = {
|
class Aes {
|
||||||
enc: (data: string, key: string) => CryptoJS.AES.encrypt(data, key).toString(),
|
static randomIv() {
|
||||||
dec: (data: string, key: string) => CryptoJS.AES.decrypt(data, key).toString(CryptoJS.enc.Utf8),
|
return crypto.randomBytes(12)
|
||||||
|
}
|
||||||
|
static normalizeKey(key: string, keyLength = 32) {
|
||||||
|
const hash = crypto.createHash('sha256')
|
||||||
|
hash.update(key)
|
||||||
|
const keyBuffer = hash.digest()
|
||||||
|
return keyLength ? keyBuffer.subarray(0, keyLength) : keyBuffer
|
||||||
|
}
|
||||||
|
static encrypt(data: string, key: string) {
|
||||||
|
const iv = this.randomIv()
|
||||||
|
return Buffer.concat([iv, crypto.createCipheriv("aes-256-gcm", this.normalizeKey(key), iv).update(data)]).toString('hex')
|
||||||
|
}
|
||||||
|
static decrypt(data: string, key: string) {
|
||||||
|
const buffer = Buffer.from(data, 'hex')
|
||||||
|
const iv = buffer.subarray(0, 12)
|
||||||
|
return crypto.createDecipheriv("aes-256-gcm", this.normalizeKey(key), iv).update(buffer.subarray(12)).toString()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const key = location.host + '_TWS_姐姐'
|
// 尽可能防止被窃取, 虽然理论上还是会被窃取
|
||||||
|
const key = crypto.createHash('sha256').update(location.host + '_TWS_姐姐_' + navigator.userAgent).digest().toString('base64')
|
||||||
|
|
||||||
if (dataIsEmpty) localStorage.tws_data = aes.enc('{}', key)
|
if (dataIsEmpty) localStorage.tws_data = Aes.encrypt('{}', key)
|
||||||
|
|
||||||
let _dec = aes.dec(localStorage.tws_data, key)
|
let _dec = Aes.decrypt(localStorage.tws_data, key)
|
||||||
if (_dec == '') _dec = '{}'
|
if (_dec == '') _dec = '{}'
|
||||||
|
|
||||||
const _data_cached = JSON.parse(_dec)
|
const _data_cached = JSON.parse(_dec)
|
||||||
|
|
||||||
// 類型定義
|
type IData = {
|
||||||
|
refresh_token?: string
|
||||||
|
split_sizes: number[]
|
||||||
|
apply(): void
|
||||||
|
access_token?: string
|
||||||
|
device_id: string
|
||||||
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
data: {
|
data?: IData
|
||||||
refresh_token?: string
|
|
||||||
split_sizes: number[]
|
|
||||||
apply(): void
|
|
||||||
access_token?: string
|
|
||||||
device_id: string
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-ignore: 忽略...
|
const data = new Proxy({} as IData, {
|
||||||
// deno-lint-ignore no-window
|
|
||||||
(window.data == null) && (window.data = new Proxy({
|
|
||||||
apply() {}
|
|
||||||
}, {
|
|
||||||
get(_obj, k) {
|
get(_obj, k) {
|
||||||
if (k == '_cached') return _data_cached
|
if (k == '_cached') return _data_cached
|
||||||
if (k == 'apply') return () => localStorage.tws_data = aes.enc(JSON.stringify(_data_cached), key)
|
if (k == 'apply') return () => localStorage.tws_data = Aes.encrypt(JSON.stringify(_data_cached), key)
|
||||||
return _data_cached[k]
|
return _data_cached[k]
|
||||||
},
|
},
|
||||||
set(_obj, k, v) {
|
set(_obj, k, v) {
|
||||||
@@ -45,7 +58,11 @@ declare global {
|
|||||||
_data_cached[k] = v
|
_data_cached[k] = v
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}))
|
})
|
||||||
|
|
||||||
// deno-lint-ignore no-window
|
if (new URL(location.href).searchParams.get('export_data') == 'true') {
|
||||||
export default window.data
|
window.data = data
|
||||||
|
console.warn("警告: 将 data 暴露到 window 有可能会导致令牌泄露!")
|
||||||
|
}
|
||||||
|
|
||||||
|
export default data
|
||||||
|
|||||||
Reference in New Issue
Block a user