package rpc import ( "context" "crypto" "crypto/hmac" "crypto/rand" "crypto/rsa" "crypto/sha256" "crypto/x509" "encoding/base64" "encoding/hex" "encoding/json" "encoding/pem" "errors" "eta/eta_mini_crm_ht/utils" "fmt" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/metadata" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" "io" "log" "os" "time" ) const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" type RpcService interface { GetPool(addr string) utils.ClientPool } type DefaultRpcClient struct { } func (d *DefaultRpcClient) WrapSign(request interface{}, doHandler func(ctx context.Context, req interface{}) error) { timestamp, nonce, sign, _ := d.signature(request, 16) fmt.Println(string(sign)) ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs( "nonce", nonce, "timestamp", fmt.Sprintf("%d", timestamp), "signature", sign, )) err := doHandler(ctx, request) if err != nil { utils.FileLog.Error("调用PRC服务失败:%v", err) } } func (d *DefaultRpcClient) getOptions() (opts []grpc.DialOption) { opts = make([]grpc.DialOption, 0) opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials())) return opts } func (d *DefaultRpcClient) GetPool(addr string) utils.ClientPool { pool, err := utils.GetPoolInstance(addr, d.getOptions()...) if err != nil { log.Fatal(err) } return pool } // 生成签名 func (d *DefaultRpcClient) generateSignature(req interface{}) string { message := req.(proto.Message) reqData, _ := anypb.New(message) reqBytes, _ := proto.Marshal(reqData) key := []byte("secret") // 秘钥应该保密 mac := hmac.New(sha256.New, key) mac.Write(reqBytes) return hex.EncodeToString(mac.Sum(nil)) } func (d *DefaultRpcClient) generateNonceStr(length int) (string, error) { result := make([]byte, length) n, err := io.ReadFull(rand.Reader, result) if err != nil { return "", err } for i := 0; i < n; i++ { result[i] = chars[int(result[i])%len(chars)] } return string(result), nil } type encryptedRequest struct { Message interface{} `json:"ciphertext"` Nonce string `json:"nonce"` // 添加随机字符串 Timestamp int64 `json:"timestamp"` // 添加时间戳 } func (d *DefaultRpcClient) signature(req interface{}, nonceLen int) (timestamp int64, nonceStr string, encodedData string, err error) { nonceStr, err = d.generateNonceStr(nonceLen) if err != nil { utils.FileLog.Error("随机字符串生成失败: %v", err) return } timestamp = time.Now().UnixMilli() // 构建加密后的数据结构 encryptedStruct := encryptedRequest{ Message: req, Nonce: nonceStr, // 添加随机字符串 Timestamp: timestamp, // 添加时间戳 } entryData, err := json.Marshal(encryptedStruct) if err != nil { utils.FileLog.Error("序列化加密后的数据失败: %v", err) return } // 使用私钥加密 var privateKey *rsa.PrivateKey privateKey, err = d.parsePrivateKeyFromPEM() if err != nil { utils.FileLog.Error("私钥解析失败: %v", err) return } var encryptedData []byte hash := sha256.Sum256(entryData) // RSA加密 encryptedData, err = rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hash[:]) if err != nil { utils.FileLog.Error("RSA加密失败: %v", err) return } // 编码加密后的数据 encodedData = base64.StdEncoding.EncodeToString(encryptedData) return } // 解析RSA公钥 func (d *DefaultRpcClient) parsePrivateKeyFromPEM() (privateKey *rsa.PrivateKey, err error) { pemBlock, err := os.ReadFile("./conf/rsa_private_key.pem") block, _ := pem.Decode(pemBlock) if block == nil { utils.FileLog.Error("公钥解析失败") return nil, errors.New("公钥解析失败") } privateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes) if err != nil { return nil, err } return }