Enchantrix/pkg/crypt/crypt.go

163 lines
3.6 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"
"github.com/Snider/Enchantrix/pkg/crypt/std/rsa"
)
// Service is the main struct for the crypt service.
type Service struct {
rsa *rsa.Service
}
// NewService creates a new crypt Service and initialises its embedded RSA service.
func NewService() *Service {
return &Service{
rsa: rsa.NewService(),
}
}
// 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
}
// --- RSA ---
// ensureRSA initializes the RSA service if it is not already.
func (s *Service) ensureRSA() {
if s.rsa == nil {
s.rsa = rsa.NewService()
}
}
// GenerateRSAKeyPair creates a new RSA key pair.
func (s *Service) GenerateRSAKeyPair(bits int) (publicKey, privateKey []byte, err error) {
s.ensureRSA()
return s.rsa.GenerateKeyPair(bits)
}
// EncryptRSA encrypts data with a public key.
func (s *Service) EncryptRSA(publicKey, data, label []byte) ([]byte, error) {
s.ensureRSA()
return s.rsa.Encrypt(publicKey, data, label)
}
// DecryptRSA decrypts data with a private key.
func (s *Service) DecryptRSA(privateKey, ciphertext, label []byte) ([]byte, error) {
s.ensureRSA()
return s.rsa.Decrypt(privateKey, ciphertext, label)
}