mcrypto.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. package packet
  2. import (
  3. "bytes"
  4. "crypto/aes"
  5. "crypto/cipher"
  6. "crypto/des"
  7. "encoding/binary"
  8. "encoding/hex"
  9. "errors"
  10. )
  11. const AESKey = "F7A72DE7D6264530F01BA49BC73EB873"
  12. const macKey = "B0FB83E39A5EBFAABE471362A58393FF"
  13. const macIV = "D951DBE037C82325"
  14. // FIXME: - 为减少内存操作,这里的[]byte应该使用*[]byte
  15. func Encrypt(plaintext []byte, keyHex string, isPacket50 bool) ([]byte, error) {
  16. key := []byte(keyHex)
  17. // 构建密文结构体: 4 byte 明文长度+密文+8 byte MAC检验码
  18. result := []byte{}
  19. // 明文长度
  20. plaintextLen := len(plaintext)
  21. plaintextLenData := make([]byte, 4) // 如果写为 []byte{},PutUint32时会报溢出
  22. binary.LittleEndian.PutUint32(plaintextLenData, uint32(plaintextLen))
  23. result = append(result, plaintextLenData...)
  24. // mac校验目标
  25. macPlainText := result[:]
  26. macPlainText = append(macPlainText, []byte{0, 0, 0, 0}...)
  27. // 对内容进行加密
  28. if isPacket50 {
  29. // 5.0 报文
  30. ciphertext, err := aesEncrypt(plaintext, key)
  31. // ciphertext, err := aesEncrypt(plaintext, key)
  32. if err != nil {
  33. return nil, err
  34. }
  35. result = append(result, ciphertext...)
  36. } else {
  37. // 4.0 报文
  38. }
  39. // MAC检验码
  40. // 注意:由于服务端的错误(遇到\0就停止),原本需要把长度+密文生成校验码,现改由长度4 byte进行校验即可
  41. macKeyData, _ := hex.DecodeString(macKey)
  42. macIVData, _ := hex.DecodeString(macIV)
  43. macData, err := macAnsi(macPlainText, macKeyData, macIVData)
  44. if err != nil {
  45. return nil, err
  46. }
  47. result = append(result, macData...)
  48. return result, nil
  49. }
  50. func Decrypt(ciphertext []byte, keyHex string, isPacket50 bool) ([]byte, error) {
  51. key := []byte(keyHex)
  52. // 对内容进行加密
  53. if isPacket50 {
  54. return aesDecrypt(ciphertext, key)
  55. } else {
  56. return nil, nil
  57. }
  58. }
  59. func aesEncrypt(plaintext, key []byte) ([]byte, error) {
  60. block, err := aes.NewCipher(key)
  61. if err != nil {
  62. return nil, errors.New("错误的数据或密钥")
  63. }
  64. ecb := NewECBEncrypter(block)
  65. content := plaintext[:]
  66. content = PKCS5Padding(content, block.BlockSize())
  67. crypted := make([]byte, len(content))
  68. ecb.CryptBlocks(crypted, content)
  69. return crypted, nil
  70. }
  71. func aesDecrypt(crypted, key []byte) ([]byte, error) {
  72. block, err := aes.NewCipher(key)
  73. if err != nil {
  74. return nil, errors.New("错误的数据或密钥")
  75. }
  76. blockMode := NewECBDecrypter(block)
  77. origData := make([]byte, len(crypted))
  78. blockMode.CryptBlocks(origData, crypted)
  79. origData = PKCS5UnPadding(origData)
  80. return origData, nil
  81. }
  82. // Des加密
  83. func desEncrypt(plaintext []byte, key []byte) ([]byte, error) {
  84. if len(plaintext) < 1 || len(key) < 1 {
  85. return nil, errors.New("错误的数据或密钥")
  86. }
  87. block, err := des.NewCipher(key)
  88. if err != nil {
  89. return nil, err
  90. }
  91. blockSize := block.BlockSize()
  92. origData := PKCS5Padding(plaintext, blockSize)
  93. out := make([]byte, len(origData))
  94. dst := out
  95. // for len(origData) > 0 {
  96. // block.Encrypt(dst, origData[:blockSize])
  97. // origData = origData[blockSize:]
  98. // dst = dst[blockSize:]
  99. // }
  100. // return out, nil
  101. block.Encrypt(dst, origData[:blockSize])
  102. origData = origData[blockSize:]
  103. dst = dst[blockSize:]
  104. return out[0:8], nil
  105. }
  106. // Des解密
  107. func desDecrypt(plaintext []byte, key []byte) ([]byte, error) {
  108. if len(plaintext) < 1 || len(key) < 1 {
  109. return nil, errors.New("wrong data or key")
  110. }
  111. block, err := des.NewCipher(key)
  112. if err != nil {
  113. return nil, err
  114. }
  115. blockSize := block.BlockSize()
  116. origData := PKCS5Padding(plaintext, blockSize)
  117. out := make([]byte, len(origData))
  118. dst := out
  119. // for len(origData) > 0 {
  120. // block.Decrypt(dst, origData[:blockSize])
  121. // origData = origData[blockSize:]
  122. // dst = dst[blockSize:]
  123. // }
  124. // return out, nil
  125. block.Decrypt(dst, origData[:blockSize])
  126. origData = origData[blockSize:]
  127. dst = dst[blockSize:]
  128. return out[0:8], nil
  129. }
  130. func macAnsiX99(plainText []byte, key []byte, iv []byte) ([]byte, error) {
  131. if len(plainText)%8 != 0 {
  132. return nil, errors.New("目标数据长度必须为8的整数倍")
  133. }
  134. if len(key) != 8 {
  135. return nil, errors.New("密钥位数不正确")
  136. }
  137. if len(iv) != 8 {
  138. return nil, errors.New("向量位数不正确")
  139. }
  140. macData := iv[:]
  141. xorData := make([]byte, 8)
  142. for i := 0; i < len(plainText); i += 8 {
  143. // 以8 byte为单位进行异或运算
  144. for j := 0; j < 8; j++ {
  145. xorData[j] = macData[j] ^ plainText[i+j]
  146. }
  147. // 异或结果的 8 byte 数据进行一次DES加密
  148. desData, err := desEncrypt(xorData, key)
  149. if err != nil {
  150. return nil, err
  151. }
  152. macData = desData[:]
  153. }
  154. return macData, nil
  155. }
  156. func macAnsiX919(plainText []byte, key []byte, iv []byte) ([]byte, error) {
  157. if len(plainText)%8 != 0 {
  158. return nil, errors.New("目标数据长度必须为8的整数倍")
  159. }
  160. if len(key) != 16 {
  161. return nil, errors.New("密钥位数不正确")
  162. }
  163. if len(iv) != 8 {
  164. return nil, errors.New("向量位数不正确")
  165. }
  166. // 分解密钥
  167. keyLeft := key[0:8]
  168. keyRight := key[8:16]
  169. // MAC(L)->R解密->L加密
  170. dataLeft, err := macAnsiX99(plainText, keyLeft, iv)
  171. if err != nil {
  172. return nil, err
  173. }
  174. dataRight, err := desDecrypt(dataLeft, keyRight)
  175. if err != nil {
  176. return nil, err
  177. }
  178. return desEncrypt(dataRight, keyLeft)
  179. }
  180. func macAnsi(plainText []byte, key []byte, iv []byte) ([]byte, error) {
  181. keyLen := len(key)
  182. if keyLen == 8 {
  183. return macAnsiX99(plainText, key, iv)
  184. } else if keyLen == 16 {
  185. return macAnsiX919(plainText, key, iv)
  186. } else {
  187. return nil, errors.New("密钥位数不正确")
  188. }
  189. }
  190. //ECB PKCS5Padding
  191. func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
  192. padding := blockSize - len(ciphertext)%blockSize
  193. padtext := bytes.Repeat([]byte{byte(padding)}, padding)
  194. return append(ciphertext, padtext...)
  195. }
  196. //ECB PKCS5Unpadding
  197. func PKCS5UnPadding(origData []byte) []byte {
  198. length := len(origData)
  199. // 去掉最后一个字节 unpadding 次
  200. unpadding := int(origData[length-1])
  201. if unpadding > unpadding {
  202. return []byte{}
  203. }
  204. return origData[:(length - unpadding)]
  205. }
  206. type ecb struct {
  207. b cipher.Block
  208. blockSize int
  209. }
  210. func newECB(b cipher.Block) *ecb {
  211. return &ecb{
  212. b: b,
  213. blockSize: b.BlockSize(),
  214. }
  215. }
  216. type ecbEncrypter ecb
  217. // NewECBEncrypter returns a BlockMode which encrypts in electronic code book
  218. // mode, using the given Block.
  219. func NewECBEncrypter(b cipher.Block) cipher.BlockMode {
  220. return (*ecbEncrypter)(newECB(b))
  221. }
  222. func (x *ecbEncrypter) BlockSize() int { return x.blockSize }
  223. func (x *ecbEncrypter) CryptBlocks(dst, src []byte) {
  224. if len(src)%x.blockSize != 0 {
  225. panic("crypto/cipher: input not full blocks")
  226. }
  227. if len(dst) < len(src) {
  228. panic("crypto/cipher: output smaller than input")
  229. }
  230. for len(src) > 0 {
  231. x.b.Encrypt(dst, src[:x.blockSize])
  232. src = src[x.blockSize:]
  233. dst = dst[x.blockSize:]
  234. }
  235. }
  236. type ecbDecrypter ecb
  237. // NewECBDecrypter returns a BlockMode which decrypts in electronic code book
  238. // mode, using the given Block.
  239. func NewECBDecrypter(b cipher.Block) cipher.BlockMode {
  240. return (*ecbDecrypter)(newECB(b))
  241. }
  242. func (x *ecbDecrypter) BlockSize() int { return x.blockSize }
  243. func (x *ecbDecrypter) CryptBlocks(dst, src []byte) {
  244. if len(src)%x.blockSize != 0 {
  245. panic("crypto/cipher: input not full blocks")
  246. }
  247. if len(dst) < len(src) {
  248. panic("crypto/cipher: output smaller than input")
  249. }
  250. for len(src) > 0 {
  251. x.b.Decrypt(dst, src[:x.blockSize])
  252. src = src[x.blockSize:]
  253. dst = dst[x.blockSize:]
  254. }
  255. }