数值与字符串转换算法

很多场景需要将数据库记录主键发送到前端,对于递增或趋势递增的主键很容易被恶意用户推测出来,因此需要一种可逆性的算法能够将数值型与字符串进行互换。

方案一(数组)、
1.随机生成一个种子([1-9]内的正整数)

int seed = new Random().nextInt(10); // 0要排除掉

2.随意一个十进制的数值,每一位都是有[0-9]组成的,所以[0-9] * seed = [0-81],因此我们需要至少82个不重复的字符

'u','4','+','1','2','I','B','U','x','z','@','c','M','G','f','<','b','(','O','T','H','=','C','D','$','&','p','d','m','o','i','n','a','Z','_','s','3','^','*','P','8','%','/','l','F','R','r','A','9','y','v','.','#','N','g','e','>',')','t','!','5','7','`','?','h','V','S','Q','0','X','K','j','W','J','q','w','|','E','6','k','L','Y'

3.以数值【52337610997641216】举例说明,假设seed取值为3
数值–>字符串

52337610997641216
5*seed2*seed3*seed3*seed7*seed6*seed1*seed0*seed9*seed9*seed7*seed6*seed4*seed1*seed2*seed1*seed6*seed
15699211830272721181236318
<Bzz=O1udd=OM1B1O

最终得到字符串:<Bzz=O1udd=OM1B1O

字符串–>数值

<Bzz=O1udd=OM1B1O
15699211830272721181236318
15/seed6/seed9/seed9/seed21/seed18/seed3/seed0/seed27/seed27/seed21/seed18/seed12/seed3/seed6/seed3/seed18/seed
52337610997641216

最终还原数值:52337610997641216

优点:算法简单
缺点:1.一次转换中,相同的数值对应的字符相同,容易让恶意用户推测出算法;2.种子只有9个取值,因此一个数值最多只有9种组合方式,第十次一定会出现重复。

一定要保证随意两个数相乘的最大值要小于等于不重复的字符个数。因为如果最大值大于字符个数,就会出现两个数对应同一个字符,在字符串反转为数值就可能出现错误(当然可以增加标识为,但是会导致字符串边长切算法更复杂,而且我们也没有这么多不重复的英文字符可用)


方案二(环路)、
方案二主要针对方案一的缺点进行改进。
1.还是用方案一中的82个字符组合,只不过在方案一是数组格式,方案二我们改进成环,将82个字符收尾相连组成一个环路。

在这里插入图片描述

2.生成种子
由于82个字符都不重复,[0-81]范围内的正整数都可以作为种子

int seed = new Random().nextInt(82);

3.以数值【52337610997641216】举例说明,假设seed取值为45
n = 1 --> offset1 = seed + number(1);
n > 1 --> offset(n) = offset(n-1) + number(n)

数值–>字符串

52337610997641216
(45+5)%82(50+2)%82(52+3)%82(55+3)%82(58+7)%82(65+6)%82(71+1)%82(72+0)%82(72+9)%82(81+9)%82(90+7)%82(97+6)%82(103+4)%82(107+1)%82(108+2)%82(110+1)%82(111+6)%82
505255586571727281815212526282935
v#etVjWWYx<=&pmos

最终得到字符串:v#etVjWWYx<=&pmos

字符串–>数值
n = 1 --> val(1) = index(1) - seed;
n > 1 --> val(n) = index(n) - index(n-1);

v#etVjWWYx<=&pmos
505255586571727281815212526282935
50-4552-5055-5258-5565-5871-6572-7172-7281-7290-8115-821-1525-2126-2528-2629-2835-29
52337610997641216

最终还原数值:52337610997641216

优点:改进了方案一中的两个缺点
缺点:如果数组中有0,则相邻两位字符相同

方案三(环路+m)、
方案三主要针对方案二的缺点进行改进。假设m=1

n = 1 --> offset1 = seed + number(1) + m;
n > 1 --> offset(n) = offset(n-1) + number(n) + m

数值–>字符串

52337610997641216
(45+5)%82+1(51+2)%82+1(54+3)%82+1(58+3)%82+1(62+7)%82+1(70+6)%82+1(77+1)%82+1(79+0)%82+1(80+9)%82+1(90+9)%82+1(100+7)%82+1(108+6)%82+1(115+4)%82+1(120+1)%82+1(122+2)%82+1(125+1)%82+1(127+6)%82+1
515458627077798081826333840434552
.gt`KEkLxOpZ*8lR#

最终得到字符串:v#etVjWWYx<=&pmos

字符串–>数值
n = 1 --> val(1) = (index(1) - 1) - seed;
n > 1 --> val(n) = (index(n) - 1) - index(n-1);

.gt`KEkLxOpZ*8lR#
515458627077798081826333840434552
(51-1)-45(54-1)-51(58-1)-54(62-1)-58(70-1)-62(77-1)-70(79-1)-77(80-1)-79(8+82-1)-80(18-1)-8)(26-1)-18(33-1)-26(38-1)-33(40-1)-38(43-1)-40(45-1)-43(52-1)-45
52337610997641216

最终还原数值:52337610997641216

优点:改进了方案而中的缺点

方案四(checksum)、
以上三个方案都能一定程度上防止恶意用户所以输入字符串,但是可能会出现恶意用户输入的字符串正好能转换为一个数值。因此需要增加一个冗余校验,考虑到复杂度和冗余字符串长度,这里采用类似checksum的冗余校验方案。
number % 82生成随机seed,然后将seed对应下标下的字符加到最终字符串中。然后在字符串转换为数值后,将数值整除82,再获取相应下标的字符串,最终进行比对。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值