我目前正在开发一个项目,我必须将一些代码从Ruby(版本1.9.3p194)“转换”为Golang(版本1.7)。这部分Ruby使用RSA公钥加密,每次执行时我总能得到一致的结果。这是使用的功能:
编辑:我忽略了在公钥加密后,还有一个base 64编码
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("\n", "")
escaped_encrypted_text = URI.escape(encrypted_key, "/+=")
然而在Golang中,由于rsa库,我无法获得一致的结果,因为加密函数每次都会使用随机参数生成不同的结果。我理解为什么它每次都需要不同,但是我无法获得与ruby生成的任何东西相似的东西。这些是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, "=")
其中一个问题是ruby可以毫无问题地对文本进行加密,而在golang中我收到的错误是密钥太短而无法加密所有内容。
如果我加密其他内容,例如“Hello”。解密时我从ruby得到错误“padding check failed”。解密的处理如下:
private_key.private_decrypt(Base64.decode64(text))
编辑:感谢gusto2的答案,我现在更清楚知道发生了什么,因为我对RSA了解不多。
现在在Golang我能够使用PKCS1 v1.5加密文本,并且确保我也尝试解密它,也在Golang中,没有问题。
然而在Ruby中,我仍然无法使用私钥解密。所以我认为Golang中使用的base64编码是个问题。所以我改变了这个部分:
encryptedText := base64.StdEncoding.EncodeToString(result)
我也删除了最后一行是等号被修剪。
完成后,它就像一个魅力。
答案 0 :(得分:2)
我不了解golang,但我可能对RSA有所了解。
差异似乎在padding。
对于红宝石 - 不使用衬垫
对于golang - 使用PKCS1v15填充
在 ruby 示例中,您使用OpenSSL::PKey::RSA::NO_PADDING
非常不安全。它被称为教科书 RSA,并不打算在现实生活中使用,因为它有许多弱点和危险的陷阱。所以 ruby示例非常危险地不安全因为使用了教科书RSA。它也仅限于加密小消息(比密钥空间小得多)。
RSA使用两种填充类型:
PKCS1 v1(通常称为PKCS1) - 这是一个确定性的填充(输出总是相同的),许多密码学家认为这个选项已经过时,因为在使用不当时发现了一些弱点,但它仍然是在使用中并且不被视为破碎。
PKCS1 v2(通常称为OAEP或PSS)是随机(随机)填充。您可以区分最后两个,因为OAEP的输出总是不同。
其中一个问题是ruby可以毫无问题地对文本进行加密,而在golang中我收到的错误是密钥太短而无法加密所有内容
你只提供了golang示例的一小部分,所以在这里我可能只假设很多东西。
当你声称golang示例输出随机输出并且根据参数PKCS1 v1.5使用时,我假设实现正在进行hybrid encryption这是使用RSA加密数据的更好和更安全的方法(使用随机密钥进行对称加密,并使用RSA对密钥进行包装/加密。