aes.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package encrypt
  2. import (
  3. "bytes"
  4. "crypto/aes"
  5. "crypto/cipher"
  6. "crypto/rand"
  7. "encoding/base64"
  8. "encoding/hex"
  9. "io"
  10. )
  11. /*CBC加密 按照golang标准库的例子代码
  12. 不过里面没有填充的部分,所以补上,根据key来决定填充blocksize
  13. */
  14. //使用PKCS7进行填充,IOS也是7
  15. func pkcs7Padding(ciphertext []byte, blockSize int) []byte {
  16. padding := blockSize - len(ciphertext)%blockSize
  17. padtext := bytes.Repeat([]byte{byte(padding)}, padding)
  18. return append(ciphertext, padtext...)
  19. }
  20. func pkcs7UnPadding(origData []byte) []byte {
  21. length := len(origData)
  22. unpadding := int(origData[length-1])
  23. return origData[:(length - unpadding)]
  24. }
  25. func ZeroPadding(ciphertext []byte, blockSize int) []byte {
  26. padding := blockSize - len(ciphertext)%blockSize
  27. padtext := bytes.Repeat([]byte{0}, padding)//用0去填充
  28. return append(ciphertext, padtext...)
  29. }
  30. //aes加密,填充模式由key决定,16位,24,32分别对应AES-128, AES-192, or AES-256.源码好像是写死16了
  31. func AesCBCEncrypt(rawData, key []byte) ([]byte, error) {
  32. block, err := aes.NewCipher(key)
  33. if err != nil {
  34. panic(err)
  35. }
  36. //填充原文
  37. blockSize := block.BlockSize()
  38. rawData = pkcs7Padding(rawData, blockSize)
  39. //初始向量IV必须是唯一,但不需要保密
  40. cipherText := make([]byte, blockSize+len(rawData))
  41. //block大小 16
  42. iv := cipherText[:blockSize]
  43. if _, err := io.ReadFull(rand.Reader, iv); err != nil {
  44. panic(err)
  45. }
  46. //block大小和初始向量大小一定要一致
  47. mode := cipher.NewCBCEncrypter(block, iv)
  48. mode.CryptBlocks(cipherText[blockSize:], rawData)
  49. return cipherText, nil
  50. }
  51. func AesCBCDecrypt(encryptData, key []byte) ([]byte, error) {
  52. block, err := aes.NewCipher(key)
  53. if err != nil {
  54. panic(err)
  55. }
  56. blockSize := block.BlockSize()
  57. if len(encryptData) < blockSize {
  58. panic("ciphertext too short")
  59. }
  60. // CBC mode always works in whole blocks.
  61. if len(encryptData)%blockSize != 0 {
  62. panic("ciphertext is not a multiple of the block size")
  63. }
  64. mode := cipher.NewCBCDecrypter(block, key)
  65. // CryptBlocks can work in-place if the two arguments are the same.
  66. mode.CryptBlocks(encryptData, encryptData)
  67. //解填充
  68. encryptData = ZeroPadding(encryptData, blockSize)
  69. return encryptData, nil
  70. }
  71. func Encrypt(rawData, key []byte) (string, error) {
  72. data, err := AesCBCEncrypt(rawData, key)
  73. if err != nil {
  74. return "", err
  75. }
  76. return base64.StdEncoding.EncodeToString(data), nil
  77. }
  78. func Decrypt(rawData string, key []byte) (string, error) {
  79. data, err := hex.DecodeString(rawData)
  80. if err != nil {
  81. return "", err
  82. }
  83. dnData, err := AesCBCDecrypt(data, key)
  84. if err != nil {
  85. return "", err
  86. }
  87. return string(dnData), nil
  88. }