Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

155 lines
3.9KB

  1. package main
  2. import (
  3. "crypto/aes"
  4. "crypto/cipher"
  5. "crypto/rand"
  6. "encoding/base64"
  7. "fmt"
  8. )
  9. //Encode convert a xml sequence into encrypted message
  10. func Encode(s string) string {
  11. d := aesEncryptMsg(random16Byte(), []byte(s), APIConfig.Appid, getAesEncryptKey())
  12. r := base64.StdEncoding.EncodeToString(d)
  13. //fmt.Println(r)
  14. return r
  15. }
  16. //Decode Decode encrypt string to xml context
  17. func Decode(s string) string {
  18. r, _ := base64.StdEncoding.DecodeString(s)
  19. _, raw, err := aesDecryptMsg([]byte(r), APIConfig.Appid, getAesEncryptKey())
  20. if err == nil {
  21. return string(raw)
  22. }
  23. return ""
  24. }
  25. // 把整数 n 格式化成 4 字节的网络字节序
  26. func encodeNetworkBytesOrder(orderBytes []byte, n int) {
  27. if len(orderBytes) != 4 {
  28. panic("the length of orderBytes must be equal to 4")
  29. }
  30. orderBytes[0] = byte(n >> 24)
  31. orderBytes[1] = byte(n >> 16)
  32. orderBytes[2] = byte(n >> 8)
  33. orderBytes[3] = byte(n)
  34. }
  35. // 从 4 字节的网络字节序里解析出整数
  36. func decodeNetworkBytesOrder(orderBytes []byte) (n int) {
  37. if len(orderBytes) != 4 {
  38. panic("the length of orderBytes must be equal to 4")
  39. }
  40. n = int(orderBytes[0])<<24 |
  41. int(orderBytes[1])<<16 |
  42. int(orderBytes[2])<<8 |
  43. int(orderBytes[3])
  44. return
  45. }
  46. func random16Byte() []byte {
  47. token := make([]byte, 16)
  48. rand.Read(token)
  49. return token
  50. }
  51. //AESEncryptMsg given an xml message and 16 bytes random string
  52. //encryptedMsg = AES_Encrypt[random(16B) + msg_len(4B) + rawXMLMsg + AppId]
  53. func aesEncryptMsg(random, rawXMLMsg []byte, AppId string, AESKey [32]byte) (encryptedMsg []byte) {
  54. const BLOCK_SIZE = 32 // PKCS#7
  55. buf := make([]byte, 20+len(rawXMLMsg)+len(AppId)+BLOCK_SIZE)
  56. plain := buf[:20]
  57. pad := buf[len(buf)-BLOCK_SIZE:]
  58. // 拼接
  59. copy(plain, random)
  60. encodeNetworkBytesOrder(plain[16:20], len(rawXMLMsg))
  61. plain = append(plain, rawXMLMsg...)
  62. plain = append(plain, AppId...)
  63. // PKCS#7 补位
  64. amountToPad := BLOCK_SIZE - len(plain)%BLOCK_SIZE
  65. for i := 0; i < amountToPad; i++ {
  66. pad[i] = byte(amountToPad)
  67. }
  68. plain = buf[:len(plain)+amountToPad]
  69. // 加密
  70. block, err := aes.NewCipher(AESKey[:])
  71. if err != nil {
  72. panic(err)
  73. }
  74. mode := cipher.NewCBCEncrypter(block, AESKey[:16])
  75. mode.CryptBlocks(plain, plain)
  76. encryptedMsg = plain
  77. return
  78. }
  79. //AESDecryptMsg given a string decode it into three parts
  80. // encryptedMsg = AES_Encrypt[random(16B) + msg_len(4B) + rawXMLMsg + AppId]
  81. func aesDecryptMsg(encryptedMsg []byte, AppId string, AESKey [32]byte) (random, rawXMLMsg []byte, err error) {
  82. const BLOCK_SIZE = 32 // PKCS#7
  83. if len(encryptedMsg) < BLOCK_SIZE {
  84. err = fmt.Errorf("the length of encryptedMsg too short: %d", len(encryptedMsg))
  85. return
  86. }
  87. if len(encryptedMsg)%BLOCK_SIZE != 0 {
  88. err = fmt.Errorf("encryptedMsg is not a multiple of the block size, the length is %d", len(encryptedMsg))
  89. return
  90. }
  91. plain := make([]byte, len(encryptedMsg)) // len(plain) >= BLOCK_SIZE
  92. // 解密
  93. block, err := aes.NewCipher(AESKey[:])
  94. if err != nil {
  95. panic(err)
  96. }
  97. mode := cipher.NewCBCDecrypter(block, AESKey[:16])
  98. mode.CryptBlocks(plain, encryptedMsg)
  99. // PKCS#7 去除补位
  100. amountToPad := int(plain[len(plain)-1])
  101. if amountToPad < 1 || amountToPad > BLOCK_SIZE {
  102. err = fmt.Errorf("the amount to pad is invalid: %d", amountToPad)
  103. return
  104. }
  105. plain = plain[:len(plain)-amountToPad]
  106. // 反拼装
  107. // len(plain) == 16+4+len(rawXMLMsg)+len(AppId)
  108. // len(AppId) > 0
  109. if len(plain) <= 20 {
  110. err = fmt.Errorf("plain msg too short, the length is %d", len(plain))
  111. return
  112. }
  113. msgLen := decodeNetworkBytesOrder(plain[16:20])
  114. if msgLen < 0 {
  115. err = fmt.Errorf("invalid msg length: %d", msgLen)
  116. return
  117. }
  118. msgEnd := 20 + msgLen
  119. if len(plain) <= msgEnd {
  120. err = fmt.Errorf("msg length too large: %d", msgLen)
  121. return
  122. }
  123. AppIdHave := string(plain[msgEnd:])
  124. if AppIdHave != AppId { // crypto/subtle.ConstantTimeCompare ???
  125. err = fmt.Errorf("AppId mismatch, have: %s, want: %s", AppIdHave, AppId)
  126. return
  127. }
  128. random = plain[:16:16]
  129. rawXMLMsg = plain[20:msgEnd]
  130. return
  131. }