go-crypt/crypt/rsa/rsa.go
Claude 7407b89b8d
refactor(ax): AX RFC-025 compliance sweep pass 1
Remove banned imports (fmt, strings, os, errors, path/filepath) across all
production and test files, replace with core.* primitives, coreio.ReadStream,
and coreerr.E. Upgrade dappco.re/go/core v0.5.0 → v0.7.0 for core.PathBase
and core.Is. Fix isRepoScoped to exclude pr.* capabilities (enforcement is at
the forge layer, not the policy engine). Add Good/Bad/Ugly test coverage to
all packages missing the mandatory three-category naming convention.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-31 08:48:56 +01:00

108 lines
2.8 KiB
Go

package rsa
import (
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/pem"
core "dappco.re/go/core"
coreerr "dappco.re/go/core/log"
)
// Service provides RSA functionality.
type Service struct{}
// NewService creates a new Service instance for RSA operations.
//
// svc := rsa.NewService()
// pub, priv, err := svc.GenerateKeyPair(4096)
func NewService() *Service {
return &Service{}
}
// GenerateKeyPair creates a new RSA key pair.
//
// pub, priv, err := svc.GenerateKeyPair(4096)
func (s *Service) GenerateKeyPair(bits int) (publicKey, privateKey []byte, err error) {
const op = "rsa.GenerateKeyPair"
if bits < 2048 {
return nil, nil, coreerr.E(op, core.Sprintf("key size too small: %d (minimum 2048)", bits), nil)
}
privKey, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
return nil, nil, coreerr.E(op, "failed to generate private key", err)
}
privKeyBytes := x509.MarshalPKCS1PrivateKey(privKey)
privKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: privKeyBytes,
})
pubKeyBytes, err := x509.MarshalPKIXPublicKey(&privKey.PublicKey)
if err != nil {
return nil, nil, coreerr.E(op, "failed to marshal public key", err)
}
pubKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "PUBLIC KEY",
Bytes: pubKeyBytes,
})
return pubKeyPEM, privKeyPEM, nil
}
// Encrypt encrypts data with a public key using RSA-OAEP.
//
// ciphertext, err := svc.Encrypt(pubPEM, []byte("secret"), nil)
func (s *Service) Encrypt(publicKey, data, label []byte) ([]byte, error) {
const op = "rsa.Encrypt"
block, _ := pem.Decode(publicKey)
if block == nil {
return nil, coreerr.E(op, "failed to decode public key", nil)
}
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, coreerr.E(op, "failed to parse public key", err)
}
rsaPub, ok := pub.(*rsa.PublicKey)
if !ok {
return nil, coreerr.E(op, "not an RSA public key", nil)
}
ciphertext, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, rsaPub, data, label)
if err != nil {
return nil, coreerr.E(op, "failed to encrypt data", err)
}
return ciphertext, nil
}
// Decrypt decrypts data with a private key using RSA-OAEP.
//
// plaintext, err := svc.Decrypt(privPEM, ciphertext, nil)
func (s *Service) Decrypt(privateKey, ciphertext, label []byte) ([]byte, error) {
const op = "rsa.Decrypt"
block, _ := pem.Decode(privateKey)
if block == nil {
return nil, coreerr.E(op, "failed to decode private key", nil)
}
priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, coreerr.E(op, "failed to parse private key", err)
}
plaintext, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, priv, ciphertext, label)
if err != nil {
return nil, coreerr.E(op, "failed to decrypt data", err)
}
return plaintext, nil
}