密码学得不好,请问这种简单用户 id 加密模式的安全性有多大问题?

2023-10-09 08:36:32 +08:00
 lithbitren

真实用户 id 是递增数字(可能随机递增),但是不想直接暴露给用户,于是想加密成固定长度的且可供人类阅读的串。

于是我就简单设计一个加密算法,根据对原始数字串进行简单的映射、移位、异或、置换,具体的参数由密钥来确定,简单两个小时写完没有优化,单线程加密百万次大约 650ms ,解密百万次大约 300ms 。

安全性肯定比不上任何一个叫得出名字的非古典加密算法,不过我密码学学得不好,让我自己反推用户 id 感觉毫无头绪。

下面是 100 个连续数字生产的密文 id (假设在某个时段用某种手段注册到了连续的 100 个 id ),所以我自制的这个加密算法有多大可能被简单破解。

[8137831387705, 8766632441404, 8910104411709, 8643189995064, 8062272707134, 8062272707109, 8360588849722, 8436168501822, 8755222343230, 9087172922277, 8146503885753, 8738860500924, 8884484149181, 8651874944952, 8034436934590, 8034436934565, 8334968587194, 8444840885182, 8729602097086, 9089977697445, 8149308546233, 8739450564796, 8882923452605, 8652532248760, 8035090949310, 8035090949285, 8333411040442, 8445494768830, 8728044791998, 8838268586533, 8138117587513, 8764834072124, 8910454312509, 8643488777784, 8060407228990, 8060407228965, 8358794412602, 8436451310142, 8755575668286, 9082675589029, 8142023198649, 8770870401980, 8879932285885, 8645246917560, 8066442497982, 8066442497957, 8330420922298, 8440339357630, 8725054428094, 9083195984549, 8142526685881, 8769180387004, 8880441020093, 8647902201528, 8064820521662, 8064820521637, 8328776925882, 8440864864958, 8725558050494, 9090802285605, 8150149895225, 8742490777660, 8877326544957, 8651196753976, 8038067215422, 8038067215397, 8327844541498, 8439881083966, 8728920743998, 9082598946597, 8141879447353, 8770726765372, 8879859837757, 8645136704312, 8066366904126, 8066366904101, 8330310725434, 8440266893118, 8724944362302, 8837958882213, 8137841437625, 8764524236732, 8910110005181, 8643179073464, 8062245008318, 8062245008293, 8360632191930, 8436140540862, 8755265947582, 8838197468709, 8138063377977, 8764762950204, 8910332072509, 8643434433080, 8060335193662, 8060335193637, 8358673225274, 8436383583806, 8755454198334, 8837982374533]

6906 次点击
所在节点    信息安全
82 条回复
lithbitren
2023-10-09 10:01:02 +08:00
@Bay0net 对对对,原来是这样破的,虽然代码里面没有 25 ,但是 25 倍数确实会有规律,然后再做差指确实可以找出别的规律,如果随机递增 id 能进一步避免吗?
xiangyuecn
2023-10-09 10:05:18 +08:00
id=[100,101,102,103,104,105];

id2=id.map(v=>v*1234567899-1111111119)

id3=id2.map(v=>(v+1111111119)/1234567899)

console.log(id,id2,id3)

没啥意思,随手写一个简单无比的,别人都懒得去破解
lithbitren
2023-10-09 10:05:22 +08:00
@Bay0net 因为密文 id 也可以存成 64 位整数,性能比字符串好,所以应该会用密文 id 来作为索引获取一部分数据,起码不会在前端暴露原始 id 。
c2const
2023-10-09 10:06:34 +08:00
1.不是密码学专业的,就不要自己设计算法了,100%有漏洞,个人项目用就自己设计的就算了,公司项目最好直接用现成的算法 :(
2.想哈希就老老实实用现成的哈希算法,加密就加密算法,现在对 AES 都有软件硬件的优化,速度不慢,想特殊点就用 Serpent 算法之类的 :)
someday3
2023-10-09 10:32:14 +08:00
密码学学完忘记的差不多了,但是记得老师每次上课都叮嘱过的一句。
一定不要自己写密码算法,就用市面上现成的。
tool2d
2023-10-09 10:36:31 +08:00
@lithbitren "但好在理论上加密过程可以不公开。"

算法公开无所谓的,现在 HMAC 这种算法都是公开的,但是你没有密码,也没办法调用 HMAC ,把密码保管好就可以了。
lithbitren
2023-10-09 10:38:34 +08:00
市面上完整的加密算法不是不好,就是加密出来的串太长,同样不具有可读性,同样也没见过多少人真的拿用户 id 上 AES 的,甚至连 hashid 都少见,八股文里也就提提雪花、uuid ,偶尔见到有人来点大数异或、加减乘除,甚至纯纯递增也不少见,比如 B 站就用了很多年的递增 AV 号。
lithbitren
2023-10-09 10:42:52 +08:00
算法公开的前提是复杂度的证明原则上可以超过宇宙时间,我这个算法显然不能,成熟的算法各种操作都十几轮几十轮,我这个只有个位数轮次,如果能无限拿到明文 id ,破起来轻轻松松。
kkwa56188
2023-10-09 10:43:08 +08:00
1. 自创的所谓"加密算法" 没有经过严格验证之前, 都可以直接认定是不安全的. 换句话说, 严格意义称得上"安全"的加密算法, 是白名单的. 你把白名单里的 AES 也好 DES 也好, 魔改了数学上就不等价了, 自然就又不白名单了
2. 这个场景就是典型的加盐 hash 一下就完事了.
zealotxxxx
2023-10-09 10:44:04 +08:00
为什么一定要可读性呢? 可读就代表,要短,要有规律。你这不是显然给自己降低强度更容易破解么?
tool2d
2023-10-09 10:49:29 +08:00
@lithbitren "算法公开的前提是复杂度的证明原则上可以超过宇宙时间"

你没懂我的意思,算法公开的前提,是你算法要提供可设置密钥功能,比如可以自己换个加盐值。

输入参数不能只有一个用户 ID ,还需要一个密钥,这样才可控。
litchinn
2023-10-09 10:51:50 +08:00
> 简单的映射、移位、异或、置换
这种方式和古典密码学一样,特征太明显了

从需求出发,我觉得你的算法只要满足你现在的需求就能用,毕竟你又不给别人用

从算法讨论出发
1. 我觉得 1 楼说的对
2. 永远不要自己设计使用加密算法
3. 安全在于密钥而不在算法

> 同样也没见过多少人真的拿用户 id 上 AES 的
感觉就没多少场景有和你这个类似的需求的,通常来说 id 本来就不是什么敏感数据,暴露一个 id 和一个 hash 或加密后的 id 根本没多少区别,特别是现在大规模使用 uuid ,雪花 id 的情况下。
担心伪造 id 应该通过数据权限控制,担心暴力刷接口应该用其他安全机制
x1aoYao
2023-10-09 10:54:36 +08:00
晃眼一看,大致都是 8 或者 9 开头,太有规律性了,一点都不随机,加密至少要看起来像是噪声一样的随机内容。
如果你只是想要生成 uuid ,有很多 hashid 算法,如果你是想加密可以直接用 AES 。

如果有特殊需求,建议至少加盐再异或,至少看起来很随机(例如原文是 int64 ,然后随机一个 int64 作为盐,然后 hash 这个盐得到数去异或原文,再把盐拼在一起得到的 int128 用密钥来进行你的映射、移位、异或、置换这些。这样同样是可逆的,但至少看起来毫无规律了。)
lithbitren
2023-10-09 10:58:14 +08:00
@tool2d 是有密钥的啊,中间一些具体的参数是由密钥生成的,当然主要是算法太简单,有密钥应该也百分百会被破解。
wupher
2023-10-09 11:00:27 +08:00
hashids
lithbitren
2023-10-09 11:01:07 +08:00
@x1aoYao 首位是用来对齐的,实际只有 12 位,其实我的思路跟你的差不多,不过不知道要做到几个轮次才能看起来毫无规律。
tool2d
2023-10-09 11:08:25 +08:00
@lithbitren "有密钥应该也百分百会被破解。"

密钥换了,中间参数都换了,这也能破解?
lithbitren
2023-10-09 11:08:35 +08:00
@x1aoYao 简单来说,如果每个 id 只是末尾加一的话,除了映射,其他移位、异或、置换改变的数字及其顺序都是极为有限的,本来就很容易找出规律,成熟的加密算法分解来说也是这些个基本操作,但轮次会多很多,而且选取的固定参数可能有其特殊性(自创加密算法可能很难找到合适参数)。
lithbitren
2023-10-09 11:12:24 +08:00
@tool2d 首先有效数字就一共只有 13 位,如果能无限拿到具体对应的 id ,爆猜都能出结果,密钥没这么重要。
cx9208
2023-10-09 11:15:40 +08:00
密码学里有一点就是不要自己发明加密算法。用户 id 可以用随机 id 或者 uuid 就够了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/980076

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX