V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
find456789
V2EX  ›  问与答

rsa 生成的公钥、私钥,可以互相交换吗?我可以把 PRIVATE KEY 发给客户端,把 PUBLIC KEY 留给自己用吗?

  •  
  •   find456789 · 40 天前 · 1384 次点击
    这是一个创建于 40 天前的主题,其中的信息可能已经有所发展或是发生改变。

    问这个问题的原因是:

    我想给软件增加 注册码的功能, 我最终选了 rsa 非对称加密算法

    但是我体验了一下, 发现 只能用 公钥 PUBLIC KEY 加密用户信息(到期时间,会员等级) ,

    // 假设这是明文 
    {
    username:aaaa,
    level:2,
    endtime:2022-12-12 12:12:12
    }
    
    

    且只能用 私钥 PRIVATE KEY 来解密,得到原文


    所以,我就考虑, 把 PRIVATE KEY 内嵌到软件内部

    把 PUBLIC KEY 存在我自己私人电脑上的注册机内部;

    然后,客户注册、付费以后,我就用我电脑的注册机,生成注册码(用 PUBLIC KEY 把明文信息加密)

    然后,我把注册码 发给客户

    // 假设注册码是这个
    lbLeK+0MeLNXPm+MlbLeK+0MeLNXPm+MlbLeK+0MeLNXPm+MlbLeK+0MeLNXPm+M==
    
    

    客户把注册码输入 软件, 软件利用 PRIVATE KEY 把密文,解密成 明文信息


    但是我在探索的过程中, 看到一些网友说,openssl 是可以通过 PRIVATE KEY 得到 PUBLIC KEY 的, 如果真的这样的话,就会被人写出 注册机来

    信息来源: https://segmentfault.com/q/1010000002932436/a-1020000002947602


    我使用 python-rsa 生成的公钥私钥格式如下:

    -----BEGIN RSA PRIVATE KEY-----
    MIICXwIBAAKBgQCGohHh3ypajwWHgFxbeUOZQehVDdjpXD+rA1RjoYIyA9fBuptv
    i5I8SuncRe0tkqKj5eYYtMgp4fjQ9SvFLjvjygrdPj+tzfefs7wiaYlxKaons3MT
    HCZRvfQ9+i5M6rdXGIcd4hQX3Og0EacNU3aeNW9f0XHqMaP5bQsNJ6HLSQIDAQAB
    AoGAPH25Vyk0GHhGXbl4xcjYbJXGU+Di4wcFvErEsfcxTlOXr32utRGa5Ogr50Kr
    7FwEI2v6VIN1pAvaBdkCQi1CysQZ8hT4KFZtnaojIyIeJFXMCSpKpM7z106FEh/L
    3mjeGGDLBamo0Pyjhg34rkEgDbci3QAIMb+nPZKFp1LbZGECRQCsTYp3AO3t7KWg
    Vn2bfJGAedOyRalNpAeWjj/SLHON08Ko9iKFG0g1HU05D+Ma7unlOwnrPDMonqxE
    tSMfZtcN8ZTnLQI9AMgIKIleej3VwiSWtUMFcJoKmTJgUcX0kDmdM9nbMnCrR5Sv
    AbNM1XqKyj8eVSjGYPYA8oFlvKjchKMGDQJEDPV0AYlHW8qdllaK8ePHibMf8dt9
    ZUJ985vVPvhq5HLVxCFm7T3lC2GdyjngqcjoPH5ZO6D2dAqjCDPbZWQ1rm3J9i0C
    PE5Yy6/KPmzbvZfhI4vlpI3hGtHdYgn72UWHqhhpP19b5sR4q1zT+kVt+Psx4T8A
    PFf+VP2ToIovHRBRPQJECXhvoSzyL+QnY9nixOucF/oB97sqfC3WQwkcNYL4v4wK
    I5YOFZHgxRBmvflkAH6KPSKDrr0GPSlu/ZDwQetWvAyDUiU=
    -----END RSA PRIVATE KEY-----
    
    -----BEGIN RSA PUBLIC KEY-----
    MIGJAoGBAIaiEeHfKlqPBYeAXFt5Q5lB6FUN2OlcP6sDVGOhgjID18G6m2+LkjxK
    6dxF7S2SoqPl5hi0yCnh+ND1K8UuO+PKCt0+P63N95+zvCJpiXEpqiezcxMcJlG9
    9D36Lkzqt1cYhx3iFBfc6DQRpw1Tdp41b1/Rceoxo/ltCw0noctJAgMBAAE=
    -----END RSA PUBLIC KEY-----
    

    由于我对算法是个新手, 所以,特来发帖,问问大家:

    我这种格式的 公钥私钥,交换使用,会有风险吗?

    私钥泄露,公钥我保存好, 别人能通过私钥,能逆向出公钥吗?

    谢谢

    第 1 条附言  ·  40 天前

    谢谢大家,在大家的提点、帮助下,我最终的方案如下:

    私钥自己保存, 公钥发给客户端软件

    发送明文的信息 和 rsa加密信息给客户端


    用户在客户端输入注册码后,软件先 从 注册码里提取出 明文 和 rsa密文

    然后用 公钥、明文、密文 进行签名校验

    验证通过则说明 明文是我写的,而不是客户端伪造的

    于是,开始从明文里,提取出 过期时间, 开始对比, 合法就让软件运行, 否则就 退出(或做其他操作)

    再次 感谢大家

    25 条回复    2021-10-22 17:45:02 +08:00
    AoEiuV020
        1
    AoEiuV020   40 天前
    能,公钥设计上就是公开的,不私密的,
    dzdh
        2
    dzdh   40 天前
    私钥也能用于加密啊
    Daylight1993
        3
    Daylight1993   40 天前
    公钥私钥,从名字就知道哪个需要自己保存的。

    所以你应该软甲里嵌入公钥,自己用私钥。
    AoEiuV020
        4
    AoEiuV020   40 天前   ❤️ 1
    你这方案,简单调整的话,你持有私钥,对“数据”进行”签名“,然后数据和签名一起经过普通的对称加密发给客户,客户端输入后解密得到“数据”和“签名”,用“数据”和写死的公钥“验证签名”,验证通过就直接使用这个“数据”,
    别人没有私钥,就无法生成签名,哪怕破解了对称加密,公钥“验证签名”这一步就过不去,
    Daylight1993
        5
    Daylight1993   40 天前
    私钥加密,公钥解密。就像比特币一样。
    Daylight1993
        6
    Daylight1993   40 天前
    说错了,公钥不是解密,而是如同 4L 所说,用来验证你的加密签名是否正确的。
    sunny352787
        7
    sunny352787   40 天前
    首先,从私钥可以算出公钥...
    sunny352787
        8
    sunny352787   40 天前
    私钥算公钥甚至不算逆向,而是生成方式就是先生成私钥然后由私钥生成公钥
    Remember
        9
    Remember   40 天前
    私钥里面是有公钥的信息的,直接可以算出来,你这把私钥都给了,就等于没加密了.
    mekingname
        10
    mekingname   40 天前
    你可以试一试这个网站: http://www.metools.info/code/c82.html

    其实,你的需求不需要解密!你只需要知道密文是通过你自己这个特定的私钥生成的就可以了。

    这个时候,用私钥对数据进行签名。用公钥来确定这一段签名是它对应的私钥签的而不是别人签的,就足够了。你不需要还原原始内容。
    find456789
        11
    find456789   40 天前
    @dzdh

    谢谢

    我用的是这个模块 https://stuvel.eu/python-rsa-doc/usage.html#encryption-and-decryption

    似乎并不支持 私钥加密信息

    它的例子用的是 公钥加密信息, 私钥解密信息
    zk8802
        12
    zk8802   40 天前 via iPhone
    一般而言,私钥是不能计算出公钥的,公钥也不能计算出私钥。这是非对称加密算法的安全性的保障之一。

    但是,因为计算 RSA 比较慢,在实践中,RSA 的私钥往往和 p 存储在一起,这样可以优化 RSA 运算时所必须的乘方运算。所以如果楼主要用 OpenSSL 的 RSA,那就不能公开私钥文件,而必须在本机用私钥加密、在客户端用公钥解密。

    多说一句,破解者一般都直接在客户端替换掉公钥,然后就可以写注册机了…所以如果只是用非对称加密算法的话,还需要加上程序的自校验,不过一般强度也不高就是了。
    leoleoasd
        14
    leoleoasd   40 天前
    @zk8802 #12 给生成的注册信息签名,这样只有有私钥的人才能签名,也是安全的
    leoleoasd
        15
    leoleoasd   40 天前
    草 @错了
    iyaozhen
        16
    iyaozhen   40 天前
    @sunny352787 从私钥可以算出公钥 咦,这个有更细节的东西嘛?我理解算不出来吧
    iyaozhen
        17
    iyaozhen   40 天前
    @find456789 反着来也是可以的,但 Python 没有直接的库,需要自己写
    find456789
        18
    find456789   40 天前
    @mekingname

    谢谢

    我的原信息里,用 json 存了软件的到期时间,如果我不解密的话,我该如何判断 给用户的注册码是否过期呢
    mekingname
        19
    mekingname   40 天前
    @find456789 这实际上很简单。软件的有效时间,你不要让用户自定义。你只给定几个固定的有效时间,例如:一个月,半年,一年。每个时间对应一个私钥。客户端也有 3 个公钥,哪个公钥能验证成功,你就知道它的有效期是多久。
    zk8802
        20
    zk8802   40 天前 via iPhone   ❤️ 1
    到期时间可以用明文存储,不用加密。你只要用私钥为到期时间(和其它的注册信息)签名,客户端用公钥验证签名就可以了。
    arthurire
        21
    arthurire   40 天前   ❤️ 1
    你发给对方的是一段明文和一个签名.

    公钥可以验证"这个签名是不是由指定明文和指定私钥生成的"

    所以到期时间必须是你写的时间,私钥是你的私钥,这个验证流程才能通过.

    所以你明文给他就好了.
    lakehylia
        22
    lakehylia   40 天前   ❤️ 1
    私钥是加密的,公钥不需要解密出密文,只需要验证正确就可以。你把到期时间用私钥加密,然后把到期时间明文跟密文一起发给客户端,客户端用公钥验证这个密文的正确性,然后到期时间跟本地比较就行。
    gps949
        23
    gps949   40 天前
    完整性、身份认证场景:私钥签名—>公钥验签
    保密场景:公钥加密—>私钥解密
    GuuJiang
        24
    GuuJiang   40 天前
    又见月经问题,参见我在 https://v2ex.com/t/704756#r_9467988 里的回复,基本可以解决类似问题的一切疑问
    ysc3839
        25
    ysc3839   40 天前
    这也是我在另一个帖子中说自己看 RSA 原理然后写一个的原因,因为现成的 RSA 实现基本上都给你层层封装了,不一定合适,自己写的话可以把长度压缩到最短。
    可以参考这个页面 https://crunch.js.org/examples/rsa.html 自己理解下 RSA 的数学计算过程。
    以及参考这个回答 https://www.zhihu.com/question/25912483/answer/31653639 有提到签名的验证的算法。
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2543 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 12:52 · PVG 20:52 · LAX 04:52 · JFK 07:52
    ♥ Do have faith in what you're doing.