V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
MySQL 5.5 Community Server
MySQL 5.6 Community Server
Percona Configuration Wizard
XtraBackup 搭建主从复制
Great Sites on MySQL
Percona
MySQL Performance Blog
Severalnines
推荐管理工具
Sequel Pro
phpMyAdmin
推荐书目
MySQL Cookbook
MySQL 相关项目
MariaDB
Drizzle
参考文档
http://mysql-python.sourceforge.net/MySQLdb.html
cncmmdwl
V2EX  ›  MySQL

mysql 有什么类似 rsa 的加密手段么?

  •  
  •   cncmmdwl · 2022-04-22 00:41:08 +08:00 · 4092 次点击
    这是一个创建于 947 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我想管理能看到用户的密码,能接触的 sql 的人看不到,password 和 md5 都是单向加密的,aes 加密解密密匙都是一把不安全,有没有什么函数能实现对密码进行 rsa 加密,管理去数据库拿用户的 password 使用私钥解码用户的实际密码?

    57 条回复    2022-04-30 12:33:34 +08:00
    Jooooooooo
        1
    Jooooooooo  
       2022-04-22 00:42:58 +08:00
    搜 kms
    cncmmdwl
        2
    cncmmdwl  
    OP
       2022-04-22 00:51:11 +08:00
    @Jooooooooo 不想加产品,有没有可能使用本地计算,比如本地计算好公钥,私钥,上传服务器只上传公钥,用户注册时候调用用户的密码用公钥加密后存 mysql 里面,这样用户再次登录时候就直接使用用户密码 rsa 加密后与 mysql 里面的密文做个判断,这样运维就拿不到密码,但是管理开源拿私钥解码密码。
    Jooooooooo
        3
    Jooooooooo  
       2022-04-22 01:05:58 +08:00
    @cncmmdwl 我的意思是你搜一下 kms 的思路, 应该是有可以借鉴的.
    dzdh
        4
    dzdh  
       2022-04-22 01:18:52 +08:00
    给数据加密,还是连接加密。

    数据加密,mysql 不带 rsa 加解密可能有插件没接触过。实现需求可能需要改造业务,业务上实现。

    单说你需求 aes 和 rsa 没啥区别,私钥漏了还是一样的。人的问题更多点吧。
    Rocketer
        5
    Rocketer  
       2022-04-22 01:20:03 +08:00 via iPhone
    没看出这跟 mysql 有什么关系,你需要的是一种稳定的非对称加密算法。

    首先排除 RSA ,因为 RSA 加盐,同样的内容每次加密结果不一样。
    cncmmdwl
        6
    cncmmdwl  
    OP
       2022-04-22 01:20:50 +08:00
    @Jooooooooo 我看了这个玩意,确实这个思路不错,我打算用 php 弄这个,但是生成一个合适的 rsa 好像又不太好弄,现在大多数 rsa 好像都已经上 2048 位了,这样话加密出来的密文好像就比较大了。
    timpaik
        7
    timpaik  
       2022-04-22 01:26:23 +08:00 via Android
    需求是什么?这种功能建议醒目提示用户
    liuidetmks
        8
    liuidetmks  
       2022-04-22 07:12:13 +08:00 via iPhone
    @cncmmdwl 尝试下 使用椭圆曲线加密,根据的用户名 sha256 作为临时私钥,和管理的公钥做 ecdh ,结果作为 aes 密码,这样密文长度和原始长度一样了。


    更安全方式是,每次使用随机公钥做 ecdh ,这样即使同样密码,加密结果也不同。
    jy28520
        9
    jy28520  
       2022-04-22 07:15:51 +08:00
    用用户的密码加密一个公用的内容 然后存入数据库
    验证密码的使用用用户的密码解密这个内容 如果成功就是密码正确否则就是密码不正确
    liuidetmks
        10
    liuidetmks  
       2022-04-22 08:43:16 +08:00
    @liuidetmks 好嘛,用户名作为临时私钥不可行,临时私钥必须销毁,要保留的是临时公钥

    还是每次生成一个临时公钥对私钥和公钥( s,P0 )临时私钥 s 和 你的公钥 P1 生成 aes 加密 key 加密密码为密文 E,
    P0+ E 组成最终密文, 销毁 s. 其中 P0 的长度应该是 33 字节

    解密过程就是用你的私钥 s1 和上面的临时公钥 P0 同样可以获取到 aes 加密 key
    unco020511
        11
    unco020511  
       2022-04-22 09:16:46 +08:00   ❤️ 7
    什么需求需要可逆性保存密码我是想不到的
    chenzheyu
        12
    chenzheyu  
       2022-04-22 09:59:38 +08:00
    这个不是应该是框架提供的吗?存 sql 的是对称加密的数据,取出来再对称解密啊
    cncmmdwl
        13
    cncmmdwl  
    OP
       2022-04-22 10:15:47 +08:00
    @timpaik 之前其他公司不是有过密码泄露问题么,我怀疑那些公司就是明文存密码,但是好像也不是,但是确实又有密码泄露问题,那么那些明文密码的黑客是如何搞到的?
    cncmmdwl
        14
    cncmmdwl  
    OP
       2022-04-22 10:16:44 +08:00
    @dzdh mysql 库有第三方运维,链接本来就加密,不想给运维看用户数据而已
    cncmmdwl
        15
    cncmmdwl  
    OP
       2022-04-22 10:18:17 +08:00
    @chenzheyu 服务器提供商不可信的情况下我觉得对称加密不太妙
    wangyu17455
        16
    wangyu17455  
       2022-04-22 10:37:54 +08:00 via Android
    新建用户,然后新建 view ,在 view 里解密,然后把这个 view 只授权给你创建的用户
    wangyu17455
        17
    wangyu17455  
       2022-04-22 10:41:04 +08:00 via Android
    但是每次查 view 都带着解密的密码好像也不安全
    chenzheyu
        18
    chenzheyu  
       2022-04-22 10:45:02 +08:00
    @cncmmdwl 如果你的服务商都不可信的,那用户输入的那一刻不就知道密码了
    cncmmdwl
        19
    cncmmdwl  
    OP
       2022-04-22 10:49:19 +08:00
    @chenzheyu web 页面 这个功能打算上线到用户端,网页登陆用公钥加密后送进服务器,这样就不存在问题了
    dzdh
        20
    dzdh  
       2022-04-22 11:16:47 +08:00
    那搜索可咋做哦。仅某些字段加密么
    yhvictor
        21
    yhvictor  
       2022-04-22 11:23:58 +08:00 via iPhone
    我觉得最好是用权限。
    改 sql 的人提交前管理 review ,然后管理或者自动化提交。
    或者两张表,正常的存 md5 ,另一张只有管理有权限存明文。

    实在要用加密的话,google 的 tink 拿来用就是了,无论椭圆曲线还是其他的加密方法都有提供。
    另外,对称加密的 cpu 开销更少,就是需要密钥管理。
    popok
        22
    popok  
       2022-04-22 11:40:05 +08:00   ❤️ 3
    管理可以用私钥看到用户密码?你们公司可真作妖呢!
    wonderfulcxm
        23
    wonderfulcxm  
       2022-04-22 11:54:01 +08:00 via iPhone
    @unco020511 有些不懂技术的沙雕老板就是这样的,他们以为的找回密码就是把用户原来的密码发给用户,如果还有一点责任心,不想明文保存密码,只能用这种可逆加密。
    deplivesb
        24
    deplivesb  
       2022-04-22 11:58:32 +08:00   ❤️ 2
    「我想管理能看到用户的密码」
    这是什么沙雕公司,赶紧报上明 排排雷
    zhzy0077
        25
    zhzy0077  
       2022-04-22 12:06:37 +08:00
    建议数据库照样 hash 落盘,密码单独加密存一个见不得人的地方,然后主管,经理,老板一人一个密码对称三层加密,三个人在一起才能看密码,和银行金库一样安全,完全满足老板的安全心
    cncmmdwl
        26
    cncmmdwl  
    OP
       2022-04-22 12:18:25 +08:00
    @wonderfulcxm 对的,就是不想在数据库保存明文密码,并且服务器上云,老板怕运维拉着数据跑了,所以想用一种单向加密方式来搞东西
    unco020511
        27
    unco020511  
       2022-04-22 12:20:58 +08:00
    @cncmmdwl #26 你说的需求不就是摘要(hash)算法做的事吗,比如 MD5.还有 hash 不是加密,加密没有单向
    cncmmdwl
        28
    cncmmdwl  
    OP
       2022-04-22 12:21:18 +08:00
    @zhzy0077 前端注册时候不久对密码加密了么,发给后端时候的密码已经是密文状态了,只要比对下是不是一样的就行了,但是领导想看用户密码,所以要一种单向加密方法,思来想去就想到了 rsa ,你这样搞待会密码加密被破好家伙全被看到了
    zhzy0077
        29
    zhzy0077  
       2022-04-22 12:23:14 +08:00
    @cncmmdwl 啥意思 AES 2048 三个对称密钥从不落盘 每次系统启动要求三个人一起输密码才能开机 谁能破你啊
    cncmmdwl
        30
    cncmmdwl  
    OP
       2022-04-22 12:23:17 +08:00
    @unco020511 hash 无法逆向算密码,rsa 公钥加密的密文可以靠私钥解迷,密码比对只需要使用被加密过的密文解密即可
    unco020511
        31
    unco020511  
       2022-04-22 12:24:16 +08:00   ❤️ 1
    @cncmmdwl "领导想看用户密码",这么无理的要求,好奇你是咋忍下来的
    cncmmdwl
        32
    cncmmdwl  
    OP
       2022-04-22 12:25:53 +08:00
    @zhzy0077 你这么把密码合适的存到这个隐秘的地方?靠不可信信道?靠对 aes 对密码加密?明文传密码百分百不行,aes 话如果服务器商拿了你的 aes 密匙,等于白加密
    zhzy0077
        33
    zhzy0077  
       2022-04-22 12:26:28 +08:00
    @cncmmdwl 啥意思 这三个密钥服务器开机的时候输入存内存里啊 为啥要交换
    cncmmdwl
        34
    cncmmdwl  
    OP
       2022-04-22 12:27:38 +08:00
    @unco020511 终有一天跑路的:)
    Chad0000
        35
    Chad0000  
       2022-04-22 12:32:51 +08:00
    @unco020511 幸好他们不做网盘相册啥的,否则就会来个“领导想看用户果照”,啊。
    twing37
        36
    twing37  
       2022-04-22 12:35:41 +08:00
    看描述.不需要搞这些撒.把权限做好了. 数据备份做好了,非明文. 如果怕内部人员脱库单干,那应对方法可太多了~
    能看用户明文密码这个需求太离谱了
    zhzy0077
        37
    zhzy0077  
       2022-04-22 12:38:50 +08:00
    @cncmmdwl 我再说清楚点 就算你 RSA 非对称加密 你私钥总是要存在一个磁盘上的 要满足你这个需求 你首先不能用云服务器 因为服务商能看到你所有的数据 所以你只能在公司或者离你公司比较近的机房买或者租一台服务器 然后对这个服务器磁盘全盘加密 不然别人把你的硬盘接另一台电脑上就全看到了 所以每次开机的时候需要一个信任的人过去输入这个磁盘加密密码 你做到这一步的时候其实和你对称加密没有区别了 因为磁盘加密本身就是对称的。

    所以实际上这么做的安全性和每次服务器启动的时候输入一个 AES 密钥 存内存不落盘 客户端 HTTPS 明文上传密码 服务器直接加密了丢 oss 上 没有本质性区别
    3dwelcome
        38
    3dwelcome  
       2022-04-22 13:25:01 +08:00
    楼主的逻辑有问题,你数据库密码用 RSA 公钥加密了,那用户登录的时候,必然需要用私钥去解密密码明文去比对。

    万一 RSA 私钥泄漏,那和 AES 密钥泄漏完全是一个意思。
    ShallowAi
        39
    ShallowAi  
       2022-04-22 14:05:24 +08:00 via Android
    使用 BCRYPT 单向加密,只能进行验证但是不能逆向获取源密码。
    要看用户密码的需求完全是无理取闹,从安全性各种理由下都不合理。
    seakingii
        40
    seakingii  
       2022-04-22 14:14:30 +08:00
    你在应用层做这个事不是很简单吗?把加密的数据存在数据库,要用的时候用程序去解密

    一定要用 MYSQL 的函数做加密解密?不太清楚有没有现成的 MYSQL 的函数,技术你可以自己写插件来扩展 MYSQL 的函数...
    GuangXiN
        41
    GuangXiN  
       2022-04-22 14:16:24 +08:00 via Android
    如果是为了用户登录为啥要用加密方案?单向哈希算法不好么?你就对用户的密码那么感兴趣么?
    cncmmdwl
        42
    cncmmdwl  
    OP
       2022-04-22 15:07:25 +08:00
    @3dwelcome 你理解错了,用户密码用类似 rsa 的加密后就不在解密,下一次验证密码用用户输入在 rsa 一次直接和数据库里的密文一比拉到
    cncmmdwl
        43
    cncmmdwl  
    OP
       2022-04-22 15:08:38 +08:00
    @ShallowAi 没办法,领导要啥我们就给啥,领导傻了我们也要跟着傻
    cncmmdwl
        44
    cncmmdwl  
    OP
       2022-04-22 15:11:58 +08:00
    @zhzy0077 你说的这个没有问题,老板的私钥生成后就送给领导保险箱里面,谁也别想拿出来,公钥云服务器上放着,甚至老板云服务器都没加密,只是要求老板能通过下载数据的方式反算密码,其他方式下无需解密
    3dwelcome
        45
    3dwelcome  
       2022-04-22 15:45:49 +08:00
    @cncmmdwl "你理解错了,用户密码用类似 rsa 的加密后就不在解密,下一次验证密码用用户输入在 rsa 一次直接和数据库里的密文一比拉到"

    正统的 RSA 每次加密后的结果都是不一样的。
    3dwelcome
        46
    3dwelcome  
       2022-04-22 15:49:14 +08:00
    当然,RSA 解密后的结果肯定是一样的。这点也是为了提升安全性考虑。
    shintendo
        47
    shintendo  
       2022-04-22 15:51:59 +08:00
    管理看了用户密码,拿去尝试登录其它网站?
    3dwelcome
        48
    3dwelcome  
       2022-04-22 16:03:53 +08:00
    @shintendo 楼主说的只是片面之词,大部分老板都不懂技术的,谁关心什么密码原文。

    也许真实需求可能刚好相反。是楼主作为技术员,想头盔一下老板的密码,登录一下老板的各种隐私账号。

    老板账号密码,可要比普通用户的密码值钱多了。
    swcat
        49
    swcat  
       2022-04-22 16:07:50 +08:00
    两个字段, 一个是密码(可以用非对称加密加密一下), 一个是 bcrypt 处理过的 hash, 验证密码的时候调用 bcrypt 的 verify 方法
    cncmmdwl
        50
    cncmmdwl  
    OP
       2022-04-22 16:35:06 +08:00
    @3dwelcome 所以我想问问有没有这种非对称加密后密文还能是一样的?
    cncmmdwl
        51
    cncmmdwl  
    OP
       2022-04-22 16:36:14 +08:00
    @3dwelcome 不至于,有这想法直接去问就行了,公司都是亲属。
    3dwelcome
        52
    3dwelcome  
       2022-04-22 16:45:15 +08:00
    @cncmmdwl "所以我想问问有没有这种非对称加密后密文还能是一样的?"

    RSA 有两种运行模式,一种是签名,保证每次结果都和上一次一样。另一种是加密,由于加了 padding 随机数,结果都不一样更安全。

    你可以用 RSA 签名模式,你这需求普通加密还不太一样。普通加密不需要对密文做二次对比。
    Bromine0x23
        53
    Bromine0x23  
       2022-04-22 20:01:06 +08:00
    虽然这个要求肯定有问题,但是可以换一个思路,把 RSA 填充用的随机数生成器换成一个返回固定值的生成器
    cncmmdwl
        54
    cncmmdwl  
    OP
       2022-04-24 21:52:52 +08:00
    @3dwelcome 我有一个想法,如果把密码签名后只留下签名,后面就用签名比对密码如何?
    cncmmdwl
        55
    cncmmdwl  
    OP
       2022-04-24 21:53:37 +08:00
    不对,这样子话就又变成单向了
    hifumi
        56
    hifumi  
       2022-04-30 12:31:36 +08:00   ❤️ 1
    这个需求还是挺简单的,只要 RSA 加密时你不加盐值就可以了呀,RSA 就是一个乘方取模运算,下面的实现支持加密、验证和解密,密钥长度可以改,只要密码比密钥短就行了(如果需要支持密码比密钥长也可以修改一下下面的 demo ,实现分组加密)

    ```
    from Cryptodome.PublicKey import RSA


    def encrypt(public_key, password):
    password = int.from_bytes(password, byteorder='big')
    encrypted_password = pow(password, public_key.e, public_key.n)
    return encrypted_password


    def decrypt(private_key, encrypted_password, length):
    decrypted = pow(encrypted_password, private_key.d, private_key.n).to_bytes(byteorder='big', length=length)
    return decrypted


    def verify_password(public_key, encrypted_password, password_to_be_verified):
    return encrypted_password == encrypt(public_key, password_to_be_verified)


    if __name__ == "__main__":
    ras_key_length = 2 ** 10
    private = RSA.generate(bits=ras_key_length)
    public = private.publickey()

    original_password = b"passwordpaordpasswordpasswordpasswordpasswordpasswordpasswordpasrdpasswordpasswordpassword"

    print("Original password:", original_password)
    encrypted = encrypt(public, original_password)

    print("Encrypted password:", hex(encrypted))
    print("Verification result:", verify_password(public, encrypted, original_password))

    decrypted = decrypt(private, encrypted, ras_key_length // 8)
    print("Decrypted password:", decrypted)
    ```

    运行结果如下
    ```
    Original password: b'passwordpaordpasswordpasswordpasswordpasswordpasswordpasswordpasrdpasswordpasswordpassword'
    Encrypted password: 0x68334196df3d5c177e55e102f939ca2f0b2275e774159f0814921440161e5aad4e54076d13039f74733068dbad1d7c69e433a21b78f4ad485110bad0d45ff9b1ad5cf71a24ae16f14e53cd4b7f3d021f3a8b3e911f493da1339918c6e7bd9f23ef0f876a2142fd7f3de4556f64a7b12cb230f0c06a57571b6ad6ee1bfef85731
    Verification result: True
    Decrypted password: b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00passwordpaordpasswordpasswordpasswordpasswordpasswordpasswordpasrdpasswordpasswordpassword'
    ```
    hifumi
        57
    hifumi  
       2022-04-30 12:33:34 +08:00
    MySQL 本身肯定是不支持类似功能的,当然也可以用存储过程来实现我刚刚发的 demo 的逻辑
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   923 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 21:30 · PVG 05:30 · LAX 13:30 · JFK 16:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.