package algos import ( "crypto/aes" "crypto/cipher" "crypto/md5" "encoding/base64" "encoding/binary" "encoding/hex" "fmt" "math/rand" "net/url" ) // Argus Argus加密器 type Argus struct{} // encryptEncPb 加密ProtoBuf func encryptEncPb(data []byte, l int) []byte { dataCopy := make([]byte, len(data)) copy(dataCopy, data) xorArray := dataCopy[:8] for i := 8; i < l; i++ { dataCopy[i] ^= xorArray[i%8] } // 反转数组 for i := 0; i < l/2; i++ { dataCopy[i], dataCopy[l-1-i] = dataCopy[l-1-i], dataCopy[i] } return dataCopy[:l] } // GetBodyHash 获取Body哈希 func GetBodyHash(stub string) []byte { sm3 := NewSM3() if stub == "" || len(stub) == 0 { return sm3.Hash(make([]byte, 16))[0:6] } stubBytes, _ := hex.DecodeString(stub) return sm3.Hash(stubBytes)[0:6] } // GetQueryHash 获取Query哈希 func GetQueryHash(query string) []byte { sm3 := NewSM3() if query == "" || len(query) == 0 { return sm3.Hash(make([]byte, 16))[0:6] } return sm3.Hash([]byte(query))[0:6] } // Encrypt Argus加密 func (a *Argus) Encrypt(xargusBean map[int]interface{}) string { // 创建ProtoBuf protobuf := NewProtoBuf(xargusBean).ToBuf() // PKCS7填充 protobuf = AddPKCS7Padding(protobuf, 16) newLen := len(protobuf) signKey := []byte{ 0xAC, 0x1A, 0xDA, 0xAE, 0x95, 0xA7, 0xAF, 0x94, 0xA5, 0x11, 0x4A, 0xB3, 0xB3, 0xA9, 0x7D, 0xD8, 0x00, 0x50, 0xAA, 0x0A, 0x39, 0x31, 0x4C, 0x40, 0x52, 0x8C, 0xAE, 0xC9, 0x52, 0x56, 0xC2, 0x8C, } sm3Output := []byte{ 0xFC, 0x78, 0xE0, 0xA9, 0x65, 0x7A, 0x0C, 0x74, 0x8C, 0xE5, 0x15, 0x59, 0x90, 0x3C, 0xCF, 0x03, 0x51, 0x0E, 0x51, 0xD3, 0xCF, 0xF2, 0x32, 0xD7, 0x13, 0x43, 0xE8, 0x8A, 0x32, 0x1C, 0x53, 0x04, } key := sm3Output[:32] keyList := make([]uint64, 0) encPb := make([]byte, newLen) for i := 0; i < 2; i++ { val1 := binary.LittleEndian.Uint64(key[i*16 : i*16+8]) val2 := binary.LittleEndian.Uint64(key[i*16+8 : i*16+16]) keyList = append(keyList, val1, val2) } for i := 0; i < newLen/16; i++ { pt := []uint64{ binary.LittleEndian.Uint64(protobuf[i*16 : i*16+8]), binary.LittleEndian.Uint64(protobuf[i*16+8 : i*16+16]), } ct := SimonEnc(pt, keyList, 0) binary.LittleEndian.PutUint64(encPb[i*16:i*16+8], ct[0]) binary.LittleEndian.PutUint64(encPb[i*16+8:i*16+16], ct[1]) } header := []byte{0xF2, 0xF7, 0xFC, 0xFF, 0xF2, 0xF7, 0xFC, 0xFF} bBuffer := encryptEncPb(append(header, encPb...), newLen+8) bBuffer = append([]byte{0xA6, 0x6E, 0xAD, 0x9F, 0x77, 0x01, 0xD0, 0x0C, 0x18}, bBuffer...) bBuffer = append(bBuffer, []byte("ao")...) // AES加密 keyHash := md5.Sum(signKey[:16]) ivHash := md5.Sum(signKey[16:]) block, _ := aes.NewCipher(keyHash[:]) paddedBuffer := AddPKCS7Padding(bBuffer, aes.BlockSize) ciphertext := make([]byte, len(paddedBuffer)) mode := cipher.NewCBCEncrypter(block, ivHash[:]) mode.CryptBlocks(ciphertext, paddedBuffer) result := append([]byte{0xF2, 0x81}, ciphertext...) return base64.StdEncoding.EncodeToString(result) } // GetSign 获取签名 func (a *Argus) GetSign( queryhash string, data string, timestamp int64, aid int, licenseID int, platform int, secDeviceID string, sdkVersion string, sdkVersionInt int, ) string { paramsDict, _ := url.ParseQuery(queryhash) deviceID := "" if val, ok := paramsDict["device_id"]; ok && len(val) > 0 { deviceID = val[0] } versionName := "" if val, ok := paramsDict["version_name"]; ok && len(val) > 0 { versionName = val[0] } xargusBean := map[int]interface{}{ 1: 0x20200929 << 1, 2: 2, 3: rand.Int63n(0x7FFFFFFF), 4: fmt.Sprintf("%d", aid), 5: deviceID, 6: fmt.Sprintf("%d", licenseID), 7: versionName, 8: sdkVersion, 9: sdkVersionInt, 10: make([]byte, 8), 11: platform, 12: timestamp << 1, 13: GetBodyHash(data), 14: GetQueryHash(queryhash), 15: map[int]interface{}{ 1: 1, 2: 1, 3: 1, 7: 3348294860, }, 16: secDeviceID, 20: "none", 21: 738, 23: map[int]interface{}{ 1: "NX551J", 2: 8196, 4: 2162219008, }, 25: 2, } return a.Encrypt(xargusBean) }