From 25f438237cf201e6c7b89d231801dcff75ea5461 Mon Sep 17 00:00:00 2001 From: Aditya Siregar Date: Thu, 7 May 2026 09:45:48 +0700 Subject: [PATCH] add included --- infra/990030524100001.pem | 9 ++++++ internal/client/dukcapil_client.go | 45 +++++++++++++++++++++--------- internal/util/rsa_util.go | 30 ++++++++++++++++++++ 3 files changed, 71 insertions(+), 13 deletions(-) create mode 100644 infra/990030524100001.pem create mode 100644 internal/util/rsa_util.go diff --git a/infra/990030524100001.pem b/infra/990030524100001.pem new file mode 100644 index 0000000..004ce21 --- /dev/null +++ b/infra/990030524100001.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2W7yEB6g1kHTHyMToWm4 +Fe5YshgLThXl/U2cIGTwbsBqqiRbuhC/OXJo1jVYabzYTzpmc2mcG6DUz38o/WND +M48Ie3g8c02r5aYSGFYbTTmYy7ES2QgjATGY8au8mxoaj7OlzLIzqa1WhSGL3mRu +KMH+vFSfoioNAwHHmOKzzAG58ObZJ3rNcAU1NCGiLPN4QtQBiu7RZrtAfIQb+bDV +byKFPSJnSgeF+7Oa7VStTCURsAf3PgmsaJ0SmGdss8nSDGDeZudIicIaHBEGIixx +bPo5lngt98Sfp8PRd4WAWyuTM7JNBNF8OgaVeZ+5T+N8yv8pwgrtkxIZq5a9/wlO +FwIDAQAB +-----END PUBLIC KEY----- diff --git a/internal/client/dukcapil_client.go b/internal/client/dukcapil_client.go index 21c57f1..e9edcb5 100644 --- a/internal/client/dukcapil_client.go +++ b/internal/client/dukcapil_client.go @@ -8,12 +8,14 @@ import ( "fmt" "io" "net/http" + "os" "strings" "time" "go-backend-template/config" "go-backend-template/internal/contract" "go-backend-template/internal/logger" + "go-backend-template/internal/util" ) // DukcapilClient performs HTTPS calls to the Dukcapil 1:N face recognition endpoint (CALL_FN). @@ -37,20 +39,37 @@ func (c *DukcapilClient) FaceMatch(ctx context.Context, req *contract.FaceMatchR return nil, errors.New("dukcapil: incomplete configuration") } - ip := req.IP - if strings.TrimSpace(ip) == "" { - ip = c.cfg.DefaultIP - } - body := contract.DukcapilFaceRequest{ - TransactionID: req.TransactionID, - TransactionSource: req.TransactionSource, - Threshold: req.Threshold, - Image: req.Image, - UserID: c.cfg.UserID, - Password: c.cfg.Password, - IP: ip, - } + ip := req.IP + if strings.TrimSpace(ip) == "" { + ip = c.cfg.DefaultIP + } + + // Load PEM public key from file + pemBytes, err := os.ReadFile("infra/990030524100001.pem") + if err != nil { + return nil, fmt.Errorf("dukcapil: failed to read PEM file: %w", err) + } + + // Encrypt UserID and Password + encryptedUserID, err := util.EncryptWithPublicKey(c.cfg.UserID, pemBytes) + if err != nil { + return nil, fmt.Errorf("dukcapil: encrypt user_id: %w", err) + } + encryptedPassword, err := util.EncryptWithPublicKey(c.cfg.Password, pemBytes) + if err != nil { + return nil, fmt.Errorf("dukcapil: encrypt password: %w", err) + } + + body := contract.DukcapilFaceRequest{ + TransactionID: req.TransactionID, + TransactionSource: req.TransactionSource, + Threshold: req.Threshold, + Image: req.Image, + UserID: encryptedUserID, + Password: encryptedPassword, + IP: ip, + } payload, err := json.Marshal(body) if err != nil { diff --git a/internal/util/rsa_util.go b/internal/util/rsa_util.go new file mode 100644 index 0000000..9d94590 --- /dev/null +++ b/internal/util/rsa_util.go @@ -0,0 +1,30 @@ +package util + +import ( + "crypto/rsa" + "crypto/x509" + "encoding/base64" + "encoding/pem" + "errors" +) + +// EncryptWithPublicKey encrypts data with a PEM public key and returns base64 encoded string +func EncryptWithPublicKey(data string, pemBytes []byte) (string, error) { + block, _ := pem.Decode(pemBytes) + 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 "", err + } + pubKey, ok := pub.(*rsa.PublicKey) + if !ok { + return "", errors.New("not RSA public key") + } + ciphertext, err := rsa.EncryptPKCS1v15(nil, pubKey, []byte(data)) + if err != nil { + return "", err + } + return base64.StdEncoding.EncodeToString(ciphertext), nil +}