aesecb.go 4.1 KB

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