gaes.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
  2. //
  3. // This Source Code Form is subject to the terms of the MIT License.
  4. // If a copy of the MIT was not distributed with this file,
  5. // You can obtain one at https://github.com/gogf/gf.
  6. // Package gaes provides useful API for AES encryption/decryption algorithms.
  7. package gaes
  8. import (
  9. "bytes"
  10. "crypto/aes"
  11. "crypto/cipher"
  12. "github.com/gogf/gf/v2/errors/gcode"
  13. "github.com/gogf/gf/v2/errors/gerror"
  14. )
  15. const (
  16. // IVDefaultValue is the default value for IV.
  17. IVDefaultValue = "I Love Go Frame!"
  18. )
  19. // Encrypt is alias of EncryptCBC.
  20. func Encrypt(plainText []byte, key []byte, iv ...[]byte) ([]byte, error) {
  21. return EncryptCBC(plainText, key, iv...)
  22. }
  23. // Decrypt is alias of DecryptCBC.
  24. func Decrypt(cipherText []byte, key []byte, iv ...[]byte) ([]byte, error) {
  25. return DecryptCBC(cipherText, key, iv...)
  26. }
  27. // EncryptCBC encrypts `plainText` using CBC mode.
  28. // Note that the key must be 16/24/32 bit length.
  29. // The parameter `iv` initialization vector is unnecessary.
  30. func EncryptCBC(plainText []byte, key []byte, iv ...[]byte) ([]byte, error) {
  31. block, err := aes.NewCipher(key)
  32. if err != nil {
  33. err = gerror.WrapCodef(gcode.CodeInvalidParameter, err, `aes.NewCipher failed for key "%s"`, key)
  34. return nil, err
  35. }
  36. blockSize := block.BlockSize()
  37. plainText = PKCS5Padding(plainText, blockSize)
  38. ivValue := ([]byte)(nil)
  39. if len(iv) > 0 {
  40. ivValue = iv[0]
  41. } else {
  42. ivValue = []byte(IVDefaultValue)
  43. }
  44. blockMode := cipher.NewCBCEncrypter(block, ivValue)
  45. cipherText := make([]byte, len(plainText))
  46. blockMode.CryptBlocks(cipherText, plainText)
  47. return cipherText, nil
  48. }
  49. // DecryptCBC decrypts `cipherText` using CBC mode.
  50. // Note that the key must be 16/24/32 bit length.
  51. // The parameter `iv` initialization vector is unnecessary.
  52. func DecryptCBC(cipherText []byte, key []byte, iv ...[]byte) ([]byte, error) {
  53. block, err := aes.NewCipher(key)
  54. if err != nil {
  55. err = gerror.WrapCodef(gcode.CodeInvalidParameter, err, `aes.NewCipher failed for key "%s"`, key)
  56. return nil, err
  57. }
  58. blockSize := block.BlockSize()
  59. if len(cipherText) < blockSize {
  60. return nil, gerror.NewCode(gcode.CodeInvalidParameter, "cipherText too short")
  61. }
  62. ivValue := ([]byte)(nil)
  63. if len(iv) > 0 {
  64. ivValue = iv[0]
  65. } else {
  66. ivValue = []byte(IVDefaultValue)
  67. }
  68. if len(cipherText)%blockSize != 0 {
  69. return nil, gerror.NewCode(gcode.CodeInvalidParameter, "cipherText is not a multiple of the block size")
  70. }
  71. blockModel := cipher.NewCBCDecrypter(block, ivValue)
  72. plainText := make([]byte, len(cipherText))
  73. blockModel.CryptBlocks(plainText, cipherText)
  74. plainText, e := PKCS5UnPadding(plainText, blockSize)
  75. if e != nil {
  76. return nil, e
  77. }
  78. return plainText, nil
  79. }
  80. func PKCS5Padding(src []byte, blockSize int) []byte {
  81. padding := blockSize - len(src)%blockSize
  82. padtext := bytes.Repeat([]byte{byte(padding)}, padding)
  83. return append(src, padtext...)
  84. }
  85. func PKCS5UnPadding(src []byte, blockSize int) ([]byte, error) {
  86. length := len(src)
  87. if blockSize <= 0 {
  88. return nil, gerror.NewCode(gcode.CodeInvalidParameter, "invalid blocklen")
  89. }
  90. if length%blockSize != 0 || length == 0 {
  91. return nil, gerror.NewCode(gcode.CodeInvalidParameter, "invalid data len")
  92. }
  93. unpadding := int(src[length-1])
  94. if unpadding > blockSize || unpadding == 0 {
  95. return nil, gerror.NewCode(gcode.CodeInvalidParameter, "invalid padding")
  96. }
  97. padding := src[length-unpadding:]
  98. for i := 0; i < unpadding; i++ {
  99. if padding[i] != byte(unpadding) {
  100. return nil, gerror.NewCode(gcode.CodeInvalidParameter, "invalid padding")
  101. }
  102. }
  103. return src[:(length - unpadding)], nil
  104. }
  105. // EncryptCFB encrypts `plainText` using CFB mode.
  106. // Note that the key must be 16/24/32 bit length.
  107. // The parameter `iv` initialization vector is unnecessary.
  108. func EncryptCFB(plainText []byte, key []byte, padding *int, iv ...[]byte) ([]byte, error) {
  109. block, err := aes.NewCipher(key)
  110. if err != nil {
  111. err = gerror.WrapCodef(gcode.CodeInvalidParameter, err, `aes.NewCipher failed for key "%s"`, key)
  112. return nil, err
  113. }
  114. blockSize := block.BlockSize()
  115. plainText, *padding = ZeroPadding(plainText, blockSize)
  116. ivValue := ([]byte)(nil)
  117. if len(iv) > 0 {
  118. ivValue = iv[0]
  119. } else {
  120. ivValue = []byte(IVDefaultValue)
  121. }
  122. stream := cipher.NewCFBEncrypter(block, ivValue)
  123. cipherText := make([]byte, len(plainText))
  124. stream.XORKeyStream(cipherText, plainText)
  125. return cipherText, nil
  126. }
  127. // DecryptCFB decrypts `plainText` using CFB mode.
  128. // Note that the key must be 16/24/32 bit length.
  129. // The parameter `iv` initialization vector is unnecessary.
  130. func DecryptCFB(cipherText []byte, key []byte, unPadding int, iv ...[]byte) ([]byte, error) {
  131. block, err := aes.NewCipher(key)
  132. if err != nil {
  133. err = gerror.WrapCodef(gcode.CodeInvalidParameter, err, `aes.NewCipher failed for key "%s"`, key)
  134. return nil, err
  135. }
  136. if len(cipherText) < aes.BlockSize {
  137. return nil, gerror.NewCode(gcode.CodeInvalidParameter, "cipherText too short")
  138. }
  139. ivValue := ([]byte)(nil)
  140. if len(iv) > 0 {
  141. ivValue = iv[0]
  142. } else {
  143. ivValue = []byte(IVDefaultValue)
  144. }
  145. stream := cipher.NewCFBDecrypter(block, ivValue)
  146. plainText := make([]byte, len(cipherText))
  147. stream.XORKeyStream(plainText, cipherText)
  148. plainText = ZeroUnPadding(plainText, unPadding)
  149. return plainText, nil
  150. }
  151. func ZeroPadding(cipherText []byte, blockSize int) ([]byte, int) {
  152. padding := blockSize - len(cipherText)%blockSize
  153. padText := bytes.Repeat([]byte{byte(0)}, padding)
  154. return append(cipherText, padText...), padding
  155. }
  156. func ZeroUnPadding(plaintext []byte, unPadding int) []byte {
  157. length := len(plaintext)
  158. return plaintext[:(length - unPadding)]
  159. }