文章目录
- 1 前言
- 2 原理及使用方法
- 3 这玩意有什么用
- 3.1 简单加密网址
- 3.2 隐藏二级目录
- 3.3 彩蛋:无限月读
- 3.4 探讨性的加密应用
- 4 转换的代码
- 4.1 将字符转为utf8数组
- 4.2 将utf8数组转换为字符串
- 4.3 最终转换
- 4.4 用R来实现
- 5 讨论
1 前言
大家可以复制一下这个网址到浏览器中打开:
https://ooooooooooooooooooooooo.ooo/ooooοооoοᴏοoοᴏοoοᴏooοᴏoᴏoᴏооoоᴏᴏoоᴏᴏοоᴏοοᴏoooоᴏоοᴏοᴏοоοοοооοοᴏоoοооοοоᴏоoоᴏоοᴏoοοᴏoοoоᴏоοоoᴏοоᴏᴏοоᴏοoоᴏᴏοоᴏοοᴏoooоᴏᴏοоoοοᴏooοᴏooοоᴏοοᴏoᴏοоοᴏοоoοοоᴏoοоoоοᴏοοοоᴏοoᴏᴏᴏοοᴏᴏοοᴏᴏοоoоοооοοᴏооoᴏᴏοοoᴏοοᴏооοоοᴏoᴏoᴏοoᴏοοоооοоοᴏoᴏοοοoᴏоοoοoοοоοoᴏoοοoᴏοοοoοoᴏᴏοoᴏᴏοoоοоοоoοοоoᴏοᴏοoοооοοоᴏᴏοоᴏоoᴏᴏοοоοᴏοоοοοᴏοoοоoοοоᴏoοоoоοᴏοοοоᴏοoоοоοоoοοоᴏoοоoоοᴏοοοоᴏοοοᴏᴏοооοοоοooᴏᴏοoᴏoоoᴏοᴏoᴏоooᴏoοoᴏοоoᴏοоoᴏοooᴏoοoᴏоooᴏоooᴏοᴏoᴏοοoᴏoᴏoᴏοᴏoᴏοᴏoᴏoоoᴏοοoᴏοooᴏοоoоοоοᴏoᴏοоoᴏοоοοοоᴏоοоοοoᴏᴏοoᴏoοoᴏοᴏoᴏoᴏoоοоοоοоοᴏoоοоᴏᴏοоᴏοοοᴏᴏοоᴏοοᴏoᴏοоοᴏοооοοоοooᴏᴏοoᴏoоoᴏoоoᴏοooᴏοᴏoᴏοooᴏоooᴏοοoᴏoᴏoᴏоooᴏοοoоοоοоοоοᴏoоοоᴏᴏοоᴏοοοᴏᴏοооοοᴏοoοоοοοоᴏοοооοοоοoοᴏоooᴏᴏοoᴏoοoоοоοоoᴏοоᴏᴏοᴏοοοоᴏоοᴏοooᴏᴏοoᴏoᴏoоοоοоᴏоοоᴏᴏοоᴏoοоoοοᴏoᴏοᴏοoοᴏoоοоοοοоoοοоοooᴏᴏοoᴏoοoоoᴏοᴏοᴏοоοοοоoᴏοооoοоoοοᴏοoοοᴏᴏοᴏoоοоοοοоοoοооοοᴏoоοоοοοоoᴏοᴏοo
不是恶作剧,大家看看打开后是不是这个页面
截图里的才是真实网址,但是如何转换成ooo的,以及有什么作用,可看下述
2 原理及使用方法
开源网址:https://github.com/lucaceriani/ooo
最简而言之,其实就是编码转换,可以比喻的理解成:把十进制的一串数字转换成二进制的一串数字,这个很好理解。
具体的实现原理是:
- 将字符转为utf8数组
- 将utf8数组转换为字符串
- 将字符串用以 4 进制的 Number 对象展示
- 填充指定字符,以达到指定长度
转换网址:https://ooooooooooooooooooooooo.ooo/
将想要转换的网址放进去,oOo一下即转换完成,可以直接copy使用了
3 这玩意有什么用
没有无用的工具,只有不正确的用法
3.1 简单加密网址
可以把一些看起来很奇怪的网址,不太好意思给人看到的网址用这个switch一下,不必多想,DDDD[Doge][Doge],下面举个例子
- 例如这种没有绑定域名的网址,觉得不好看,可以直接oOo转换一下,还能把ssh认证问题给解决了(即网址左边的“不安全标识”)
3.2 隐藏二级目录
- 例如像这里主域名后面的/什么什么/什么什么,这是二级目录,若自己搭建的shiny网站或者其他个人blog,有一些想要保密或者只给自己信任的人看的网页可以隐藏了。举例
主页/a页面/b页面/c页面
,如果想让人只使用c页面,那可以给switch一下,a和b页面如果不设置超链接在主页,是比较难访问的,涉及到反编码,一般人找不到(懒得找)
3.3 彩蛋:无限月读
有同学提到,既然能把网址增长,那能否把增长的网址再增长,当然可以[Doge],因为它的转换原理并不是a转换成b这样的,而是a变成b,再变成c,c再转换成d,然后再将d按一定规则扩产到对应长度
。因此扩产完长度的d,可以重新成为一个新的a再以此转换。
这里笔者将GPT专栏的链接转换了3次,已经一个屏幕快装不下了
但是有弊端,这是打不开的,因为转换过的网址再去转换,就已经不是原来那个网址了。为何一次转换浏览器可以打开,笔者还未渗透原理,但是猜测浏览器能自动识别这种格式的链接,但是经过多次转换后肯定无法识别的,这时只能通过反编码,因为转换规则是定死的,因此逆向运行一次便可反转。勿杠,下面会分享代码,记得一部番也有句挺有意思的台词谎言的谎言,就是真相
,可能也是这种逻辑吧。
已介绍完基本原理和使用方法,一般使用者止步于此了,如果感兴趣的可以往下看
3.4 探讨性的加密应用
像需要把本地的一个基因集给转换加密,是不可行的。因此基于第二个猜测,oOo网站转换后的网址,可以发现都是带https://
的,但这是本地文件,不可能在线打开的。因此可以认为oOo其实还是经过了自己的一个包装,不然无法解释怎么把一个未经过ssh认证的网址变成一个安全网址
,GitHub上有源码但还没细读,应该会有这样的处理的。
但是,可以把代码或者文本文件上传到云盘,锁定,然后将链接进行转换达到一定的保护效果。也提到过,因为oOo可能会自行包装,因此过于重要的文件不建议试了,除非,自己转换
4 转换的代码
都是基于JavaScript编写的通用型代码,笔者在【南城大前端】的https://mp.weixin.qq.com/s/V8o05zh-6H6ejg8_-jLltg基础上稍作优化,可以直接运行
4.1 将字符转为utf8数组
转换后的每个字符都有一个特定的唯一数值,比如 http 转换后的 utf8 格式数组即是 [104, 116, 116, 112]
function toUTF8Array(str) {
const utf8 = [];
for (let i = 0; i < str.length; i++) {
let charcode = str.charCodeAt(i);
if (charcode < 0x80) {
utf8.push(charcode);
} else if (charcode < 0x800) {
utf8.push(0xc0 | (charcode >> 6), 0x80 | (charcode & 0x3f));
} else if (charcode < 0xd800 || charcode >= 0xe000) {
utf8.push(
0xe0 | (charcode >> 12),
0x80 | ((charcode >> 6) & 0x3f),
0x80 | (charcode & 0x3f)
);
} else {
charcode =
((charcode & 0x3ff) << 10) | (str.charCodeAt(++i) & 0x3ff);
utf8.push(
0xf0 | (charcode >> 18),
0x80 | ((charcode >> 12) & 0x3f),
0x80 | ((charcode >> 6) & 0x3f),
0x80 | (charcode & 0x3f)
);
}
}
return utf8;
}
4.2 将utf8数组转换为字符串
function Utf8ArrayToStr(array) {
let out = "";
let i = 0;
const len = array.length;
while (i < len) {
const c = array[i++];
if ((c >> 7) === 0) {
// 0xxxxxxx
out += String.fromCharCode(c);
} else if ((c >> 5) === 0x06) {
// 110x xxxx 10xx xxxx
const char2 = array[i++];
out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
} else if ((c >> 4) === 0x0E) {
// 1110 xxxx 10xx xxxx 10xx xxxx
const char2 = array[i++];
const char3 = array[i++];
out += String.fromCharCode(
((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)
);
}
}
return out;
}
4.3 最终转换
# 将字符串用以 4 进制的 Number 对象展示
n.toString(4)
# 填充
str.padStart(4, '0')
4.4 用R来实现
javascript笔者仅学习了一年多,尚未入门,换回熟悉的R同样实现。第一步: R语言中使用的是向量而不是数组,因此要用有符号整数类型来存储UTF-8字节。第二步: R语言中使用的是向量,R中没有无符号整数类型,因此使用有符号整数类型来存储UTF-8字节
## step1
toUTF8Array <- function(str) {
utf8 <- integer(0)
for (i in seq_along(str)) {
charcode <- utf8ToInt(substr(str, i, i))
if (charcode < 0x80) {
utf8 <- c(utf8, charcode)
} else if (charcode < 0x800) {
utf8 <- c(utf8, bitwOr(0xc0, bitwShiftR(charcode, 6)),
bitwOr(0x80, bitwAnd(charcode, 0x3f)))
} else if (charcode < 0xd800 || charcode >= 0xe000) {
utf8 <- c(utf8, bitwOr(0xe0, bitwShiftR(charcode, 12)),
bitwOr(0x80, bitwAnd(bitwShiftR(charcode, 6), 0x3f)),
bitwOr(0x80, bitwAnd(charcode, 0x3f)))
} else {
i <- i + 1
charcode <- bitwOr(bitwShiftL(bitwAnd(charcode, 0x3ff), 10),
bitwAnd(utf8ToInt(substr(str, i, i)), 0x3ff))
utf8 <- c(utf8, bitwOr(0xf0, bitwShiftR(charcode, 18)),
bitwOr(0x80, bitwAnd(bitwShiftR(charcode, 12), 0x3f)),
bitwOr(0x80, bitwAnd(bitwShiftR(charcode, 6), 0x3f)),
bitwOr(0x80, bitwAnd(charcode, 0x3f)))
}
}
print(utf8)
return(utf8)
}
## step2
Utf8ArrayToStr <- function(array) {
out <- ""
i <- 1
len <- length(array)
while (i <= len) {
c <- array[i]
if ((bitwShiftR(c, 7)) == 0) {
# 0xxxxxxx
out <- paste(out, intToUtf8(c), sep="")
} else if ((bitwShiftR(c, 5)) == 0x06) {
# 110x xxxx 10xx xxxx
char2 <- array[i+1]
out <- paste(out, intToUtf8(((c & 0x1F) << 6) | (char2 & 0x3F)), sep="")
i <- i + 1
} else if ((bitwShiftR(c, 4)) == 0x0E) {
# 1110 xxxx 10xx xxxx 10xx xxxx
char2 <- array[i+1]
char3 <- array[i+2]
out <- paste(out, intToUtf8(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)), sep="")
i <- i + 2
}
i <- i + 1
}
return(out)
}
# 将数字转换为4进制字符串
as.character(intToBits(n, 4))
# 使用0填充前导位数
sprintf("%04s", str)
5 讨论
这个确实是个挺有趣的东西,不过使用的话见仁见智,ChatGPT对这个工具的评价原话:需要注意的是,将代码转换为"ooo"只是一种有趣的玩笑方式,并不推荐在实际工作中使用。
如果开发出有其他用法可以讨论交流