dal-license-server/internal/service/crypto_service.go
djuka dc0114e4b7 Inicijalni commit: kompletna implementacija + dokumentacija + testovi
- Kompletna Go implementacija licencnog servera (19 Go fajlova)
- Klijentski API: activate, deactivate, validate
- Admin API: CRUD licence, stats, audit log
- Admin dashboard: htmx + Go templates
- RSA-2048 potpisivanje licencnih podataka
- Rate limiting i API key autentifikacija
- MySQL migracije i seed podaci (ESIR, ARV, LIGHT_TICKET)
- Unit testovi: keygen, crypto, model, middleware (24 testa)
- Dokumentacija: SPEC.md, ARCHITECTURE.md, SETUP.md, API.md, TESTING.md, README.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 07:42:25 +00:00

64 lines
1.4 KiB
Go

package service
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"fmt"
"os"
)
type CryptoService struct {
privateKey *rsa.PrivateKey
}
func NewCryptoService(keyPath string) (*CryptoService, error) {
data, err := os.ReadFile(keyPath)
if err != nil {
return nil, fmt.Errorf("read private key: %w", err)
}
block, _ := pem.Decode(data)
if block == nil {
return nil, fmt.Errorf("failed to decode PEM block")
}
key, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
// Try PKCS8
pkcs8Key, err2 := x509.ParsePKCS8PrivateKey(block.Bytes)
if err2 != nil {
return nil, fmt.Errorf("parse private key: %w", err)
}
var ok bool
key, ok = pkcs8Key.(*rsa.PrivateKey)
if !ok {
return nil, fmt.Errorf("not an RSA private key")
}
}
return &CryptoService{privateKey: key}, nil
}
func (s *CryptoService) Sign(data []byte) (string, error) {
hash := sha256.Sum256(data)
sig, err := rsa.SignPKCS1v15(rand.Reader, s.privateKey, crypto.SHA256, hash[:])
if err != nil {
return "", fmt.Errorf("sign: %w", err)
}
return "RSA-SHA256:" + base64.StdEncoding.EncodeToString(sig), nil
}
func (s *CryptoService) PublicKeyPEM() (string, error) {
pubBytes, err := x509.MarshalPKIXPublicKey(&s.privateKey.PublicKey)
if err != nil {
return "", err
}
block := &pem.Block{Type: "PUBLIC KEY", Bytes: pubBytes}
return string(pem.EncodeToMemory(block)), nil
}