forked from ifElser/lapi-rapi
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbit-chaos.js
146 lines (132 loc) · 4.11 KB
/
bit-chaos.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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
const isClient = typeof window !== 'undefined'
const TextAPI = isClient ? {
encode: text => (new TextEncoder()).encode(text),
decode: data => (new TextDecoder()).decode(Uint8Array.from(data))
} : {
encode: text => Buffer.from(text),
decode: data => Buffer.from(data).toString('utf8')
}
module.exports = class BitChaos {
constructor (secret) {
secret = Uint8Array.from(secret).filter(byte => !!byte)
function origin (chunk, length) {
let result = chunk
length = length & 3
const logic = {
add: (key) => {
let ring = 255, len = length
while(--len) { ring = (ring << 8) | ring };
result = (result + key) & ring
return logic
},
sub: (key) => {
let ring = 255, len = length
while(--len) { ring = (ring << 8) | ring };
result = (result >= key ? result - key : ring + 1 + result - key)
return logic
},
xor: (key) => {
result = result ^ key
return logic
},
done: () => result
}
return logic
}
this.encrypt = (message, mode = 'array') => {
const fns = ['add', 'sub', 'xor']
if(typeof message === 'string') message = TextAPI.encode(message); else
if(message instanceof ArrayBuffer) message = new Uint8Array(message); else
if(!(message instanceof Uint8Array)) message = Uint8Array.from(message)
const data = Uint8Array.from(message)
const slen = secret.length
const dlen = data.length
let encrypted = []
const mask = 192
let sptr = 0
let dptr = 0
while(dptr < dlen){
let len = 0
let seq = secret[sptr++]
sptr = sptr >= slen ? sptr - slen : sptr
let shift = 0
let state, chunk
while(mask >> shift) {
let step = (seq & (mask >> shift)) >> (6 - shift)
if(step) {
if(!len) {
len = dlen - dptr < step ? dlen - dptr : step;
chunk = data.slice(dptr, dptr + len).reduce((value, byte) => (value ? (value << 8) | byte : byte), 0)
state = origin(chunk, len)
}
let key = secret.slice(sptr, sptr + len).reduce((key, byte) => (key ? (key << 8) | byte : byte), 0)
state = state[fns[step - 1]](key)
sptr += len
sptr = sptr >= slen ? sptr - slen : sptr
}
shift += 2
}
let result = state.done()
let part = []
let l = len
while(l--) {
part.unshift(result & 255)
result >>= 8
}
encrypted = encrypted.concat(part)
dptr += len
}
if(mode === 'array') return encrypted;
if(mode === 'bytearray') return Uint8Array.from(encrypted);
return TextAPI.decode(encrypted)
}
this.decrypt = (message, mode = 'text') => {
const fns = ['sub', 'add', 'xor']
if(typeof message === 'string') message = TextAPI.encode(message);
if(message instanceof ArrayBuffer) message = new Uint8Array(message); else
if(!(message instanceof Uint8Array)) message = Uint8Array.from(message)
const data = Uint8Array.from(message)
const slen = secret.length
const dlen = data.length
let decrypted = []
let sptr = 0
let dptr = 0
while(dptr < dlen){
let len = 0
let seq = secret[sptr++]
sptr = sptr >= slen ? sptr - slen : sptr
let state, chunk
let shift = 0
let mask = 192
let steps = []
while(mask >> shift) {
let step = (seq & (mask >> shift)) >> (6 - shift)
if(step) {
if(!len) {
len = dlen - dptr < step ? dlen - dptr : step;
chunk = data.slice(dptr, dptr + len).reduce((value, byte) => (value ? (value << 8) | byte : byte), 0)
state = origin(chunk, len)
}
let key = secret.slice(sptr, sptr + len).reduce((key, byte) => (key ? (key << 8) | byte : byte), 0)
steps.unshift({fn: fns[step - 1], key})
sptr += len
sptr = sptr >= slen ? sptr - slen : sptr
}
shift += 2
}
let result = steps.reduce((state, {fn, key}) => state[fn](key), state).done()
let part = []
let l = len
while(l--) {
part.unshift(result & 255)
result >>= 8
}
decrypted = decrypted.concat(part)
dptr += len
}
if(mode === 'array') return decrypted;
if(mode === 'bytearray') return Uint8Array.from(decrypted);
return TextAPI.decode(decrypted)
}
}
}