根据 id 生成唯一可反转短字符串(防止用户 id 等暴露), 用 hashids 稳妥不? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
kkk212
V2EX    程序员

根据 id 生成唯一可反转短字符串(防止用户 id 等暴露), 用 hashids 稳妥不?

  •  
  •   kkk212 2018-12-19 11:55:56 +08:00 6493 次点击
    这是一个创建于 2494 天前的主题,其中的信息可能已经有所发展或是发生改变。

    https://hashids.org/ Hashids is a small open-source library that generates short, unique, non-sequential ids from numbers.

    It converts numbers like 347 into strings like “ yr8 ”, or array of numbers like [27, 986] into “ 3kTMd ”.

    You can also decode those ids back. This is useful in bundling several parameters into one or simply using them as short UIDs.

    比如字符串长度设置 4-6 位,等用户量大了接近 4-6 位字符能表示的用户量时, 会不会出现重复的。

    39 条回复    2018-12-20 02:04:55 +08:00
    luosuosile
        1
    luosuosile  
       2018-12-19 11:58:41 +08:00   1
    我也遇到这个问题了,,帮顶吧。。本来我都打算用 uuid 了,顺带一提网上搜到的 short uuid 不太靠谱,评论都说几万条就重复了。
    kkk212
        2
    kkk212  
    OP
       2018-12-19 12:07:37 +08:00
    @luosuosile 我目前用的方案是,单独建一个表添加唯一索引,随机生成 6 位的字符串,然后插入千万条记录。这样是能保证重复问题,但是用的时候增加了一条 sql 查询。hashids 优点是能直接加密反转,不过还不太敢用。
    binux
        3
    binux  
       2018-12-19 12:13:36 +08:00
    Do you have a question or comment that involves "security" and "hashids" in the same sentence? Don't use Hashids. Here are some ways to decode:

    https://hashids.org/#decoding

    前面有个帖子我就说了,找个加密算法(比如 AES )算一下就行了。
    kkk212
        4
    kkk212  
    OP
       2018-12-19 12:23:15 +08:00
    @binux 怎么做到短字符串呢,比如 id 30 用 3jdhey 代替
    jedrek
        5
    jedrek  
       2018-12-19 12:31:48 +08:00
    hashids 不是用来加密的, 这东西和 base64 是一样的东西, 区别是 hashids 可以加个盐再编码
    binux
        6
    binux  
       2018-12-19 12:33:39 +08:00
    @kkk212 用 ctr 模式
    binux
        7
    binux  
       2018-12-19 12:42:06 +08:00
    @binux 看了下 ctr 模式可以算出加密用的块 stream 啊,你用小一点的块?
    kkk212
        8
    kkk212  
    OP
       2018-12-19 12:55:23 +08:00
    @binux 主要看到一些网站,用户主页的 id 有用用户昵称的,有用字符串的( 6 位左右)。用字符串的话,比如用 MD5 就行,但是 16 位或 32 位太长了不好看。开始没看 hashids 原理, 感觉 hashids 可以,有点缺点就是不定长和能看出来原数字的大小。谢谢,我一会再看看 aes
    kkk212
        9
    kkk212  
    OP
       2018-12-19 13:11:37 +08:00
    嗯,看了 hashids 原理明白了。但是为什么说不是用来加密的,加了盐值就和 base64 只是编码转换不一样了
    kkk212
        10
    kkk212  
    OP
       2018-12-19 13:12:42 +08:00
    @jedrek 嗯,看了 hashids 原理明白了。但是为什么说不是用来加密的,加了盐值就和 base64 只是编码转换不一样了
    xenme
        11
    xenme  
       2018-12-19 13:22:41 +08:00 via iPhone
    看你要求多安全,一般安全性自己撸一个 base64 的变种,基本没人看得出来,也是最简单的加密。不要说 base64 不是加密,只是大家都知道加解密方式而已。
    leonard916
        12
    leonard916  
       2018-12-19 13:25:02 +08:00
    @xenme 不是加密 只是把 byte[]成字符串而已
    xenme
        13
    xenme  
       2018-12-19 13:33:26 +08:00
    有哪种加密不是把 byte[]或者 string[]变成另外一串 byte[]或者 string[]么?
    只是变换的方式(加密算法)不同罢了。

    只是说现在 base64 类型的加密实在没有安全性,而且更多被人用来当做一种编码方式而已。
    jedrek
        14
    jedrek  
       2018-12-19 13:51:33 +08:00
    @kkk212 加了盐值是跟默认编码后结果不一样, 有了个“定制化”的编码结果. 但是编码算法是一样的.
    并不是说 hashids 完全不行, 还是取决你的用途, 如果想把一长串数字缩得很短, 直观上看不出来, hashids 是个很好的方案; 但若为了不让客户端知道解码后的值, 就不应该这么做, 因为很容易就能破解, 应该考虑对称加密的算法.
    jedrek
        15
    jedrek  
       2018-12-19 13:54:46 +08:00
    @kkk212 加了盐值是跟默认编码后结果不一样, 有了个“定制化”的编码结果. 但是编码算法是一样的.
    并不是说 hashids 完全不行, 还是取决你的用途, 如果想把一长串数字缩得很短, 直观上看不出来, hashids 是个很好的方案; 但若为了不让客户端知道解码前(此处修正)的值, 就不应该这么做, 因为很容易就能破解, 应该考虑对称加密的算法.
    woodensail
        16
    woodensail  
       2018-12-19 13:58:02 +08:00
    @xenme 现代密码学中,安全性不来自于算法的保密而来自于密钥的保密。所以 base64 和各种不引入外部密钥的数据编码方案都不能称之为加密。
    xenme
        17
    xenme  
       2018-12-19 14:14:45 +08:00
    @woodensail 针对楼主的需求来说,算法和密钥都是不需要公开的,安全性要求不是特别高的情况下,类似 base64/hashid 这种“加密”足够满足需求了。
    kkk212
        18
    kkk212  
    OP
       2018-12-19 14:27:39 +08:00
    @xenme 可 hashid 的算法是暴露的
    woodensail
        19
    woodensail  
       2018-12-19 14:29:31 +08:00
    @xenme 同楼上,不要把希望寄托在别人不会拆包上,搞黑产的有这个耐心。
    jedrek
        20
    jedrek  
       2018-12-19 14:29:46 +08:00
    @kkk212 这么说可能都脱离了你的用途了. 说说你的用途和为啥想这么用. 说不定有更好的方案
    xenme
        21
    xenme  
       2018-12-19 14:30:54 +08:00
    个人以为加盐后,hashid 足够满足你要求了。
    默认 hashid 基本是 base62,6 位的话,最多可以表示 56800235584,超过 500 亿,你用户量也不可能更多了。
    xenme
        22
    xenme  
       2018-12-19 14:39:58 +08:00
    @woodensail 前面也说了,安全性要求并不是特别高的话,可以考虑 hashid,毕竟即使黑进后台了,也就知道个用户量而已或者用户真正的 ID,并不能怎么样。而且,即使用更安全的算法,能进来看到算法和 salt 的人,估计你的安全算法的密钥也暴露了。
    @kkk212 这个 id 的 hash 应该是你在用户注册之后,在后台生成后返回给前台用来代替 user id 的。所以,对应的算法以及 salt 是只有后台人员才知道的。你并不需要在前台编解码,所以并没有暴露出来。
    kkk212
        23
    kkk212  
    OP
       2018-12-19 14:40:28 +08:00
    @jedrek 就是用一个短的字符串代替用户 id 来显示, 不能解密也不会暴露真实的 id。目前用的方案是,生成好一个存储 6 位字符串记录的表(插入 2000 万记录), 创建新用户的时候查出来对应 id 的字符串,存到用户表里。但是用户多了,存储字符串的表查询就会慢了,并且这样得定期维护字符串表,感觉费事。
    jedrek
        24
    jedrek  
       2018-12-19 14:57:27 +08:00
    @kkk212 我有第一个问题: 真实用户 ID 一定不能暴露吗? 可否说说担忧的原因?
    kkk212
        25
    kkk212  
    OP
       2018-12-19 16:03:46 +08:00
    @jedrek 用户主页开放的话,比如防止按照用户 id,爬用户信息。
    jedrek
        26
    jedrek  
       2018-12-19 16:05:46 +08:00
    @jedrek 这个好解决, 用户 ID 不是连续自增的就可以了, 参考 instagram 的 ID 策略
    lawler
        27
    lawler  
       2018-12-19 16:32:30 +08:00
    用户 ID + 任意固定整数 -> 转 32 进制。

    例如 用户 id 1
    固定整数 987412312

    10 进制值是 987412313
    显示 id 是 tdldqp

    不定期更新任意固定整数。
    chinvo
        28
    chinvo  
       2018-12-19 16:36:19 +08:00 via iPhone
    @lawler #27 为了避免重复,你只能增大这个参数而不能减小,而且还需要一个专门的字段保存过去的 ID 对应的字符串
    lawler
        29
    lawler  
       2018-12-19 16:38:45 +08:00
    @chinvo 不需要啊。出站入站时反转 userid,换句话说,明天别人拿这个 id 访问这个页面的时候,就是别人的数据了。这个值不入库的。参数只要不是负值,任意值都没问题。
    zhengxiaowai
        30
    zhengxiaowai  
       2018-12-19 16:42:07 +08:00
    @kkk212 https://github.com/zhengxiaowai/shortuuid

    看看这个,实测百万无重复
    chinvo
        31
    chinvo  
       2018-12-19 16:45:02 +08:00 via iPhone
    @lawler #29 你得考虑持久化 URL 的问题,被检索的 URL、印刷的二维码和其他物料
    chinvo
        32
    chinvo  
       2018-12-19 16:45:25 +08:00 via iPhone
    我厂用 ksuid
    kkk212
        33
    kkk212  
    OP
       2018-12-19 16:53:04 +08:00
    @chinvo ksuid 位数长呀
    arthasgxy
        34
    arthasgxy  
       2018-12-19 16:58:30 +08:00
    好奇请教一下楼上各位,我司有类似的,只不过是纯数字,不知道是不是与你们同样的目的。
    每个用户,3、4 个 xxid,都是纯数字,有的长,有的短,一直不知道搞这么多有什么特别的意义?
    chinvo
        35
    chinvo  
       2018-12-19 17:06:20 +08:00 via iPhone
    @arthasgxy #34 大概是历史遗留问题,不同子系统甚至不同表里面用的 ID 不同
    chinvo
        36
    chinvo  
       2018-12-19 17:06:36 +08:00 via iPhone
    @kkk212 #33 emm,确实长了点
    chinvo
        37
    chinvo  
       2018-12-19 17:07:35 +08:00 via iPhone
    @kkk212 #33 snowflake 呢?或者自己实现类 ksuid,把 payload 从 128bit 减到 64bit
    arthasgxy
        38
    arthasgxy  
       2018-12-19 17:13:37 +08:00
    @chinvo 感谢回复。
    感觉上应该跟历史没啥关系。新项目,也是这样搞的。
    agdhole
        39
    agdhole  
       2018-12-20 02:04:55 +08:00
    转成 int 32/64? steam 是这么做的,不过很长
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5777 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 43ms UTC 06:11 PVG 14:11 LAX 23:11 JFK 02:11
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86