cli/pkg/crypt/rsa/rsa.go
Claude 95261a92ff feat: add crypto, session, sigil, and node packages
Add new packages for cryptographic operations, session management,
and I/O handling:
- pkg/crypt/chachapoly: ChaCha20-Poly1305 AEAD encryption
- pkg/crypt/lthn: Lethean-specific key derivation and encryption
- pkg/crypt/rsa: RSA key generation, encryption, and signing
- pkg/io/node: CryptoNote node I/O and protocol handling
- pkg/io/sigil: Cryptographic sigil generation and verification
- pkg/session: Session parsing, HTML rendering, search, and video
- internal/cmd/forge: Forgejo auth status command
- internal/cmd/session: Session management CLI command

Also gitignore build artifacts (bugseti binary, i18n-validate).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 20:52:28 +00:00

91 lines
2.3 KiB
Go

package rsa
import (
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/pem"
"fmt"
)
// Service provides RSA functionality.
type Service struct{}
// NewService creates and returns a new Service instance for performing RSA-related operations.
func NewService() *Service {
return &Service{}
}
// GenerateKeyPair creates a new RSA key pair.
func (s *Service) GenerateKeyPair(bits int) (publicKey, privateKey []byte, err error) {
if bits < 2048 {
return nil, nil, fmt.Errorf("rsa: key size too small: %d (minimum 2048)", bits)
}
privKey, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
return nil, nil, fmt.Errorf("failed to generate private key: %w", 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, fmt.Errorf("failed to marshal public key: %w", err)
}
pubKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "PUBLIC KEY",
Bytes: pubKeyBytes,
})
return pubKeyPEM, privKeyPEM, nil
}
// Encrypt encrypts data with a public key.
func (s *Service) Encrypt(publicKey, data, label []byte) ([]byte, error) {
block, _ := pem.Decode(publicKey)
if block == nil {
return nil, fmt.Errorf("failed to decode public key")
}
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse public key: %w", err)
}
rsaPub, ok := pub.(*rsa.PublicKey)
if !ok {
return nil, fmt.Errorf("not an RSA public key")
}
ciphertext, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, rsaPub, data, label)
if err != nil {
return nil, fmt.Errorf("failed to encrypt data: %w", err)
}
return ciphertext, nil
}
// Decrypt decrypts data with a private key.
func (s *Service) Decrypt(privateKey, ciphertext, label []byte) ([]byte, error) {
block, _ := pem.Decode(privateKey)
if block == nil {
return nil, fmt.Errorf("failed to decode private key")
}
priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse private key: %w", err)
}
plaintext, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, priv, ciphertext, label)
if err != nil {
return nil, fmt.Errorf("failed to decrypt data: %w", err)
}
return plaintext, nil
}