├── common.go ├── crypto.go ├── crypto_test.go ├── format.go ├── mode.go ├── padding.go └── readme.md /common.go: -------------------------------------------------------------------------------- 1 | package cryptoEx 2 | 3 | import "crypto/cipher" 4 | 5 | type Crypto interface { 6 | Encrypt(src, key, vector []byte) (string, error) 7 | Decrypt(src, key, vector []byte) (string, error) 8 | } 9 | 10 | type cryptoMode interface { 11 | Encrypt(block cipher.Block, data, key, vector []byte) ([]byte, error) 12 | Decrypt(block cipher.Block, data, key, vector []byte) ([]byte, error) 13 | } 14 | 15 | type cryptoPadding interface { 16 | Padding(ciphertext []byte, blockSize int) []byte 17 | UnPadding(origData []byte) []byte 18 | } 19 | 20 | type cryptoFormat interface { 21 | Encode(ciphertext []byte) string 22 | Decode(ciphertext string) ([]byte, error) 23 | } 24 | 25 | type CryptoData struct { 26 | Mode cryptoMode 27 | Padding cryptoPadding 28 | Format cryptoFormat 29 | } 30 | -------------------------------------------------------------------------------- /crypto.go: -------------------------------------------------------------------------------- 1 | package cryptoEx 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/des" 6 | ) 7 | 8 | type aesCrypto struct { 9 | *CryptoData 10 | } 11 | 12 | type desCrypto struct { 13 | *CryptoData 14 | } 15 | 16 | func NewAESCrypto(data *CryptoData) Crypto { 17 | return &aesCrypto{data} 18 | } 19 | 20 | func NewDESCrypto(data *CryptoData) Crypto { 21 | return &desCrypto{data} 22 | } 23 | 24 | func (this *aesCrypto) Encrypt(src, key, vector []byte) (string, error) { 25 | // standard 26 | block, err := aes.NewCipher(key) 27 | if err != nil { 28 | return "", err 29 | } 30 | // padding 31 | src = this.Padding.Padding(src, block.BlockSize()) 32 | // mode 33 | ciphertext, err := this.Mode.Encrypt(block, src, key, vector) 34 | if err != nil { 35 | return "", err 36 | } 37 | // format 38 | return this.Format.Encode(ciphertext), nil 39 | } 40 | 41 | func (this *aesCrypto) Decrypt(src, key, vector []byte) (string, error) { 42 | // format 43 | data, err := this.Format.Decode(string(src)) 44 | if err != nil { 45 | return "", err 46 | } 47 | // standard 48 | block, err := aes.NewCipher(key) 49 | if err != nil { 50 | return "", err 51 | } 52 | // mode 53 | plaintext, err := this.Mode.Decrypt(block, data, key, vector) 54 | if err != nil { 55 | return "", err 56 | } 57 | // padding 58 | return string(this.Padding.UnPadding(plaintext)), nil 59 | } 60 | 61 | func (this *desCrypto) Encrypt(src, key, vector []byte) (string, error) { 62 | // standard 63 | block, err := des.NewCipher(key) 64 | if err != nil { 65 | return "", err 66 | } 67 | // padding 68 | src = this.Padding.Padding(src, block.BlockSize()) 69 | // mode 70 | ciphertext, err := this.Mode.Encrypt(block, src, key, vector) 71 | if err != nil { 72 | return "", err 73 | } 74 | // format 75 | return this.Format.Encode(ciphertext), nil 76 | } 77 | 78 | func (this *desCrypto) Decrypt(src, key, vector []byte) (string, error) { 79 | // format 80 | data, err := this.Format.Decode(string(src)) 81 | if err != nil { 82 | return "", err 83 | } 84 | // standard 85 | block, err := des.NewCipher(key) 86 | if err != nil { 87 | return "", err 88 | } 89 | // mode 90 | plaintext, err := this.Mode.Decrypt(block, data, key, vector) 91 | if err != nil { 92 | return "", err 93 | } 94 | // padding 95 | return string(this.Padding.UnPadding(plaintext)), nil 96 | } 97 | -------------------------------------------------------------------------------- /crypto_test.go: -------------------------------------------------------------------------------- 1 | package cryptoEx 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestAESCrypto(t *testing.T) { 8 | content := []byte("Online project hosting using Git. ") 9 | 10 | key := []byte("X7WBOELqgn6dc8CN") // 16 byte 11 | vector := []byte("7vcUPpqeblkHO0Qx") // 16 byte 12 | 13 | aes := NewAESCrypto(&CryptoData{ 14 | Mode: &ECBMode{}, 15 | Padding: &PKCS5Padding{}, 16 | Format: &HexFormat{}, 17 | }) 18 | encryptStr, _ := aes.Encrypt(content, key, vector) 19 | decryptStr, _ := aes.Decrypt([]byte(encryptStr), key, vector) 20 | t.Log(encryptStr) 21 | t.Log(decryptStr) 22 | } 23 | 24 | func TestDESCrypto(t *testing.T) { 25 | content := []byte("Online project hosting using Git. ") 26 | 27 | key := []byte("Lyp5NVOq") // 8 byte 28 | vector := []byte("oW7nlMbS") // 8 byte 29 | 30 | des := NewDESCrypto(&CryptoData{ 31 | Mode: &OFBMode{}, 32 | Padding: &ZeroPadding{}, 33 | Format: &Base64Format{}, 34 | }) 35 | encryptStr, _ := des.Encrypt(content, key, vector) 36 | decryptStr, _ := des.Decrypt([]byte(encryptStr), key, vector) 37 | t.Log(encryptStr) 38 | t.Log(decryptStr) 39 | } 40 | -------------------------------------------------------------------------------- /format.go: -------------------------------------------------------------------------------- 1 | package cryptoEx 2 | 3 | import ( 4 | "encoding/base64" 5 | "encoding/hex" 6 | "fmt" 7 | ) 8 | 9 | type Base64Format struct { 10 | } 11 | 12 | type HexFormat struct { 13 | } 14 | 15 | func (this *Base64Format) Encode(ciphertext []byte) string { 16 | return base64.StdEncoding.EncodeToString(ciphertext) 17 | } 18 | func (this *Base64Format) Decode(ciphertext string) ([]byte, error) { 19 | return base64.StdEncoding.DecodeString(ciphertext) 20 | } 21 | 22 | func (this *HexFormat) Encode(ciphertext []byte) string { 23 | return fmt.Sprintf("%X", ciphertext) 24 | } 25 | func (this *HexFormat) Decode(ciphertext string) ([]byte, error) { 26 | return hex.DecodeString(ciphertext) 27 | } 28 | -------------------------------------------------------------------------------- /mode.go: -------------------------------------------------------------------------------- 1 | package cryptoEx 2 | 3 | import ( 4 | "crypto/cipher" 5 | "errors" 6 | ) 7 | 8 | type ECBMode struct { 9 | } 10 | 11 | type CBCMode struct { 12 | } 13 | 14 | type CTRMode struct { 15 | } 16 | 17 | type OFBMode struct { 18 | } 19 | 20 | type CFBMode struct { 21 | } 22 | 23 | func (this *ECBMode) Encrypt(block cipher.Block, data, key, iv []byte) ([]byte, error) { 24 | bs := block.BlockSize() 25 | if len(data)%bs != 0 { 26 | return nil, errors.New("Need a multiple of the blocksize") 27 | } 28 | ciphertext := make([]byte, len(data)) 29 | dst := ciphertext 30 | for len(data) > 0 { 31 | block.Encrypt(dst, data[:bs]) 32 | data = data[bs:] 33 | dst = dst[bs:] 34 | } 35 | return ciphertext, nil 36 | } 37 | 38 | func (this *ECBMode) Decrypt(block cipher.Block, data, key, iv []byte) ([]byte, error) { 39 | bs := block.BlockSize() 40 | if len(data)%bs != 0 { 41 | return nil, errors.New("input not full blocks") 42 | } 43 | plaintext := make([]byte, len(data)) 44 | dst := plaintext 45 | for len(data) > 0 { 46 | block.Decrypt(dst, data[:bs]) 47 | data = data[bs:] 48 | dst = dst[bs:] 49 | } 50 | return plaintext, nil 51 | } 52 | 53 | func (this *CBCMode) Encrypt(block cipher.Block, data, key, iv []byte) ([]byte, error) { 54 | mode := cipher.NewCBCEncrypter(block, iv) 55 | ciphertext := make([]byte, len(data)) 56 | mode.CryptBlocks(ciphertext, data) 57 | return ciphertext, nil 58 | } 59 | 60 | func (this *CBCMode) Decrypt(block cipher.Block, data, key, iv []byte) ([]byte, error) { 61 | mode := cipher.NewCBCDecrypter(block, iv) 62 | plaintext := make([]byte, len(data)) 63 | mode.CryptBlocks(plaintext, data) 64 | return plaintext, nil 65 | } 66 | 67 | func (this *CTRMode) Encrypt(block cipher.Block, data, key, iv []byte) ([]byte, error) { 68 | mode := cipher.NewCTR(block, iv) 69 | ciphertext := make([]byte, len(data)) 70 | mode.XORKeyStream(ciphertext, data) 71 | return ciphertext, nil 72 | } 73 | 74 | func (this *CTRMode) Decrypt(block cipher.Block, data, key, iv []byte) ([]byte, error) { 75 | mode := cipher.NewCTR(block, iv) 76 | plaintext := make([]byte, len(data)) 77 | mode.XORKeyStream(plaintext, data) 78 | return plaintext, nil 79 | } 80 | 81 | func (this *OFBMode) Encrypt(block cipher.Block, data, key, iv []byte) ([]byte, error) { 82 | mode := cipher.NewOFB(block, iv) 83 | ciphertext := make([]byte, len(data)) 84 | mode.XORKeyStream(ciphertext, data) 85 | return ciphertext, nil 86 | } 87 | 88 | func (this *OFBMode) Decrypt(block cipher.Block, data, key, iv []byte) ([]byte, error) { 89 | mode := cipher.NewOFB(block, iv) 90 | plaintext := make([]byte, len(data)) 91 | mode.XORKeyStream(plaintext, data) 92 | return plaintext, nil 93 | } 94 | 95 | func (this *CFBMode) Encrypt(block cipher.Block, data, key, iv []byte) ([]byte, error) { 96 | mode := cipher.NewCFBEncrypter(block, iv) 97 | ciphertext := make([]byte, len(data)) 98 | mode.XORKeyStream(ciphertext, data) 99 | return ciphertext, nil 100 | } 101 | 102 | func (this *CFBMode) Decrypt(block cipher.Block, data, key, iv []byte) ([]byte, error) { 103 | mode := cipher.NewCFBDecrypter(block, iv) 104 | plaintext := make([]byte, len(data)) 105 | mode.XORKeyStream(plaintext, data) 106 | return plaintext, nil 107 | } 108 | -------------------------------------------------------------------------------- /padding.go: -------------------------------------------------------------------------------- 1 | package cryptoEx 2 | 3 | import ( 4 | "bytes" 5 | ) 6 | 7 | type PKCS5Padding struct { 8 | } 9 | 10 | type ZeroPadding struct { 11 | } 12 | 13 | func (this *PKCS5Padding) Padding(ciphertext []byte, blockSize int) []byte { 14 | padding := blockSize - len(ciphertext)%blockSize 15 | padtext := bytes.Repeat([]byte{byte(padding)}, padding) 16 | return append(ciphertext, padtext...) 17 | } 18 | 19 | func (this *PKCS5Padding) UnPadding(origData []byte) []byte { 20 | length := len(origData) 21 | unpadding := int(origData[length-1]) 22 | return origData[:(length - unpadding)] 23 | } 24 | 25 | func (this *ZeroPadding) Padding(ciphertext []byte, blockSize int) []byte { 26 | padding := blockSize - len(ciphertext)%blockSize 27 | padtext := bytes.Repeat([]byte{0}, padding) 28 | return append(ciphertext, padtext...) 29 | } 30 | 31 | func (this *ZeroPadding) UnPadding(origData []byte) []byte { 32 | return bytes.TrimFunc(origData, 33 | func(r rune) bool { 34 | return r == rune(0) 35 | }) 36 | } 37 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # 说明 2 | > 主要针对“AES和DES加密算法”的应用: 3 | - 加密模式:"ECB", "CBC", "CTR", "OFB", "CFB" 4 | - 填充方式:"PKCS5", "PKCS7", "ZERO" 5 | - 输出格式:"BASE64", "HEX" 6 | 7 | # demo 8 | ```golang 9 | package main 10 | 11 | import ( 12 | "fmt" 13 | 14 | cryptoEx "github.com/lylib/go-crypto" 15 | ) 16 | 17 | func main() { 18 | AES_Demo() 19 | DES_Demo() 20 | } 21 | 22 | func AES_Demo() { 23 | fmt.Println("AES Demo") 24 | content := []byte("Online project hosting using Git. ") 25 | 26 | key := []byte("X7WBOELqgn6dc8CN") // 16 byte 27 | vector := []byte("7vcUPpqeblkHO0Qx") // 16 byte 28 | 29 | aes := cryptoEx.NewAESCrypto(&cryptoEx.CryptoData{ 30 | Mode: &cryptoEx.ECBMode{}, 31 | Padding: &cryptoEx.PKCS5Padding{}, 32 | Format: &cryptoEx.HexFormat{}, 33 | }) 34 | encryptStr, _ := aes.Encrypt(content, key, vector) 35 | decryptStr, _ := aes.Decrypt([]byte(encryptStr), key, vector) 36 | fmt.Println(encryptStr) 37 | fmt.Println(decryptStr) 38 | } 39 | 40 | func DES_Demo() { 41 | fmt.Println("DES_Demo") 42 | content := []byte("Online project hosting using Git. ") 43 | 44 | key := []byte("Lyp5NVOq") // 8 byte 45 | vector := []byte("oW7nlMbS") // 8 byte 46 | 47 | des := cryptoEx.NewDESCrypto(&cryptoEx.CryptoData{ 48 | Mode: &cryptoEx.OFBMode{}, 49 | Padding: &cryptoEx.ZeroPadding{}, 50 | Format: &cryptoEx.Base64Format{}, 51 | }) 52 | encryptStr, _ := des.Encrypt(content, key, vector) 53 | decryptStr, _ := des.Decrypt([]byte(encryptStr), key, vector) 54 | fmt.Println(encryptStr) 55 | fmt.Println(decryptStr) 56 | } 57 | 58 | ``` --------------------------------------------------------------------------------