RSA加密/解密在Python和Golang之间无法正常工作?

huangapple go评论99阅读模式
英文:

RSA Encryption/Decryption between Python and Golang not working?

问题

当我使用Go加密字符串后,我无法使用Python解密它。显然我做错了什么,但我无法确定问题所在。非常感谢任何帮助。

基本上,我使用以下函数加密字符串(我可以使用Go解密,但无法使用Python解密):

func encryptString(s string) string {
	publicKey, _ := os.ReadFile("public.pem")
	block, _ := pem.Decode([]byte(publicKey))
	if block.Type != "PUBLIC KEY" {
		log.Fatal("error decoding public key from pem")
	}
	parsedKey, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		log.Fatal("error parsing key")
	}
	var ok bool
	var pubkey *rsa.PublicKey
	if pubkey, ok = parsedKey.(*rsa.PublicKey); !ok {
		log.Fatal("unable to parse public key")
	}
	rng := rand.Reader
	ciphertext, err := rsa.EncryptOAEP(sha256.New(), rng, pubkey, []byte(s), nil)
	if err != nil {
		log.Fatal(err)
	}
	return base64.StdEncoding.EncodeToString(ciphertext)
}

这是我使用的Python代码来尝试解码加密的字符串:

import os
import base64
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric.padding import MGF1, OAEP
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
from cryptography.hazmat.primitives.serialization import load_pem_private_key

encrypted_message = "<REMOVED>"
encrypted_message_bytes = base64.b64decode(encrypted_message.encode("utf-8"))
PRIVATE_KEY = os.getenv("PRIVATE_KEY")
private_key_bytes = PRIVATE_KEY.encode("utf-8")
private_key: RSAPrivateKey = load_pem_private_key(private_key_bytes, None)
padding = OAEP(mgf=MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None)
decrypted_message = private_key.decrypt(encrypted_message_bytes, padding)
print(decrypted_message)

运行时,我只得到以下错误:

Traceback (most recent call last):
  File "decrypt_test.py", line 14, in <module>
    decrypted_message = private_key.decrypt(encrypted_message_bytes, padding)
  File "venv/lib/python3.9/site-packages/cryptography/hazmat/backends/openssl/rsa.py", line 424, in decrypt
    return _enc_dec_rsa(self._backend, self, ciphertext, padding)
  File "venv/lib/python3.9/site-packages/cryptography/hazmat/backends/openssl/rsa.py", line 87, in _enc_dec_rsa
    return _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum, padding)
  File "venv/lib/python3.9/site-packages/cryptography/hazmat/backends/openssl/rsa.py", line 151, in _enc_dec_rsa_pkey_ctx
    raise ValueError("Encryption/decryption failed.")
ValueError: Encryption/decryption failed.

我对生产中的Python代码没有任何控制权,所以我只想对Go代码进行更改。我在另一方面也遇到了同样的问题,但我认为问题是一样的。

非常感谢任何想法。

英文:

When I encrypt a string with Go, I am unable to decrypt it again with Python. I'm clearly doing something wrong, but I'm unable to identify the problem. Any assistance greatly appreciated.

Essentially, I'm encrypting a string with the following function (which I'm then able to decrypt with Go, but not Python):

func encryptString(s string) string {
	publicKey, _ := os.ReadFile(&quot;public.pem&quot;)
	block, _ := pem.Decode([]byte(publicKey))
	if block.Type != &quot;PUBLIC KEY&quot; {
		log.Fatal(&quot;error decoding public key from pem&quot;)
	}
	parsedKey, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		log.Fatal(&quot;error parsing key&quot;)
	}
	var ok bool
	var pubkey *rsa.PublicKey
	if pubkey, ok = parsedKey.(*rsa.PublicKey); !ok {
		log.Fatal(&quot;unable to parse public key&quot;)
	}
	rng := rand.Reader
	ciphertext, err := rsa.EncryptOAEP(sha256.New(), rng, pubkey, []byte(s), nil)
	if err != nil {
		log.Fatal(err)
	}
	return base64.StdEncoding.EncodeToString(ciphertext)
}

This is the python code I'm using to try and decode the encrypted string:

import os
import base64
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric.padding import MGF1, OAEP
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
from cryptography.hazmat.primitives.serialization import load_pem_private_key

encrypted_message = &quot;&lt;REMOVED&gt;&quot;
encrypted_message_bytes = base64.b64decode(encrypted_message.encode(&quot;utf-8&quot;))
PRIVATE_KEY = os.getenv(&quot;PRIVATE_KEY&quot;)
private_key_bytes = PRIVATE_KEY.encode(&quot;utf-8&quot;)
private_key: RSAPrivateKey = load_pem_private_key(private_key_bytes, None)
padding = OAEP(mgf=MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None)
decrypted_message = private_key.decrypt(encrypted_message_bytes, padding)
print(decrypted_message)

On running this, I just get the following error:

Traceback (most recent call last):
  File &quot;decrypt_test.py&quot;, line 14, in &lt;module&gt;
    decrypted_message = private_key.decrypt(encrypted_message_bytes, padding)
  File &quot;venv/lib/python3.9/site-packages/cryptography/hazmat/backends/openssl/rsa.py&quot;, line 424, in decrypt
    return _enc_dec_rsa(self._backend, self, ciphertext, padding)
  File &quot;venv/lib/python3.9/site-packages/cryptography/hazmat/backends/openssl/rsa.py&quot;, line 87, in _enc_dec_rsa
    return _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum, padding)
  File &quot;venv/lib/python3.9/site-packages/cryptography/hazmat/backends/openssl/rsa.py&quot;, line 151, in _enc_dec_rsa_pkey_ctx
    raise ValueError(&quot;Encryption/decryption failed.&quot;)
ValueError: Encryption/decryption failed.

I don't have any control over the python code in production, so I would like to only make changes to Go code. I also have the same problem the other way around, but I expect it's the same issue.

Any thoughts greatly appreciated.

答案1

得分: 1

一个以pem格式的私钥有多行,也许你可以尝试从文件中读取私钥。

PRIVATE_KEY = open('./private.pem', 'r').read()

下面的代码在我的测试服务器上运行成功。

encrypt.go

package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"crypto/x509"
	"encoding/base64"
	"encoding/pem"
	"fmt"
	"log"
	"os"
)

func main() {
	s := "heloo"
	publicKey, _ := os.ReadFile("./rsa_public_key.pem")
	block, _ := pem.Decode([]byte(publicKey))
	if block.Type != "PUBLIC KEY" {
		log.Fatal("error decoding public key from pem")
	}
	parsedKey, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		log.Fatal("error parsing key")
	}
	var ok bool
	var pubkey *rsa.PublicKey
	if pubkey, ok = parsedKey.(*rsa.PublicKey); !ok {
		log.Fatal("unable to parse public key")
	}
	rng := rand.Reader
	ciphertext, err := rsa.EncryptOAEP(sha256.New(), rng, pubkey, []byte(s), nil)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(base64.StdEncoding.EncodeToString(ciphertext))
}

decrypt.py

import base64
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric.padding import MGF1, OAEP
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
from cryptography.hazmat.primitives.serialization import load_pem_private_key

encrypted_message = "CQMKIcEnqtkvyduwtVNNzdEH23DlQVBaI1rbo/5TA1syW4/ZUyXuHmGTuxqK6+d0gqF7/l2uFGoCY/gQ6FFaVk2JTZqJwYbX5AzZRYI77PuZdjhSROT01LIdDgdRJqO9kqDcIRr1M2b7tRp9a3nF6LwhL9DdX7Z9P1qnNHUEE30="
encrypted_message_bytes = base64.b64decode(encrypted_message.encode("utf-8"))
PRIVATE_KEY = open('./rsa_private_key.pem', 'r').read()
private_key_bytes = PRIVATE_KEY.encode("utf-8")
private_key: RSAPrivateKey = load_pem_private_key(private_key_bytes, None)
padding = OAEP(mgf=MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None)
decrypted_message = private_key.decrypt(encrypted_message_bytes, padding)
print(decrypted_message)

用于生成RSA密钥的命令

openssl genrsa -out rsa_private_key.pem 1024
openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

cat ./rsa_private_key.pem

-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDabYklPLIPvrwmPpuQZcIjfEnOLq5YtSdOzvDRrFcd0XXBz2Vc
THC+VzgE38l5DqMagdhea0/2UNRBIEQrpLPNwNbvVa7eRmgzOnv3P7R4ylOLorkw
CLpUedOHJ+9pe8mbJ2Z4npKw0Y+JPuqgNY1ZB/PcqaajCoZHgTvdYe14DwIDAQAB
AoGAdQSVorNfmXvPhJWp9bPuS+B8Ec+Ea9WxF1FaRpoTmc/rTEd1v/rbs706L7JM
V2R2EO9bIUpQbl9jNvi4TMFR6X103WdMpkcoUb9l7h583MNCoT7sblwXO5PfVjg7
UWSFv1eDJGWWpbcRCKYCLJ21jxt3smr95uLbvv9w8+GgysECQQDtgHHW5e4YjAcA
AdagVMRnoNUlIsZxMh0dnug2S67XPl53L8KXDk263B8zNGZgYZKBsr2or4rZPF3m
xaqtLONxAkEA63DG0Ood9K1A5OwnROyucxB55w1iOU0omCnBjUjWbI1s6zn+KjOt
Orq1Kx32hQXiMeqht+r94TXVR+x7zhtTfwJAFOyyGurbFVKQ81E2JZ4SR8cFwGXV
8fcmVYvAjbgRSWl3TSzqCgD6nDH0lcBSHL+79q1WxFvi8cy9wS09IlDIIQJBAN4L
TnZZVkcb3sgHsEFgtmXudAlkpe5ExrQ7LT+CIjfeaYqu9vX2JrnsvFAdwhFSqzFI
h5xdE3MCwlNCxMBtJSECQQDATTfT3SquwB1RwIbJ4uD4DDs4ooilMi+6mcYvS+Uf
WGXGmdNHxflUM8HYgfN9nIpI36czrxJfURJ4ueQjZo4l
-----END RSA PRIVATE KEY-----

cat ./rsa_public_key.pem

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDabYklPLIPvrwmPpuQZcIjfEnO
Lq5YtSdOzvDRrFcd0XXBz2VcTHC+VzgE38l5DqMagdhea0/2UNRBIEQrpLPNwNbv
Va7eRmgzOnv3P7R4ylOLorkwCLpUedOHJ+9pe8mbJ2Z4npKw0Y+JPuqgNY1ZB/Pc
qaajCoZHgTvdYe14DwIDAQAB
-----END PUBLIC KEY-----
$ go run ./encrypt.go
wgM33DAJABF0MC0BkflewXPABVdyWpzYMsYhMVKs13OS7SB+fkW31kxL7dipxxEqmTPWXCGFu8o3QxDY82VgcfEywSdigml22KXUN1Qg1VIU6yZg6i34wuD07/8zalW+pza9F43Mj0/XRKnn10ZagfgkBYaytk1zQ4cKcYp4JrM=
$ python3 ./decrypt.py
b'heloo'
英文:

A private key in pem format has multi lines, maybe you could try to read the private key from file

PRIVATE_KEY = open(&#39;./private.pem&#39;, &#39;r&#39;).read()

The codes below worked on my test server

encrypt.go

package main

import (
	&quot;crypto/rand&quot;
	&quot;crypto/rsa&quot;
	&quot;crypto/sha256&quot;
	&quot;crypto/x509&quot;
	&quot;encoding/base64&quot;
	&quot;encoding/pem&quot;
	&quot;fmt&quot;
	&quot;log&quot;
	&quot;os&quot;
)

func main() {
	s := &quot;heloo&quot;
	publicKey, _ := os.ReadFile(&quot;./rsa_public_key.pem&quot;)
	block, _ := pem.Decode([]byte(publicKey))
	if block.Type != &quot;PUBLIC KEY&quot; {
		log.Fatal(&quot;error decoding public key from pem&quot;)
	}
	parsedKey, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		log.Fatal(&quot;error parsing key&quot;)
	}
	var ok bool
	var pubkey *rsa.PublicKey
	if pubkey, ok = parsedKey.(*rsa.PublicKey); !ok {
		log.Fatal(&quot;unable to parse public key&quot;)
	}
	rng := rand.Reader
	ciphertext, err := rsa.EncryptOAEP(sha256.New(), rng, pubkey, []byte(s), nil)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(base64.StdEncoding.EncodeToString(ciphertext))
}

decrypt.py

import base64
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric.padding import MGF1, OAEP
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
from cryptography.hazmat.primitives.serialization import load_pem_private_key
encrypted_message = &quot;CQMKIcEnqtkvyduwtVNNzdEH23DlQVBaI1rbo/5TA1syW4/ZUyXuHmGTuxqK6+d0gqF7/l2uFGoCY/gQ6FFaVk2JTZqJwYbX5AzZRYI77PuZdjhSROT01LIdDgdRJqO9kqDcIRr1M2b7tRp9a3nF6LwhL9DdX7Z9P1qnNHUEE30=&quot;
encrypted_message_bytes = base64.b64decode(encrypted_message.encode(&quot;utf-8&quot;))
PRIVATE_KEY = open(&#39;./rsa_private_key.pem&#39;, &#39;r&#39;).read()
private_key_bytes = PRIVATE_KEY.encode(&quot;utf-8&quot;)
private_key: RSAPrivateKey = load_pem_private_key(private_key_bytes, None)
padding = OAEP(mgf=MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None)
decrypted_message = private_key.decrypt(encrypted_message_bytes, padding)
print(decrypted_message)

commands used to generate RSA keys

openssl genrsa -out rsa_private_key.pem 1024
openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

cat ./rsa_private_key.pem

-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDabYklPLIPvrwmPpuQZcIjfEnOLq5YtSdOzvDRrFcd0XXBz2Vc
THC+VzgE38l5DqMagdhea0/2UNRBIEQrpLPNwNbvVa7eRmgzOnv3P7R4ylOLorkw
CLpUedOHJ+9pe8mbJ2Z4npKw0Y+JPuqgNY1ZB/PcqaajCoZHgTvdYe14DwIDAQAB
AoGAdQSVorNfmXvPhJWp9bPuS+B8Ec+Ea9WxF1FaRpoTmc/rTEd1v/rbs706L7JM
V2R2EO9bIUpQbl9jNvi4TMFR6X103WdMpkcoUb9l7h583MNCoT7sblwXO5PfVjg7
UWSFv1eDJGWWpbcRCKYCLJ21jxt3smr95uLbvv9w8+GgysECQQDtgHHW5e4YjAcA
AdagVMRnoNUlIsZxMh0dnug2S67XPl53L8KXDk263B8zNGZgYZKBsr2or4rZPF3m
xaqtLONxAkEA63DG0Ood9K1A5OwnROyucxB55w1iOU0omCnBjUjWbI1s6zn+KjOt
Orq1Kx32hQXiMeqht+r94TXVR+x7zhtTfwJAFOyyGurbFVKQ81E2JZ4SR8cFwGXV
8fcmVYvAjbgRSWl3TSzqCgD6nDH0lcBSHL+79q1WxFvi8cy9wS09IlDIIQJBAN4L
TnZZVkcb3sgHsEFgtmXudAlkpe5ExrQ7LT+CIjfeaYqu9vX2JrnsvFAdwhFSqzFI
h5xdE3MCwlNCxMBtJSECQQDATTfT3SquwB1RwIbJ4uD4DDs4ooilMi+6mcYvS+Uf
WGXGmdNHxflUM8HYgfN9nIpI36czrxJfURJ4ueQjZo4l
-----END RSA PRIVATE KEY-----

cat ./rsa_public_key.pem

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDabYklPLIPvrwmPpuQZcIjfEnO
Lq5YtSdOzvDRrFcd0XXBz2VcTHC+VzgE38l5DqMagdhea0/2UNRBIEQrpLPNwNbv
Va7eRmgzOnv3P7R4ylOLorkwCLpUedOHJ+9pe8mbJ2Z4npKw0Y+JPuqgNY1ZB/Pc
qaajCoZHgTvdYe14DwIDAQAB
-----END PUBLIC KEY-----
$ go run ./encrypt.go
wgM33DAJABF0MC0BkflewXPABVdyWpzYMsYhMVKs13OS7SB+fkW31kxL7dipxxEqmTPWXCGFu8o3QxDY82VgcfEywSdigml22KXUN1Qg1VIU6yZg6i34wuD07/8zalW+pza9F43Mj0/XRKnn10ZagfgkBYaytk1zQ4cKcYp4JrM=
$ python3 ./decrypt.py
b&#39;heloo&#39;

答案2

得分: 0

我不完全确定发生了什么变化,但当我重新访问时,它确实开始工作了。我确实改变了加载证书文件等的方式,所以可能存在密钥不匹配或其他类似问题,正如这里所建议的那样。我可以确认在Python和Go之间进行加密/解密是可行的。感谢那些回应的人。

英文:

I'm not entirely sure what changed, but when I revisited this, it did start working. I did change the way I was loading the certificate files etc. and so there may have been an issue there with mismatched keys or something like that as suggested here. I can confirm performing encryption/decryption between python/Go does work. Thanks to those that responded.

huangapple
  • 本文由 发表于 2021年10月20日 16:58:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/69643120.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定