github.com/binbinly/pkg@v0.0.11-0.20240321014439-f4fbf666eb0f/util/xcrypto/aes.go (about)

     1  package xcrypto
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/aes"
     6  	"crypto/cipher"
     7  	"errors"
     8  	"io"
     9  )
    10  
    11  // AesCBCEncrypt 加密
    12  func AesCBCEncrypt(originText, key, iv []byte) ([]byte, error) {
    13  
    14  	// 创建一个cipher.Block。参数key为密钥,长度只能是16、24、32字节,用以选择AES-128、AES-192、AES-256
    15  	block, err := aes.NewCipher(key)
    16  	if err != nil {
    17  		return nil, err
    18  	}
    19  
    20  	// 返回加密字节块的大小
    21  	blockSize := block.BlockSize()
    22  
    23  	// PKCS5填充需加密内容
    24  	originText = pKCS5Padding(originText, blockSize)
    25  
    26  	// 返回一个密码分组链接模式的、底层用Block加密的cipher.BlockMode,初始向量iv的长度必须等于Block的块尺寸(Block块尺寸等于密钥尺寸)
    27  	blockMode := cipher.NewCBCEncrypter(block, iv)
    28  
    29  	// 根据 需加密内容[]byte长度,初始化一个新的byte数组,返回byte数组内存地址
    30  	cipherText := make([]byte, len(originText))
    31  
    32  	// 加密或解密连续的数据块,将加密内容存储到dst中,src需加密内容的长度必须是块大小的整数倍,src和dst可指向同一内存地址
    33  	blockMode.CryptBlocks(cipherText, originText)
    34  
    35  	return cipherText, nil
    36  }
    37  
    38  // AesCBCDecrypt 解密
    39  func AesCBCDecrypt(cipherText, key, iv []byte) ([]byte, error) {
    40  
    41  	// 创建一个cipher.Block。参数key为密钥,长度只能是16、24、32字节,用以选择AES-128、AES-192、AES-256
    42  	block, err := aes.NewCipher(key)
    43  	if err != nil {
    44  		return nil, err
    45  	}
    46  
    47  	// 返回一个密码分组链接模式的、底层用b解密的cipher.BlockMode,初始向量iv必须和加密时使用的iv相同
    48  	blockMode := cipher.NewCBCDecrypter(block, iv)
    49  
    50  	// 根据 密文[]byte长度,初始化一个新的byte数组,返回byte数组内存地址
    51  	originText := make([]byte, len(cipherText))
    52  
    53  	// 加密或解密连续的数据块,将解密内容存储到dst中,src需加密内容的长度必须是块大小的整数倍,src和dst可指向同一内存地址
    54  	blockMode.CryptBlocks(originText, cipherText)
    55  
    56  	// PKCS5反填充解密内容
    57  	originText = pKCS5UnPadding(originText)
    58  	return originText, nil
    59  }
    60  
    61  // AesCFBEncrypt 加密
    62  func AesCFBEncrypt(originText, key, iv []byte) ([]byte, error) {
    63  
    64  	// 创建一个cipher.Block。参数key为密钥,长度只能是16、24、32字节,用以选择AES-128、AES-192、AES-256
    65  	block, err := aes.NewCipher(key)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  
    70  	// 根据 需加密内容[]byte长度,初始化一个新的byte数组,返回byte数组内存地址
    71  	cipherText := make([]byte, aes.BlockSize+len(originText))
    72  
    73  	// 返回一个密码反馈模式的、底层用block加密的cipher.Stream,初始向量iv的长度必须等于block的块尺寸
    74  	stream := cipher.NewCFBEncrypter(block, iv)
    75  
    76  	// 从加密器的key流和src中依次取出字节二者xor后写入dst,src和dst可指向同一内存地址
    77  	// cipherText[:aes.BlockSize]为iv值,所以只写入cipherText后面部分
    78  	stream.XORKeyStream(cipherText[aes.BlockSize:], originText)
    79  
    80  	return cipherText, nil
    81  }
    82  
    83  // AesCFBDecrypt 解密
    84  func AesCFBDecrypt(cipherText, key, iv []byte) ([]byte, error) {
    85  
    86  	// 创建一个cipher.Block。参数key为密钥,长度只能是16、24、32字节,用以选择AES-128、AES-192、AES-256
    87  	block, err := aes.NewCipher(key)
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  
    92  	if len(cipherText) < aes.BlockSize {
    93  		return nil, errors.New("cipherText too short")
    94  	}
    95  
    96  	// 只使用cipherText除去iv部分
    97  	cipherText = cipherText[aes.BlockSize:]
    98  
    99  	// 返回一个密码反馈模式的、底层用block解密的cipher.Stream,初始向量iv必须和加密时使用的iv相同
   100  	stream := cipher.NewCFBDecrypter(block, iv)
   101  
   102  	// 从加密器的key流和src中依次取出字节二者xor后写入dst,src和dst可指向同一内存地址
   103  	stream.XORKeyStream(cipherText, cipherText)
   104  
   105  	return cipherText, nil
   106  }
   107  
   108  // AesCTREncrypt 加密
   109  func AesCTREncrypt(originText, key, iv []byte) ([]byte, error) {
   110  
   111  	// 创建一个cipher.Block。参数key为密钥,长度只能是16、24、32字节,用以选择AES-128、AES-192、AES-256
   112  	block, err := aes.NewCipher(key)
   113  	if err != nil {
   114  		return nil, err
   115  	}
   116  
   117  	// 根据 需加密内容[]byte长度,初始化一个新的byte数组,返回byte数组内存地址
   118  	cipherText := make([]byte, aes.BlockSize+len(originText))
   119  
   120  	// 返回一个计数器模式的、底层采用block生成key流的cipher.Stream,初始向量iv的长度必须等于block的块尺寸
   121  	stream := cipher.NewCTR(block, iv)
   122  
   123  	// 从加密器的key流和src中依次取出字节二者xor后写入dst,src和dst可指向同一内存地址
   124  	// cipherText[:aes.BlockSize]为iv值,所以只写入cipherText后面部分
   125  	stream.XORKeyStream(cipherText[aes.BlockSize:], originText)
   126  
   127  	return cipherText, nil
   128  }
   129  
   130  // AesCTRDecrypt 解密
   131  func AesCTRDecrypt(cipherText, key, iv []byte) ([]byte, error) {
   132  
   133  	// 创建一个cipher.Block。参数key为密钥,长度只能是16、24、32字节,用以选择AES-128、AES-192、AES-256
   134  	block, err := aes.NewCipher(key)
   135  	if err != nil {
   136  		return nil, err
   137  	}
   138  
   139  	// 只使用cipherText除去iv部分
   140  	cipherText = cipherText[aes.BlockSize:]
   141  
   142  	// 返回一个计数器模式的、底层采用block生成key流的cipher.Stream,初始向量iv的长度必须等于block的块尺寸
   143  	stream := cipher.NewCTR(block, iv)
   144  
   145  	// 从加密器的key流和src中依次取出字节二者xor后写入dst,src和dst可指向同一内存地址
   146  	stream.XORKeyStream(cipherText, cipherText)
   147  
   148  	return cipherText, nil
   149  }
   150  
   151  // AesGCMEncrypt 加密
   152  func AesGCMEncrypt(originText, key, nonce []byte) ([]byte, error) {
   153  
   154  	// 创建一个cipher.Block。参数key为密钥,长度只能是16、24、32字节,用以选择AES-128、AES-192、AES-256
   155  	block, err := aes.NewCipher(key)
   156  	if err != nil {
   157  		return nil, err
   158  	}
   159  
   160  	// 函数用迦洛瓦计数器模式包装提供的128位Block接口,并返回cipher.AEAD
   161  	g, err := cipher.NewGCM(block)
   162  	if err != nil {
   163  		return nil, err
   164  	}
   165  
   166  	// 返回加密结果。认证附加的additionalData,将加密结果添加到dst生成新的加密结果,nonce的长度必须是NonceSize()字节,且对给定的key和时间都是独一无二的
   167  	cipherText := g.Seal(nil, nonce, originText, nil)
   168  
   169  	return cipherText, nil
   170  }
   171  
   172  // AesGCMDecrypt 解密
   173  func AesGCMDecrypt(cipherText, key, nonce []byte) ([]byte, error) {
   174  
   175  	// 创建一个cipher.Block。参数key为密钥,长度只能是16、24、32字节,用以选择AES-128、AES-192、AES-256
   176  	block, err := aes.NewCipher(key)
   177  	if err != nil {
   178  		return nil, err
   179  	}
   180  
   181  	// 函数用迦洛瓦计数器模式包装提供的128位Block接口,并返回cipher.AEAD
   182  	astc, err := cipher.NewGCM(block)
   183  	if err != nil {
   184  		return nil, err
   185  	}
   186  
   187  	// 返回解密结果。认证附加的additionalData,将解密结果添加到dst生成新的加密结果,nonce的长度必须是NonceSize()字节,nonce和data都必须和加密时使用的相同
   188  	return astc.Open(nil, nonce, cipherText, nil)
   189  }
   190  
   191  // AesOFBEncrypt 加密
   192  func AesOFBEncrypt(originText, key, iv []byte) ([]byte, error) {
   193  
   194  	// 创建一个cipher.Block。参数key为密钥,长度只能是16、24、32字节,用以选择AES-128、AES-192、AES-256
   195  	block, err := aes.NewCipher(key)
   196  	if err != nil {
   197  		return nil, err
   198  	}
   199  
   200  	// 根据 需加密内容[]byte长度,初始化一个新的byte数组,返回byte数组内存地址
   201  	cipherText := make([]byte, aes.BlockSize+len(originText))
   202  
   203  	// 返回一个输出反馈模式的、底层采用b生成key流的cipher.Stream,初始向量iv的长度必须等于b的块尺寸
   204  	stream := cipher.NewOFB(block, iv)
   205  
   206  	// 从加密器的key流和src中依次取出字节二者xor后写入dst,src和dst可指向同一内存地址
   207  	// cipherText[:aes.BlockSize]为iv值,所以只写入cipherText后面部分
   208  	stream.XORKeyStream(cipherText[aes.BlockSize:], originText)
   209  
   210  	return cipherText, nil
   211  }
   212  
   213  // AesOFBDecrypt 解密
   214  func AesOFBDecrypt(cipherText, key, iv []byte) ([]byte, error) {
   215  
   216  	// 创建一个cipher.Block。参数key为密钥,长度只能是16、24、32字节,用以选择AES-128、AES-192、AES-256
   217  	block, err := aes.NewCipher(key)
   218  	if err != nil {
   219  		return nil, err
   220  	}
   221  
   222  	// 只使用cipherText除去iv部分
   223  	cipherText = cipherText[aes.BlockSize:]
   224  
   225  	// 返回一个输出反馈模式的、底层采用b生成key流的cipher.Stream,初始向量iv的长度必须等于b的块尺寸
   226  	stream := cipher.NewOFB(block, iv)
   227  
   228  	// 从加密器的key流和src中依次取出字节二者xor后写入dst,src和dst可指向同一内存地址
   229  	stream.XORKeyStream(cipherText, cipherText)
   230  
   231  	return cipherText, nil
   232  }
   233  
   234  // AesOFBEncryptStreamReader 加密
   235  func AesOFBEncryptStreamReader(originText, key, iv []byte) ([]byte, error) {
   236  
   237  	// 创建一个cipher.Block。参数key为密钥,长度只能是16、24、32字节,用以选择AES-128、AES-192、AES-256
   238  	block, err := aes.NewCipher(key)
   239  	if err != nil {
   240  		return nil, err
   241  	}
   242  
   243  	// 返回一个输出反馈模式的、底层采用b生成key流的cipher.Stream,初始向量iv的长度必须等于b的块尺寸
   244  	stream := cipher.NewOFB(block, iv)
   245  
   246  	// 初始化cipher.StreamReader。将一个cipher.Stream与一个io.Reader关联起来,Read方法会调用XORKeyStream方法来处理获取的所有切片
   247  	reader := &cipher.StreamReader{
   248  		S: stream,
   249  		R: bytes.NewReader(originText),
   250  	}
   251  
   252  	return io.ReadAll(reader)
   253  }
   254  
   255  // AesOFBDecryptStreamWriter 解密
   256  func AesOFBDecryptStreamWriter(cipherText, key, iv []byte) ([]byte, error) {
   257  
   258  	// 创建一个cipher.Block。参数key为密钥,长度只能是16、24、32字节,用以选择AES-128、AES-192、AES-256
   259  	block, err := aes.NewCipher(key)
   260  	if err != nil {
   261  		return nil, err
   262  	}
   263  
   264  	// 返回一个输出反馈模式的、底层采用b生成key流的cipher.Stream,初始向量iv的长度必须等于b的块尺寸
   265  	stream := cipher.NewOFB(block, iv)
   266  
   267  	// 声明buffer
   268  	var originText bytes.Buffer
   269  
   270  	// 初始化cipher.StreamWriter。将一个cipher.Stream与一个io.Writer接口关联起来,Write方法会调用XORKeyStream方法来处理提供的所有切片
   271  	// 如果Write方法返回的n小于提供的切片的长度,则表示StreamWriter不同步,必须丢弃。StreamWriter没有内建的缓存,不需要调用Close方法去清空缓存
   272  	writer := &cipher.StreamWriter{
   273  		S: stream,
   274  		W: &originText,
   275  	}
   276  
   277  	// 把reader内容拷贝到writer, writer会调用write方法写入内容
   278  	if _, err = io.Copy(writer, bytes.NewReader(cipherText)); err != nil {
   279  		return nil, err
   280  	}
   281  
   282  	return originText.Bytes(), nil
   283  }