mcrypto.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  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. var err error
  73. defer func() {
  74. if err := recover(); err != nil {
  75. return
  76. }
  77. }()
  78. block, err := aes.NewCipher(key)
  79. if err != nil {
  80. return nil, err
  81. }
  82. blockMode := NewECBDecrypter(block)
  83. origData := make([]byte, len(crypted))
  84. blockMode.CryptBlocks(origData, crypted)
  85. origData = PKCS5UnPadding(origData)
  86. return origData, err
  87. }
  88. // Des加密
  89. func desEncrypt(plaintext []byte, key []byte) ([]byte, error) {
  90. if len(plaintext) < 1 || len(key) < 1 {
  91. return nil, errors.New("错误的数据或密钥")
  92. }
  93. block, err := des.NewCipher(key)
  94. if err != nil {
  95. return nil, err
  96. }
  97. blockSize := block.BlockSize()
  98. origData := PKCS5Padding(plaintext, blockSize)
  99. out := make([]byte, len(origData))
  100. dst := out
  101. // for len(origData) > 0 {
  102. // block.Encrypt(dst, origData[:blockSize])
  103. // origData = origData[blockSize:]
  104. // dst = dst[blockSize:]
  105. // }
  106. // return out, nil
  107. block.Encrypt(dst, origData[:blockSize])
  108. origData = origData[blockSize:]
  109. dst = dst[blockSize:]
  110. return out[0:8], nil
  111. }
  112. // Des解密
  113. func desDecrypt(plaintext []byte, key []byte) ([]byte, error) {
  114. if len(plaintext) < 1 || len(key) < 1 {
  115. return nil, errors.New("wrong data or key")
  116. }
  117. block, err := des.NewCipher(key)
  118. if err != nil {
  119. return nil, err
  120. }
  121. blockSize := block.BlockSize()
  122. origData := PKCS5Padding(plaintext, blockSize)
  123. out := make([]byte, len(origData))
  124. dst := out
  125. // for len(origData) > 0 {
  126. // block.Decrypt(dst, origData[:blockSize])
  127. // origData = origData[blockSize:]
  128. // dst = dst[blockSize:]
  129. // }
  130. // return out, nil
  131. block.Decrypt(dst, origData[:blockSize])
  132. origData = origData[blockSize:]
  133. dst = dst[blockSize:]
  134. return out[0:8], nil
  135. }
  136. func macAnsiX99(plainText []byte, key []byte, iv []byte) ([]byte, error) {
  137. if len(plainText)%8 != 0 {
  138. return nil, errors.New("目标数据长度必须为8的整数倍")
  139. }
  140. if len(key) != 8 {
  141. return nil, errors.New("密钥位数不正确")
  142. }
  143. if len(iv) != 8 {
  144. return nil, errors.New("向量位数不正确")
  145. }
  146. macData := iv[:]
  147. xorData := make([]byte, 8)
  148. for i := 0; i < len(plainText); i += 8 {
  149. // 以8 byte为单位进行异或运算
  150. for j := 0; j < 8; j++ {
  151. xorData[j] = macData[j] ^ plainText[i+j]
  152. }
  153. // 异或结果的 8 byte 数据进行一次DES加密
  154. desData, err := desEncrypt(xorData, key)
  155. if err != nil {
  156. return nil, err
  157. }
  158. macData = desData[:]
  159. }
  160. return macData, nil
  161. }
  162. func macAnsiX919(plainText []byte, key []byte, iv []byte) ([]byte, error) {
  163. if len(plainText)%8 != 0 {
  164. return nil, errors.New("目标数据长度必须为8的整数倍")
  165. }
  166. if len(key) != 16 {
  167. return nil, errors.New("密钥位数不正确")
  168. }
  169. if len(iv) != 8 {
  170. return nil, errors.New("向量位数不正确")
  171. }
  172. // 分解密钥
  173. keyLeft := key[0:8]
  174. keyRight := key[8:16]
  175. // MAC(L)->R解密->L加密
  176. dataLeft, err := macAnsiX99(plainText, keyLeft, iv)
  177. if err != nil {
  178. return nil, err
  179. }
  180. dataRight, err := desDecrypt(dataLeft, keyRight)
  181. if err != nil {
  182. return nil, err
  183. }
  184. return desEncrypt(dataRight, keyLeft)
  185. }
  186. func macAnsi(plainText []byte, key []byte, iv []byte) ([]byte, error) {
  187. keyLen := len(key)
  188. if keyLen == 8 {
  189. return macAnsiX99(plainText, key, iv)
  190. } else if keyLen == 16 {
  191. return macAnsiX919(plainText, key, iv)
  192. } else {
  193. return nil, errors.New("密钥位数不正确")
  194. }
  195. }
  196. // ECB PKCS5Padding
  197. func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
  198. padding := blockSize - len(ciphertext)%blockSize
  199. padtext := bytes.Repeat([]byte{byte(padding)}, padding)
  200. return append(ciphertext, padtext...)
  201. }
  202. // ECB PKCS5Unpadding
  203. func PKCS5UnPadding(origData []byte) []byte {
  204. length := len(origData)
  205. // 去掉最后一个字节 unpadding 次
  206. unpadding := int(origData[length-1])
  207. if unpadding > unpadding {
  208. return []byte{}
  209. }
  210. return origData[:(length - unpadding)]
  211. }
  212. type ecb struct {
  213. b cipher.Block
  214. blockSize int
  215. }
  216. func newECB(b cipher.Block) *ecb {
  217. return &ecb{
  218. b: b,
  219. blockSize: b.BlockSize(),
  220. }
  221. }
  222. type ecbEncrypter ecb
  223. // NewECBEncrypter returns a BlockMode which encrypts in electronic code book
  224. // mode, using the given Block.
  225. func NewECBEncrypter(b cipher.Block) cipher.BlockMode {
  226. return (*ecbEncrypter)(newECB(b))
  227. }
  228. func (x *ecbEncrypter) BlockSize() int { return x.blockSize }
  229. func (x *ecbEncrypter) CryptBlocks(dst, src []byte) {
  230. if len(src)%x.blockSize != 0 {
  231. panic("crypto/cipher: input not full blocks")
  232. }
  233. if len(dst) < len(src) {
  234. panic("crypto/cipher: output smaller than input")
  235. }
  236. for len(src) > 0 {
  237. x.b.Encrypt(dst, src[:x.blockSize])
  238. src = src[x.blockSize:]
  239. dst = dst[x.blockSize:]
  240. }
  241. }
  242. type ecbDecrypter ecb
  243. // NewECBDecrypter returns a BlockMode which decrypts in electronic code book
  244. // mode, using the given Block.
  245. func NewECBDecrypter(b cipher.Block) cipher.BlockMode {
  246. return (*ecbDecrypter)(newECB(b))
  247. }
  248. func (x *ecbDecrypter) BlockSize() int { return x.blockSize }
  249. func (x *ecbDecrypter) CryptBlocks(dst, src []byte) {
  250. if len(src)%x.blockSize != 0 {
  251. panic("crypto/cipher: input not full blocks")
  252. }
  253. if len(dst) < len(src) {
  254. panic("crypto/cipher: output smaller than input")
  255. }
  256. for len(src) > 0 {
  257. x.b.Decrypt(dst, src[:x.blockSize])
  258. src = src[x.blockSize:]
  259. dst = dst[x.blockSize:]
  260. }
  261. }