# Fun.FontDecode **Repository Path**: sephil/Fun.FontDecode ## Basic Information - **Project Name**: Fun.FontDecode - **Description**: 现在很多网站使用字体加密的方式来保护页面内容,即:你在页面上看到的文字内容不能直接复制或者下载下来,复制或下载得到的内容是乱码。 Fun.FontDecode 是一个 C# 编写的解密库,通过这个库可以解密得到原始的文字内容。 - **Primary Language**: C# - **License**: BSD-3-Clause - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2020-05-24 - **Last Updated**: 2022-06-07 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Fun.FontDecode #### 介绍 现在很多网站使用字体加密的方式来保护页面内容,即:你在页面上看到的文字内容不能直接复制或者下载下来,复制或下载得到的内容是乱码。 Fun.FontDecode 是一个 C# 编写的解密库,通过这个库可以解密得到原始的文字内容。 #### 加密原理 我们在显示器上看到的文字其本质其实是一种图形,计算机是不能直接处理图形的,所以我们需要将文字的图形保存下来,然后操作系统中制定一个对应的规则让文字与图形一一对应。其中,图形的集合就是我们所说的字体,而对应的规则就是文字的编码。当要显示一个文字时,操作系统根据文字的编码到字体中查找其对应的图形,然后将图形显示在屏幕上,这样我们才能够在屏幕上看到这个文字。举个例子,字母 A 的 ASCII 编码是 65,当操作系统要显示字母 A 时,会到字体中查找编码 65 对应的图形,然后把这个图形显示在屏幕上即可。如果使用不同的字体,那么我们看到的字母 A 的样子是不一样的,但是所有字体的提供者都会遵守同一个编码规则,即编码 65 代表的就是字母 "A"。 字体加密其实就是利用了这个规则,把文字编码和图形的对应规则全部打乱了,比如把图形 "A" 的对应编码改成 3456,虽然你在屏幕上看到的是 "A",但复制或下载下来的文字的编码其实是 3456,操作系统根据编码 3456 在正常的字体中得到的图形就不知道是个什么样的,所以这样的文字内容就没法在其他地方正常使用了。 目前字体加密方式有两种用法,一种是使用预先生成好的字体,然后输出时把文字转换成字体对应的编码,放到页面里显示即可。暂且叫它 **静态方式** 。这种方式解密,我们只需要找到字体文件,分析出编码对应规则后记录在代码里就可以了, **发布时不需要附带额外的文件** 。还有一种是每次页面显示时都重新生成一个新字体和编码对应规则,然后文字再做转换显示。这种我称为 **动态方式** 。两种方法本质上没有不同,只是第二种方式 **每次解密时都需要下载对应的字体文件进行分析和匹配** ,操作上繁琐一些。 #### 使用方法-静态 1. 分析页面和 CSS,找到字体文件的存放路径,下载到本地; 2. 用 Fun.FontDecode.Viewer 工具打开字体文件,就能看到文字的点阵图形与它对应的编码; 3. 填写 Viewer 右侧的文字与编码对应规则,如图中所示的, 对应字符 2, 对应字符 4; 4. 点击 Copy Static 按钮,Viewer 将自动生成字典代码并复制到剪贴板,然后将此代码粘贴到代码里; 4. 使用 `Fun.FontDecode.StaticFontDecoder` 解密。 参考如下代码: ``` static IDictionary FCharMapping = new Dictionary() { 复制的字典代码 }; string Decode(string text) { return new StaticFontDecoder(FCharMapping).Decode(text); } ``` #### 使用方法-动态 这种方法解密要麻烦一些 1. 分析页面和 CSS,找到字体文件的存放路径,下载到本地; 2. 用 Fun.FontDecode.Viewer 工具打开字体文件,就能看到文字的点阵图形与它对应的编码; 3. 填写 Viewer 右侧的文字与编码对应规则,如图中所示的, 对应字符 2, 对应字符 4; 4. 点击 Copy Dynamic 按钮,Viewer 将自动生成字典代码并复制到剪贴板,然后将此代码粘贴到代码里; 5. 每次解密时必须 **先下载字体文件** ,再使用 `Fun.FontDecode.DynamicFontDecoder` 解密。 参考如下代码: ``` static IDictionary FCharMapping = new Dictionary() { 复制的字典代码 }; // 先下载 eot 字体文件,然后将字体文件作为参数传入 // EmbeddedOpenTypeParser 解析支持文件、流、字节数组、Base64编码的字体数据 // 这个示例里是将字体文件的所有内容作为字节数组传入 string Decode(byte[] fontSource, string text) { var eotParser = new EmbeddedOpenTypeParser(); eotParser.Parse(fontSource); return new DynamicFontDecoder(eotParser.FontData, FCharMapping).Decode(text); } ``` #### 其他说明 1. 基本上大部分网站的字体加密都只针对 0-9 和个别符号、汉字,分析的工作量不大的。 2. 动态加密时,生成的字体点阵图形会有一些偏差,如果解密得不到正确结果,将 `DynamicFontDecoder.ErrorRange` 放大一些试试。 3. 目前这个库只支持 eot 字体文件的解析,ttf、woff 解析没有测试过。不过一般页面上都会同时提供 eot 和 woff 字体。