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

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

RSA Encryption/Decryption between Python and Golang not working?

问题

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

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

  1. func encryptString(s string) string {
  2. publicKey, _ := os.ReadFile("public.pem")
  3. block, _ := pem.Decode([]byte(publicKey))
  4. if block.Type != "PUBLIC KEY" {
  5. log.Fatal("error decoding public key from pem")
  6. }
  7. parsedKey, err := x509.ParsePKIXPublicKey(block.Bytes)
  8. if err != nil {
  9. log.Fatal("error parsing key")
  10. }
  11. var ok bool
  12. var pubkey *rsa.PublicKey
  13. if pubkey, ok = parsedKey.(*rsa.PublicKey); !ok {
  14. log.Fatal("unable to parse public key")
  15. }
  16. rng := rand.Reader
  17. ciphertext, err := rsa.EncryptOAEP(sha256.New(), rng, pubkey, []byte(s), nil)
  18. if err != nil {
  19. log.Fatal(err)
  20. }
  21. return base64.StdEncoding.EncodeToString(ciphertext)
  22. }

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

  1. import os
  2. import base64
  3. from cryptography.hazmat.primitives import hashes
  4. from cryptography.hazmat.primitives.asymmetric.padding import MGF1, OAEP
  5. from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
  6. from cryptography.hazmat.primitives.serialization import load_pem_private_key
  7. encrypted_message = "<REMOVED>"
  8. encrypted_message_bytes = base64.b64decode(encrypted_message.encode("utf-8"))
  9. PRIVATE_KEY = os.getenv("PRIVATE_KEY")
  10. private_key_bytes = PRIVATE_KEY.encode("utf-8")
  11. private_key: RSAPrivateKey = load_pem_private_key(private_key_bytes, None)
  12. padding = OAEP(mgf=MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None)
  13. decrypted_message = private_key.decrypt(encrypted_message_bytes, padding)
  14. print(decrypted_message)

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

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

  1. func encryptString(s string) string {
  2. publicKey, _ := os.ReadFile(&quot;public.pem&quot;)
  3. block, _ := pem.Decode([]byte(publicKey))
  4. if block.Type != &quot;PUBLIC KEY&quot; {
  5. log.Fatal(&quot;error decoding public key from pem&quot;)
  6. }
  7. parsedKey, err := x509.ParsePKIXPublicKey(block.Bytes)
  8. if err != nil {
  9. log.Fatal(&quot;error parsing key&quot;)
  10. }
  11. var ok bool
  12. var pubkey *rsa.PublicKey
  13. if pubkey, ok = parsedKey.(*rsa.PublicKey); !ok {
  14. log.Fatal(&quot;unable to parse public key&quot;)
  15. }
  16. rng := rand.Reader
  17. ciphertext, err := rsa.EncryptOAEP(sha256.New(), rng, pubkey, []byte(s), nil)
  18. if err != nil {
  19. log.Fatal(err)
  20. }
  21. return base64.StdEncoding.EncodeToString(ciphertext)
  22. }

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

  1. import os
  2. import base64
  3. from cryptography.hazmat.primitives import hashes
  4. from cryptography.hazmat.primitives.asymmetric.padding import MGF1, OAEP
  5. from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
  6. from cryptography.hazmat.primitives.serialization import load_pem_private_key
  7. encrypted_message = &quot;&lt;REMOVED&gt;&quot;
  8. encrypted_message_bytes = base64.b64decode(encrypted_message.encode(&quot;utf-8&quot;))
  9. PRIVATE_KEY = os.getenv(&quot;PRIVATE_KEY&quot;)
  10. private_key_bytes = PRIVATE_KEY.encode(&quot;utf-8&quot;)
  11. private_key: RSAPrivateKey = load_pem_private_key(private_key_bytes, None)
  12. padding = OAEP(mgf=MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None)
  13. decrypted_message = private_key.decrypt(encrypted_message_bytes, padding)
  14. print(decrypted_message)

On running this, I just get the following error:

  1. Traceback (most recent call last):
  2. File &quot;decrypt_test.py&quot;, line 14, in &lt;module&gt;
  3. decrypted_message = private_key.decrypt(encrypted_message_bytes, padding)
  4. File &quot;venv/lib/python3.9/site-packages/cryptography/hazmat/backends/openssl/rsa.py&quot;, line 424, in decrypt
  5. return _enc_dec_rsa(self._backend, self, ciphertext, padding)
  6. File &quot;venv/lib/python3.9/site-packages/cryptography/hazmat/backends/openssl/rsa.py&quot;, line 87, in _enc_dec_rsa
  7. return _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum, padding)
  8. File &quot;venv/lib/python3.9/site-packages/cryptography/hazmat/backends/openssl/rsa.py&quot;, line 151, in _enc_dec_rsa_pkey_ctx
  9. raise ValueError(&quot;Encryption/decryption failed.&quot;)
  10. 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格式的私钥有多行,也许你可以尝试从文件中读取私钥。

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

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

encrypt.go

  1. package main
  2. import (
  3. "crypto/rand"
  4. "crypto/rsa"
  5. "crypto/sha256"
  6. "crypto/x509"
  7. "encoding/base64"
  8. "encoding/pem"
  9. "fmt"
  10. "log"
  11. "os"
  12. )
  13. func main() {
  14. s := "heloo"
  15. publicKey, _ := os.ReadFile("./rsa_public_key.pem")
  16. block, _ := pem.Decode([]byte(publicKey))
  17. if block.Type != "PUBLIC KEY" {
  18. log.Fatal("error decoding public key from pem")
  19. }
  20. parsedKey, err := x509.ParsePKIXPublicKey(block.Bytes)
  21. if err != nil {
  22. log.Fatal("error parsing key")
  23. }
  24. var ok bool
  25. var pubkey *rsa.PublicKey
  26. if pubkey, ok = parsedKey.(*rsa.PublicKey); !ok {
  27. log.Fatal("unable to parse public key")
  28. }
  29. rng := rand.Reader
  30. ciphertext, err := rsa.EncryptOAEP(sha256.New(), rng, pubkey, []byte(s), nil)
  31. if err != nil {
  32. log.Fatal(err)
  33. }
  34. fmt.Println(base64.StdEncoding.EncodeToString(ciphertext))
  35. }

decrypt.py

  1. import base64
  2. from cryptography.hazmat.primitives import hashes
  3. from cryptography.hazmat.primitives.asymmetric.padding import MGF1, OAEP
  4. from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
  5. from cryptography.hazmat.primitives.serialization import load_pem_private_key
  6. encrypted_message = "CQMKIcEnqtkvyduwtVNNzdEH23DlQVBaI1rbo/5TA1syW4/ZUyXuHmGTuxqK6+d0gqF7/l2uFGoCY/gQ6FFaVk2JTZqJwYbX5AzZRYI77PuZdjhSROT01LIdDgdRJqO9kqDcIRr1M2b7tRp9a3nF6LwhL9DdX7Z9P1qnNHUEE30="
  7. encrypted_message_bytes = base64.b64decode(encrypted_message.encode("utf-8"))
  8. PRIVATE_KEY = open('./rsa_private_key.pem', 'r').read()
  9. private_key_bytes = PRIVATE_KEY.encode("utf-8")
  10. private_key: RSAPrivateKey = load_pem_private_key(private_key_bytes, None)
  11. padding = OAEP(mgf=MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None)
  12. decrypted_message = private_key.decrypt(encrypted_message_bytes, padding)
  13. print(decrypted_message)

用于生成RSA密钥的命令

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

cat ./rsa_private_key.pem

  1. -----BEGIN RSA PRIVATE KEY-----
  2. MIICXQIBAAKBgQDabYklPLIPvrwmPpuQZcIjfEnOLq5YtSdOzvDRrFcd0XXBz2Vc
  3. THC+VzgE38l5DqMagdhea0/2UNRBIEQrpLPNwNbvVa7eRmgzOnv3P7R4ylOLorkw
  4. CLpUedOHJ+9pe8mbJ2Z4npKw0Y+JPuqgNY1ZB/PcqaajCoZHgTvdYe14DwIDAQAB
  5. AoGAdQSVorNfmXvPhJWp9bPuS+B8Ec+Ea9WxF1FaRpoTmc/rTEd1v/rbs706L7JM
  6. V2R2EO9bIUpQbl9jNvi4TMFR6X103WdMpkcoUb9l7h583MNCoT7sblwXO5PfVjg7
  7. UWSFv1eDJGWWpbcRCKYCLJ21jxt3smr95uLbvv9w8+GgysECQQDtgHHW5e4YjAcA
  8. AdagVMRnoNUlIsZxMh0dnug2S67XPl53L8KXDk263B8zNGZgYZKBsr2or4rZPF3m
  9. xaqtLONxAkEA63DG0Ood9K1A5OwnROyucxB55w1iOU0omCnBjUjWbI1s6zn+KjOt
  10. Orq1Kx32hQXiMeqht+r94TXVR+x7zhtTfwJAFOyyGurbFVKQ81E2JZ4SR8cFwGXV
  11. 8fcmVYvAjbgRSWl3TSzqCgD6nDH0lcBSHL+79q1WxFvi8cy9wS09IlDIIQJBAN4L
  12. TnZZVkcb3sgHsEFgtmXudAlkpe5ExrQ7LT+CIjfeaYqu9vX2JrnsvFAdwhFSqzFI
  13. h5xdE3MCwlNCxMBtJSECQQDATTfT3SquwB1RwIbJ4uD4DDs4ooilMi+6mcYvS+Uf
  14. WGXGmdNHxflUM8HYgfN9nIpI36czrxJfURJ4ueQjZo4l
  15. -----END RSA PRIVATE KEY-----

cat ./rsa_public_key.pem

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

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

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

The codes below worked on my test server

encrypt.go

  1. package main
  2. import (
  3. &quot;crypto/rand&quot;
  4. &quot;crypto/rsa&quot;
  5. &quot;crypto/sha256&quot;
  6. &quot;crypto/x509&quot;
  7. &quot;encoding/base64&quot;
  8. &quot;encoding/pem&quot;
  9. &quot;fmt&quot;
  10. &quot;log&quot;
  11. &quot;os&quot;
  12. )
  13. func main() {
  14. s := &quot;heloo&quot;
  15. publicKey, _ := os.ReadFile(&quot;./rsa_public_key.pem&quot;)
  16. block, _ := pem.Decode([]byte(publicKey))
  17. if block.Type != &quot;PUBLIC KEY&quot; {
  18. log.Fatal(&quot;error decoding public key from pem&quot;)
  19. }
  20. parsedKey, err := x509.ParsePKIXPublicKey(block.Bytes)
  21. if err != nil {
  22. log.Fatal(&quot;error parsing key&quot;)
  23. }
  24. var ok bool
  25. var pubkey *rsa.PublicKey
  26. if pubkey, ok = parsedKey.(*rsa.PublicKey); !ok {
  27. log.Fatal(&quot;unable to parse public key&quot;)
  28. }
  29. rng := rand.Reader
  30. ciphertext, err := rsa.EncryptOAEP(sha256.New(), rng, pubkey, []byte(s), nil)
  31. if err != nil {
  32. log.Fatal(err)
  33. }
  34. fmt.Println(base64.StdEncoding.EncodeToString(ciphertext))
  35. }

decrypt.py

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

commands used to generate RSA keys

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

cat ./rsa_private_key.pem

  1. -----BEGIN RSA PRIVATE KEY-----
  2. MIICXQIBAAKBgQDabYklPLIPvrwmPpuQZcIjfEnOLq5YtSdOzvDRrFcd0XXBz2Vc
  3. THC+VzgE38l5DqMagdhea0/2UNRBIEQrpLPNwNbvVa7eRmgzOnv3P7R4ylOLorkw
  4. CLpUedOHJ+9pe8mbJ2Z4npKw0Y+JPuqgNY1ZB/PcqaajCoZHgTvdYe14DwIDAQAB
  5. AoGAdQSVorNfmXvPhJWp9bPuS+B8Ec+Ea9WxF1FaRpoTmc/rTEd1v/rbs706L7JM
  6. V2R2EO9bIUpQbl9jNvi4TMFR6X103WdMpkcoUb9l7h583MNCoT7sblwXO5PfVjg7
  7. UWSFv1eDJGWWpbcRCKYCLJ21jxt3smr95uLbvv9w8+GgysECQQDtgHHW5e4YjAcA
  8. AdagVMRnoNUlIsZxMh0dnug2S67XPl53L8KXDk263B8zNGZgYZKBsr2or4rZPF3m
  9. xaqtLONxAkEA63DG0Ood9K1A5OwnROyucxB55w1iOU0omCnBjUjWbI1s6zn+KjOt
  10. Orq1Kx32hQXiMeqht+r94TXVR+x7zhtTfwJAFOyyGurbFVKQ81E2JZ4SR8cFwGXV
  11. 8fcmVYvAjbgRSWl3TSzqCgD6nDH0lcBSHL+79q1WxFvi8cy9wS09IlDIIQJBAN4L
  12. TnZZVkcb3sgHsEFgtmXudAlkpe5ExrQ7LT+CIjfeaYqu9vX2JrnsvFAdwhFSqzFI
  13. h5xdE3MCwlNCxMBtJSECQQDATTfT3SquwB1RwIbJ4uD4DDs4ooilMi+6mcYvS+Uf
  14. WGXGmdNHxflUM8HYgfN9nIpI36czrxJfURJ4ueQjZo4l
  15. -----END RSA PRIVATE KEY-----

cat ./rsa_public_key.pem

  1. -----BEGIN PUBLIC KEY-----
  2. MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDabYklPLIPvrwmPpuQZcIjfEnO
  3. Lq5YtSdOzvDRrFcd0XXBz2VcTHC+VzgE38l5DqMagdhea0/2UNRBIEQrpLPNwNbv
  4. Va7eRmgzOnv3P7R4ylOLorkwCLpUedOHJ+9pe8mbJ2Z4npKw0Y+JPuqgNY1ZB/Pc
  5. qaajCoZHgTvdYe14DwIDAQAB
  6. -----END PUBLIC KEY-----
  1. $ go run ./encrypt.go
  2. wgM33DAJABF0MC0BkflewXPABVdyWpzYMsYhMVKs13OS7SB+fkW31kxL7dipxxEqmTPWXCGFu8o3QxDY82VgcfEywSdigml22KXUN1Qg1VIU6yZg6i34wuD07/8zalW+pza9F43Mj0/XRKnn10ZagfgkBYaytk1zQ4cKcYp4JrM=
  1. $ python3 ./decrypt.py
  2. 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:

确定