github.com/lingyao2333/mo-zero@v1.4.1/core/codec/aesecb.go (about) 1 package codec 2 3 import ( 4 "bytes" 5 "crypto/aes" 6 "crypto/cipher" 7 "encoding/base64" 8 "errors" 9 10 "github.com/lingyao2333/mo-zero/core/logx" 11 ) 12 13 // ErrPaddingSize indicates bad padding size. 14 var ErrPaddingSize = errors.New("padding size error") 15 16 type ecb struct { 17 b cipher.Block 18 blockSize int 19 } 20 21 func newECB(b cipher.Block) *ecb { 22 return &ecb{ 23 b: b, 24 blockSize: b.BlockSize(), 25 } 26 } 27 28 type ecbEncrypter ecb 29 30 // NewECBEncrypter returns an ECB encrypter. 31 func NewECBEncrypter(b cipher.Block) cipher.BlockMode { 32 return (*ecbEncrypter)(newECB(b)) 33 } 34 35 func (x *ecbEncrypter) BlockSize() int { return x.blockSize } 36 37 // why we don't return error is because cipher.BlockMode doesn't allow this 38 func (x *ecbEncrypter) CryptBlocks(dst, src []byte) { 39 if len(src)%x.blockSize != 0 { 40 logx.Error("crypto/cipher: input not full blocks") 41 return 42 } 43 if len(dst) < len(src) { 44 logx.Error("crypto/cipher: output smaller than input") 45 return 46 } 47 48 for len(src) > 0 { 49 x.b.Encrypt(dst, src[:x.blockSize]) 50 src = src[x.blockSize:] 51 dst = dst[x.blockSize:] 52 } 53 } 54 55 type ecbDecrypter ecb 56 57 // NewECBDecrypter returns an ECB decrypter. 58 func NewECBDecrypter(b cipher.Block) cipher.BlockMode { 59 return (*ecbDecrypter)(newECB(b)) 60 } 61 62 func (x *ecbDecrypter) BlockSize() int { 63 return x.blockSize 64 } 65 66 // why we don't return error is because cipher.BlockMode doesn't allow this 67 func (x *ecbDecrypter) CryptBlocks(dst, src []byte) { 68 if len(src)%x.blockSize != 0 { 69 logx.Error("crypto/cipher: input not full blocks") 70 return 71 } 72 if len(dst) < len(src) { 73 logx.Error("crypto/cipher: output smaller than input") 74 return 75 } 76 77 for len(src) > 0 { 78 x.b.Decrypt(dst, src[:x.blockSize]) 79 src = src[x.blockSize:] 80 dst = dst[x.blockSize:] 81 } 82 } 83 84 // EcbDecrypt decrypts src with the given key. 85 func EcbDecrypt(key, src []byte) ([]byte, error) { 86 block, err := aes.NewCipher(key) 87 if err != nil { 88 logx.Errorf("Decrypt key error: % x", key) 89 return nil, err 90 } 91 92 decrypter := NewECBDecrypter(block) 93 decrypted := make([]byte, len(src)) 94 decrypter.CryptBlocks(decrypted, src) 95 96 return pkcs5Unpadding(decrypted, decrypter.BlockSize()) 97 } 98 99 // EcbDecryptBase64 decrypts base64 encoded src with the given base64 encoded key. 100 // The returned string is also base64 encoded. 101 func EcbDecryptBase64(key, src string) (string, error) { 102 keyBytes, err := getKeyBytes(key) 103 if err != nil { 104 return "", err 105 } 106 107 encryptedBytes, err := base64.StdEncoding.DecodeString(src) 108 if err != nil { 109 return "", err 110 } 111 112 decryptedBytes, err := EcbDecrypt(keyBytes, encryptedBytes) 113 if err != nil { 114 return "", err 115 } 116 117 return base64.StdEncoding.EncodeToString(decryptedBytes), nil 118 } 119 120 // EcbEncrypt encrypts src with the given key. 121 func EcbEncrypt(key, src []byte) ([]byte, error) { 122 block, err := aes.NewCipher(key) 123 if err != nil { 124 logx.Errorf("Encrypt key error: % x", key) 125 return nil, err 126 } 127 128 padded := pkcs5Padding(src, block.BlockSize()) 129 crypted := make([]byte, len(padded)) 130 encrypter := NewECBEncrypter(block) 131 encrypter.CryptBlocks(crypted, padded) 132 133 return crypted, nil 134 } 135 136 // EcbEncryptBase64 encrypts base64 encoded src with the given base64 encoded key. 137 // The returned string is also base64 encoded. 138 func EcbEncryptBase64(key, src string) (string, error) { 139 keyBytes, err := getKeyBytes(key) 140 if err != nil { 141 return "", err 142 } 143 144 srcBytes, err := base64.StdEncoding.DecodeString(src) 145 if err != nil { 146 return "", err 147 } 148 149 encryptedBytes, err := EcbEncrypt(keyBytes, srcBytes) 150 if err != nil { 151 return "", err 152 } 153 154 return base64.StdEncoding.EncodeToString(encryptedBytes), nil 155 } 156 157 func getKeyBytes(key string) ([]byte, error) { 158 if len(key) <= 32 { 159 return []byte(key), nil 160 } 161 162 keyBytes, err := base64.StdEncoding.DecodeString(key) 163 if err != nil { 164 return nil, err 165 } 166 167 return keyBytes, nil 168 } 169 170 func pkcs5Padding(ciphertext []byte, blockSize int) []byte { 171 padding := blockSize - len(ciphertext)%blockSize 172 padtext := bytes.Repeat([]byte{byte(padding)}, padding) 173 return append(ciphertext, padtext...) 174 } 175 176 func pkcs5Unpadding(src []byte, blockSize int) ([]byte, error) { 177 length := len(src) 178 unpadding := int(src[length-1]) 179 if unpadding >= length || unpadding > blockSize { 180 return nil, ErrPaddingSize 181 } 182 183 return src[:length-unpadding], nil 184 }