From 6585dd456acd2357deb0e5d9e40c0fc29db085a2 Mon Sep 17 00:00:00 2001 From: linquan <349589071@qq.com> Date: Thu, 7 Aug 2025 17:47:42 +0800 Subject: [PATCH] caid --- caid.go | 243 ++++----------- .../serviceGame/internal/advertisement.go | 23 +- internal/serviceGame/internal/caid/caid.go | 288 +++++------------- internal/serviceGame/internal/manage.go | 46 ++- 4 files changed, 175 insertions(+), 425 deletions(-) diff --git a/caid.go b/caid.go index 0bb9cf4..054ffc5 100644 --- a/caid.go +++ b/caid.go @@ -2,26 +2,17 @@ package main import ( "bytes" - "context" "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/base64" "encoding/json" "encoding/pem" + "errors" "fmt" - "github.com/gogf/gf/v2/encoding/gcharset" - "github.com/gogf/gf/v2/encoding/gjson" - "github.com/gogf/gf/v2/frame/g" - "io" "io/ioutil" - "log" - "math/big" ) -const pubKeyBase64 = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCk2GwklLJO0m4Z5PffSSRlv7jNkQhFyoESukIu2duXN9YaC9G7SCQQnyHYs1Si/W4z/u5a4OXBE5+jZ9W9zmc1wfVelf2vnzTfKABA6AJhlsUXs2UjPQrxNRCgu4rALQ2TlbobqqLpIWtm5rqboXs3yJpRfgaLlJvAdihxx2XYQIDAQAB" -const maxDecryptBlock = 128 - func main() { // 设备公共信息 deviceInfo := map[string]string{ @@ -39,47 +30,30 @@ func main() { "deviceInitTime": "1632467920.301150749", } - // 公钥字符串,注意需要剔除换行符 - //PUBK := pubKeyBase64 // 分配的API接入的公钥字符串 - //privateKey, err := ioutil.ReadFile("manifest/config/dev_10702/public_for_api.pem") - //if err != nil { - // fmt.Println(err) - // return - //} - - // 序列化设备信息为JSON - jsonBytes, err := json.Marshal(deviceInfo) - if err != nil { - fmt.Printf("JSON序列化错误: %v\n", err) - return - } - jsonStr := string(jsonBytes) - // 加密设备信息 - encryptedDeviceByte, err := encrypt(jsonStr) + encryptedDeviceByte, err := encrypt(deviceInfo) if err != nil { fmt.Printf("加密错误 encrypt: %v\n", err) return } fmt.Printf("加密后的设备信息: encryptedDeviceByte: %s\n", encryptedDeviceByte) - ctx := context.TODO() - url := "https://caid.china-caa.org/v1.0/get" - data := map[string]interface{}{"dev_id": "10702", "encrypted_device_info": "mbJbTVF1b2m/4i59seIcqAizHHwtt4oMXOXmXKREqaGdVnDKrllvQlNiCt0xpazhcmrzs5aJP9nkEaeuI3omZvdOc1dSJG4oQPPE5X49ErfQL4IT867QzqFPt7AoYtV0DfGarTWwiUPo8JTcIdQBwL7bKgoog93qj8xl/q3y80tgyjVUfQPPWS/UVPfTzMy/lazKm1qY5SIHkm6vJDaUPSC3d4kEQdpicZo1H5cjeCyukP16O5t2PsksTqMJHOg62UIRO6zTNL0Q14+YWfmEaAeUiQrjH8nAfh+Jx3/N3CkcGAJOPrbCRCgfmSIwQ2F6D/pjQd3BNuSKB9W/a+PljRaA54reu0+2L0KJnfhmPXnqltLEclV1PGORYcx5cDK/tbfeXmmvLuPtroH1Dd/+Kc0hz5t2BAHiCh9M6kSqDOXF0muQIM6Mfc473F/uEeiwLZdQ6QbpYdXPYoB+jzQXrDkblpTWhBw4NKdEhR2o2sjVK73YP9BQHmEohzblfHCJ"} - g.Client().SetHeader("Content-Type", "application/json") - g.Client().SetHeader("Cache-Control", "no-cache") - log.Printf("sendMsgHugeAmount - url: %s, data: %s", url, gjson.MustEncodeString(data)) - marshal, _ := json.Marshal(data) - bytes, err := g.Client().Post(ctx, url, string(marshal)) - if err != nil { - return - } - src := string(bytes.ReadAll()) - tmp, err := gcharset.ToUTF8("UTF-8", src) - if err != nil { - return - } - fmt.Println("Deposit - json: ", tmp) + //url := "https://caid.china-caa.org/v1.0/get" + //data := map[string]interface{}{"dev_id": "10702", "encrypted_device_info": encryptedDeviceByte} + //g.Client().SetHeader("Content-Type", "application/json") + //g.Client().SetHeader("Cache-Control", "no-cache") + //log.Printf("sendMsgHugeAmount - url: %s, data: %s", url, gjson.MustEncodeString(data)) + //marshal, _ := json.Marshal(data) + //bytes, err := g.Client().Post(context.TODO(), url, string(marshal)) + //if err != nil { + // return + //} + //src := string(bytes.ReadAll()) + //tmp, err := gcharset.ToUTF8("UTF-8", src) + //if err != nil { + // return + //} + //fmt.Println("Deposit - json: ", tmp) ////tmp, err := SendCaidMsg(ctx, url, data) //if err != nil { // fmt.Println("SendCaidMsg err:", err) @@ -94,9 +68,9 @@ func main() { // fmt.Println("SendCaidMsg err:", resJson.Get("message").String()) // return //} - caid := "J5LdxnMrcpDiNrn2QLZvCPavphS9nUqu7uwCEjLkEvtP2blwhevgGvQD7AKajkEc+PIC2TuIFxbSGK9Jsm27CrsW446pi+gIIc3OdKB4jqQJoDD77BbJC3I105DnsEwgR8uLvSVy0NgqFq+rf4GRYwp93Jy2eZdDKkS+Y0BgTEQkedK1P29hyYEELLQzvJrq9XlwfYx1QcGGcofZmq56B65IbQQfRvoXAiSl2cm12qFkpD8KbPmvy66xE6yu3SFAMC6iAEdfW4W8hz0Qv9Bht2nhDxsm4c39z1mU41s1oP5lJ5kkUl4yU3NWRO19jIYOm8lMJb19oDc+weBaMkgIbQ==" - - fmt.Println("Deposit - caid: ", caid) + //caid := "J5LdxnMrcpDiNrn2QLZvCPavphS9nUqu7uwCEjLkEvtP2blwhevgGvQD7AKajkEc+PIC2TuIFxbSGK9Jsm27CrsW446pi+gIIc3OdKB4jqQJoDD77BbJC3I105DnsEwgR8uLvSVy0NgqFq+rf4GRYwp93Jy2eZdDKkS+Y0BgTEQkedK1P29hyYEELLQzvJrq9XlwfYx1QcGGcofZmq56B65IbQQfRvoXAiSl2cm12qFkpD8KbPmvy66xE6yu3SFAMC6iAEdfW4W8hz0Qv9Bht2nhDxsm4c39z1mU41s1oP5lJ5kkUl4yU3NWRO19jIYOm8lMJb19oDc+weBaMkgIbQ==" + // + //fmt.Println("Deposit - caid: ", caid) //encryptedDeviceInfo, err := encryptWithPublicKey(jsonStr, vm.publicKey) //if err != nil { @@ -113,59 +87,6 @@ func main() { } -// 使用公钥加密数据 -func encryptWithPublicKey(data string, rsaPubKey *rsa.PublicKey) (string, error) { - //// 解码Base64格式的公钥 - //pubKeyBytes, err := base64.StdEncoding.DecodeString(pubKeyStr) - //if err != nil { - // return "", fmt.Errorf("公钥Base64解码错误: %v", err) - //} - // - //// 解析公钥 - //publicKey, err := x509.ParsePKIXPublicKey(pubKeyBytes) - //if err != nil { - // return "", fmt.Errorf("公钥解析错误: %v", err) - //} - // - //// 断言为RSA公钥 - //rsaPubKey, ok := publicKey.(*rsa.PublicKey) - //if !ok { - // return "", errors.New("不是RSA公钥") - //} - - // 计算最大加密块大小 - maxEncryptBlock := rsaPubKey.Size() - 42 // PKCS#1 OAEP加密需要预留42字节 - - dataBytes := []byte(data) - dataLen := len(dataBytes) - var encryptedBytes []byte - - // 分段加密 - for i := 0; i < dataLen; i += maxEncryptBlock { - end := i + maxEncryptBlock - if end > dataLen { - end = dataLen - } - - // 加密当前块 - encryptedBlock, err := rsa.EncryptOAEP( - nil, - rand.Reader, - rsaPubKey, - dataBytes[i:end], - nil, - ) - if err != nil { - return "", fmt.Errorf("加密错误: %v", err) - } - - encryptedBytes = append(encryptedBytes, encryptedBlock...) - } - - // Base64编码加密结果 - return base64.StdEncoding.EncodeToString(encryptedBytes), nil -} - func ImportSPKIPublicKeyPEM() *rsa.PublicKey { pubKeyBytes, err := ioutil.ReadFile("manifest/config/dev_10702/public_for_api.pem") if err != nil { @@ -176,98 +97,50 @@ func ImportSPKIPublicKeyPEM() *rsa.PublicKey { fmt.Printf(" body.Bytes : %s\n byte: %s\n", body.Type, body.Bytes) publicKey, _ := x509.ParsePKIXPublicKey(body.Bytes) if publicKey, ok := publicKey.(*rsa.PublicKey); ok { + fmt.Printf("publicKey : %d\n ", publicKey.Size()) return publicKey } else { return nil } } -func encrypt(data string) (string, error) { - //raw, err := base64.StdEncoding.DecodeString(data) - //if err != nil { - // return nil, fmt.Errorf("base64 decode %w: %s", err, data) - //} - +func encrypt(deviceInfo map[string]string) (string, error) { pubKey := ImportSPKIPublicKeyPEM() - fmt.Printf("data: len: %d\n pubkey: %v\n", len(data), pubKey) - maxEncryptBlock := 117 - //ciphertextBytes, _ := base64.StdEncoding.DecodeString(data) - reader := bytes.NewReader([]byte(data)) - var writer bytes.Buffer - ciphertextBytesChunk := make([]byte, maxEncryptBlock) - fmt.Println("chunk: ", len([]byte(data)), len(ciphertextBytesChunk)) - for { - n, _ := io.ReadFull(reader, ciphertextBytesChunk) - if n == 0 { - fmt.Println("chunk: n ", n) - break - } - encryptChunk(ciphertextBytesChunk, &writer, pubKey) - fmt.Println("chunk: ", len(ciphertextBytesChunk)) + fmt.Printf("data: len: %d\n pubkey: %v\n", len(deviceInfo), pubKey) + + // 2. 计算RSA最大加密块大小(PKCS#1 v1.5填充需要11字节) + keySize := pubKey.Size() // 密钥字节长度(如2048位密钥为256字节) + maxEncryptBlock := keySize - 11 // 最大单次加密数据长度(256-11=245字节) + if maxEncryptBlock <= 0 { + return "", errors.New("无效的RSA公钥长度(必须≥11字节)") } - // Concatenate decrypted signature chunks - decryptedData := writer.String() - fmt.Println(decryptedData) - //reader := bytes.NewReader([]byte(data)) - //var writer bytes.Buffer - //chunk := make([]byte, maxEncryptBlock) - //fmt.Println("chunk: ", len(chunk)) - //for { - // n, err := io.ReadFull(reader, chunk) - // if err != nil && errors.Is(err, io.ErrUnexpectedEOF) { - // return nil, fmt.Errorf("read encrypt data: %w", err) - // } - // if n == 0 { - // break - // } - // encryptChunk(chunk, &writer, pubKey) - //} - output := bytes.TrimRight(bytes.TrimLeft(writer.Bytes(), "\x00"), "\n") - if bytes.Count(output, []byte("\x00")) > 0 { - after := bytes.ReplaceAll(output, []byte("\x00"), []byte{}) - log.Println("WARN: remove \x00 from caid's response", "before", output, "after", after) - output = after + + // 序列化设备信息为JSON + data, err := json.Marshal(deviceInfo) + if err != nil { + fmt.Printf("JSON序列化错误: %v\n", err) + return "", fmt.Errorf("JSON序列化错误: %v\n", err) } - //return output, nil - return string(output), nil -} -func encryptChunk(ciphertextBytesChunk []byte, writer *bytes.Buffer, pubKey *rsa.PublicKey) { - // Decrypt each signature chunk - ciphertextInt := new(big.Int) - ciphertextInt.SetBytes(ciphertextBytesChunk) - decryptedPaddedInt := doEncrypt(new(big.Int), pubKey, ciphertextInt) - // Remove padding - decryptedPaddedBytes := make([]byte, pubKey.Size()) - decryptedPaddedInt.FillBytes(decryptedPaddedBytes) - start := bytes.Index(decryptedPaddedBytes[1:], []byte{0}) + 1 // // 0001FF...FF00: Find index after 2nd 0x00 - decryptedBytes := decryptedPaddedBytes[start:] - // Write decrypted signature chunk - writer.Write(decryptedBytes) -} + plaintext := data + // 3. 分块加密 + var encryptedBlocks [][]byte + for offset := 0; offset < len(plaintext); offset += maxEncryptBlock { + end := offset + maxEncryptBlock + if end > len(plaintext) { + end = len(plaintext) + } + block := plaintext[offset:end] -func doEncrypt(c *big.Int, pub *rsa.PublicKey, m *big.Int) *big.Int { - // Textbook RSA - e := big.NewInt(int64(pub.E)) - c.Exp(m, e, pub.N) - return c -} + // 执行RSA加密(使用公钥指数e) + encryptedBlock, err := rsa.EncryptPKCS1v15(rand.Reader, pubKey, block) + if err != nil { + return "", fmt.Errorf("第%d字节块加密失败: %w", offset, err) + } + encryptedBlocks = append(encryptedBlocks, encryptedBlock) + } + + // 4. 拼接所有加密块并进行Base64编码 + encryptedBytes := bytes.Join(encryptedBlocks, nil) + // 4. 拼接所有加密块并进行Base64编码 + return base64.StdEncoding.EncodeToString(encryptedBytes), nil -//func encryptChunk(chunk []byte, writer *bytes.Buffer, pubKey *rsa.PublicKey) { -// // Decrypt each signature chunk -// ciphertextInt := new(big.Int) -// ciphertextInt.SetBytes(chunk) -// decryptedPaddedInt := doEncrypt(new(big.Int), pubKey, ciphertextInt) -// // Remove padding -// decryptedPaddedBytes := make([]byte, pubKey.Size()) -// decryptedPaddedInt.FillBytes(decryptedPaddedBytes) -// start := bytes.Index(decryptedPaddedBytes[1:], []byte{0}) + 1 // // 0001FF...FF00: Find index after 2nd 0x00 -// decryptedBytes := decryptedPaddedBytes[start:] -// // Write decrypted signature chunk -// writer.Write(decryptedBytes) -//} -// -//func doEncrypt(c *big.Int, pub *rsa.PublicKey, m *big.Int) *big.Int { -// // Textbook RSA -// e := big.NewInt(int64(pub.E)) -// c.Exp(m, e, pub.N) -// return c -//} +} diff --git a/internal/serviceGame/internal/advertisement.go b/internal/serviceGame/internal/advertisement.go index 2da7579..6345ce1 100644 --- a/internal/serviceGame/internal/advertisement.go +++ b/internal/serviceGame/internal/advertisement.go @@ -324,24 +324,7 @@ func AdvertiseHugeAmount(ctx context.Context, req *game.AdvertiseHAReq) (res *ga } func HugeAmount(ctx context.Context, req *game.AdvertiseHAReq) { - if req.Platform == "ios1" { - //url := "https://caid.china-caa.org/v1.0/get" - //data := map[string]interface{}{"dev_id": "10702", "encrypted_device_info": caid.EncryptDeviceInfo()} - //tmp, err := SendCaidMsg(ctx, url, data) - //if err != nil { - // fmt.Println("SendCaidMsg err:", err) - // return - //} - //resJson, err := gjson.DecodeToJson(tmp) - //if err != nil { - // fmt.Println("SendCaidMsg DecodeToJson err:", err) - // return - //} - //if resJson != nil && resJson.Get("code").Int() != 0 { - // fmt.Println("SendCaidMsg err:", resJson.Get("message").String()) - // return - //} - //req.Caid = resJson.Get("data").String() + if req.Platform == "ios" { if req.Caid != "" { decryptedByte, err := caid.Decrypt(req.Caid) if err != nil { @@ -350,9 +333,7 @@ func HugeAmount(ctx context.Context, req *game.AdvertiseHAReq) { } req.Caid = string(decryptedByte) } - - log.Printf("HugeAmount req2: %s", gjson.MustEncodeString(req)) - return + //log.Printf("HugeAmount caid: %s", gjson.MustEncodeString(req)) } req2 := game.CSHAReq{ diff --git a/internal/serviceGame/internal/caid/caid.go b/internal/serviceGame/internal/caid/caid.go index 186266f..a2a2d25 100644 --- a/internal/serviceGame/internal/caid/caid.go +++ b/internal/serviceGame/internal/caid/caid.go @@ -12,169 +12,35 @@ import ( "fmt" "io" "io/ioutil" - "log" "math/big" ) const maxDecryptBlock = 128 -// -//func Decrypt(data string) ([]byte, error) { -// raw, err := base64.StdEncoding.DecodeString(data) -// if err != nil { -// return nil, fmt.Errorf("base64 decode %w: %s", err, data) -// } -// // 初始化ViewModel -// vm, err := NewViewModel() -// if err != nil { -// log.Printf("初始化失败: %v", err) -// return nil, fmt.Errorf("base64 decode %w: %s", err, data) -// } -// reader := bytes.NewReader(raw) -// var writer bytes.Buffer -// chunk := make([]byte, maxDecryptBlock) -// for { -// n, err := io.ReadFull(reader, chunk) -// if err != nil && errors.Is(err, io.ErrUnexpectedEOF) { -// return nil, fmt.Errorf("read decrypted data: %w", err) -// } -// if n == 0 { -// break -// } -// pubKey := vm.publicKey -// decryptChunk(chunk, &writer, pubKey) -// } -// output := bytes.TrimRight(bytes.TrimLeft(writer.Bytes(), "\x00"), "\n") -// if bytes.Count(output, []byte("\x00")) > 0 { -// after := bytes.ReplaceAll(output, []byte("\x00"), []byte{}) -// log.Println("WARN: remove \x00 from caid's response", "before", output, "after", after) -// output = after -// } -// return output, nil -//} -// -//func decryptChunk(chunk []byte, writer *bytes.Buffer, pubKey *rsa.PublicKey) { -// // Decrypt each signature chunk -// ciphertextInt := new(big.Int) -// ciphertextInt.SetBytes(chunk) -// decryptedPaddedInt := doDecrypt(new(big.Int), pubKey, ciphertextInt) -// // Remove padding -// decryptedPaddedBytes := make([]byte, pubKey.Size()) -// decryptedPaddedInt.FillBytes(decryptedPaddedBytes) -// start := bytes.Index(decryptedPaddedBytes[1:], []byte{0}) + 1 // // 0001FF...FF00: Find index after 2nd 0x00 -// decryptedBytes := decryptedPaddedBytes[start:] -// // Write decrypted signature chunk -// writer.Write(decryptedBytes) -//} -// -//func doDecrypt(c *big.Int, pub *rsa.PublicKey, m *big.Int) *big.Int { -// // Textbook RSA -// e := big.NewInt(int64(pub.E)) -// c.Exp(m, e, pub.N) -// return c -//} +/* +url := "https://caid.china-caa.org/v1.0/get" +data := map[string]interface{}{"dev_id": "10702", "encrypted_device_info": caid.EncryptDeviceInfo()} +tmp, err := SendCaidMsg(ctx, url, data) -// ViewModel 处理业务逻辑的视图模型 -type ViewModel struct { - publicKey *rsa.PublicKey - privateKey *rsa.PrivateKey -} - -// NewViewModel 初始化视图模型 -func NewViewModel() (*ViewModel, error) { - pubKeyBytes, err := ioutil.ReadFile("manifest/config/dev_10702/public_for_api.pem") - if err != nil { - fmt.Println(err) - } - fmt.Printf("pubKeyBytes: %s", pubKeyBytes) - block, _ := pem.Decode(pubKeyBytes) - if block != nil { - pubKeyBytes = block.Bytes - } - fmt.Printf("pubKeyBytes: %s", fmt.Sprint(pubKeyBytes)) - pubKey, err := x509.ParsePKIXPublicKey(pubKeyBytes) if err != nil { - return nil, fmt.Errorf("解析公钥失败: %w", err) - } - rsaPubKey, ok := pubKey.(*rsa.PublicKey) - if !ok { - return nil, errors.New("无效的RSA公钥类型1") + fmt.Println("SendCaidMsg err:", err) + return } - return &ViewModel{publicKey: rsaPubKey}, nil -} +resJson, err := gjson.DecodeToJson(tmp) -// EncryptDeviceInfo 加密设备信息 -func (vm *ViewModel) EncryptDeviceInfo(deviceInfo map[string]string) (string, error) { - jsonData, err := json.Marshal(deviceInfo) if err != nil { - return "", fmt.Errorf("JSON序列化失败: %w", err) + fmt.Println("SendCaidMsg DecodeToJson err:", err) + return } - plaintext := string(jsonData) - maxBlockSize := vm.publicKey.Size() - 11 // PKCS#1 v1.5填充最大块大小 - fmt.Println("EncryptDeviceInfo", maxBlockSize, len(jsonData), len(plaintext)) - var encryptedBlocks [][]byte - - for i := 0; i < len(plaintext); i += maxBlockSize { - end := i + maxBlockSize - if end > len(plaintext) { - end = len(plaintext) - } - - block := []byte(plaintext[i:end]) - encryptedBlock, err := rsa.EncryptPKCS1v15(rand.Reader, vm.publicKey, block) - if err != nil { - return "", fmt.Errorf("RSA加密失败: %w", err) - } - - encryptedBlocks = append(encryptedBlocks, encryptedBlock) - fmt.Printf("EncryptDeviceInfo encryptedBlocks: %s, encryptedBlock: %s, block: %s \n", encryptedBlocks, string(encryptedBlock), string(block)) + if resJson != nil && resJson.Get("code").Int() != 0 { + fmt.Println("SendCaidMsg err:", resJson.Get("message").String()) + return } - return base64.StdEncoding.EncodeToString(bytesJoin(encryptedBlocks)), nil -} - -// DecryptResponse 解密响应数据 -func (vm *ViewModel) DecryptResponse(ciphertextBase64 string) (string, error) { - ciphertextBytes, err := base64.StdEncoding.DecodeString(ciphertextBase64) - if err != nil { - return "", fmt.Errorf("响应数据Base64解码失败: %w", err) - } - - maxBlockSize := vm.privateKey.Size() - var decryptedBlocks [][]byte - - for i := 0; i < len(ciphertextBytes); i += maxBlockSize { - end := i + maxBlockSize - if end > len(ciphertextBytes) { - end = len(ciphertextBytes) - } - - block := ciphertextBytes[i:end] - decryptedBlock, err := rsa.DecryptPKCS1v15(rand.Reader, vm.privateKey, block) - if err != nil { - return "", fmt.Errorf("RSA解密失败: %w", err) - } - decryptedBlocks = append(decryptedBlocks, decryptedBlock) - } - - return string(bytesJoin(decryptedBlocks)), nil -} - -// 辅助函数:合并字节切片 -func bytesJoin(s [][]byte) []byte { - var totalLen int - for _, b := range s { - totalLen += len(b) - } - res := make([]byte, totalLen) - for i, b := range s { - copy(res[i:], b) - } - return res -} - +req.Caid = resJson.Get("data").String() +*/ func EncryptDeviceInfo() string { // 设备公共信息 deviceInfo := map[string]string{ @@ -192,76 +58,15 @@ func EncryptDeviceInfo() string { "deviceInitTime": "1632467920.301150749", } - // 初始化ViewModel - vm, err := NewViewModel() + encryptedDeviceInfo, err := Encrypt(deviceInfo) if err != nil { - log.Printf("初始化失败: %v", err) - return "" - } - - // 加密设备信息 - encryptedDeviceInfo, err := vm.EncryptDeviceInfo(deviceInfo) - if err != nil { - log.Printf("设备信息加密失败: %v", err) + fmt.Println(err) return "" } - fmt.Printf("加密设备信息: %s\n", encryptedDeviceInfo) - // 模拟响应解密(使用加密结果模拟响应数据) - //responseData := encryptedDeviceInfo // 实际应从接口获取encrypted_device_info字段 return encryptedDeviceInfo } -func main1() { - // 设备公共信息 - deviceInfo := map[string]string{ - "bootTimeInSec": "1595643553", - "countryCode": "CN", - "language": "zh-Hans-CN", - "deviceName": "e910dddb2748c36b47fcde5dd720eec1", - "systemVersion": "14.0", - "machine": "iPhone10,3", - "memory": "3955589120", - "disk": "63900340224", - "sysFileTime": "1595214620.383940", - "model": "D22AP", - "timeZone": "28800", - "deviceInitTime": "1632467920.301150749", - } - - // 初始化ViewModel - vm, err := NewViewModel() - if err != nil { - log.Fatalf("初始化失败: %v", err) - } - - // 加密设备信息 - encryptedDeviceInfo, err := vm.EncryptDeviceInfo(deviceInfo) - if err != nil { - log.Fatalf("设备信息加密失败: %v", err) - } - fmt.Printf("加密设备信息: %s\n", encryptedDeviceInfo) - - // 模拟响应解密(使用加密结果模拟响应数据) - responseData := encryptedDeviceInfo // 实际应从接口获取encrypted_device_info字段 - - // 解密响应数据 - decryptedData, err := vm.DecryptResponse(responseData) - if err != nil { - log.Fatalf("响应解密失败: %v", err) - } - fmt.Printf("解密后数据: %s\n", decryptedData) - - // 解析JSON数组(示例) - var caidsArray []interface{} - if err := json.Unmarshal([]byte(decryptedData), &caidsArray); err != nil { - log.Fatalf("JSON解析失败: %v", err) - } - fmt.Printf("CAIDs数组: %+v\n", caidsArray) -} - -//const maxDecryptBlock = 128 - func Decrypt(data string) ([]byte, error) { raw, err := base64.StdEncoding.DecodeString(data) if err != nil { @@ -274,13 +79,12 @@ func Decrypt(data string) ([]byte, error) { pubKeyBytes, err := ioutil.ReadFile("manifest/config/dev_10702/public_for_api.pem") if err != nil { fmt.Println(err) + return nil, err } - fmt.Printf("pubKeyBytes: %s\n", pubKeyBytes) block, _ := pem.Decode(pubKeyBytes) if block != nil { pubKeyBytes = block.Bytes } - fmt.Printf("pubKeyBytes: %s\n", fmt.Sprint(pubKeyBytes)) pubKey, err := x509.ParsePKIXPublicKey(pubKeyBytes) if err != nil { return nil, fmt.Errorf("解析公钥失败: %w", err) @@ -302,7 +106,7 @@ func Decrypt(data string) ([]byte, error) { output := bytes.TrimRight(bytes.TrimLeft(writer.Bytes(), "\x00"), "\n") if bytes.Count(output, []byte("\x00")) > 0 { after := bytes.ReplaceAll(output, []byte("\x00"), []byte{}) - log.Println("WARN: remove \x00 from caid's response", "before", output, "after", after) + //log.Println("WARN: remove \x00 from caid's response", "before", output, "after", after) output = after } fmt.Printf(" output: %s\n", string(output)) @@ -329,3 +133,59 @@ func doDecrypt(c *big.Int, pub *rsa.PublicKey, m *big.Int) *big.Int { c.Exp(m, e, pub.N) return c } +func ImportSPKIPublicKeyPEM() *rsa.PublicKey { + pubKeyBytes, err := ioutil.ReadFile("manifest/config/dev_10702/public_for_api.pem") + if err != nil { + fmt.Println(err) + } + fmt.Printf("encrypt pubKeyBytes: %s\n", string(pubKeyBytes)) + body, _ := pem.Decode(pubKeyBytes) + fmt.Printf(" body.Bytes : %s\n byte: %s\n", body.Type, body.Bytes) + publicKey, _ := x509.ParsePKIXPublicKey(body.Bytes) + if publicKey, ok := publicKey.(*rsa.PublicKey); ok { + fmt.Printf("publicKey : %d\n ", publicKey.Size()) + return publicKey + } else { + return nil + } +} +func Encrypt(data map[string]string) (string, error) { + jsonBytes, err := json.Marshal(data) + if err != nil { + fmt.Printf("JSON序列化错误: %v\n", err) + return "", fmt.Errorf("JSON序列化错误: %v\n", err) + } + + pubKey := ImportSPKIPublicKeyPEM() + fmt.Printf("data: len: %d\n pubkey: %v\n", len(data), pubKey) + + // 2. 计算RSA最大加密块大小(PKCS#1 v1.5填充需要11字节) + keySize := pubKey.Size() // 密钥字节长度(如2048位密钥为256字节) + maxEncryptBlock := keySize - 11 // 最大单次加密数据长度(256-11=245字节) + if maxEncryptBlock <= 0 { + return "", errors.New("无效的RSA公钥长度(必须≥11字节)") + } + plaintext := jsonBytes + // 3. 分块加密 + var encryptedBlocks [][]byte + for offset := 0; offset < len(plaintext); offset += maxEncryptBlock { + end := offset + maxEncryptBlock + if end > len(plaintext) { + end = len(plaintext) + } + block := plaintext[offset:end] + + // 执行RSA加密(使用公钥指数e) + encryptedBlock, err := rsa.EncryptPKCS1v15(rand.Reader, pubKey, block) + if err != nil { + return "", fmt.Errorf("第%d字节块加密失败: %w", offset, err) + } + encryptedBlocks = append(encryptedBlocks, encryptedBlock) + } + + // 4. 拼接所有加密块并进行Base64编码 + encryptedBytes := bytes.Join(encryptedBlocks, nil) + // 4. 拼接所有加密块并进行Base64编码 + return base64.StdEncoding.EncodeToString(encryptedBytes), nil + +} diff --git a/internal/serviceGame/internal/manage.go b/internal/serviceGame/internal/manage.go index 57b56db..f3b7df6 100644 --- a/internal/serviceGame/internal/manage.go +++ b/internal/serviceGame/internal/manage.go @@ -82,7 +82,7 @@ func SetGmToClient(ctx context.Context, req *game.SetGmToClientReq) (res *game.S return nil, errors.New("区服选择错误!当前区服在<" + fmt.Sprint(serverInfo.Id) + "><" + serverInfo.Name + ">区") } - g.Log().Info(ctx, "SetGmToClient - ServerConfig: ", gjson.MustEncodeString(ServerConfig)) + //g.Log().Info(ctx, "SetGmToClient - ServerConfig: ", gjson.MustEncodeString(ServerConfig)) ip := ServerConfig[fmt.Sprint(req.ServerId)] url := "http://" + ip + "/GM?Ids=" + fmt.Sprint(unit.Uid) + "&State=" + fmt.Sprint(req.State) g.Log().Info(ctx, "SetGmToClient - req: ", url) @@ -112,8 +112,26 @@ func ChangeGm(ctx context.Context, req *game.ChangeGmReq) (res *game.ChangeGmRes if len(unit) == 0 { return nil, errors.New("找不到账号") } - server = fmt.Sprint(unit[0].Server) - filter["_id"] = unit[0].Uid + if len(unit) == 1 { + server = fmt.Sprint(unit[0].Server) + filter["_id"] = unit[0].Uid + } else { + serverList := "" + for _, v := range unit { + if v.Server == req.ServerId { + filter["_id"] = v.Uid + server = fmt.Sprint(v.Server) + break + } + if len(serverList) > 0 { + serverList += "," + } + serverList += fmt.Sprint(v.Server) + } + if server == "" { + return nil, errors.New("所选区服不存在该玩家!该玩家存在多个区服{" + serverList + "}里,请注意选择区服!") + } + } } else { uid, err := GetStringIdToUid(ctx, req.Uid) if err != nil { @@ -124,8 +142,26 @@ func ChangeGm(ctx context.Context, req *game.ChangeGmReq) (res *game.ChangeGmRes if len(unit) == 0 { return nil, errors.New("找不到账号") } - server = fmt.Sprint(unit[0].Server) - filter["_id"] = unit[0].Uid + if len(unit) == 1 { + server = fmt.Sprint(unit[0].Server) + filter["_id"] = unit[0].Uid + } else { + serverList := "" + for _, v := range unit { + if v.Server == req.ServerId { + filter["_id"] = v.Uid + server = fmt.Sprint(v.Server) + break + } + if len(serverList) > 0 { + serverList += "," + } + serverList += fmt.Sprint(v.Server) + } + if server == "" { + return nil, errors.New("所选区服不存在该玩家!该玩家存在多个区服{" + serverList + "}里,请注意选择区服!") + } + } } if MongoDatabaseList[server] == nil { return nil, errors.New("数据库不存在,请联系管理员")