新手问题 关于 ruby 的 rsa 公钥加密问题,请教各位大神,谢谢🙏

sunjirui · August 31, 2019 · Last by sunjirui replied at September 03, 2019 · 3423 hits
data = "hello"
rsa = OpenSSL::PKey::RSA.new(File.read("xxx.pem"))
string1 = rsa.public_encrypt(data)
string2 = Base64.urlsafe_encode64(string1)

总是签名不过,不知道这个位置哪里写错了,用 go 写的签名可以过

   // 部分省略
    data = "hello"
path := "xxx.pem"
publickey, errfile := LoadFile(path)
    block, _ := pem.Decode(publickey)
    pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
pub := pubInterface.(*rsa.PublicKey)
partLen := pub.N.BitLen()/8 - 11
    chunks := split([]byte(data), partLen)
    buffer := bytes.NewBufferString("")
for _, chunk := range chunks {
    bytes, err := rsa.EncryptPKCS1v15(rand.Reader, pub, chunk)
    if err != nil {
        return "", err
    }
    buffer.Write(bytes)
}
return base64.RawURLEncoding.EncodeToString(buffer.Bytes())

尝试补全 go 的加密方法

package main
import (
    "crypto/rand"
    "crypto/rsa"
    "crypto/x509"
    "encoding/pem"
    "bytes"
    "encoding/base64"
    "fmt"
)

func SplitSubN(s string, n int) []string {
    sub := ""
    subs := []string{}

    runes := bytes.Runes([]byte(s))
    l := len(runes)
    for i, r := range runes {
        sub = sub + string(r)
        if (i + 1) % n == 0 {
            subs = append(subs, sub)
            sub = ""
        } else if (i + 1) == l {
            subs = append(subs, sub)
        }
    }

    return subs
}

func main() {
    data := "hello"
    const publickey = `
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDw8cUnDShPMYFDZkL65Y0nUyyN
0Nqxgz6vsFEJj3I3A1nsaQBmGC1urtO9pGJkFzaXkQo7s2y+S53qdsWNufKk8U2l
SpiGjm4WWCucJTnYpC+nMwAAd/nmQudCtH4czJOkK4m29Tv6fUmvOtcSpQzW7zL0
47I6qkkAadGb8CAg9wIDAQAB
-----END PUBLIC KEY-----`
    block, _ := pem.Decode([]byte(publickey))
    pubInterface, _ := x509.ParsePKIXPublicKey(block.Bytes)
    pub := pubInterface.(*rsa.PublicKey)
    partLen := pub.N.BitLen()/8 - 11
    fmt.Println(partLen)
    chunks := SplitSubN(data, partLen)
    buffer := bytes.NewBufferString("")
    for _, chunk := range chunks {
        bytes, err := rsa.EncryptPKCS1v15(rand.Reader, pub, []byte(chunk))
        if err != nil {
            fmt.Println("", err)
        }
        buffer.Write(bytes)
    }
    fmt.Println(base64.RawURLEncoding.EncodeToString(buffer.Bytes()))
}

#=> "runNVN4ZjB_Z-aA7-7ovGP4bVPNJdKpvXpR47Wn9mdvTYqhUp1z-vN_Q_mGylXH_y423cZyipKnZDEP0dTZFGMfsNhL81NOBNG981pQZ87t9_F2mnyqsoXOR6pUL7j4VQUExMsx3caeMOc_0KkQbjGGnbSvwQ9ewtH7UQBcYiUE"

然后用 ruby 解密

private_pem = <<-EOS
-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAPDxxScNKE8xgUNm
QvrljSdTLI3Q2rGDPq+wUQmPcjcDWexpAGYYLW6u072kYmQXNpeRCjuzbL5Lnep2
xY258qTxTaVKmIaObhZYK5wlOdikL6czAAB3+eZC50K0fhzMk6Qribb1O/p9Sa86
1xKlDNbvMvTjsjqqSQBp0ZvwICD3AgMBAAECgYBjForF7JtPNkS6uyuAkzbhnUsN
Z38I0bjN9+zbyapnBXHNz8DiO78zbaKWsyvjjchdvMBAnSFzgRWIfx/vkTE/59GF
gfn7VLbvKMYULzbkZbh8NcwNjJLfLtNXmqt973uSiNah9JTeCHQd062VI5D64QHv
GgKMDAJ6Z2W4jSn8gQJBAPuXT0597Z3ciY6G0EHAhHrJNieDNJboUFodQlHqpTrs
SLmGTJVswj3Su2vi7ZEPyErHjL2vdrs1hDXKFVik+rkCQQD1KrKA7xUdYRwGnIry
CMH+uaECSmKhnZgFVg9zCSpDEaTOjenGGVuu6sXWmJKj7PZ1pFHsPrzOCSp/3Pk6
hmEvAkBL22NeFzn9zvDquFsyeAl5vBFH+JdyqLkRcqD8cfM/wN5skcGljBVE7rTz
4ogepNOPOHuG9dCmwYwLa9Lj11qBAkAafynZq31BtpwbztFphS7KQ++12qo8Q1cJ
xJpY2XW61+5S8J2Cbn0tM2x8W/MFSnf8kOzVtpYbQnxYY16AR8O7AkEAkHLKWspk
QFWRUlliBVpJg+GHe9VI7ND3wWIbV4H1kmyt08959LBpg7cZLu06PXUShwtADaE9
42Ta3K/fSme4Tw==
-----END PRIVATE KEY-----
EOS

s = 'KAPye436VwAqMZ6amu9UeODAh-3dhU6KNbcVXmBU-HK_geeHjyktLzOREMvWPnLcJ7mdddPwwHPEBZfaVliCFl0o9IDIUe7JfEHvmfG7limTUyii08O2b1cBu8pAnev3BxUfDJRqqh84-66Qiiur-syQQkAdnzH-wuG3DJ_UPgo'
rsa = OpenSSL::PKey::RSA.new(private_pem)
rsa.private_decrypt(Base64.urlsafe_decode64(s))

成功解密出 hello

然后用 ruby 加密

public_pem = <<-EOS
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDw8cUnDShPMYFDZkL65Y0nUyyN
0Nqxgz6vsFEJj3I3A1nsaQBmGC1urtO9pGJkFzaXkQo7s2y+S53qdsWNufKk8U2l
SpiGjm4WWCucJTnYpC+nMwAAd/nmQudCtH4czJOkK4m29Tv6fUmvOtcSpQzW7zL0
47I6qkkAadGb8CAg9wIDAQAB
-----END PUBLIC KEY-----
EOS

data = 'hello'
rsa = OpenSSL::PKey::RSA.new(public_pem)
Base64.urlsafe_encode64 rsa.public_encrypt(data)

用上面 ruby 的解密方法也能解密

https://golang.org/pkg/crypto/rsa/#EncryptPKCS1v15

https://ruby-doc.org/stdlib-2.5.1/libdoc/openssl/rdoc/OpenSSL/PKey/RSA.html#method-i-public_encrypt

https://commondatastorage.googleapis.com/chromium-boringssl-docs/rsa.h.html#RSA_PKCS1_PADDING

https://stackoverflow.com/questions/47981709/ruby-rsa-public-key-encryption-to-golang

结论:你写的是对的

第一感觉是,同样是加密,用 go 写要长好多。

楼主可以先对比下两个版本 encrypt 出来的 string1 是不是一致。

Reply to w7938940

谢谢,我再试试😀

Reply to zhengpd

好的,谢谢

Reply to zhengpd

非对称加密,每次加密结果都会不一样

Reply to w7938940

是哦,那就对比不了了

Reply to w7938940

非对称不是这个意思……

每次加密结果不一样的是用了随机 iv 的加密方式,例如对称的 AES。

而以 RSA 的使用场景(签名、交换对称加密的 key 等),并不需要随机 iv。

Reply to luikore

OpenSSL::PKey::RSA#public_encrypt 默认是有 padding 的,所以具体到楼主的代码每次结果是会不一样

谢谢大家,找到问题了,不是这部分的问题😂

sunjirui closed this topic. 03 Sep 19:58
You need to Sign in before reply, if you don't have an account, please Sign up first.