golang Golang RSA-OAEP加密和解密

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang Golang RSA-OAEP加密和解密相关的知识,希望对你有一定的参考价值。

package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha1"
	"crypto/x509"
	"encoding/base64"
	"encoding/pem"
	"fmt"
)

func main() {
	var publicKeyData = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAygGoUiTD+LjwZIgwFZyj
iibWNQ2LM9xZ2pjKQGP8iUBtAuAW629/Ofw8qxToMyixPrG4A7j8+KOPwYrWPGV6
Og//4zm3cG+1hQvnNUWtMjHHBY8OByUPQ6/T8XHER1DxFBfnWfFLZ1yFX6oNNuvt
LgOreI6ehehJd5IB/4mOjMvFEBgOEejado2n55VNdcFpdQ3RcvGV+f/rl/lsIM08
QvL3lc5gqawj53sW9YZi1DL/uN48R+ghvAYhtx2jpHDBvlH1NCF1rU6CynYsgV9Q
Iksv0ihwl4T+k5F9ir0uv0WIS6kKKS1SRpAprRKunos4PlE8l2+jC6LaJUPhDZlj
/wIDAQAB
-----END PUBLIC KEY-----
`
	var privateKeyData = `
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAygGoUiTD+LjwZIgwFZyjiibWNQ2LM9xZ2pjKQGP8iUBtAuAW
629/Ofw8qxToMyixPrG4A7j8+KOPwYrWPGV6Og//4zm3cG+1hQvnNUWtMjHHBY8O
ByUPQ6/T8XHER1DxFBfnWfFLZ1yFX6oNNuvtLgOreI6ehehJd5IB/4mOjMvFEBgO
Eejado2n55VNdcFpdQ3RcvGV+f/rl/lsIM08QvL3lc5gqawj53sW9YZi1DL/uN48
R+ghvAYhtx2jpHDBvlH1NCF1rU6CynYsgV9QIksv0ihwl4T+k5F9ir0uv0WIS6kK
KS1SRpAprRKunos4PlE8l2+jC6LaJUPhDZlj/wIDAQABAoIBAHIcX5YPeLie2AUi
PW9n7aYT7DtJ7FGebw+h8dZP5Q8vWqUeKzRR5p+90hOemtCTcxSEVfucWyKlWoat
Q/oYJOR5t0YHi40zPWnr4G7ibkUFg3Sra/QzRh0pTON+La9PlO+R1TmkqcC4rgrt
R8u3mGK+5fUTM49XOXEXBJPyg5kaXQpiA4BoIRdRnCSitNxWA8kxMkQYJYlwAYab
cKo4Ik/J6+YGG7m2FtrUAWpWVUMBzEYOmGJ7JhSJ1u0UC/Oh1HOS1xlGopkmexbd
EygY3hTNWzHmYaYcYQs0f+8aVcVL64Gm0dtqvAHNnBvudMThhQgdYPc39mNLbrwI
ks4uS8ECgYEA9XfvcGKsNrHA0nqoPUPMT0Nfvv/4XCaKOYk25brH4LbqJPm6CiU6
uNlKFQsxzHPmx7OEK7EYVVZCbSO9s4t/xCzDVNbOZ9kDL6bkTX9DArLE4d6IRF/1
WW/AlNPuwVgxl0kcJILFtLqA1WoC5UWMhbYe2YB/Q3rCozmn0AiwyqECgYEA0qxd
KClKAMIsrB0WJ9gZEsJOpFi4q4g6T1BwT40Xj6Ul6o6DHi6hFhPgZAstqmnY0ANz
ezQ2yxtIm7zSy7S+nwDUycjY9riJcomc/YQZNA2QVM16hEv84VLwH1MVV2wkTb41
DWjbcg/ZNofZHl9AQIw7es+R3mmtDN+8BZOZSp8CgYBHtwmaUQm1VQtbswAyHfuz
8KApgklCSvQ5SRBj38UDrw0LTnZ+/k+Ar+MH8ORUskvrblQgG7ZbQD9Z+YYzzX6/
hsBuqe9Vwb4/jsfGqHagdDA3OTegmlRpE9A06xInJKggZfi15gry+UYok7dS2pXq
fsHWk8capOP2oiKYEeHs4QKBgF2KcLaDVrtte/5Tz+GTHtbodZidWCm5jAJpeeSo
hfye3G4AJxHArH+sBacGG5md88mwrpbWwTl/fMbBmWsfbsAU02ZhCozJtSWpGo6q
F7K4DwzIS4zwXHEDrWCLOF+fwaLPQKkalM1ZYh3HRc0ph9LhMQu/nEn/6/laYhar
yZWLAoGASvCrpFKn0qllMKNUetBmYFpgtjmnNuW7l0xT2UftkW6AuFjU19gKgXhe
I+uZciHQ8kIUHfNLYBbhETsF3iqsklKfeoIr23zYHLE5GpoC151IpKf4guoPbCHX
a1oCDuZm//f5HMePb9juJN0WR//d5jWuizAycZf41XoEd8Bqydg=
-----END RSA PRIVATE KEY-----
`
	pubKeyBlock, _ := pem.Decode([]byte(publicKeyData))
	hash := sha1.New()
	random := rand.Reader
	msg := []byte("helloworldjemyme")
	var pub *rsa.PublicKey
	pubInterface, parseErr := x509.ParsePKIXPublicKey(pubKeyBlock.Bytes)
	if parseErr != nil {
		fmt.Println("Load public key error")
		panic(parseErr)
	}
	pub = pubInterface.(*rsa.PublicKey)
	encryptedData, encryptErr := rsa.EncryptOAEP(hash, random, pub, msg, nil)
	if encryptErr != nil {
		fmt.Println("Encrypt data error")
		panic(encryptErr)
	}
	encodedData := base64.URLEncoding.EncodeToString(encryptedData)
	fmt.Println(encodedData)
	fmt.Println()
	fmt.Println("------I AM JUST A LINE------")
	fmt.Println()
	privateKeyBlock, _ := pem.Decode([]byte(privateKeyData))
	var pri *rsa.PrivateKey
	pri, parseErr = x509.ParsePKCS1PrivateKey(privateKeyBlock.Bytes)
	if parseErr != nil {
		fmt.Println("Load private key error")
		panic(parseErr)
	}
	decryptedData, decryptErr := rsa.DecryptOAEP(hash, random, pri, encryptedData, nil)
	if decryptErr != nil {
		fmt.Println("Decrypt data error")
		panic(decryptErr)
	}
	fmt.Println(string(decryptedData))
}

Python 和 Golang 之间的 RSA 加密/解密不起作用? [关闭]

【中文标题】Python 和 Golang 之间的 RSA 加密/解密不起作用? [关闭]【英文标题】:RSA Encryption/Decryption between Python and Golang not working? [closed] 【发布时间】:2021-12-07 02:32:00 【问题描述】:

当我用 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 代码进行更改。反过来,我也有同样的问题,但我希望这是同样的问题。

任何想法都非常感谢。

【问题讨论】:

OAEP 不幸地被证明对许多实现者来说太复杂了,因此一些实现对 MGF1 哈希进行了假设,即它应该是 SHA1。我不熟悉 Go 的加密,所以我会尝试使用 OAEP(mgf=MGF1(algorithm=hashes.SHA1()), algorithm=hashes.SHA256(), ... 的 python 解密器。如果这不起作用(下面的答案表明这不是问题),那么其他可能性包括不匹配的公钥/私钥或密文损坏。 rsa.EncryptOAEP() 将第一个参数中指定的摘要用于在 OAEP 上下文中应用的 both 摘要(seg here),因此此处为 SHA256,因此与Python 代码。我的密钥也无法重现问题(与发布的答案一致),因此代码本身很可能不是问题的原因。 【参考方案1】:

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

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

以下代码在我的测试服务器上运行

加密.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))

解密.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'

【讨论】:

错误发生在private_key.decrypt,而不是load_pem_private_key。 @Peter 我已经在我的测试服务器上验证了【参考方案2】:

我不完全确定发生了什么变化,但是当我重新审视它时,它确实开始起作用了。我确实改变了加载证书文件等的方式,因此可能存在密钥不匹配或类似此处建议的问题。我可以确认在 python/Go 之间执行加密/解密确实有效。感谢那些回复的人。

【讨论】:

以上是关于golang Golang RSA-OAEP加密和解密的主要内容,如果未能解决你的问题,请参考以下文章

golang GoLang使用AES加密将字符串加密到base64,反之亦然。

golang GoLang使用AES加密将字符串加密到base64,反之亦然。

golang GoLang使用AES加密将字符串加密到base64,反之亦然。

golang golang gpg / openpgp加密/解密示例

golang进行加密

golang 在golang中使用AES256 GCM加密文本