github.com/XiaoMi/Gaea@v1.2.5/util/crypto/xaes_ecb.go (about)

     1  // Copyright 2019 The Gaea Authors. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package crypto
    16  
    17  import (
    18  	"bytes"
    19  	"crypto/aes"
    20  	"crypto/cipher"
    21  	"fmt"
    22  )
    23  
    24  func pkcs5Padding(ciphertext []byte, blockSize int) []byte {
    25  	padding := blockSize - len(ciphertext)%blockSize
    26  	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
    27  	return append(ciphertext, padtext...)
    28  }
    29  
    30  func pkcs5UnPadding(origData []byte) ([]byte, error) {
    31  	length := len(origData)
    32  	if length <= 0 {
    33  		return origData, nil
    34  	}
    35  
    36  	unpadding := int(origData[length-1])
    37  	if length < unpadding {
    38  		err := fmt.Errorf("pkcs5UnPadding failed, invalid padding length")
    39  		return nil, err
    40  	}
    41  
    42  	return origData[:(length - unpadding)], nil
    43  }
    44  
    45  type ecbEncrypter struct {
    46  	b         cipher.Block
    47  	blockSize int
    48  }
    49  
    50  // EncryptECB encrypt data in ecb mode
    51  func EncryptECB(key string, data []byte) (result []byte, err error) {
    52  	block, err := aes.NewCipher([]byte(key))
    53  	if err != nil {
    54  		return
    55  	}
    56  
    57  	dataPadding := pkcs5Padding(data, block.BlockSize())
    58  	result = make([]byte, len(dataPadding))
    59  
    60  	mode := newECBEncrypter(block)
    61  	err = mode.cryptBlocks(result, dataPadding)
    62  	if err != nil {
    63  		return
    64  	}
    65  
    66  	return
    67  }
    68  
    69  // DecryptECB decrypt data in ecb mode
    70  func DecryptECB(key string, data []byte) (result []byte, err error) {
    71  	block, err := aes.NewCipher([]byte(key))
    72  	if err != nil {
    73  		return
    74  	}
    75  
    76  	mode := newECBDecrypter(block)
    77  	err = mode.cryptBlocks(data, data)
    78  	if err != nil {
    79  		return
    80  	}
    81  
    82  	result, err = pkcs5UnPadding(data)
    83  	if err != nil {
    84  		return
    85  	}
    86  
    87  	return
    88  }
    89  
    90  func newECBEncrypter(b cipher.Block) (c *ecbEncrypter) {
    91  	c = new(ecbEncrypter)
    92  	c.b = b
    93  	c.blockSize = b.BlockSize()
    94  	return
    95  }
    96  
    97  func (e *ecbEncrypter) BlockSize() (size int) {
    98  	size = e.blockSize
    99  	return
   100  }
   101  
   102  func (e *ecbEncrypter) cryptBlocks(dst []byte, src []byte) (err error) {
   103  	if len(src)%e.blockSize != 0 {
   104  		err = fmt.Errorf("len(src)[%v] not full blocks, blocksize[%v]", len(src), e.blockSize)
   105  		return
   106  	}
   107  
   108  	if len(dst) < len(src) {
   109  		err = fmt.Errorf("output[%v] is smaller than input[%v]", len(dst), len(src))
   110  		return
   111  	}
   112  
   113  	for len(src) > 0 {
   114  		e.b.Encrypt(dst, src[:e.blockSize])
   115  		src = src[e.blockSize:]
   116  		dst = dst[e.blockSize:]
   117  	}
   118  	return
   119  }
   120  
   121  type ecbDecrypter struct {
   122  	b         cipher.Block
   123  	blockSize int
   124  }
   125  
   126  func newECBDecrypter(b cipher.Block) (c *ecbDecrypter) {
   127  	c = new(ecbDecrypter)
   128  	c.b = b
   129  	c.blockSize = b.BlockSize()
   130  	return
   131  }
   132  
   133  func (e *ecbDecrypter) BlockSize() (size int) {
   134  	size = e.blockSize
   135  	return
   136  }
   137  
   138  func (e *ecbDecrypter) cryptBlocks(dst []byte, src []byte) (err error) {
   139  	if len(src)%e.blockSize != 0 {
   140  		err = fmt.Errorf("len(src)[%v] not full blocks, blocksize[%v]", len(src), e.blockSize)
   141  		return
   142  	}
   143  	if len(dst) < len(src) {
   144  		err = fmt.Errorf("output[%v] is smaller than input[%v]", len(dst), len(src))
   145  		return
   146  	}
   147  
   148  	for len(src) > 0 {
   149  		e.b.Decrypt(dst, src[:e.blockSize]) // different from encrypter here.
   150  		src = src[e.blockSize:]
   151  		dst = dst[e.blockSize:]
   152  	}
   153  
   154  	return
   155  }