initial go implementation

This commit is contained in:
2025-11-23 12:12:20 +08:00
commit f40ace4058
12 changed files with 368 additions and 0 deletions

View File

@@ -0,0 +1,52 @@
package crypto
import (
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"errors"
"fmt"
)
func Decrypt(ciphertextB64, key, iv string) (string, error) {
ciphertext, err := base64.StdEncoding.DecodeString(ciphertextB64)
if err != nil {
return "", fmt.Errorf("base64 decode failed: %v", err)
}
block, err := aes.NewCipher([]byte(key))
if err != nil {
return "", fmt.Errorf("AES init failed: %v", err)
}
if len(iv) != aes.BlockSize {
return "", fmt.Errorf("IV must be %d bytes", aes.BlockSize)
}
mode := cipher.NewCBCDecrypter(block, []byte(iv))
plaintext := make([]byte, len(ciphertext))
mode.CryptBlocks(plaintext, ciphertext)
unpadded, err := pkcs7Unpad(plaintext)
if err != nil {
return "", fmt.Errorf("PKCS7 unpadding failed: %v", err)
}
return string(unpadded), nil
}
func pkcs7Unpad(data []byte) ([]byte, error) {
if len(data) == 0 {
return nil, errors.New("empty data")
}
padSize := int(data[len(data)-1])
if padSize > len(data) || padSize > aes.BlockSize {
return nil, fmt.Errorf("invalid padding size: %d", padSize)
}
for i := range padSize {
if data[len(data)-1-i] != byte(padSize) {
return nil, errors.New("invalid padding content")
}
}
return data[:len(data)-padSize], nil
}

View File

@@ -0,0 +1,41 @@
package crypto
import (
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"fmt"
)
func Encrypt(plaintext, key, iv string) (string, error) {
padded := pkcs7Pad([]byte(plaintext))
block, err := aes.NewCipher([]byte(key))
if err != nil {
return "", fmt.Errorf("AES init failed: %v", err)
}
if len(iv) != aes.BlockSize {
return "", fmt.Errorf("IV must be %d bytes", aes.BlockSize)
}
mode := cipher.NewCBCEncrypter(block, []byte(iv))
ciphertext := make([]byte, len(padded))
mode.CryptBlocks(ciphertext, padded)
ciphertextB64 := base64.StdEncoding.EncodeToString(ciphertext)
return ciphertextB64, nil
}
func pkcs7Pad(buf []byte) []byte {
bufLen := len(buf)
padLen := aes.BlockSize - bufLen%aes.BlockSize
padded := make([]byte, bufLen+padLen)
copy(padded, buf)
for i := range padLen {
padded[bufLen+i] = byte(padLen)
}
return padded
}

View File

@@ -0,0 +1,31 @@
package format
import (
"bytes"
"encoding/json"
)
func FormatJSON(input string) string {
var data any
if err := json.Unmarshal([]byte(input), &data); err != nil {
var out bytes.Buffer
if err := json.Indent(&out, []byte(input), "", " "); err == nil {
return out.String()
}
return input
}
var out bytes.Buffer
encoder := json.NewEncoder(&out)
encoder.SetEscapeHTML(false)
encoder.SetIndent("", " ")
if err := encoder.Encode(data); err != nil {
return input
}
formatted := out.String()
if len(formatted) > 0 && formatted[len(formatted)-1] == '\n' {
formatted = formatted[:len(formatted)-1]
}
return formatted
}