donglun2010 2017-12-26 17:19
浏览 106
已采纳

Ruby RSA公钥加密到Golang

I'm currently working on a project where I have to "convert" some code from Ruby(version 1.9.3p194) to Golang(version 1.7). There is this part where Ruby uses RSA public key encryption and I always get a consistent result every time it gets executed. This is the function used:

Edit: I overlooked that after the public key encryption, there is a base 64 encoding as well

public_key = OpenSSL::PKey::RSA.new(public_encryption_key)
public_encrypted_text = public_key.public_encrypt(text, OpenSSL::PKey::RSA::NO_PADDING)
base64_encrypted_text = Base64.encode64(public_encrypted_text).gsub("
", "")
escaped_encrypted_text = URI.escape(encrypted_key, "/+=")

However in Golang, due to the rsa library I can't get a consistent result since the function to encrypt takes a random parameter to generate different result each time. I understand why it needs to be different every time, but i can't get anything remotely similar to what ruby generates. These are the functions used in Golang:

//keyBytes is the public key as []byte
block, _ := pem.Decode(keyBytes)
key, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
    return nil, err
}

pubKey, ok := key.(*rsa.PublicKey)
if !ok {
    return nil, errors.New("Cannot convert to rsa.PublicKey")
}

result, err := rsa.EncryptPKCS1v15(cryptorand.Reader, pubKey, text)
encryptedText := base64.URLEncoding.EncodeToString(result)
encryptedText = strings.TrimRight(encryptedText, "=")

One of the problems is that ruby can encrypt the text with no problem, and in golang I'm getting an error that the key is too short to encrypt everything.

If I encrypt something else, like "Hello". When decrypting I get from ruby the error "padding check failed". The decryption is being handle like follows:

private_key.private_decrypt(Base64.decode64(text))  

EDIT: Thanks to the answer of gusto2 I now know better what is going on since I didn't have much understanding of RSA.

Now in Golang I was able to encrypt the text using PKCS1 v1.5, and just to be sure I tried to decrypt that as well, also in Golang, with no problem.

However in Ruby I still wasn't able to decrypt using the private key. So I figured that the base64 encoding used in Golang was the issue. So I changed that part to this:

encryptedText := base64.StdEncoding.EncodeToString(result)

And also I removed the last line were the equal sign was being trimmed.

With that done it worked like a charm.

  • 写回答

1条回答 默认 最新

  • douniewei6346 2017-12-27 07:16
    关注

    I am no knowledgeable about golang, however I may know something about RSA.

    The difference seems to be in the padding.

    For ruby - no padding is used
    For golang - PKCS1v15 padding is used

    In the rubyexample you use OpenSSL::PKey::RSA::NO_PADDING is used which is VERY VERY unsafe. It is called textbook RSA and is not inteded in real-life use as it has many weaknesses and dangerous traps. So the ruby example is very dangerously unsafe because of using the textbook RSA. As well it is limited to encrypting small messages (much smaller than the keyspace).

    There are two padding types used with RSA:

    • PKCS1 v1 (commonly referred as PKCS1) - this is a deterministic padding (the output is always the same), many cryptographers consider this option obsolete as some weaknesses has been found when not used properly, but it is still in use and not considered broken.

    • PKCS1 v2 (commonly refered as OAEP or PSS) which is stochastic (randomized) padding. You can distinguish the last two as the output of OAEP is always different.

    One of the problems is that ruby can encrypt the text with no problem, and in golang I'm getting an error that the key is too short to encrypt everything

    You've provided only a small part of the golang example, so here I may only assume many things.

    As you claim the golang example outputs randomized output and according to the parameters PKCS1 v1.5 is used, I'd assume the implementation is doing hybrid encryption which is good and much safer way to encrypt data with RSA (using symmetric encryption with random key and wrap/encrypt the key with RSA).

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!