Enchantrix/pkg/crypt/crypt.go
google-labs-jules[bot] d5ae9a44e1 feat: Implement Good, Bad, and Ugly testing strategy
This commit refactors the test suites for the `crypt` and `trix` packages to follow the Good, Bad, and Ugly testing strategy.

- `_Good` tests cover the ideal "happy path" scenarios.
- `_Bad` tests cover expected failure scenarios with well-formed but invalid inputs.
- `_Ugly` tests cover malicious or malformed inputs designed to cause crashes or panics.

This new testing structure makes the test suite more organized, comprehensive, and robust.

Additionally, this commit includes a bug fix for the `Luhn` function, which now correctly handles empty and single-digit strings.
2025-10-31 02:03:33 +00:00

160 lines
3.7 KiB
Go

package crypt
import (
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"encoding/binary"
"encoding/hex"
"strconv"
"strings"
"github.com/Snider/Enchantrix/pkg/crypt/std/lthn"
)
// Service is the main struct for the crypt service.
type Service struct{}
// NewService creates a new crypt service.
func NewService() *Service {
return &Service{}
}
// HashType defines the supported hashing algorithms.
type HashType string
const (
LTHN HashType = "lthn"
SHA512 HashType = "sha512"
SHA256 HashType = "sha256"
SHA1 HashType = "sha1"
MD5 HashType = "md5"
)
// --- Hashing ---
// Hash computes a hash of the payload using the specified algorithm.
func (s *Service) Hash(lib HashType, payload string) string {
switch lib {
case LTHN:
return lthn.Hash(payload)
case SHA512:
hash := sha512.Sum512([]byte(payload))
return hex.EncodeToString(hash[:])
case SHA1:
hash := sha1.Sum([]byte(payload))
return hex.EncodeToString(hash[:])
case MD5:
hash := md5.Sum([]byte(payload))
return hex.EncodeToString(hash[:])
case SHA256:
fallthrough
default:
hash := sha256.Sum256([]byte(payload))
return hex.EncodeToString(hash[:])
}
}
// --- Checksums ---
// Luhn validates a number using the Luhn algorithm.
func (s *Service) Luhn(payload string) bool {
payload = strings.ReplaceAll(payload, " ", "")
if len(payload) <= 1 {
return false
}
sum := 0
isSecond := len(payload)%2 == 0
for _, r := range payload {
digit, err := strconv.Atoi(string(r))
if err != nil {
return false // Contains non-digit
}
if isSecond {
digit = digit * 2
if digit > 9 {
digit = digit - 9
}
}
sum += digit
isSecond = !isSecond
}
return sum%10 == 0
}
// Fletcher16 computes the Fletcher-16 checksum.
func (s *Service) Fletcher16(payload string) uint16 {
data := []byte(payload)
var sum1, sum2 uint16
for _, b := range data {
sum1 = (sum1 + uint16(b)) % 255
sum2 = (sum2 + sum1) % 255
}
return (sum2 << 8) | sum1
}
// Fletcher32 computes the Fletcher-32 checksum.
func (s *Service) Fletcher32(payload string) uint32 {
data := []byte(payload)
if len(data)%2 != 0 {
data = append(data, 0)
}
var sum1, sum2 uint32
for i := 0; i < len(data); i += 2 {
val := binary.LittleEndian.Uint16(data[i : i+2])
sum1 = (sum1 + uint32(val)) % 65535
sum2 = (sum2 + sum1) % 65535
}
return (sum2 << 16) | sum1
}
// Fletcher64 computes the Fletcher-64 checksum.
func (s *Service) Fletcher64(payload string) uint64 {
data := []byte(payload)
if len(data)%4 != 0 {
padding := 4 - (len(data) % 4)
data = append(data, make([]byte, padding)...)
}
var sum1, sum2 uint64
for i := 0; i < len(data); i += 4 {
val := binary.LittleEndian.Uint32(data[i : i+4])
sum1 = (sum1 + uint64(val)) % 4294967295
sum2 = (sum2 + sum1) % 4294967295
}
return (sum2 << 32) | sum1
}
// --- PGP ---
// @snider
// The PGP functions are commented out pending resolution of the dependency issues.
//
// import "io"
// import "github.com/Snider/Enchantrix/openpgp"
//
// // EncryptPGP encrypts data for a recipient, optionally signing it.
// func (s *Service) EncryptPGP(writer io.Writer, recipientPath, data string, signerPath, signerPassphrase *string) error {
// var buf bytes.Buffer
// err := openpgp.EncryptPGP(&buf, recipientPath, data, signerPath, signerPassphrase)
// if err != nil {
// return err
// }
//
// // Copy the encrypted data to the original writer.
// if _, err := writer.Write(buf.Bytes()); err != nil {
// return err
// }
//
// return nil
// }
//
// // DecryptPGP decrypts a PGP message, optionally verifying the signature.
// func (s *Service) DecryptPGP(recipientPath, message, passphrase string, signerPath *string) (string, error) {
// return openpgp.DecryptPGP(recipientPath, message, passphrase, signerPath)
// }