[toc]
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]
functiontoUTF8Array(str) { constutf8= []; for (leti=0; i<str.length; i++) { letcharcode=str.charCodeAt(i); if (charcode<0x80) { utf8.push(charcode); } elseif (charcode<0x800) { utf8.push(0xc0| (charcode>>6), 0x80| (charcode&0x3f)); } elseif (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) ); } } returnutf8; }
4.2 将utf8数组转换为字符串
functionUtf8ArrayToStr(array) { letout=""; leti=0; constlen=array.length; while (i<len) { constc=array[i++]; if ((c>>7) ===0) { // 0xxxxxxxout+=String.fromCharCode(c); } elseif ((c>>5) ===0x06) { // 110x xxxx 10xx xxxxconstchar2=array[i++]; out+=String.fromCharCode(((c&0x1F) <<6) | (char2&0x3F)); } elseif ((c>>4) ===0x0E) { // 1110 xxxx 10xx xxxx 10xx xxxxconstchar2=array[i++]; constchar3=array[i++]; out+=String.fromCharCode( ((c&0x0F) <<12) | ((char2&0x3F) <<6) | ((char3&0x3F) <<0) ); } } returnout; }
4.3 最终转换
# 将字符串用以 4 进制的 Number 对象展示n.toString(4) # 填充str.padStart(4, '0')
4.4 用R来实现
javascript笔者仅学习了一年多,尚未入门,换回熟悉的R同样实现。第一步:R语言中使用的是向量而不是数组,因此要用有符号整数类型来存储UTF-8字节。第二步:R语言中使用的是向量,R中没有无符号整数类型,因此使用有符号整数类型来存储UTF-8字节
## step1toUTF8Array<-function(str) { utf8<-integer(0) for (iinseq_along(str)) { charcode<-utf8ToInt(substr(str, i, i)) if (charcode<0x80) { utf8<-c(utf8, charcode) } elseif (charcode<0x800) { utf8<-c(utf8, bitwOr(0xc0, bitwShiftR(charcode, 6)), bitwOr(0x80, bitwAnd(charcode, 0x3f))) } elseif (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+1charcode<-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) } ## step2Utf8ArrayToStr<-function(array) { out<-""i<-1len<-length(array) while (i<=len) { c<-array[i] if ((bitwShiftR(c, 7)) ==0) { # 0xxxxxxxout<-paste(out, intToUtf8(c), sep="") } elseif ((bitwShiftR(c, 5)) ==0x06) { # 110x xxxx 10xx xxxxchar2<-array[i+1] out<-paste(out, intToUtf8(((c&0x1F) <<6) | (char2&0x3F)), sep="") i<-i+1 } elseif ((bitwShiftR(c, 4)) ==0x0E) { # 1110 xxxx 10xx xxxx 10xx xxxxchar2<-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)
4 讨论
这个确实是个挺有趣的东西,不过使用的话见仁见智,ChatGPT对这个工具的评价原话:需要注意的是,将代码转换为"ooo"只是一种有趣的玩笑方式,并不推荐在实际工作中使用。
如果开发出有其他用法可以讨论交流