102 lines
2.2 KiB
JavaScript
102 lines
2.2 KiB
JavaScript
class RC4 {
|
|
constructor(key) {
|
|
this.key = Buffer.isBuffer(key) ? key : Buffer.from(key, "utf8")
|
|
this.s = new Array(256)
|
|
this.init()
|
|
}
|
|
|
|
init() {
|
|
for (let i = 0; i < 256; i++) {
|
|
this.s[i] = i
|
|
}
|
|
|
|
let j = 0
|
|
for (let i = 0; i < 256; i++) {
|
|
j = (j + this.s[i] + this.key[i % this.key.length]) % 256
|
|
this.swap(i, j)
|
|
}
|
|
}
|
|
|
|
swap(i, j) {
|
|
const temp = this.s[i]
|
|
this.s[i] = this.s[j]
|
|
this.s[j] = temp
|
|
}
|
|
|
|
encrypt(data) {
|
|
const input = Buffer.isBuffer(data) ? data : Buffer.from(data, "utf8")
|
|
const output = Buffer.alloc(input.length)
|
|
|
|
let i = 0,
|
|
j = 0
|
|
|
|
for (let k = 0; k < input.length; k++) {
|
|
i = (i + 1) % 256
|
|
j = (j + this.s[i]) % 256
|
|
this.swap(i, j)
|
|
|
|
const keystream = this.s[(this.s[i] + this.s[j]) % 256]
|
|
output[k] = input[k] ^ keystream
|
|
}
|
|
|
|
return output
|
|
}
|
|
|
|
decrypt(data) {
|
|
return this.encrypt(data)
|
|
}
|
|
}
|
|
|
|
class Crypto {
|
|
constructor(config) {
|
|
this.config = config
|
|
this.rc4 = new RC4(config.rc4Key)
|
|
this.nonce = Buffer.from(config.nonce, "utf8")
|
|
}
|
|
|
|
encrypt(data) {
|
|
if (!this.config.enabled) return data
|
|
|
|
const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data)
|
|
return this.rc4.encrypt(buffer)
|
|
}
|
|
|
|
decrypt(data) {
|
|
if (!this.config.enabled) return data
|
|
|
|
const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data)
|
|
return this.rc4.decrypt(buffer)
|
|
}
|
|
|
|
generateNonce() {
|
|
const timestamp = Date.now()
|
|
const random = Math.floor(Math.random() * 0xffffffff)
|
|
|
|
const nonceBuffer = Buffer.alloc(16)
|
|
nonceBuffer.writeUInt32BE(timestamp >> 32, 0)
|
|
nonceBuffer.writeUInt32BE(timestamp & 0xffffffff, 4)
|
|
nonceBuffer.writeUInt32BE(random, 8)
|
|
nonceBuffer.writeUInt32BE(random ^ timestamp, 12)
|
|
|
|
return nonceBuffer
|
|
}
|
|
|
|
hash(data) {
|
|
const crypto = require("crypto")
|
|
return crypto.createHash("sha256").update(data).digest()
|
|
}
|
|
|
|
xorWithNonce(data) {
|
|
const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data)
|
|
const result = Buffer.alloc(buffer.length)
|
|
|
|
for (let i = 0; i < buffer.length; i++) {
|
|
result[i] = buffer[i] ^ this.nonce[i % this.nonce.length]
|
|
}
|
|
|
|
return result
|
|
}
|
|
}
|
|
|
|
module.exports = { RC4, Crypto }
|