Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

新增 RSA PKCS1 加解密功能以兼容境外接口 #109

Merged
merged 1 commit into from
May 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 43 additions & 2 deletions utils/rsa_crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"fmt"
)

// EncryptOAEPWithPublicKey 使用公钥进行加密
// EncryptOAEPWithPublicKey 使用 OAEP padding方式用公钥进行加密
func EncryptOAEPWithPublicKey(message string, publicKey *rsa.PublicKey) (ciphertext string, err error) {
if publicKey == nil {
return "", fmt.Errorf("you should input *rsa.PublicKey")
Expand All @@ -24,7 +24,7 @@ func EncryptOAEPWithPublicKey(message string, publicKey *rsa.PublicKey) (ciphert
return ciphertext, nil
}

// EncryptOAEPWithCertificate 先解析出证书中的公钥,然后使用公钥进行加密
// EncryptOAEPWithCertificate 先解析出证书中的公钥,然后使用 OAEP padding方式公钥进行加密
func EncryptOAEPWithCertificate(message string, certificate *x509.Certificate) (ciphertext string, err error) {
if certificate == nil {
return "", fmt.Errorf("you should input *x509.Certificate")
Expand All @@ -36,6 +36,31 @@ func EncryptOAEPWithCertificate(message string, certificate *x509.Certificate) (
return EncryptOAEPWithPublicKey(message, publicKey)
}

// EncryptPKCS1v15WithPublicKey 使用PKCS1 padding方式用公钥进行加密
func EncryptPKCS1v15WithPublicKey(message string, publicKey *rsa.PublicKey) (ciphertext string, err error) {
if publicKey == nil {
return "", fmt.Errorf("you should input *rsa.PublicKey")
}
ciphertextByte, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, []byte(message))
if err != nil {
return "", fmt.Errorf("encrypt message with public key err:%s", err.Error())
}
ciphertext = base64.StdEncoding.EncodeToString(ciphertextByte)
return ciphertext, nil
}

// EncryptPKCS1v15WithCertificate 先解析出证书中的公钥,然后使用PKCS1 padding方式用公钥进行加密
func EncryptPKCS1v15WithCertificate(message string, certificate *x509.Certificate) (ciphertext string, err error) {
if certificate == nil {
return "", fmt.Errorf("you should input *x509.Certificate")
}
publicKey, ok := certificate.PublicKey.(*rsa.PublicKey)
if !ok {
return "", fmt.Errorf("certificate is invalid")
}
return EncryptPKCS1v15WithPublicKey(message, publicKey)
}

// DecryptOAEP 使用私钥进行解密
func DecryptOAEP(ciphertext string, privateKey *rsa.PrivateKey) (message string, err error) {
if privateKey == nil {
Expand All @@ -51,3 +76,19 @@ func DecryptOAEP(ciphertext string, privateKey *rsa.PrivateKey) (message string,
}
return string(messageBytes), nil
}

// DecryptPKCS1v15 使用私钥对PKCS1 padding方式加密的字符串进行解密
func DecryptPKCS1v15(ciphertext string, privateKey *rsa.PrivateKey) (message string, err error) {
if privateKey == nil {
return "", fmt.Errorf("you should input *rsa.PrivateKey")
}
decodedCiphertext, err := base64.StdEncoding.DecodeString(ciphertext)
if err != nil {
return "", fmt.Errorf("base64 decode failed, error=%s", err.Error())
}
messageBytes, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, decodedCiphertext)
if err != nil {
return "", fmt.Errorf("decrypt ciphertext with private key err:%s", err)
}
return string(messageBytes), nil
}
71 changes: 58 additions & 13 deletions utils/rsa_crypto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
package utils

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

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -67,34 +73,73 @@ fHMq4tsbKO0dKAeydPM/nrUZBmaYQVKMVOORGLFjFKVO7JV6Kq/R86ouhjEPgJOe
2xulNBUcjicqtZlBdEh/PWCYP2SpGVDclKm8jeo175T3EVAkdKzzmfpxtMmnMlmq
cTJOU9TxuGvNASMtjj7pYIerTx+xgZDXEVBWFW9PjJ0TV06tCRsgSHItgg==
-----END CERTIFICATE-----`
testRSACryptoUtilPrivateKey *rsa.PrivateKey
testRSACryptoUtilPublicKey *rsa.PublicKey
testRSACryptoUtilCertificate *x509.Certificate
)

func TestEncryptAndDecrypt(t *testing.T) {
privatKey, err := LoadPrivateKey(testingKey(testRSACryptoUtilPrivateKeyStr))
func init() {
var err error
testRSACryptoUtilPrivateKey, err = LoadPrivateKey(testingKey(testRSACryptoUtilPrivateKeyStr))
if err != nil {
panic(fmt.Errorf("fail to load the private key:%s", err.Error()))
}
testRSACryptoUtilPublicKey, err = LoadPublicKey(testRSACryptoUtilPublicKeyStr)
if err != nil {
panic(fmt.Errorf("fail to load the public key:%s", err.Error()))
}
testRSACryptoUtilCertificate, err = LoadCertificate(testRSACryptoUtilMchCertificateStr)
if err != nil {
panic(fmt.Errorf("fail to load the certificate key:%s", err.Error()))
}
}

func TestOAEPCrypto(t *testing.T) {

const message = "hello world"
// 使用OAEP padding方式对证书加密
ciphertext, err := EncryptOAEPWithCertificate(message, testRSACryptoUtilCertificate)
require.NoError(t, err)

publicKey, err := LoadPublicKey(testRSACryptoUtilPublicKeyStr)
// 使用OAEP padding方式用公有库直接进行私钥解密,以验证加密正确
decodedCiphertext, err := base64.StdEncoding.DecodeString(ciphertext)
require.NoError(t, err)
decryptMessageBytes, err := rsa.DecryptOAEP(
sha1.New(), rand.Reader, testRSACryptoUtilPrivateKey, decodedCiphertext, nil)
require.NoError(t, err)
assert.Equal(t, message, string(decryptMessageBytes))

certificate, err := LoadCertificate(testRSACryptoUtilMchCertificateStr)
// 使用OAEP padding方式直接公钥加密
ciphertext, err = EncryptOAEPWithPublicKey(message, testRSACryptoUtilPublicKey)
require.NoError(t, err)

// 使用OAEP padding方式私钥解密
decryptMessage, err := DecryptOAEP(ciphertext, testRSACryptoUtilPrivateKey)
require.NoError(t, err)
assert.Equal(t, message, decryptMessage)
}

func TestPKCS1v15Crypto(t *testing.T) {

const message = "hello world"
// 使用证书加密
cipertext, err := EncryptOAEPWithCertificate(message, certificate)

// 使用PKCS1 padding对证书加密
ciphertext, err := EncryptPKCS1v15WithCertificate(message, testRSACryptoUtilCertificate)
require.NoError(t, err)

// 私钥解密
decryptMessage, err := DecryptOAEP(cipertext, privatKey)
// 使用PKCS1 padding对用公有库直接进行私钥解密,以验证加密正确
decodedCiphertext, err := base64.StdEncoding.DecodeString(ciphertext)
require.NoError(t, err)
assert.Equal(t, message, decryptMessage)
decryptMessageBytes, err := rsa.DecryptPKCS1v15(rand.Reader, testRSACryptoUtilPrivateKey, decodedCiphertext)
require.NoError(t, err)
assert.Equal(t, message, string(decryptMessageBytes))

// 直接公钥加密
cipertext, err = EncryptOAEPWithPublicKey(message, publicKey)
// 使用PKCS1 padding进行公钥加密
ciphertext, err = EncryptPKCS1v15WithPublicKey(message, testRSACryptoUtilPublicKey)
require.NoError(t, err)

// 私钥解密
decryptMessage, err = DecryptOAEP(cipertext, privatKey)
// 使用PKCS1 padding进行私钥解密
decryptMessage, err := DecryptPKCS1v15(ciphertext, testRSACryptoUtilPrivateKey)
require.NoError(t, err)
assert.Equal(t, message, decryptMessage)
}