V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
lqzhgood
V2EX  ›  程序员

[加密算法] 有没有可以 ‘限制密文长度’ 且 ‘可逆’ 加密算法?

  •  
  •   lqzhgood · 2019-01-29 16:07:24 +08:00 · 11000 次点击
    这是一个创建于 2159 天前的主题,其中的信息可能已经有所发展或是发生改变。
    steam 账号丢了~ 我估摸着是撞库。
    用 算法 代替 密码 的想法由来已久了,是时候行动了。

    大致想法如下:
    域名 /用户名等----------算法--------->密码----------- [秘钥 + 加密算法] ---------> 密文

    虽然通过算法生成后的密码已经足够好了(至少不会被撞库),但是还是想一步到位。再用一个加密算法加固下。

    因为准备再写一个 Chrome 扩展来解决密文生成的问题,所以准备用 js 现实,看了下 node 的库 cryptojs。
    但是 AES 4 位秘钥 10 位密码 生成的密文 高达 44 位。。。。
    一般密码填写仅允许 16 位。

    实在对密码学不了解。。。。

    在这里求一个
    4~6 位秘钥 + 10 位左右文本 生成的密文长度能在 ‘ 16 位’ 以内的 ‘可逆’ 加密算法。。。
    第 1 条附言  ·  2019-01-29 16:46:49 +08:00
    好吧,怪我没说清
    不是 固定长度啊!!!!!

    画个图~
    10 位左右文本 + 4~6 位密钥 ------ [算法] -------> 16 位以内密文
    第 2 条附言  ·  2019-01-29 16:48:27 +08:00
    16 位以内密文 指的是 0-16 位的密文,不是固定 16 位长度的密文。
    第 3 条附言  ·  2019-01-30 09:41:45 +08:00

    感谢大家的留言,打开了很多思路。 很多人阅读形式是关键词式的, 16位 可逆 加密再加密 密码学。然后就直接回复了。 虽然过年了,对吧。但是这不是娱乐新闻。请不要浮躁对待。不过还是感谢您的留言 增加了热度 :)

    这里回应几个关键词:
    16位固定长度: 是在 [0,16] 区间内的长度。非 [16,16]
    可逆: 我希望以后看到一串乱码我能反推他原来的样子,知道这是哪个网站哪个账号的密码
    造轮子: 据我所知目前所有的管理器都是生成随机密码的,并不能自定义根据域名等生成。理由同上
    装下整个世界: 10位文本+4位秘钥 = 14位。 16位的容量足够装下14位的世界
    加密再加密: 根据规则生成密码只能抵抗脱裤后的批量扫描。
       如 域名+用户名+固定字符 的规则--> qquserABC_! 有心人一看就知道规则了。如果你说自己定个规则乱序一下,uAqsBqerC! 或者说错位输入 wwidrtABC_!这样至少一眼瞄过去就不知道了呀。但是这不就已经是 加密再加密了 吗?


    我知道自己造密码学的轮子大概率要跪,但我家不是国防部,好比世界上没有撬不开的锁,但你只要比邻居的好就行了。我只想让我的密码 在很长一段时间内 比其他人强那么一些就行了。不用那么极端 需要拿量子计算机来破

    最后留下结论。
    算法: #12 可以用置换加密; 轮子: #28 已经有了全套轮子。在此感谢 不过他使用的是哈希+随机,是不可逆的。如果想要可逆,只要自己把这部分改成置换加密即可。但是这样改造后不要公开你的代码,因为你的算法已经明文了。

    over

    68 条回复    2022-09-27 19:35:27 +08:00
    binux
        1
    binux  
       2019-01-29 16:14:36 +08:00 via Android   ❤️ 1
    你这 44 位和 16 位,这两个位是同一个量词吗?
    Vegetable
        2
    Vegetable  
       2019-01-29 16:16:02 +08:00   ❤️ 1
    如果你的用户名是 16 位以上的,比如邮箱
    可逆的算法无法稳定的将密文控制在 16 位以内.
    可逆没必要吧.
    btw,很多加密算法要把结果转为 hex,hex 是十六进制,26 个字母都没用全.
    flowfire
        3
    flowfire  
       2019-01-29 16:17:30 +08:00 via Android   ❤️ 1
    不存在,固定输出长度不可能有可逆
    youzhao
        4
    youzhao  
       2019-01-29 16:18:26 +08:00   ❤️ 1
    @flowfire 说得对
    crab
        5
    crab  
       2019-01-29 16:19:46 +08:00   ❤️ 1
    取加密后前 16 位
    lqzhgood
        6
    lqzhgood  
    OP
       2019-01-29 16:23:42 +08:00
    @flowfire
    我不是说固定长度=16。
    我只是说 16 位以内的。
    因为一般密码最多允许 16 位
    lqzhgood
        7
    lqzhgood  
    OP
       2019-01-29 16:24:47 +08:00
    @binux 是的。。 我说的是 "abcde".length = 5 位
    exch4nge
        8
    exch4nge  
       2019-01-29 16:27:46 +08:00
    想要密文跟明文长度一样的话,用流加密吧,或者用 CTR 分组模式当流加密用也行。具体 node 里什么库,什么函数,我不是特别清楚。
    flowfire
        9
    flowfire  
       2019-01-29 16:27:59 +08:00 via Android
    @lqzhgood 跟位数是多少没关系,只要长度不可变,就不可能可逆,就好比固定尺寸的盒子不可能装下所有东西,不论这个盒子有多大
    lastpass
        10
    lastpass  
       2019-01-29 16:29:19 +08:00
    既然已经使用浏览器,不如换个思路?
    直接 lastpass 完全随机密码走起。
    连我自己都不知道密码,还有比这更安全的吗?
    要是在线不放心。可以试试完全本地版 keepass 嘛。
    lqzhgood
        11
    lqzhgood  
    OP
       2019-01-29 16:29:22 +08:00
    @Vegetable
    谢谢提醒~
    我在想是不是自己弄个 密码表
    1-0 a-z A-Z 然后乱七八糟的符号加进去~ 弄个 100 进制。

    然后想个啥算法把 文本 通过这个 100 进制 映射成 一个密文。 这样应该可以很大程度缩短密文的长度了。
    catror
        12
    catror  
       2019-01-29 16:29:44 +08:00
    没看懂,加密后的密文打算用来干啥?也作为密码用?
    如果要长度不变,就用简单的置换加密,规则自己定义。
    ZRS
        13
    ZRS  
       2019-01-29 16:32:36 +08:00
    密文长度和明文长度一致是可以做到的,流加密就是这样


    不过说到底...请使用密码管理软件不要自己造轮子...
    lqzhgood
        14
    lqzhgood  
    OP
       2019-01-29 16:33:24 +08:00
    @flowfire 没搞懂您说的长度不可变啥意思~
    我是说 一段 10 个字符长度的文本通过 4~6 个字符的秘钥 生成 0-16 个字符之间密文。 这样的算法。
    reus
        15
    reus  
       2019-01-29 16:36:11 +08:00
    可逆怎么可能限制长度,不要试图挑战香农
    dbw9580
        16
    dbw9580  
       2019-01-29 17:17:05 +08:00 via Android
    TomVista
        17
    TomVista  
       2019-01-29 17:21:06 +08:00
    你在密码里固定位置插入固定字符,然后进行一些可逆的骚操作,最后在逆回来,然后去字符串???可以把.

    没学过加密.
    pabupa
        18
    pabupa  
       2019-01-29 17:47:46 +08:00 via Android
    原来有好几把钥匙,现在只需要一把! O_o
    ysc3839
        19
    ysc3839  
       2019-01-29 17:56:18 +08:00
    推荐使用 KeePass 密码管理器。比自己实现简单多了。
    sdijeenx
        20
    sdijeenx  
       2019-01-29 18:12:46 +08:00
    没必要吧,用随机数代替账号密码不就好了么=3=
    我的用户名就是滚键盘按出来的,密码用 keychain 建议密码。

    辣鸡箱里随便找的代码片,LZ 拿去玩吧=3=

    #输出 16 位随机数

    import random

    def getradnstring(a):
    out = ''
    for x in range(1,a):
    out += random.choice('abcdefghijklmnopqrstuvwxyz')
    return out

    getradnstring(17)
    1010543618
        21
    1010543618  
       2019-01-29 18:13:44 +08:00
    我都是根据域名生成密码,但改密码新旧密码不能相同就头疼了
    xxgirl2
        22
    xxgirl2  
       2019-01-29 18:50:29 +08:00
    ubuntu 自带密码管理器 pass,使用 gpg 加密
    likuku
        23
    likuku  
       2019-01-29 19:43:50 +08:00
    想太多,密码学太艰深,即便搞清概念又能怎样?

    买个密码管理软件,梳理一遍自己用的密码,每个服务统统换不同的高强度密码。酱紫才能实际解决问题。
    Kagari
        24
    Kagari  
       2019-01-29 19:47:45 +08:00 via Android
    花密
    2exploring
        25
    2exploring  
       2019-01-29 19:51:08 +08:00
    想弄出定长的结果,你可以做一次散列(散列的结果够长了吧),然后截取你要的长度就行了。

    不过我还是要说,现成的密码管理软件多好,干吗要自己造轮子。。
    ruixingchen
        26
    ruixingchen  
       2019-01-29 19:51:34 +08:00 via iPhone
    lastpass 解决问题,或者花蜜也行
    2exploring
        27
    2exploring  
       2019-01-29 19:52:38 +08:00
    @2exploring 才发现你要可逆的,散列不行,当我没说。。。
    codeklaus
        28
    codeklaus  
       2019-01-29 21:00:15 +08:00   ❤️ 2
    要是只实现这个想法的话, 异或就行了啊
    比如你的密文 0123456789, 随便搞个秘钥 j987, 你就 0123 xor j987, 4567 xor j987, 89 xor j9 这样. 你的文本是多少位密文就是多少位, 然后楼主拿这个密文当密码, 我理解的对不对?

    但是还是推荐楼主使用密码管理............ 比如钥匙链这种
    23f0baf3
        29
    23f0baf3  
       2019-01-29 21:12:12 +08:00
    https://github.com/emersion/passwordmaker 各种算法都有,还可自行修改结果(替换字符,加前后缀等)
    gam2046
        30
    gam2046  
       2019-01-29 21:29:06 +08:00
    异或?

    密码表?

    原文与限定的最终长度太相近,并没有多余的空间来操作了。
    AlphaTr
        31
    AlphaTr  
       2019-01-29 21:51:50 +08:00
    好几年前自己有类似的想法,供参考,就是用的哈希算法,不是可逆的; https://blog.alphatr.com/randpsw.html
    shintendo
        32
    shintendo  
       2019-01-29 22:13:09 +08:00
    楼主,要是有“限制长度+可逆”的加密算法,你首先应该拿来做压缩工具
    liberize
        33
    liberize  
       2019-01-29 23:36:30 +08:00
    @flowfire RSA 了解一下,密文长度等于密钥长度,也就是固定的
    kersbal
        34
    kersbal  
       2019-01-29 23:46:01 +08:00
    为何要可逆。。。另外,一句老话“不要自己写加密函数”
    flowfire
        35
    flowfire  
       2019-01-29 23:46:36 +08:00
    @liberize #33 你要么就是对 RSA 有什么误解,要么就是对我的话有什么误解
    flowfire
        36
    flowfire  
       2019-01-29 23:47:17 +08:00
    @kersbal #34 那句话是 密码学不要造轮子
    liberize
        37
    liberize  
       2019-01-29 23:49:18 +08:00
    密钥是固定的? RC4 密文长度等于明文长度,由于限制密文是 ASCII 字符,可以 RC4 以后做 BASE64
    liberize
        38
    liberize  
       2019-01-29 23:56:49 +08:00
    @flowfire 『就好比固定尺寸的盒子不可能装下所有东西』 信息论大家都学过,就不要卖弄了
    楼主说的明文长度也是有限制的,而且比密文还短,他没有要求装下『所有东西』
    Xs0ul
        39
    Xs0ul  
       2019-01-30 00:12:20 +08:00
    lz 想把随机生成的密码再次加密,来当做注册用的密码,这其实完全没意义吧?对网站来说还是个随机敲出来的乱码密码

    除非你想防的是本地木马破解你的密码数据库
    kersbal
        40
    kersbal  
       2019-01-30 00:20:45 +08:00
    @flowfire 容易造出个轮子看上去是圆的其实是方的。。。
    hearfish
        41
    hearfish  
       2019-01-30 00:21:31 +08:00 via iPhone
    Aes128, 每个 block 是 128 bit 也就是 16 bytes, 你的密码才 10 位,理论上没问题啊, 只是实际操作上密文可能是诸如 0x10 之类的字符,再转义成可打印的字符就超过 16 位了
    fakeshadow
        42
    fakeshadow  
       2019-01-30 00:54:37 +08:00
    我一般是用 bip39,自己的短密码只用来加密产生的私钥
    enjoyCoding
        43
    enjoyCoding  
       2019-01-30 01:18:55 +08:00 via iPhone
    就不能好好申请嘛 搞这搞着都忘记玩游戏了喂
    dommyet
        44
    dommyet  
       2019-01-30 01:41:43 +08:00
    openssl rand -base64 16
    weyou
        45
    weyou  
       2019-01-30 02:35:02 +08:00 via Android
    如果存在这个算法,那它最大的价值不是加密领域,而是数据压缩领域。
    leavic
        46
    leavic  
       2019-01-30 06:10:20 +08:00 via Android
    你这个想法基本等同于靠一个 md5 逆推出一个 iso 镜像
    billwsy
        47
    billwsy  
       2019-01-30 06:20:32 +08:00
    @codeklaus 我觉得 28#是正解,密钥再扩展一下就能对付任何长度了。。只是,这个算法随随便便就可以被破解,几乎抵挡不住任何 threat model
    lqzhgood
        48
    lqzhgood  
    OP
       2019-01-30 08:56:19 +08:00
    @weyou
    @leavic
    请审题~ 我没想让 16 位的密码装下整个世界。
    16 位密码 装不下 10 位文本+4 位秘钥?

    前面已经有人提到了。置换加密就能满足。
    strongcoder
        49
    strongcoder  
       2019-01-30 09:16:37 +08:00 via iPhone
    1Password 可以帮你
    yahon
        50
    yahon  
       2019-01-30 09:46:28 +08:00
    弄个密码表 再加上一些错位混淆算法 这样就能加密解密了
    bumz
        51
    bumz  
       2019-01-30 10:22:52 +08:00
    对抗人眼的话
    古典密码学的方法都可以
    替换,比如 ROT13,或者和一组只有你知道的固定的随机数做异或
    或者置换都能满足你的需求

    其实 base64 (编码,非加密)都能骗过人眼(逃
    harde
        52
    harde  
       2019-01-30 10:31:25 +08:00
    用 1Password 等密码管理软件才是正道。
    每个站点密码不一样,谁爱撞,谁撞去。
    lcatt
        53
    lcatt  
       2019-01-30 10:37:47 +08:00
    域名+用户名+固定字符 就很好了,一般忘记密码才是最大的挑战,除了支付及绑定邮箱几个密码外都可以用,防撞库就行,没那么多“有心人”。如果真需要防人眼就再做个异或其他混淆就行。
    hanru
        54
    hanru  
       2019-01-30 10:43:59 +08:00 via Android
    与其造一个千疮百孔的破轮子,为什么不使用现成的、漏洞不那么多的密码管理软件?

    为什么?
    liuzhaowei55
        55
    liuzhaowei55  
       2019-01-30 11:00:54 +08:00
    恩尼格玛密码机,可以符合你的要求,不过他只支持字母,且不区分大小写。
    https://zh.wikipedia.org/wiki/%E6%81%A9%E5%B0%BC%E6%A0%BC%E7%8E%9B%E5%AF%86%E7%A0%81%E6%9C%BA
    恩尼格玛密码机的一个实现,需要 flash,超级精美,建议大家都看下。
    http://enigmaco.de/enigma/enigma.html
    woostundy
        56
    woostundy  
       2019-01-30 11:07:40 +08:00
    学密码学一定要先学信息论呀,单从你这个标题来看,是反信息论基础的
    woostundy
        57
    woostundy  
       2019-01-30 11:10:07 +08:00
    你这思路是映射,而不是可逆加密。
    Yanni0507
        58
    Yanni0507  
       2019-01-30 11:19:17 +08:00
    Abstract:楼主可以用 RC4 或者 RSA 算法来实现。但是它们都对原文有要求,只包含数字和字母的话原文最多 16 个字符,包含扩展 ASCII 表中的特殊字符的话,原文最多 12 个字符。

    不管是 AES 还是 RSA 加密出来的直接结果都是 byte[],它们按照通用的规则完全转换成可显示字符的时候都是有 bit 位扩充的。
    比如按照十六进制显示,一个 byte 需要两个字符,
    按照 Base64 编码,3 个 byte 需要 4 个字符,
    ASCII 和扩展 ASCII 里面又有太多的不可显示字符。
    那么楼主要求密文最多 16 个字符 -> 加密结果最多 12 个字符 -> 原文最多 96bit。
    如果能保证原文符合 Base64 要求(大小写字母,数字,‘/’,‘=’),那原文长度最大 16 个字符。
    否则最好的情况是按照扩展 ASCII 码表,原文最大长度 12 个字符。
    我知道的符合要求的算法还有:RC4,RSA,都不是分组加密算法,原文长度比较随意。具体怎么实现楼主可以放狗搜一下
    yikyo
        59
    yikyo  
       2019-01-30 11:26:36 +08:00
    不可逆,网上有开源实现,https://github.com/tmthrgd/mpw-js
    yikyo
        60
    yikyo  
       2019-01-30 11:28:34 +08:00
    补上一句,算法公开,但是加密种子是由用户自定义的。
    zjyl1994
        61
    zjyl1994  
       2019-01-30 11:34:40 +08:00
    太复杂了,你这个需求很简单。用不上什么加密算法都,找个哈希就行。
    MD5(你的网站名+你的总密码+随便一个什么固定的字符串),然后得到 16 个字符得 HEX 结果,取其中一部分做大小写变换和特殊字符替换即可。
    安全性高的狠,给你一个结果,你肯定没法反推总密码。哈希的难度在哪摆着呢
    zjyl1994
        62
    zjyl1994  
       2019-01-30 11:37:12 +08:00
    而且我是不明白要可逆的意义在哪里,网站名啥的都是可以公开的,我觉得你亮出来也没问题。
    完全可以存起来啊
    libook
        63
    libook  
       2019-01-30 12:26:10 +08:00
    点子不错,不过会不会不同网站对密码格式的限制条件不同呢?
    比如有的网站必须包含数字、字母小写、字母大写,但不支持符号;
    有的网站要求必须包含数字、字母小写、字母大写、符号;
    有的网站要求符号必须多于 3 个;
    有的网站要求同一个字符在密码中不能出现超过 4 次……

    这样你的算法要根据不同网站对密码格式的要求切换不同模式。
    imdoge
        64
    imdoge  
       2019-01-30 12:35:33 +08:00
    https://github.com/ivanakimov/hashids.js
    你指的是这种吗? generate YouTube-like ids from numbers
    libook
        65
    libook  
       2019-01-30 12:44:03 +08:00
    Node.js 官方有 crypto module,基本上就是字符串转 Buffer,然后加密和散列,很方便,可以直接用。

    https://nodejs.org/api/crypto.html

    密码验证的原理根本上是碰撞,即你输入的密码(最终处理成的数据),和设置的密码(最终处理成的数据)一致,则认为验证通过。所以“可逆”并不是一个必须条件,除非你有其他的用途需要加密后的密文还能直接还原成原文。

    因为加密算法是要在原有数据上“加”密,所以加密后的密文的大小一定是大于等于原文的,你也可以使用压缩算法,比如你加密后的密文是 0-9、a-f,36 进制,然后你可以把它映射成 0-9、a-f、A-F、~!@#$%^&*()_+`-={}[]:;"'<,>.?/|\这些,94 进制,这样你的密文可以无损缩短长度,由于无损压缩,所以可以完美还原,但也还是有限的,如果你的原文中有不可控长度的变量,比如网站域名,有 t.cn 这种的,也有 http://www.thisisthelongesteuropeandomainnameallovertheworldandnowitismine.eu/ 这样的,由于这种不可控性使得最终加密出来的密文的长度也是不可控的。
    libook
        66
    libook  
       2019-01-30 12:47:43 +08:00
    接着上面的“碰撞”理论来说,你这个点子虽然新奇,但还是没解决撞库的问题,如果这种算法使用的人多了,那以后撞库的时候也完全可以撞算法,相比之下,不用统一的算法、变量来生成密码既简单又能彻底免疫撞库的情况,何乐不为。
    hujiulong
        67
    hujiulong  
       2019-12-25 15:41:15 +08:00   ❤️ 1
    偶然看到这个帖,楼主你想要的应该是 Format-preserving encryption(FPE),也就是格式保留加密,例如文本长度是 16,加密后得到的密文长度也是 16
    sgwk
        68
    sgwk  
       2022-09-27 19:35:27 +08:00
    @hujiulong 他应该找到就是 fpe
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3065 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 38ms · UTC 10:57 · PVG 18:57 · LAX 02:57 · JFK 05:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.