Appearance
Sample Encryption Standard的设计与实现
该算法是我在开发Rockstar的数据查询软件时为了加密展示玩家
rid
所研究的算法,可对长度较短的整数进行加密展示该算法作为抛砖引玉,供大家参考
有的朋友可能会很好奇,为何对一些简单的数字都需要进行加密,直接放出来不是更简单快捷?其实这是为了保护被查询者的隐私和方便各位准确的定位数据
索引和玩家标识是对数据库索引和rid进行处理后产生的,这些数据都是6-10位数的随机数字。如果暴露了这些数据不仅不方便记忆,还会对玩家的隐私造成影响
如果暴露了数据库主键,有心人可以轻易的遍历整个数据库,把所有玩家的数据都拷贝一部分,这就变相的泄露了隐私。而rid的大量泄露后果更加严重,Rockstar标识玩家依靠分配的身份编号,即rid(数字ID)。外挂追战局用的也是rid,如果暴露出来,查询程序实质上也相当于为外挂提供了便利
因此迫切地需要一个将能将这些隐私数字转化为不泄密又方便好记的加密算法,我姑且按照参考的DES算法将其命名为简单加密算法(Sample Encryption Standard)即SES
目标需求
- 面向对象: 短长度的数字,不大于20位数。且数据类型为整形,表示的数也不需要填充0到一定长度
- 需求性质:
- 基础要求: 消息机密性、秘钥保密性、消息认证
- 雪崩性: 小变化、大不同
- 抗选择文本攻击: 已知算法、原文、密文也找不出其他数据
- 加密结果: 将简单的非逻辑的数字转化为无法直接解密,方便记忆的形式
在参考了多种加密方式后,我决定采用类DES的形式对数据进行加密,然后将收集到的数据按规则转化为类车牌样式
为什么是类DES
由于需要对加密后的结果解密,因此MD5、RSA、HASH、ECC等非对称加密算法就首先出局。而AES算法对数据定长的要求比较严格,RC2算法又和DES算法结构类似。因此我决定以DES算法为蓝本,实现一个基于Feistel网络结构的加密算法
Feistel 密码结构: 在密码学研究中,Feistel 密码结构是用于分组密码。基本思想是将密码分位等长的左右两组,每轮迭代进行亦或加密
什么是类车牌样式
因为使密文尽量地短,必须对数据加密结果进行压缩。压缩长度最直接的方式就是使用将数字转化为更高进制。比如四位二进制1110
转化为十进制只需要两位的14
就能表示,而十六进制更是只需要一位e
就能表示
那么为什么说是类车牌呢,因为十进制和十六进制的压缩度不够高,而64进制的表示因为包含大小写不同的字母而难以识别(1ilj0o
)。而26个大写字母加10个数字既能覆盖压缩度合理的32进制区间又有余量舍去造成混淆的一些字符(1I 0O OQ Z
)
这听着像不像是现行的92式汽车车牌?不过稍有不同的是,汽车车牌为了管理方便在开头添加了牌照的归属地信息,而且得益于字符的字体固定,QZ这样在特殊字体下可能造成误解的字符也可以使用
加密算法的实现
由于Feistel
网络的操作需要将数据分成两部分,因此加密数据的长度需要是偶数。而类车牌样式又要求数据长度是5的倍数。因此求得的数据必须满足长度为10的倍数,这也导致了加密后的结果的程度每次长度的增加都是两位
可以考虑采用类base64
的64位加密方式,这样最小公倍数就是6,可以实现单字符的长度增加和更高地压缩率。但是识别又成了问题,需要在日后的使用中观察
预处理
加密算法本质上是对二进制处理,如何将不定长度的数字输入转化为可处理的二进制就需要依靠预处理了
起始偏置
考虑到数据长度对于加密的抗破解能力的影响,需要对数据进行偏置。即将待加密的原数据与一个约定的大小合适的数字相加,将数据的初始位数扩充到一个安全的范围
转换成二进制
由于待加密的数据本身就是便于转化为二进制的十进制整数,因此简单的转化为二进制即可。填充数据只需要在前面补0至总长度为十的倍数即可
初始混淆
为了使密码得到更好地扩散和实现雪崩性,因此对数据进行初始混淆。由于时间精力有限且输入长度不确定,因此采用简单线性变化
加密时先进行魔术,再进行桶混淆。解密时反序完成即可
魔术混淆
类似于早期Flash游戏的加密,按序遍历二进制,将奇数个数据添加至新字符串的末尾,偶数个字符串添加至新字符串的开头
桶混淆
类似于桶排序,预生成n个桶(n=4)。按序遍历字符串将第i个字符串放入第i%n个桶中,最后将n个桶内的字符串按桶的顺序相加
轮加密
轮数选择和数据处理
将数据等分为Left
Right
两组,一共进行待处理的二进制数据长度次迭代运算。
秘钥处理
将密钥使用utf-8
编码转换为二进制,每次使用对密钥按区间循环请求数据
如密钥是1234,实际使用时每次取长度为三的轮密钥,每轮的密钥为123、412、341...
轮加密过程
- 将
Right
组与轮密钥进行异或后再与Left
组异或 - 由于无法进行E扩展置换和S盒替代、P盒置换,因此每次处理后的
Right
循环左移一位作为替代方案 Left
组与Right
组更换位置
结果映射
将结果的二进制按每五位分组,按照32位的长度字符映射表进行转换,具体映射可自行设置
例:ABCDEFGHJKLMNPRSTUWQXY0123456789
小结
虽然由于水平和精力有限,加密的算法略显简陋。但是依然满足可能出现的抗选择文本攻击的需求,如果存在被攻击的可能性,使用3SES方案即可