Skip to content

Commit

Permalink
feat: 加密
Browse files Browse the repository at this point in the history
  • Loading branch information
miaoyin committed Nov 9, 2023
1 parent dfc858c commit bd06bd3
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 109 deletions.
4 changes: 2 additions & 2 deletions cfg/cfg_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ func ExampleCfg_String() {
}

func ExampleCfg_Read() {
data, err := cfg.New("key").Read([]byte(`a=AES(A/43wTj2AVQboZZ0lNMqbw==)
b=DES(LABOK5l6Q64=)
data, err := cfg.New("key").Read([]byte(`a=AES(oY8aex0d4WjWokMZSUDyDQ==)
b=DES(azzeIdDM09M=)
c=DES[abc]`))

fmt.Println(string(data))
Expand Down
4 changes: 2 additions & 2 deletions cfg/cfg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import (

const (
_file = "test.toml"
_data = `k1 = "AES(A/43wTj2AVQboZZ0lNMqbw==)"
k2 = "DES(LABOK5l6Q64=)"
_data = `k1 = "AES(oY8aex0d4WjWokMZSUDyDQ==)"
k2 = "DES(Jiga4xHtvWM=)"
k3 = "DES[中文]"`
_keyErr = "key err"
)
Expand Down
85 changes: 70 additions & 15 deletions cfg/cipher.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,99 @@ package cfg

import (
"crypto/aes"
"crypto/cipher"
"crypto/des" // nolint
"crypto/cipher" // nolint
"crypto/des" // nolint
"crypto/md5" // nolint
"crypto/sha256"
"encoding/base64"
"fmt"
"strings"

"github.com/xuender/kit/los"
)

type Cipher int

const (
AES Cipher = iota
DES
AESMD5
DESMD5
)

// nolint
var ciphers = [...]Cipher{AES, DES}
var (
ciphers = [...]Cipher{AES, DES}
_names = map[Cipher]string{AES: "AES", DES: "DES", AESMD5: "AESMD5", DESMD5: "DESMD5"}
)

func (p Cipher) String() string {
if p == DES {
return "DES"
func (p Cipher) Encrypt(src, key string) string {
return base64.StdEncoding.EncodeToString(p.EncryptBytes([]byte(src), key))
}

func (p Cipher) EncryptBytes(src []byte, key string) []byte {
blockMode, blockSize := p.Block(key, true)

src = pkcs5Padding(src, blockSize)

cryted := make([]byte, len(src))
blockMode.CryptBlocks(cryted, src)

return cryted
}

func (p Cipher) Decrypt(src, key string) (string, error) {
data, err := p.DecryptBytes(los.Must(base64.StdEncoding.DecodeString(src)), key)
if err != nil {
return "", err
}

return "AES"
return string(data), nil
}

func (p Cipher) DecryptBytes(src []byte, key string) ([]byte, error) {
var (
blockMode, _ = p.Block(key, false)
orig = make([]byte, len(src))
)

blockMode.CryptBlocks(orig, src)

return pkcs5Trimming(orig)
}

func (p Cipher) String() string {
return _names[p]
}

func (p Cipher) Block(key string) cipher.Block {
keyBytes := sha256.Sum256([]byte(key))
if p == DES {
// nolint
block, _ := des.NewCipher(keyBytes[:8])
func (p Cipher) Block(key string, isEnc bool) (cipher.BlockMode, int) {
var (
keyBytes []byte
block cipher.Block
blockSize int
)

if p == AESMD5 || p == DESMD5 {
tmp := md5.Sum([]byte(key)) // nolint
keyBytes = tmp[:]
} else {
tmp := sha256.Sum256([]byte(key))
keyBytes = tmp[:]
}

return block
if p == DES || p == DESMD5 {
blockSize = 8
block = los.Must(des.NewCipher(keyBytes[:blockSize])) // nolint
} else {
block = los.Must(aes.NewCipher(keyBytes))
blockSize = block.BlockSize()
}

block, _ := aes.NewCipher(keyBytes[:])
if isEnc {
return cipher.NewCBCEncrypter(block, keyBytes[:blockSize]), blockSize
}

return block
return cipher.NewCBCDecrypter(block, keyBytes[:blockSize]), blockSize
}

func (p Cipher) Stringify(data []byte) string {
Expand Down
13 changes: 13 additions & 0 deletions cfg/cipher_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,16 @@ func ExampleIsEncrypt() {
// true
// false
}

func ExampleCipher_Decrypt() {
fmt.Println(cfg.AESMD5.Decrypt(cfg.AESMD5.Encrypt("AESMD5", "pass"), "pass"))
fmt.Println(cfg.DESMD5.Decrypt(cfg.DESMD5.Encrypt("DESMD5", "pass"), "pass"))
fmt.Println(cfg.AES.Decrypt(cfg.AES.Encrypt("AES", "pass"), "pass"))
fmt.Println(cfg.DES.Decrypt(cfg.DES.Encrypt("DES", "pass"), "pass"))

// Output:
// AESMD5 <nil>
// DESMD5 <nil>
// AES <nil>
// DES <nil>
}
76 changes: 6 additions & 70 deletions cfg/crypto.go
Original file line number Diff line number Diff line change
@@ -1,97 +1,33 @@
package cfg

import (
"crypto/rand"
)

func Encrypt(str, key string) (string, error) {
data, cipher, err := Parse(str)
if err != nil {
return "", err
}

return EncryptByCipher(data, key, cipher), nil
return cipher.Stringify(cipher.EncryptBytes(data, key)), nil
}

// EncryptByCipher 加密.
func EncryptByCipher(str []byte, key string, cipher Cipher) string {
var (
ret []byte
block = cipher.Block(key)
srcBytes = Padding(str, block.BlockSize())
tmp = make([]byte, block.BlockSize())
)

for index := 0; index < len(srcBytes); index += block.BlockSize() {
block.Encrypt(tmp, srcBytes[index:index+block.BlockSize()])
ret = append(ret, tmp...)
}

return cipher.Stringify(ret)
func EncryptByCipher(src []byte, key string, cipher Cipher) string {
return cipher.Stringify(cipher.EncryptBytes(src, key))
}

// Decrypt 解密.
func Decrypt(src, key string) (string, error) {
var ret []byte

srcBytes, cipher, err := Parse(src)
if err != nil {
return "", err
}

var (
block = cipher.Block(key)
tmp = make([]byte, block.BlockSize())
)

for index := 0; index < len(srcBytes); index += block.BlockSize() {
block.Decrypt(tmp, srcBytes[index:index+block.BlockSize()])
ret = append(ret, tmp...)
}

text, err := UnPadding(ret)
ret, err := cipher.DecryptBytes(srcBytes, key)
if err != nil {
return "", err
}

if _checkRegex.MatchString(text) {
return text, err
if _checkRegex.Match(ret) {
return string(ret), err
}

return "", ErrKey
}

func Padding(cipherText []byte, blockSize int) []byte {
var (
padding = getPaddingSize(cipherText, blockSize)
padData = make([]byte, padding-1)
)

_, _ = rand.Read(padData)
// nolint
padData = append(padData, byte(padding))

return append(cipherText, padData...)
}

func UnPadding(cipherText []byte) (string, error) {
var (
length = len(cipherText)
cipherLen = int(cipherText[length-1])
)

if length < cipherLen {
return "", ErrKey
}

return string(cipherText[:length-cipherLen]), nil
}

func getPaddingSize(cipherText []byte, blockSize int) int {
remainder := len(cipherText) % blockSize
if remainder == 0 {
return blockSize
}

return blockSize - remainder
}
16 changes: 4 additions & 12 deletions cfg/crypto_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,17 @@ func ExampleEncrypt() {

func ExampleEncryptByCipher() {
str := cfg.EncryptByCipher([]byte("123"), "password", cfg.AES)
fmt.Println(str[:4])

fmt.Println(str[:4])
fmt.Println(cfg.Decrypt(str, "password"))
// Output:
// AES(
// 123 <nil>
}

func ExampleDecrypt() {
fmt.Println(cfg.Decrypt("AES(A/43wTj2AVQboZZ0lNMqbw==)", "key"))

str := cfg.EncryptByCipher([]byte("123"), "", cfg.DES)
fmt.Println(cfg.Decrypt(str, ""))

_, err := cfg.Decrypt(str, "err")
fmt.Println(err)
func ExampleDecrypt_md5() {
fmt.Println(cfg.AESMD5.Decrypt("lob52vO/Av/yk0Ty+DBDag==", "pass"))

// Output:
// aaa <nil>
// 123 <nil>
// password error
// abc <nil>
}
8 changes: 0 additions & 8 deletions cfg/crypto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,6 @@ func TestDecryptWith(t *testing.T) {
}
}

func TestPadding(t *testing.T) {
t.Parallel()

if data := cfg.Padding([]byte("1234"), 4); data[0] != '1' {
t.Error("padding error")
}
}

func TestEncrypt(t *testing.T) {
t.Parallel()

Expand Down
23 changes: 23 additions & 0 deletions cfg/padding.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package cfg

import "bytes"

func pkcs5Trimming(encrypt []byte) ([]byte, error) {
var (
length = len(encrypt)
cipherLen = int(encrypt[length-1])
)

if length < cipherLen {
return nil, ErrKey
}

return encrypt[:length-cipherLen], nil
}

func pkcs5Padding(cipherText []byte, blockSize int) []byte {
padding := blockSize - len(cipherText)%blockSize
padText := bytes.Repeat([]byte{byte(padding)}, padding)

return append(cipherText, padText...)
}

0 comments on commit bd06bd3

Please sign in to comment.