加解密部分
package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"io"
)
// 使用PKCS7进行填充,IOS也是7
func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
func PKCS7UnPadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}
// aes加密,填充秘钥key的16位,24,32分别对应AES-128, AES-192, or AES-256.
func AesCBCEncrypt(rawData, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
blockSize := block.BlockSize()
rawData = PKCS7Padding(rawData, blockSize)
//初始向量IV必须是唯一,但不需要保密
cipherText := make([]byte, blockSize+len(rawData))
iv := cipherText[:blockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(cipherText[blockSize:], rawData)
return cipherText, nil
}
func AesCBCDncrypt(encryptData, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
blockSize := block.BlockSize()
if len(encryptData) < blockSize {
panic("ciphertext too short")
}
iv := encryptData[:blockSize]
encryptData = encryptData[blockSize:]
// CBC mode always works in whole blocks.
if len(encryptData)%blockSize != 0 {
panic("ciphertext is not a multiple of the block size")
}
mode := cipher.NewCBCDecrypter(block, iv)
// CryptBlocks can work in-place if the two arguments are the same.
mode.CryptBlocks(encryptData, encryptData)
//解填充
encryptData = PKCS7UnPadding(encryptData)
return encryptData, nil
}
func Encrypt(rawData, key []byte) (string, error) {
data, err := AesCBCEncrypt(rawData, key)
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(data), nil
}
func Dncrypt(rawData string, key []byte) (string, error) {
data, err := base64.StdEncoding.DecodeString(rawData)
if err != nil {
return "", err
}
dnData, err := AesCBCDncrypt(data, key)
if err != nil {
return "", err
}
return string(dnData), nil
}
命令行处理部分
package main
import (
"fmt"
"github.com/spf13/cobra"
)
var pass string
var key string
var ciperCmd = &cobra.Command{
Use: "cipher",
Short: "用于对字符串进行加密解密",
Run: func(cmd *cobra.Command, args []string) {
key := PKCS7Padding([]byte(key), 16)
dFlag, _ := cmd.Flags().GetBool("decry")
eFlag, _ := cmd.Flags().GetBool("encry")
if dFlag && eFlag {
panic("不能同时指定 decry(d) 和 encry(e)")
} else if !dFlag && !eFlag {
panic("必须要指定 decry(d) 和 encry(e) 中的一个")
} else if dFlag {
res, err := Dncrypt(pass, key)
if err != nil {
panic(err)
} else {
fmt.Println(res)
}
} else {
res, err := Encrypt([]byte(pass), key)
if err != nil {
panic(err)
} else {
fmt.Println(res)
}
}
},
}
func init() {
ciperCmd.Flags().BoolP("encry", "e", false, "如果需要加密指定此参数")
ciperCmd.Flags().BoolP("decry", "d", false, "如果需要解密指定此参数")
ciperCmd.Flags().StringVarP(&pass, "string", "s", "", "指定需要加密或者解密的字符串")
ciperCmd.MarkFlagRequired("pass")
}
func main() {
key = "yAoLOEe46mikbDT5"
ciperCmd.Execute()
}