From c8704062446d734c8a9edfb0253497cd46bf1f7d Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sat, 4 Jan 2025 18:17:13 -0600 Subject: [PATCH] move cryptography to its own folder/files --- pkg/cryptography/aes.go | 63 ++++++++++++++++++++++++++++++++++ pkg/cryptography/constants.go | 22 ++++++++++++ pkg/cryptography/curve25519.go | 25 ++++++++++++++ pkg/cryptography/ed25519.go | 18 ++++++++++ pkg/cryptography/hkdf.go | 17 +++++++++ pkg/cryptography/hmac.go | 26 ++++++++++++++ 6 files changed, 171 insertions(+) create mode 100644 pkg/cryptography/aes.go create mode 100644 pkg/cryptography/constants.go create mode 100644 pkg/cryptography/curve25519.go create mode 100644 pkg/cryptography/ed25519.go create mode 100644 pkg/cryptography/hkdf.go create mode 100644 pkg/cryptography/hmac.go diff --git a/pkg/cryptography/aes.go b/pkg/cryptography/aes.go new file mode 100644 index 0000000..4effcd3 --- /dev/null +++ b/pkg/cryptography/aes.go @@ -0,0 +1,63 @@ +package cryptography + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "errors" + "io" +) + +func EncryptAESCBC(key, plaintext []byte) ([]byte, error) { + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + + // Generate IV + iv := make([]byte, aes.BlockSize) + if _, err := io.ReadFull(rand.Reader, iv); err != nil { + return nil, err + } + + // Add PKCS7 padding + padding := aes.BlockSize - len(plaintext)%aes.BlockSize + padtext := make([]byte, len(plaintext)+padding) + copy(padtext, plaintext) + for i := len(plaintext); i < len(padtext); i++ { + padtext[i] = byte(padding) + } + + // Encrypt + mode := cipher.NewCBCEncrypter(block, iv) + ciphertext := make([]byte, len(padtext)) + mode.CryptBlocks(ciphertext, padtext) + + return append(iv, ciphertext...), nil +} + +func DecryptAESCBC(key, ciphertext []byte) ([]byte, error) { + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + + if len(ciphertext) < aes.BlockSize { + return nil, errors.New("ciphertext too short") + } + + iv := ciphertext[:aes.BlockSize] + ciphertext = ciphertext[aes.BlockSize:] + + if len(ciphertext)%aes.BlockSize != 0 { + return nil, errors.New("ciphertext is not a multiple of block size") + } + + mode := cipher.NewCBCDecrypter(block, iv) + plaintext := make([]byte, len(ciphertext)) + mode.CryptBlocks(plaintext, ciphertext) + + // Remove PKCS7 padding + padding := int(plaintext[len(plaintext)-1]) + return plaintext[:len(plaintext)-padding], nil +} diff --git a/pkg/cryptography/constants.go b/pkg/cryptography/constants.go new file mode 100644 index 0000000..c3c3c29 --- /dev/null +++ b/pkg/cryptography/constants.go @@ -0,0 +1,22 @@ +package cryptography + +import ( + "crypto/sha256" + + "golang.org/x/crypto/curve25519" +) + +const ( + SHA256Size = 32 +) + +// GetBasepoint returns the standard Curve25519 basepoint +func GetBasepoint() []byte { + return curve25519.Basepoint +} + +func Hash(data []byte) []byte { + h := sha256.New() + h.Write(data) + return h.Sum(nil) +} diff --git a/pkg/cryptography/curve25519.go b/pkg/cryptography/curve25519.go new file mode 100644 index 0000000..8671444 --- /dev/null +++ b/pkg/cryptography/curve25519.go @@ -0,0 +1,25 @@ +package cryptography + +import ( + "crypto/rand" + + "golang.org/x/crypto/curve25519" +) + +func GenerateKeyPair() (privateKey, publicKey []byte, err error) { + privateKey = make([]byte, curve25519.ScalarSize) + if _, err := rand.Read(privateKey); err != nil { + return nil, nil, err + } + + publicKey, err = curve25519.X25519(privateKey, curve25519.Basepoint) + if err != nil { + return nil, nil, err + } + + return privateKey, publicKey, nil +} + +func DeriveSharedSecret(privateKey, peerPublicKey []byte) ([]byte, error) { + return curve25519.X25519(privateKey, peerPublicKey) +} diff --git a/pkg/cryptography/ed25519.go b/pkg/cryptography/ed25519.go new file mode 100644 index 0000000..14fc7e5 --- /dev/null +++ b/pkg/cryptography/ed25519.go @@ -0,0 +1,18 @@ +package cryptography + +import ( + "crypto/ed25519" + "crypto/rand" +) + +func GenerateSigningKeyPair() (ed25519.PublicKey, ed25519.PrivateKey, error) { + return ed25519.GenerateKey(rand.Reader) +} + +func Sign(privateKey ed25519.PrivateKey, message []byte) []byte { + return ed25519.Sign(privateKey, message) +} + +func Verify(publicKey ed25519.PublicKey, message, signature []byte) bool { + return ed25519.Verify(publicKey, message, signature) +} diff --git a/pkg/cryptography/hkdf.go b/pkg/cryptography/hkdf.go new file mode 100644 index 0000000..e53582a --- /dev/null +++ b/pkg/cryptography/hkdf.go @@ -0,0 +1,17 @@ +package cryptography + +import ( + "crypto/sha256" + "io" + + "golang.org/x/crypto/hkdf" +) + +func DeriveKey(secret, salt, info []byte, length int) ([]byte, error) { + hkdfReader := hkdf.New(sha256.New, secret, salt, info) + key := make([]byte, length) + if _, err := io.ReadFull(hkdfReader, key); err != nil { + return nil, err + } + return key, nil +} diff --git a/pkg/cryptography/hmac.go b/pkg/cryptography/hmac.go new file mode 100644 index 0000000..0b949b0 --- /dev/null +++ b/pkg/cryptography/hmac.go @@ -0,0 +1,26 @@ +package cryptography + +import ( + "crypto/hmac" + "crypto/rand" + "crypto/sha256" +) + +func GenerateHMACKey(size int) ([]byte, error) { + key := make([]byte, size) + if _, err := rand.Read(key); err != nil { + return nil, err + } + return key, nil +} + +func ComputeHMAC(key, message []byte) []byte { + h := hmac.New(sha256.New, key) + h.Write(message) + return h.Sum(nil) +} + +func ValidateHMAC(key, message, messageHMAC []byte) bool { + expectedHMAC := ComputeHMAC(key, message) + return hmac.Equal(messageHMAC, expectedHMAC) +}