package main import ( "bytes" "context" "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/base64" "encoding/json" "encoding/pem" "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{ "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", } // 公钥字符串,注意需要剔除换行符 //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) 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) ////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 //} caid := "J5LdxnMrcpDiNrn2QLZvCPavphS9nUqu7uwCEjLkEvtP2blwhevgGvQD7AKajkEc+PIC2TuIFxbSGK9Jsm27CrsW446pi+gIIc3OdKB4jqQJoDD77BbJC3I105DnsEwgR8uLvSVy0NgqFq+rf4GRYwp93Jy2eZdDKkS+Y0BgTEQkedK1P29hyYEELLQzvJrq9XlwfYx1QcGGcofZmq56B65IbQQfRvoXAiSl2cm12qFkpD8KbPmvy66xE6yu3SFAMC6iAEdfW4W8hz0Qv9Bht2nhDxsm4c39z1mU41s1oP5lJ5kkUl4yU3NWRO19jIYOm8lMJb19oDc+weBaMkgIbQ==" fmt.Println("Deposit - caid: ", caid) //encryptedDeviceInfo, err := encryptWithPublicKey(jsonStr, vm.publicKey) //if err != nil { // fmt.Printf("加密错误 encryptWithPublicKey: %v\n", err) // return //} // 将encryptedDeviceInfo填入请求中的encrypted_device_info字段 // 解密响应数据示例 // 假设从响应中获取的data字段值 //fmt.Printf("解密后的响应数据: %s\n ,decryptedByte: %s\n", decryptedData, string(decryptedByte)) } // 使用公钥加密数据 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 { 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 { 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) //} 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)) } // 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 } //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) } 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 } //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 //}