原创

探讨搜狗翻译加密算法

2019-10-11 Friday 12:00

本文编写于:2019年10月11日,搜狗翻译加密算法随时会变,因此当您阅读到此篇文章的时候可能无法完全按照文章操作步骤执行,请注意。
注:本文仅供探讨学习所用,请勿用于违法牟利等用途。

前言

类似百度、搜狗、有道等翻译平台是提供了官方的API接入的,但这些平台都实行收费制,例如翻译百万字符50元,而这些平台又都提供了官方的网页版,供普通用户使用,完全免费。
因此有些开发者可能就会想,能否调用网页版的接口,这样就不会收费了,但是,既然人家都做了收费的,那肯定不会让你轻易的调用他们免费的接口,因此都会进行一些加密处理,例如最常见的采用签名验证字符串。
如果开发者想要调用网页版接口,那就必须要得知签名验证字符串的计算方法,而网页的源码又是完全可见的,因此可以在网页html、js中找寻签名验证字符串是如何计算得出的。
本篇文章就带大家一步步计算出搜狗翻译的签名验证字符串,并可成功调用搜狗翻译!

1.抓包

搜狗在线翻译的网址为:
http://fanyi.sogou.com/
我们可以看到其网页还是很简单的,直接在编辑框里输入要翻译的文本后即会立马翻译。
这里我们就可以开始抓包了,看一下它翻译的时候都提交了哪些数据。
我使用的抓包工具为“Fiddler”,大家可以按需选择,反正能抓到数据就行。
启动Fiddler后在网页里输入一个带翻译的文本,这里我输入“你好”作为测试,可以看到Fiddler抓出了很多数据。
一般来说,这类的网站请求数据都会采用post形式,而返回的结果一般是JSON或XML,因此过滤了一下就找到了这么个请求:

POST http://fanyi.sogou.com/reventondc/translateV2 HTTP/1.1
Accept: application/json
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: http://fanyi.sogou.com/
Accept-Language: zh-CN
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Connection: Keep-Alive
Content-Length: 213
Host: fanyi.sogou.com
Pragma: no-cache
Cookie: YYID=D832CE22323DA4E13D30F316600BFD4D; IMEVER=9.3.0.3129; SUV=004EC7C50EDCE77A5CD8EC629688D985; CXID=B37E0E718CDB6032AE47178CECB439C1; SUID=6AE7DC0E3665860A5CFB7D65000C079F; IPLOC=CN4419; ssuid=8255104706; wuid=AAEmjU2WKAAAAAqLFCRHyw4AGwY=; SNUID=55704A9B959301E530428D6E96C6E4D2; ad=AZllllllll2N0xdQlllllVLG4CYlllllRH8XVkllll9lllllpklll5@@@@@@@@@@; ABTEST=0|1566913274|v17; SELECTION_SWITCH=1; HISTORY_SWITCH=1

以上为请求报头,具体的post数据为:

from=zh-CHS&to=en&text=%E4%BD%A0%E5%A5%BD&client=pc&fr=browser_pc&pid=sogou-dict-vr&dict=true&word_group=true&second_query=true&uuid=35bf7b98-ba4d-48ac-8d9e-3fd187da8b21&needQc=1&s=312120fbca14043ca2a9d8019ac49a54

我们可以使用一些在线测试网络请求的网站进行测试,例如
http://coolaf.com/
我们先使用最简单的方法,只填写请求的URL跟post数据,然后点击“提交”,可以看到返回了JSON,如下所示:
注:因数据太长,因此此处只展示重要数据。

{
    "translate": {
        "errorCode": "10",
        "from": "zh-CHS",
        "source": "sogou",
        "text": "",
        "to": "en",
        "orig_text": "",
    }
}

可以看到其中并没有返回翻译结果,并且errorCode参数是10,注:一般来说,接口中要存在errorCode参数的话,其通常0代表成功,非0代表出错,所以证明搜索翻译光提交post数据是不行的,还需要额外参数。
按照老司机的经验,感觉请求出错应该是少了Content-Type、Referer、User-Agent、Cookie这几个,我们可以测试下:
在网页里点击“显示高级功能”,然后在“header”编辑框中填入

Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://fanyi.sogou.com/
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Cookie: YYID=D832CE22323DA4E13D30F316600BFD4D; IMEVER=9.3.0.3129; SUV=004EC7C50EDCE77A5CD8EC629688D985; CXID=B37E0E718CDB6032AE47178CECB439C1; SUID=6AE7DC0E3665860A5CFB7D65000C079F; IPLOC=CN4419; ssuid=8255104706; wuid=AAEmjU2WKAAAAAqLFCRHyw4AGwY=; SNUID=55704A9B959301E530428D6E96C6E4D2; ad=AZllllllll2N0xdQlllllVLG4CYlllllRH8XVkllll9lllllpklll5@@@@@@@@@@; ABTEST=0|1566913274|v17; SELECTION_SWITCH=1; HISTORY_SWITCH=1

然后再次点击“提交”,可以看到返回了如下的JSON数据:
注:因数据太长,因此此处只展示重要数据。

{
    "data": {
        "translate": {
            "errorCode": "0",
            "source": "sogou",
            "dit": "Hello",
            "from": "zh-CHS",
            "text": "你好",
            "to": "en",
            "orig_text": "你好",
        },
}

可以看到返回的JSON中是有我们所要的翻译结果数据的,证明提交成功!
注:Content-Type、Referer、User-Agent这三个参数值都是固定的,而Cookie在每次打开翻译网页时都会发生变化,这Cookie要如何获取就八仙过海各显神通咯。

2.分析提交数据

既然已经模拟请求成功了,那我们就要开始分析提交的数据了,但提交的参数很多,其中有些参数可能无需提交,因此我们可以去掉一些参数后进行网络请求,最终测试出来必须提交的参数为:
from=zh-CHS
看名字应该是翻译源语言,zh-CHS是代表中文的意思
to=en
目标语言,en为英文
text=%E4%BD%A0%E5%A5%BD
这个就是我们要翻译的文本了,可以将上面的数据进行URL解码,得出的结果就是“你好”
pid=sogou-dict-vr
应该是类似用户ID的标识
s=312120fbca14043ca2a9d8019ac49a54
这个s参数看上去很像是签名验证字符串,我们可以测试下,将它的数据稍微改一下,例如把开头的“3”改成“4”,然后提交看看。
提交后发现果然返回的JSON出错了,并没有返回翻译结果。
那我们在测试下其它的参数,看看哪些参数是无法修改的。
最后发现from、to、text参数都无法修改,而pid修改后无影响。
因此可以得出,s的确是签名验证字符串,并且s的计算方式肯定跟from、to、text三个参数有关,否则也不会修改其中一个就请求失败了。

3.寻找加密方式

现在我们就开始进入最后一步,寻找加密方式了,只要找出s是如何计算得出的,那么我们就可以随意的调用搜狗翻译接口了!
首先我们需要先保存搜狗翻译网页所用到的所有文件,这里可以使用浏览器的保存功能,推荐使用chrome(谷歌浏览器)。
使用chrome打开搜狗翻译的网址:
http://fanyi.sogou.com/
然后直接按Ctrl+S保存网页,这里选择一个文件夹保存,例如我保存在D盘的搜狗翻译文件夹中,保存的文件名也叫搜狗翻译,然后点击保存。
这时候我们去D盘的搜狗翻译文件夹中,可以看到有
“搜狗翻译_files”文件夹

“搜狗翻译 - 上网从搜狗开始.html”文件
前者“搜狗翻译_files”文件夹中是所有搜狗翻译网页用到的js、css等资源文件,而“搜狗翻译 - 上网从搜狗开始.html”就是搜狗翻译的网页html了。
之前抓包我们得知,最后获取翻译结果是请求了如下的网址
http://fanyi.sogou.com/reventondc/translateV2
如果了解网页js的,那知道js的网络请求是无法跨域的,因此上面的网址在js代码中请求的准确地址应该是
/reventondc/translateV2
好,这时候我们就要找出最后的网络请求到底是在哪里发起的,然后一步步找寻到s是如何得出的。
我们先在“搜狗翻译 - 上网从搜狗开始.html”中搜索下上面的地址。
提示没有找到,这并不奇怪,一般加密的都不会直接放在html中的。
这下我们需要去js文件中寻找了,进入“搜狗翻译_files”文件夹中。
我们可以看到文件夹中有png、css、js等文件,我们这里只关注js后缀的。
注:作者这边使用chrome保存下来的js文件后缀是XX.js.下载,后缀会多出“.下载”,不过无影响,直接使用记事本打开即可。
我们先找到第一个js文件,文件名为
app.85a13e6c.js
此文件一看就很像是用来加密的,不要问我为什么,单身的直觉。
好,使用记事本打开此文件,然后我们直接搜索:
/reventondc/translateV2
ok,完美,有搜索结果!
这时候我们就要仔细看看js代码了,不过上下光标动了动,发现代码基本没换行,一行朗读了无数的代码,这还怎么让人阅读那!
这时候可以用到代码格式化工具,可直接使用网页版,网址为:
http://tool.oschina.net/codeformat/js/
将js代码复制到网页中的带格式化编辑框中,点击格式化,然后找到结果编辑框,将代码复制出来,哎哟,一下就很清楚了。
好,这时候我们来具体看看之前我们搜索到的结果那快的代码:

		$.ajax({
"url": "/reventondc/translateV2",
"method": "post",
"dataType": "json",
"headers": {
"Accept": "application/json"
},
"data": W

这里发现的确是发起了网络请求,提交的数据是变量W,那我们网上浏览浏览,找寻一下W的定义,找到了如下的代码:

W = {
"from": R,
"to": O,
"text": M,
"client": "pc",
"fr": "browser_pc",
"pid": "sogou-dict-vr",
"dict": !0,
"word_group": !0,
"second_query": !0,
"uuid": B,
"needQc": f.need,
"s": J
};

这里我们已经看到了最后网络请求所用到的from、to、text、pid、s的参数定义。
from、to、text、pid参数我们已经知道其内容了,不需要再寻找具体的值,这里最关键的代码就是:

"s": J

可以看到s签名验证字符串的值是J变量,那我们在网上找找J的定义,找到了如下的代码:

J = s("" + R + O + M + V),

这个代码意思是将R、O、M、V四个字符串相加,然后传给s方法,而J的值就是s方法的返回值!
那问题又来了,我们还需要找到R、O、M、V四个变量的具体值,诶诶,有没有仔细的小伙伴发现,好像R、O、M三个变量我们见到过?在W变量的定义部分有如下代码:

"from": R,
"to": O,
"text": M,

这下就很明白了,R其实就是from参数的值,而O跟M分别是to跟text参数的值。
所以这里也能看出,为什么最终的s签名验证字符串跟from、to、text三个参数有关联了,毕竟s的值可是用这三个参数加上V计算而出的!
好,成功就在眼前,我们在寻找下V的定义,网上浏览,找到了如下代码:

var V = window.seccode,

V的值是变量window.seccode的值,那我们在寻找下window.seccode的值是什么。
啊哦,很遗憾,直接使用搜索功能,找出的结果中都没有看到window.seccode的定义,因此可以得知,window.seccode的值并不在此文件中。
我们在回到“搜狗翻译_files”文件夹中,打开其他文件,开始搜索window.seccode。
最后找来找去,吧所有js文件都找完了,居然都没有!不过,却在“logtrace”这个无后缀的文件中发现了window.seccode!
搜索到的代码块为:

window.seccode=8511813095152;

由此,我们也知道了V的值,就是8511813095152!

4.最后一步

我们先来整理下,最后发起网络请求的时候,x签名验证字符串的值是变量J,而J的值是s方法的返回值,而掉s方法的时候,传入了四个变量拼接起来的字符串,而这四个变量按照顺序分别是参数from、to、text以及最后一个V变量,其值为“8511813095152”!
之前我们测试的时候from、to、text的值分别为:
from=zh-CHS
to=en
text=%E4%BD%A0%E5%A5%BD
好,现在我们已经得知了四个变量的具体值,我们来手动拼接一下,最终得到的字符串是:
zh-CHSen%E4%BD%A0%E5%A5%BD8511813095152
而我们之前s签名验证字符串的值是:
312120fbca14043ca2a9d8019ac49a54
好!最后一步!找寻s方法是如何将拼接的字符串计算成最终s的值的!
这里有兴趣的朋友可以继续查找s方法的定义,作者很懒,不继续分析s方法了,好了,文章到此结束。
一板砖拍死作者!
这都到最后一步了居然给我看这个?
哈哈哈!
为了不被读者拍死,就直接告诉你们啦!,s方法其实就是MD5加密方法,我们可以测试下,将
zh-CHSen%E4%BD%A0%E5%A5%BD8511813095152
进行MD5加密,这里可以使用在线MD5加密网站,网址为:
https://md5jiami.51240.com/
输入带加密的数据后点击加密,然后下光标找到32位的加密结果,是:
7636e026dbaada3ae6961cdefad04268
啊哦,怎么跟之前我们抓包的
312120fbca14043ca2a9d8019ac49a54
不一样呢?
哈哈哈哈~
好了,最后科普,在js网络提交的时候参数会进行URL编码,因此text的值在提交之前是没有进行url编码的,也就是说,在计算签名的时候,其是原文状态,而之前就有说过,text其实就是我们要翻译的文本,上面例子中的值也就是“你好”!
所以最终要进行MD5的字符串其实是
zh-CHSen你好8511813095152
大家自己去进行加密看结果吧~哈哈~

后续

经过这洋洋洒洒几千字下来,我们总算是得知了搜狗翻译的签名验证字符串是如何计算得出的了,大家可以测试翻译其他文本,然后重新计算s的值,最后提交给服务器,看看能否成功返回翻译结果。
有时候研究下各大平台的加密算法还是很有意思的,经常会让你感叹,居然还能这么玩?
好了,本文就到此结束,作者对html、js了解并不深,有错误之处欢迎批评改正。
作者:落寞
联系QQ:1402440758
作者博客:https://www.lmdbk.com/


随手打赏
关闭

感谢您的支持!

扫码打赏,你说多少就多少
打赏二维码

打开

支付宝

扫一扫,即可进行扫码打赏哦