hashids加密算法基础与扩展

前言

hashids的核心原理是映射,将原有字符映射为其它字符,且此映射是可逆的,网上有具体的原理和库,本文主要描述相关思路。

  • 映射即通过某种规则将数据A变为数据B,如果可逆,则同样通过反操作可以将数据B映射为数据A
    • 所以可以编码,也可以编码,不同于hash256编码和MD5编码这种
    • 为了编码的安全性,通常需要将规则分为逻辑规则和初始数据部分
      • 逻辑规则就是基本的映射算法
      • 初始数据部分可以理解为辅助逻辑规则生成具体映射方法的参数
    • 因为映射是可逆的,所以信息不能损失,只能通过各种规则来变换,如此方可解码
  • 只要建立合理的规则,可以兼容所有的数据类型(数字、不同类型字符串等等)
    • 网上常见为对数字编码,但是掌握原理后可扩展

实现

下文以伪代码对加解码描述思路。

// source = 输入数据
// secret = 编码的字符串,即初始数据部分
// 方法返回编码后的字符串
String encode(String source,String secret){
    //1. 根据 secret 和固有的逻辑规则生成具体的映射规则M
    //2. 使用规则M 对source 编码,得到的字符串坐返回
}

映射规则的生成

按照内容映射

方式一,在简单模式下,可以生成一个固定内容的映射规则

将 A 映射为B ,将B映射为D,将C映射为A
输入 [ABC]
输出 [BDA]

方式二,整理好需要支持的字符内容集合,通过位置做内容映射

定义此方法仅仅支持ABCD四个字符的编码,则
原始字符为 [ABCD];  用过洗牌算法将字符打乱为  [BCAD]
输入 [ABC]
根据原有字符在集合中的位置,到新集合中寻找对于字符做映射
输出 [BCA]

按照位置映射

通过当前字符的位置,将之做内容映射

假设规则为    当前字符变换为 (编码字符集的索引位置 + 当前输入的索引位置 ) % 字符集长度 的对应原始字符串[ABCD]的索引的位置的字符。
定义此方法仅仅支持ABCD四个字符的集合, 则支持的字符集长度 = 4;原始字符串[ABCD]的索引的位置=[0,1,2,3]
 
编码逻辑:
输入字符集为 [AACC];
按照字符和位置依次处理:
    输入字值,输入索引 -> (输入字值在输入字符集的索引值 + 字符在原始字符串中索引值) % 4 = 在原始字符串中的索引位置 = 编码后字符
    这里可以理解为找到原始字符对应的编码集中的字符,并向环形后移动输入字符对应索引值得到的原始字符串中的字符。
    A,索引0 -> 0 + 0 = 0 % 4 = 0 = A
    A,索引1 -> 1 + 0 = 1 % 4 = 1 = B
    C,索引2 -> 2 + 2 = 4 % 4 = 0 = A
    C,索引3 -> 3 + 2 = 5 % 4 = 1 = B
输出 [BCAB]
 
解码逻辑, 由于原值的索引范围是 0 - 3, 未防止取余带来的数据变为负数,这里加上 4以保证正数索引,这里加上4是为了保证值为正数, 同样可以理解为是反向移动
    编码后的值,编码串对应索引 -> (编码值对应原始字符串对应索引 - 编码串位置索引 + 4) % 4 = 原始值串[索引] = 原始值 
    A,索引0 -> 0 - 0 + 4 = 4 % 4 = A
    B,索引1 -> 1 - 1 + 4 = 4 % 4 = A
    A,索引0 -> 0 - 2 + 4 = 2 % 4 = C
    B,索引1 -> 1 - 3 + 4 = 2 % 4 = C
输出 [AACC]

通过位置映射的优点是同一个字符在不同位置展示的值是不同的,如此增加了破解的难度;

对于某些需要高位或者低补充固定字符的内容来说,编码后肉眼可见的变得更加复杂。

扩展

混合多种映射

将一段内容按照内容和位置,甚至其它自定义规则,按照顺序依次映射,则得到的结果将更难以还原,映射的规则的复杂度也大大提示。

但是,同一种规则的多次映射却没有必要,因为输入的参数和输出的结果在规则确定的情况下,是一定的,不论中间经过多少次变换。

假设按照内容映射
输入  a ->  映射为 b ->  将b 映射为 c  ->   将c映射为  d ;   实质上等同于将 a 映射为 d; 因为中间的几个映射规则最终可以组合为一个;

只有调整输入内容,同时制定对应的规则才能形成更加复杂的规则;如同维度的增加,配上对应的处理规则的组合形成的复杂的多维多次函数。

上文例举的只是最简单的两个维度:内容,当前字符对应的位置。

编码的secret

静态secret

上文提到可以每种输入可以看成一种维度,而这些维度都是在编码串中已知存在的,不具有很高的保密性;如果我们加入其它维度,将之混入映射的规则之中,则编码后的字符串还原的难度大增,此维度即为secret。通常我们使用一个静态内容,比如一个字符串来作为静态的secret,一般而言信息越多,规则越复杂(因为映射后对应内容规则的的重复映射次数越少,也就越具有随机性)。

示例

假设现在定义了一个 secret = 2431 ;  
 
生成两种映射规则, 规则A为位置映射,规则B为内容映射,支持ABCD四种字符的映射;
step1:
    生成原始字符串原本对应的索引 [A,B,C,D] = [0,1,2,3]
step2:
    规则A,通过secret将原本对应的索引映射 [A,B,C,D] = [0 + 2,1 + 4,2 + 3,3 + 1] = [2,5,5,4];
    取余以获取支持的字符串  [2 % 4,5 % 4,5 % 4,4 % 4] = [2,1,1,0];
    通过setp1 逆向查找对应字符串 = [C,B,B,A]   
step3:
    规则B,通过secret 中每一个字符表示 ABCD 四种字符的交换规则,通过规则生成映射表,这里将位置2与4交换,将位置3与1交换;
 
    映射表 = ABCD ->  ADCB -> CDAB ;
     [C,B,B,A]     ->  [A,D,D,C];
 
通过两种规则可以按照顺序来混合生成结果 [A,B,C,D] ->  [A,D,D,C];

动态secret

如果secret是动态生成的,比如根据时间来,不同时间自动根据规则、或者根据约定好的字符串来作为secret, 其复杂度可以进一步提升。但是考虑到解码要求,其可能附上解码需要的信息,导致编码后的内容增长。通常情况在高下可按照模块或者应用、用户来区分,而不是完全的动态生成规则。

源码

这里提供了一种常见的字符串hashids编解码,仅供理解文章参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值