remove public key
This commit is contained in:
parent
06fbeb64a0
commit
f2881bfcc9
@ -9,7 +9,6 @@ type Dukcapil struct {
|
|||||||
Methode string `mapstructure:"methode"`
|
Methode string `mapstructure:"methode"`
|
||||||
UserID string `mapstructure:"user_id"`
|
UserID string `mapstructure:"user_id"`
|
||||||
Password string `mapstructure:"password"`
|
Password string `mapstructure:"password"`
|
||||||
PublicKeyPath string `mapstructure:"public_key_path"`
|
|
||||||
DefaultIP string `mapstructure:"default_ip"`
|
DefaultIP string `mapstructure:"default_ip"`
|
||||||
TimeoutSecond int `mapstructure:"timeout_second"`
|
TimeoutSecond int `mapstructure:"timeout_second"`
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,6 +33,5 @@ dukcapil:
|
|||||||
methode: "CALL_FN"
|
methode: "CALL_FN"
|
||||||
user_id: "281020241202039900305241000011252"
|
user_id: "281020241202039900305241000011252"
|
||||||
password: "Fjskdhv35$%"
|
password: "Fjskdhv35$%"
|
||||||
public_key_path: "infra/dukcapil_public.pem"
|
|
||||||
default_ip: "10.160.86.53"
|
default_ip: "10.160.86.53"
|
||||||
timeout_second: 30
|
timeout_second: 30
|
||||||
|
|||||||
@ -3,19 +3,12 @@ package client
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
|
||||||
"crypto/rsa"
|
|
||||||
"crypto/x509"
|
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"encoding/pem"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go-backend-template/config"
|
"go-backend-template/config"
|
||||||
@ -23,14 +16,10 @@ import (
|
|||||||
"go-backend-template/internal/logger"
|
"go-backend-template/internal/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DukcapilClient performs HTTPS calls to the Dukcapil 1:N face recognition
|
// DukcapilClient performs HTTPS calls to the Dukcapil 1:N face recognition endpoint (CALL_FN).
|
||||||
// endpoint (CALL_FN). It loads and caches the configured RSA public key used
|
|
||||||
// to encrypt sensitive credentials.
|
|
||||||
type DukcapilClient struct {
|
type DukcapilClient struct {
|
||||||
cfg config.Dukcapil
|
cfg config.Dukcapil
|
||||||
http *http.Client
|
http *http.Client
|
||||||
pubKey *rsa.PublicKey
|
|
||||||
keyMu sync.Mutex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDukcapilClient(cfg config.Dukcapil) *DukcapilClient {
|
func NewDukcapilClient(cfg config.Dukcapil) *DukcapilClient {
|
||||||
@ -42,28 +31,12 @@ func NewDukcapilClient(cfg config.Dukcapil) *DukcapilClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FaceMatch performs a 1:N face match call. user_id/password are encrypted
|
// FaceMatch performs a 1:N face match call. The image must already be base64 encoded.
|
||||||
// with the configured public key (RSA PKCS1v15 -> base64). The image must
|
|
||||||
// already be base64 encoded.
|
|
||||||
func (c *DukcapilClient) FaceMatch(ctx context.Context, req *contract.FaceMatchRequest) (*contract.DukcapilFaceResponse, error) {
|
func (c *DukcapilClient) FaceMatch(ctx context.Context, req *contract.FaceMatchRequest) (*contract.DukcapilFaceResponse, error) {
|
||||||
if c.cfg.BaseURL == "" || c.cfg.CustomerID == "" || c.cfg.Methode == "" {
|
if c.cfg.BaseURL == "" || c.cfg.CustomerID == "" || c.cfg.Methode == "" {
|
||||||
return nil, errors.New("dukcapil: incomplete configuration")
|
return nil, errors.New("dukcapil: incomplete configuration")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub, err := c.loadPublicKey()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("dukcapil: load public key: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
encUserID, err := encryptAndEncode(pub, []byte(c.cfg.UserID))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("dukcapil: encrypt user_id: %w", err)
|
|
||||||
}
|
|
||||||
encPassword, err := encryptAndEncode(pub, []byte(c.cfg.Password))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("dukcapil: encrypt password: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ip := req.IP
|
ip := req.IP
|
||||||
if strings.TrimSpace(ip) == "" {
|
if strings.TrimSpace(ip) == "" {
|
||||||
ip = c.cfg.DefaultIP
|
ip = c.cfg.DefaultIP
|
||||||
@ -74,8 +47,8 @@ func (c *DukcapilClient) FaceMatch(ctx context.Context, req *contract.FaceMatchR
|
|||||||
TransactionSource: req.TransactionSource,
|
TransactionSource: req.TransactionSource,
|
||||||
Threshold: req.Threshold,
|
Threshold: req.Threshold,
|
||||||
Image: req.Image,
|
Image: req.Image,
|
||||||
UserID: encUserID,
|
UserID: c.cfg.UserID,
|
||||||
Password: encPassword,
|
Password: c.cfg.Password,
|
||||||
IP: ip,
|
IP: ip,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,47 +95,5 @@ func (c *DukcapilClient) FaceMatch(ctx context.Context, req *contract.FaceMatchR
|
|||||||
return &out, nil
|
return &out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *DukcapilClient) loadPublicKey() (*rsa.PublicKey, error) {
|
|
||||||
c.keyMu.Lock()
|
|
||||||
defer c.keyMu.Unlock()
|
|
||||||
if c.pubKey != nil {
|
|
||||||
return c.pubKey, nil
|
|
||||||
}
|
|
||||||
if c.cfg.PublicKeyPath == "" {
|
|
||||||
return nil, errors.New("public key path not configured")
|
|
||||||
}
|
|
||||||
raw, err := os.ReadFile(c.cfg.PublicKeyPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
block, _ := pem.Decode(raw)
|
|
||||||
if block == nil {
|
|
||||||
return nil, errors.New("invalid PEM file")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try PKIX first (BEGIN PUBLIC KEY) then PKCS1 (BEGIN RSA PUBLIC KEY).
|
|
||||||
if pub, err := x509.ParsePKIXPublicKey(block.Bytes); err == nil {
|
|
||||||
rsaPub, ok := pub.(*rsa.PublicKey)
|
|
||||||
if !ok {
|
|
||||||
return nil, errors.New("public key is not RSA")
|
|
||||||
}
|
|
||||||
c.pubKey = rsaPub
|
|
||||||
return rsaPub, nil
|
|
||||||
}
|
|
||||||
rsaPub, err := x509.ParsePKCS1PublicKey(block.Bytes)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("parse rsa public key: %w", err)
|
|
||||||
}
|
|
||||||
c.pubKey = rsaPub
|
|
||||||
return rsaPub, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// encryptAndEncode mimics PHP openssl_public_encrypt (default padding =
|
|
||||||
// PKCS1v15) and base64-encodes the ciphertext.
|
|
||||||
func encryptAndEncode(pub *rsa.PublicKey, plaintext []byte) (string, error) {
|
|
||||||
cipherBytes, err := rsa.EncryptPKCS1v15(rand.Reader, pub, plaintext)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return base64.StdEncoding.EncodeToString(cipherBytes), nil
|
|
||||||
}
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user