[加密算法] 有没有可以 ‘限制密文长度’ 且 ‘可逆’ 加密算法? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
lqzhgood
V2EX    程序员

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

  •  
  •   lqzhgood 2019-01-29 16:07:24 +08:00 11532 次点击
    这是一个创建于 2447 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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 进制 映射成 一个密文。 这样应该可以很大程度缩短密文的长度了。
        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     Solana     2587 人在线   最高记录 6679     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 05:10 PVG 13:10 LAX 22:10 JFK 01:10
    Do have faith in what you're doing.
    ubao 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