From 986fc38b43c03c10817bbd41f26d29d2b5b3f9c6 Mon Sep 17 00:00:00 2001 From: Rick <1450685+LinuxSuRen@users.noreply.github.com> Date: Mon, 1 Jul 2024 22:09:46 +0800 Subject: [PATCH 1/2] Add RSA encryption function to templates --- pkg/render/template.go | 30 +++++++++++++++++++++++ pkg/render/template_test.go | 47 +++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/pkg/render/template.go b/pkg/render/template.go index 51e41ec5e..2545828fa 100644 --- a/pkg/render/template.go +++ b/pkg/render/template.go @@ -32,6 +32,10 @@ import ( "github.com/Masterminds/sprig/v3" "github.com/linuxsuren/api-testing/pkg/secret" "github.com/linuxsuren/api-testing/pkg/util" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "errors" ) var secretGetter secret.SecretGetter @@ -85,6 +89,7 @@ func FuncMap() template.FuncMap { } funcs[item.FuncName] = item.Func } + funcs["rasEncryptWithPublicKey"] = rasEncryptWithPublicKey return funcs } @@ -217,3 +222,28 @@ type AdvancedFunc struct { GoDogExper string Generator func(ctx context.Context, fields string) (err error) } + +// rasEncryptWithPublicKey encrypts the given content with the provided public key +func rasEncryptWithPublicKey(content, key string) (string, error) { + block, _ := pem.Decode([]byte(key)) + if block == nil { + return "", errors.New("failed to parse PEM block containing the public key") + } + + pub, err := x509.ParsePKIXPublicKey(block.Bytes) + if err != nil { + return "", fmt.Errorf("failed to parse DER encoded public key: %s", err) + } + + rsaPub, ok := pub.(*rsa.PublicKey) + if !ok { + return "", errors.New("key type is not RSA") + } + + encryptedData, err := rsa.EncryptPKCS1v15(rand.Reader, rsaPub, []byte(content)) + if err != nil { + return "", fmt.Errorf("failed to encrypt with RSA public key: %s", err) + } + + return base64.StdEncoding.EncodeToString(encryptedData), nil +} diff --git a/pkg/render/template_test.go b/pkg/render/template_test.go index cec3a0e91..45ede9a59 100644 --- a/pkg/render/template_test.go +++ b/pkg/render/template_test.go @@ -18,6 +18,11 @@ package render import ( "bytes" "context" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/base64" + "encoding/pem" "io" "testing" @@ -233,3 +238,45 @@ func TestSecret(t *testing.T) { assert.Equal(t, "hello", string(data)) }) } + +func TestRasEncryptWithPublicKey(t *testing.T) { + // Generate a new RSA key pair + privateKey, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + t.Fatalf("Failed to generate private key: %v", err) + } + publicKey := &privateKey.PublicKey + + // Encode the public key to PEM format + pubASN1, err := x509.MarshalPKIXPublicKey(publicKey) + if err != nil { + t.Fatalf("Failed to marshal public key: %v", err) + } + pubBytes := pem.EncodeToMemory(&pem.Block{ + Type: "RSA PUBLIC KEY", + Bytes: pubASN1, + }) + + // Encrypt a message using the public key + message := "hello world" + encryptedMessage, err := rasEncryptWithPublicKey(message, string(pubBytes)) + if err != nil { + t.Fatalf("Failed to encrypt message: %v", err) + } + + // Decrypt the message using the private key + decodedMessage, err := base64.StdEncoding.DecodeString(encryptedMessage) + if err != nil { + t.Fatalf("Failed to decode message: %v", err) + } + decryptedBytes, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, decodedMessage) + if err != nil { + t.Fatalf("Failed to decrypt message: %v", err) + } + + // Verify the decrypted message + decryptedMessage := string(decryptedBytes) + if decryptedMessage != message { + t.Fatalf("Decrypted message does not match original. Got: %s, want: %s", decryptedMessage, message) + } +} From 14443d2aaaae5c7a5d0da6221d454751047c1fce Mon Sep 17 00:00:00 2001 From: rick Date: Wed, 3 Jul 2024 14:13:39 +0000 Subject: [PATCH 2/2] fix the compile errors --- pkg/render/template.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/pkg/render/template.go b/pkg/render/template.go index 2545828fa..205667226 100644 --- a/pkg/render/template.go +++ b/pkg/render/template.go @@ -10,7 +10,7 @@ You may obtain a copy of the License at Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and +See the License for the specific language 24 permissions and limitations under the License. */ package render @@ -19,6 +19,7 @@ import ( "bytes" "context" "crypto/md5" + "crypto/rand" "crypto/sha256" "encoding/base64" "encoding/hex" @@ -26,16 +27,17 @@ import ( "fmt" "html/template" "io" - "math/rand" + mathrand "math/rand" "strings" - "github.com/Masterminds/sprig/v3" - "github.com/linuxsuren/api-testing/pkg/secret" - "github.com/linuxsuren/api-testing/pkg/util" "crypto/rsa" "crypto/x509" "encoding/pem" "errors" + + "github.com/Masterminds/sprig/v3" + "github.com/linuxsuren/api-testing/pkg/secret" + "github.com/linuxsuren/api-testing/pkg/util" ) var secretGetter secret.SecretGetter @@ -163,7 +165,7 @@ var advancedFuncs = []AdvancedFunc{{ }, { FuncName: "randEnum", Func: func(items ...string) string { - return items[rand.Intn(len(items))] + return items[mathrand.Intn(len(items))] }, }, { FuncName: "randEmail",