You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

83 lines
3.5 KiB
JavaScript

3 years ago
const aesjs = require('./aes-64bit')
3 years ago
const crc = require('node-crc')
const crypto = require("crypto")
3 years ago
function randomIntInc(low, high) {
return Math.floor(Math.random() * (high - low + 1) + low)
3 years ago
}
3 years ago
class BOSkrypt {
constructor() {
}
//
encrypt(payload, key, keyIndex) {
key = Buffer.from(key, 'hex')
const iv = Buffer.from([ keyIndex, randomIntInc(0x00, 0xFF), randomIntInc(0x00, 0xFF) ])
const UNIXNOW = Math.floor(new Date().valueOf()/1e3)
const timestamp = (UNIXNOW - 1388534400).toString(16).padStart(2*4, '0')
const ivPadBuffer = Buffer.from("00".repeat(8), 'hex')
const _ivWithTimestamp = Buffer.from(timestamp + iv.toString('hex'), 'hex')
const _iv56bitCRC = crc.crc8(_ivWithTimestamp)
const ivWithTimestamp = Buffer.concat([
_ivWithTimestamp,
_iv56bitCRC
])
const ivWithTimestampPadded = Buffer.concat([ ivWithTimestamp, ivPadBuffer ])
const uncPayloadHash = Buffer.from(crypto.createHash("sha1").update(payload).digest('hex').substring(0,10), 'hex') // first 40bits. 2*40/8
let preparedPayload = "ENCR" + payload + '\x00'.repeat(
payload.length < 20
? randomIntInc(0,10)
: 0) // random null-fill
3 years ago
let compressedPreparedPayload = preparedPayload.split('').map(x => { //foreach char run this
return x.charCodeAt(0) //get byte
.toString(2) // to base2/bcd/"binary"
.padStart(8, '0') // pad to 8 digits (dec4 = 100 => 00000100)
.split('') // to array
.reverse() // reverse
.join('') // back to string
.substring(0, 7) //take first 7 chars
}).join('') //join to one complete string
let compressedPayload = []
for (let i=0;i<compressedPreparedPayload.length;i+=8) {
let byte = parseInt(
compressedPreparedPayload
.substring(i, i+8) //select 8char chunk from bigstring
.split('') // to array
.reverse() // reverse
.join(''), // back to string
2) // parse from base2
compressedPayload.push( byte ) //put in array
}
compressedPayload = Buffer.from(compressedPayload)
const toEncryptData = Buffer.concat([
uncPayloadHash, compressedPayload
])
let encryptedPayload = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter(ivWithTimestampPadded)).encrypt(toEncryptData)
const encrpytedIncludingIVandSHA1Checksum = Buffer.concat([
ivWithTimestamp, encryptedPayload
])
return encrpytedIncludingIVandSHA1Checksum.toString('base64')
}
1 year ago
decrypt(encrpytedIncludingIVandSHA1Checksum, key) {
key = Buffer.from(key, 'hex')
const ivPadBuffer = Buffer.from("00".repeat(8), 'hex')
let encrpytedIncludingIVandSHA1ChecksumArray = Buffer.from(encrpytedIncludingIVandSHA1Checksum, 'base64')
let ivWithTimestamp = encrpytedIncludingIVandSHA1ChecksumArray.slice(0, 8)
const ivWithTimestampPadded = Buffer.concat([ ivWithTimestamp, ivPadBuffer ])
let encryptedBuffer = encrpytedIncludingIVandSHA1ChecksumArray.slice(8)
let encryptedPayload = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter(ivWithTimestampPadded)).decrypt(encryptedBuffer)
let compressedPayload = Buffer.from(encryptedPayload).slice(5)
let uncompressed = ""
{
let b8s = ""
for (let b8 of compressedPayload) b8s += b8.toString(2).padStart(8, '0').split('').reverse().join('')
for (let i = 0; i < b8s.length; i += 7) uncompressed += String.fromCharCode(parseInt(b8s.substring(i, i + 7).split('').reverse().join(''), 2))
}
return {
keyIndex: ivWithTimestampPadded[4],
uncompressed
}
}
3 years ago
}
module.exports = new BOSkrypt()