161 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			161 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
|  | package westdex | ||
|  | 
 | ||
|  | import ( | ||
|  | 	"bytes" | ||
|  | 	"crypto/aes" | ||
|  | 	"crypto/cipher" | ||
|  | 	"crypto/md5" | ||
|  | 	"crypto/sha1" | ||
|  | 	"encoding/base64" | ||
|  | 	"encoding/hex" | ||
|  | ) | ||
|  | 
 | ||
|  | const ( | ||
|  | 	KEY_SIZE = 16 // AES-128, 16 bytes | ||
|  | ) | ||
|  | 
 | ||
|  | // Encrypt encrypts the given data using AES encryption in ECB mode with PKCS5 padding | ||
|  | func Encrypt(data, secretKey string) (string, error) { | ||
|  | 	key := generateAESKey(KEY_SIZE*8, []byte(secretKey)) | ||
|  | 	ciphertext, err := aesEncrypt([]byte(data), key) | ||
|  | 	if err != nil { | ||
|  | 		return "", err | ||
|  | 	} | ||
|  | 	return base64.StdEncoding.EncodeToString(ciphertext), nil | ||
|  | } | ||
|  | 
 | ||
|  | // Decrypt decrypts the given base64-encoded string using AES encryption in ECB mode with PKCS5 padding | ||
|  | func Decrypt(encodedData, secretKey string) ([]byte, error) { | ||
|  | 	ciphertext, err := base64.StdEncoding.DecodeString(encodedData) | ||
|  | 	if err != nil { | ||
|  | 		return nil, err | ||
|  | 	} | ||
|  | 	key := generateAESKey(KEY_SIZE*8, []byte(secretKey)) | ||
|  | 	plaintext, err := aesDecrypt(ciphertext, key) | ||
|  | 	if err != nil { | ||
|  | 		return nil, err | ||
|  | 	} | ||
|  | 	return plaintext, nil | ||
|  | } | ||
|  | 
 | ||
|  | // generateAESKey generates a key for AES encryption using a SHA-1 based PRNG | ||
|  | func generateAESKey(length int, password []byte) []byte { | ||
|  | 	h := sha1.New() | ||
|  | 	h.Write(password) | ||
|  | 	state := h.Sum(nil) | ||
|  | 
 | ||
|  | 	keyBytes := make([]byte, 0, length/8) | ||
|  | 	for len(keyBytes) < length/8 { | ||
|  | 		h := sha1.New() | ||
|  | 		h.Write(state) | ||
|  | 		state = h.Sum(nil) | ||
|  | 		keyBytes = append(keyBytes, state...) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return keyBytes[:length/8] | ||
|  | } | ||
|  | 
 | ||
|  | // aesEncrypt encrypts plaintext using AES in ECB mode with PKCS5 padding | ||
|  | func aesEncrypt(plaintext, key []byte) ([]byte, error) { | ||
|  | 	block, err := aes.NewCipher(key) | ||
|  | 	if err != nil { | ||
|  | 		return nil, err | ||
|  | 	} | ||
|  | 	paddedPlaintext := pkcs5Padding(plaintext, block.BlockSize()) | ||
|  | 	ciphertext := make([]byte, len(paddedPlaintext)) | ||
|  | 	mode := newECBEncrypter(block) | ||
|  | 	mode.CryptBlocks(ciphertext, paddedPlaintext) | ||
|  | 	return ciphertext, nil | ||
|  | } | ||
|  | 
 | ||
|  | // aesDecrypt decrypts ciphertext using AES in ECB mode with PKCS5 padding | ||
|  | func aesDecrypt(ciphertext, key []byte) ([]byte, error) { | ||
|  | 	block, err := aes.NewCipher(key) | ||
|  | 	if err != nil { | ||
|  | 		return nil, err | ||
|  | 	} | ||
|  | 	plaintext := make([]byte, len(ciphertext)) | ||
|  | 	mode := newECBDecrypter(block) | ||
|  | 	mode.CryptBlocks(plaintext, ciphertext) | ||
|  | 	return pkcs5Unpadding(plaintext), nil | ||
|  | } | ||
|  | 
 | ||
|  | // pkcs5Padding pads the input to a multiple of the block size using PKCS5 padding | ||
|  | func pkcs5Padding(src []byte, blockSize int) []byte { | ||
|  | 	padding := blockSize - len(src)%blockSize | ||
|  | 	padtext := bytes.Repeat([]byte{byte(padding)}, padding) | ||
|  | 	return append(src, padtext...) | ||
|  | } | ||
|  | 
 | ||
|  | // pkcs5Unpadding removes PKCS5 padding from the input | ||
|  | func pkcs5Unpadding(src []byte) []byte { | ||
|  | 	length := len(src) | ||
|  | 	unpadding := int(src[length-1]) | ||
|  | 	return src[:(length - unpadding)] | ||
|  | } | ||
|  | 
 | ||
|  | // ECB mode encryption/decryption | ||
|  | type ecb struct { | ||
|  | 	b         cipher.Block | ||
|  | 	blockSize int | ||
|  | } | ||
|  | 
 | ||
|  | func newECB(b cipher.Block) *ecb { | ||
|  | 	return &ecb{ | ||
|  | 		b:         b, | ||
|  | 		blockSize: b.BlockSize(), | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | type ecbEncrypter ecb | ||
|  | 
 | ||
|  | func newECBEncrypter(b cipher.Block) cipher.BlockMode { | ||
|  | 	return (*ecbEncrypter)(newECB(b)) | ||
|  | } | ||
|  | 
 | ||
|  | func (x *ecbEncrypter) BlockSize() int { return x.blockSize } | ||
|  | 
 | ||
|  | func (x *ecbEncrypter) CryptBlocks(dst, src []byte) { | ||
|  | 	if len(src)%x.blockSize != 0 { | ||
|  | 		panic("crypto/cipher: input not full blocks") | ||
|  | 	} | ||
|  | 	if len(dst) < len(src) { | ||
|  | 		panic("crypto/cipher: output smaller than input") | ||
|  | 	} | ||
|  | 	for len(src) > 0 { | ||
|  | 		x.b.Encrypt(dst, src[:x.blockSize]) | ||
|  | 		src = src[x.blockSize:] | ||
|  | 		dst = dst[x.blockSize:] | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | type ecbDecrypter ecb | ||
|  | 
 | ||
|  | func newECBDecrypter(b cipher.Block) cipher.BlockMode { | ||
|  | 	return (*ecbDecrypter)(newECB(b)) | ||
|  | } | ||
|  | 
 | ||
|  | func (x *ecbDecrypter) BlockSize() int { return x.blockSize } | ||
|  | 
 | ||
|  | func (x *ecbDecrypter) CryptBlocks(dst, src []byte) { | ||
|  | 	if len(src)%x.blockSize != 0 { | ||
|  | 		panic("crypto/cipher: input not full blocks") | ||
|  | 	} | ||
|  | 	if len(dst) < len(src) { | ||
|  | 		panic("crypto/cipher: output smaller than input") | ||
|  | 	} | ||
|  | 	for len(src) > 0 { | ||
|  | 		x.b.Decrypt(dst, src[:x.blockSize]) | ||
|  | 		src = src[x.blockSize:] | ||
|  | 		dst = dst[x.blockSize:] | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | // Md5Encrypt 用于对传入的message进行MD5加密 | ||
|  | func Md5Encrypt(message string) string { | ||
|  | 	hash := md5.New() | ||
|  | 	hash.Write([]byte(message))              // 将字符串转换为字节切片并写入 | ||
|  | 	return hex.EncodeToString(hash.Sum(nil)) // 将哈希值转换为16进制字符串并返回 | ||
|  | } |