前言

想法

无意中看到了Ook!编码,感觉看起来非常有趣,可以做个简单的编码方法玩玩

就当作一篇水文写写吧

Ook!编码

它看起来像这样

1
2
3
4
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook.
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
Ook. Ook? Ook. Ook? Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook! Ook. Ook. Ook.

实际上它的意思是这样的

Brainfuck的命令替换

我想做的编码方法原理和它是不一样的,只是看起来好像就是那些字符,哈哈

规划

既然是简单的,那么就不考虑编码和解码的效率、可靠性了

编码时我就直接把字符串先转换为二进制,然后用特定字符替代

解码时就把特定字符先转换为二进制再转换回字符串

开始

编码

既然是简单的,那么简单的语言能够快速完成想法,这里选了Python3

先把字符串转换成整数型数值,再转换成二机制

一个个来,那么就用循环搞定

1
2
3
4
5
6
7
8
a = "str input哈"


for i in range(len(a)):
print(a[i], end=":")
b = ord(a[i])
c = bin(b)
print(" to bin: {}".format(c))

输出如图

开始编码了,感觉转成字符串再一个个处理会比单纯除法方便和简单

1
d = str(c)

如果不想转字符串可以直接在循环里这样除,也是可以的

1
2
d = c % 10
c = c / 10

规定一些特定字符

如注释所写,LX代表开头,即二机制串开头0b

!代表二机制数值0

?代表二机制数值1

1
2
3
4
code1 = "Lx"
code2 = "LX"#开头
state1 = "!"#0
state2 = "?"#1

使用全局变量 encode_str 存储编码完成的值

1
encode_str = "" #字符串也就是str数据

要让它在省略0b后开始编码,那么就让它在索引为2(变量ii)时把特定字符改成Lx避免混淆

为了判断0b,所以遍历只到字符串的倒数第二位

但是由于开头LX后面也要编码,即0b后面的第一个二机制值也要编码,所以索引在1的时候就要开始编码0和1

1
2
3
4
5
6
7
8
9
10
for ii in range(len(d) - 1):
if d[ii] + d[ii+1] == "0b":
encode_str += code2
elif ii > 1:
encode_str += code1
if ii > 0:
if d[ii+1] == "0":
encode_str += state1
else:
encode_str += state2

简单的还可以这样写

这样直接遍历整个字符串即可

1
2
3
4
5
6
7
8
9
10
11
12
if_index_is_zer0 = 0
d = d[2:len(d)] #仅取0b后的字符(分割字符串从2到d的最后一个字符)
for ii in range(len(d)):
if if_index_is_zer0 == 0:
encode_str += code2
if_index_is_zer0 = 1
else:
encode_str += code1
if d[ii] == "0":
encode_str += state1
else:
encode_str += state2

然后编码出来就是这样了

1
LX?Lx?Lx?Lx!Lx!Lx?Lx?LX?Lx?Lx?Lx!Lx?Lx!Lx!LX?Lx?Lx?Lx!Lx!Lx?Lx!LX?Lx!Lx!Lx!Lx!Lx!LX?Lx?Lx!Lx?Lx!Lx!Lx?LX?Lx?Lx!Lx?Lx?Lx?Lx!LX?Lx?Lx?Lx!Lx!Lx!Lx!LX?Lx?Lx?Lx!Lx?Lx!Lx?LX?Lx?Lx?Lx!Lx?Lx!Lx!LX?Lx!Lx?Lx!Lx?Lx!Lx!Lx?Lx?Lx!Lx!Lx?Lx!Lx!Lx!

单独拎出来字符串s

1
LX?Lx?Lx?Lx!Lx!Lx?Lx?
1
1110011

一致,没问题

完整编码代码

所以编码代码可以这样写:

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
a = "str input哈"

code1 = "Lx"
code2 = "LX"#开头
state1 = "!"#0
state2 = "?"#1
encode_str = ""

for i in range(len(a)):
#print(a[i])
b = ord(a[i])
c = bin(b)
d = str(c)
for ii in range(len(d) - 1):
if d[ii] + d[ii+1] == "0b":
encode_str += code2
elif ii > 1:
encode_str += code1
if ii > 0:
if d[ii+1] == "0":
encode_str += state1
else:
encode_str += state2

print(encode_str)

也可以这样写:

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
a = "str input哈"

code1 = "Lx"
code2 = "LX"#开头
state1 = "!"#0
state2 = "?"#1
encode_str = ""

for i in range(len(a)):
#print(a[i])
b = ord(a[i])
c = bin(b)
d = str(c)
if_index_is_zer0 = 0
d = d[2:len(d)]
for ii in range(len(d)):
if if_index_is_zer0 == 0:
encode_str += code2
if_index_is_zer0 = 1
else:
encode_str += code1
if d[ii] == "0":
encode_str += state1
else:
encode_str += state2

print(encode_str)

解码

解码过程感觉要简单一点

先把LX开头的字符串单独拎出来

如何找LX开头?可以判断索引值能否被3整除

1
2
3
4
5
6
7
8
a = "LX?Lx?Lx?Lx!Lx!Lx?Lx?LX?Lx?Lx?Lx!Lx?Lx!Lx!LX?Lx?Lx?Lx!Lx!Lx?Lx!LX?Lx!Lx!Lx!Lx!Lx!LX?Lx?Lx!Lx?Lx!Lx!Lx?LX?Lx?Lx!Lx?Lx?Lx?Lx!LX?Lx?Lx?Lx!Lx!Lx!Lx!LX?Lx?Lx?Lx!Lx?Lx!Lx?LX?Lx?Lx?Lx!Lx?Lx!Lx!LX?Lx!Lx?Lx!Lx?Lx!Lx!Lx?Lx?Lx!Lx!Lx?Lx!Lx!Lx!"


for i in range(len(a)):
if i % 3 == 0:
print(a[i], end="")
print(a[i+1], end="")
print(a[i+2], end=" ")

结果如图

只需判断a[i+1]是否为X就行了

由于for循环中索引最高只能到字符串长度的数字-1(len(a)-1),所以对于这次长度为231的字符串,它遍历时最大索引(index)为230,而这个数字不能被3整除,所以整除的数字最大只能到228

这样写会导致最后一段无法读出

1
2
3
4
5
6
7
8
9
for i in range(len(a)):
if i % 3 == 0:
if a[i+1] == "X":
count.append(i)
if len(count) == 2:
str_yiduan = a[count[0]:count[1]]
count[0] = count[1]
count.pop()
print(str_yiduan)

输出如图

加上

1
2
if i == len(a) - 3:
count.append(i)

这样写才是正确的

1
2
3
4
5
6
7
8
9
10
11
for i in range(len(a)):
if i % 3 == 0:
if a[i+1] == "X":
count.append(i)
if i == len(a) - 3:
count.append(i+3)
if len(count) == 2:
str_yiduan = a[count[0]:count[1]]
count[0] = count[1]
count.pop()
print(str_yiduan)

转回去到存储二进制字符串

1
2
3
4
5
6
7
8
9
10
for i in str_store:
str_read = "0b"
for ii in range(len(i)):
if ii % 3 == 0:
if i[ii+2] == "!":
str_read += '0'
elif i[ii+2] == "?":
str_read += '1'

print(str_read)

结果如下

把字符串中的二进制转成十进制(后面使用chr()函数要求输入10进制)

1
int(str_read,2)

扩展知识:

字符串(如“0b1110011”)转二进制可以这样写

1
str_read.encode()

再转回字符串

1
chr(int(str_read,2))

非常可惜的是,中文没法转回来,估计要用GBK编码

再处理一下

1
2
3
4
5
6
7
8
9
for i in str_store:
str_read = "0b"
for ii in range(len(i)):
if ii % 3 == 0:
if i[ii+2] == state1:
str_read += '0'
elif i[ii+2] == state2:
str_read += '1'
decode_str += chr(int(str_read,2))

结果如下

完整解码代码

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
a = "LX?Lx?Lx?Lx!Lx!Lx?Lx?LX?Lx?Lx?Lx!Lx?Lx!Lx!LX?Lx?Lx?Lx!Lx!Lx?Lx!LX?Lx!Lx!Lx!Lx!Lx!LX?Lx?Lx!Lx?Lx!Lx!Lx?LX?Lx?Lx!Lx?Lx?Lx?Lx!LX?Lx?Lx?Lx!Lx!Lx!Lx!LX?Lx?Lx?Lx!Lx?Lx!Lx?LX?Lx?Lx?Lx!Lx?Lx!Lx!LX?Lx!Lx?Lx!Lx?Lx!Lx!Lx?Lx?Lx!Lx!Lx?Lx!Lx!Lx!"

code1 = "Lx"
code2 = "LX"#开头
state1 = "!"#0
state2 = "?"#1

count = []
str_store = []
decode_str = ""

for i in range(len(a)):
if i % 3 == 0:
#print(a[i],a[i+1],a[i+2])
if a[i+1] == code2[len(code2)-1]:
count.append(i)
if i == len(a) - 3:
count.append(i+3)
if len(count) == 2:
str_yiduan = a[count[0]:count[1]]
count[0] = count[1]
count.pop()
str_store.append(str_yiduan)
print(str_yiduan)

print("\n", end="")
for i in str_store:
str_read = "0b"
for ii in range(len(i)):
if ii % 3 == 0:
if i[ii+2] == state1:
str_read += '0'
elif i[ii+2] == state2:
str_read += '1'
decode_str += chr(int(str_read,2))

print(decode_str)

结束

谢谢观看

来试试现场加密(支持编码中文)


JavaScript源代码在此

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
<script>
function encode_lx() {
var str_encode = "";
var input_str = "";
input_str = document.getElementById("info-input").value;
for (var i=0;i<input_str.length;i++) {
var char_one = "";
char_one = input_str.charAt(i);
char_one = char_one.charCodeAt(0).toString(2);
var started = 0;
for (var ii=0;ii<char_one.length;ii++) {
if (!started) {
str_encode += "LX";
started = 1;
} else {
str_encode += "Lx";
}
if (char_one.charAt(ii) == 0) {
str_encode += "!";
} else {
str_encode += "?";
}

}
document.getElementById("info-input").value = "";
document.getElementById("info-output").value = str_encode;
}

}
function decode_lx() {
var str0 = "";
str0 = document.getElementById("info-output").value;
var array_index = new Array();
var a_count = 0;
var decoded_str = "";
for (var i=0;i<str0.length;i++) {
if (i%3 == 0) {
if (str0.charAt(i) + str0.charAt(i+1) == "LX") {
array_index[a_count] = i;
a_count += 1;
}
}
if (i == str0.length - 1) {
array_index[a_count] = str0.length;
a_count += 1;
}
}

var str1 = "";
for (var aa=0;aa<array_index.length-1;aa++) {
str1 = str0.substring(array_index[aa],array_index[aa+1]);
var pre_decoded_str = "";
for (aaa in str1) {
if (str1[aaa] == "!") {
pre_decoded_str += '0';
} else if (str1[aaa] == "?") {
pre_decoded_str += '1';
}
}
decoded_str += String.fromCharCode(parseInt(pre_decoded_str,2));
}
document.getElementById("info-output").value = "";
document.getElementById("info-input").value = decoded_str;
}
</script>

此篇文章由于图片是截图,图片大小很小,所以使用base64的方法显示

EOF