@@ -2,6 +2,9 @@ use async_trait::async_trait;
22use bytes:: Bytes ;
33use std:: sync:: Arc ;
44
5+ #[ cfg( feature = "sign-provider" ) ]
6+ use std:: collections:: HashSet ;
7+
58#[ async_trait]
69pub trait SignProvider : Send + Sync + std:: fmt:: Debug {
710 async fn sign ( & self , cmd : & str , seq : u32 , data : & [ u8 ] ) -> Option < SignResult > ;
@@ -19,20 +22,20 @@ pub struct SignResult {
1922}
2023
2124#[ derive( Debug ) ]
22- pub struct DefaultSignProvider ;
25+ pub struct NoOpSignProvider ;
2326
2427#[ async_trait]
25- impl SignProvider for DefaultSignProvider {
28+ impl SignProvider for NoOpSignProvider {
2629 async fn sign ( & self , _cmd : & str , _seq : u32 , _data : & [ u8 ] ) -> Option < SignResult > {
2730 None
2831 }
2932
3033 fn platform ( & self ) -> & str {
31- "default "
34+ "noop "
3235 }
3336}
3437
35- impl Default for DefaultSignProvider {
38+ impl Default for NoOpSignProvider {
3639 fn default ( ) -> Self {
3740 Self
3841 }
@@ -75,3 +78,190 @@ impl Default for AndroidSignProvider {
7578}
7679
7780pub type BoxedSignProvider = Arc < dyn SignProvider > ;
81+
82+ #[ cfg( feature = "sign-provider" ) ]
83+ mod default {
84+ use super :: * ;
85+ use serde:: { Deserialize , Serialize } ;
86+
87+ const SIGN_API_URL : & str = "" ;
88+
89+ #[ derive( Debug , Serialize ) ]
90+ struct SignRequest {
91+ cmd : String ,
92+ seq : u32 ,
93+ src : String ,
94+ }
95+
96+ #[ derive( Debug , Deserialize ) ]
97+ struct SignResponse {
98+ value : SignResponseValue ,
99+ }
100+
101+ #[ derive( Debug , Deserialize ) ]
102+ struct SignResponseValue {
103+ sign : String ,
104+ token : String ,
105+ extra : String ,
106+ }
107+
108+ #[ derive( Debug ) ]
109+ pub struct DefaultSignProvider {
110+ client : reqwest:: Client ,
111+ whitelist : HashSet < String > ,
112+ }
113+
114+ impl DefaultSignProvider {
115+ pub fn new ( ) -> Self {
116+ let whitelist = Self :: build_whitelist ( ) ;
117+ Self {
118+ client : reqwest:: Client :: new ( ) ,
119+ whitelist,
120+ }
121+ }
122+
123+ fn build_whitelist ( ) -> HashSet < String > {
124+ let mut set = HashSet :: new ( ) ;
125+
126+ set. insert ( "trpc.o3.ecdh_access.EcdhAccess.SsoEstablishShareKey" . to_string ( ) ) ;
127+ set. insert ( "trpc.o3.ecdh_access.EcdhAccess.SsoSecureAccess" . to_string ( ) ) ;
128+ set. insert ( "trpc.o3.report.Report.SsoReport" . to_string ( ) ) ;
129+ set. insert ( "MessageSvc.PbSendMsg" . to_string ( ) ) ;
130+ set. insert ( "wtlogin.trans_emp" . to_string ( ) ) ;
131+ set. insert ( "wtlogin.login" . to_string ( ) ) ;
132+ set. insert ( "wtlogin.exchange_emp" . to_string ( ) ) ;
133+ set. insert ( "trpc.login.ecdh.EcdhService.SsoKeyExchange" . to_string ( ) ) ;
134+
135+ set. insert ( "trpc.login.ecdh.EcdhService.SsoNTLoginPasswordLogin" . to_string ( ) ) ;
136+ set. insert ( "trpc.login.ecdh.EcdhService.SsoNTLoginEasyLogin" . to_string ( ) ) ;
137+ set. insert ( "trpc.login.ecdh.EcdhService.SsoNTLoginPasswordLoginNewDevice" . to_string ( ) ) ;
138+ set. insert ( "trpc.login.ecdh.EcdhService.SsoNTLoginEasyLoginUnusualDevice" . to_string ( ) ) ;
139+ set. insert ( "trpc.login.ecdh.EcdhService.SsoNTLoginPasswordLoginUnusualDevice" . to_string ( ) ) ;
140+ set. insert ( "trpc.login.ecdh.EcdhService.SsoNTLoginRefreshTicket" . to_string ( ) ) ;
141+ set. insert ( "trpc.login.ecdh.EcdhService.SsoNTLoginRefreshA2" . to_string ( ) ) ;
142+
143+ set. insert ( "OidbSvcTrpcTcp.0x11ec_1" . to_string ( ) ) ;
144+ set. insert ( "OidbSvcTrpcTcp.0x758_1" . to_string ( ) ) ;
145+ set. insert ( "OidbSvcTrpcTcp.0x7c1_1" . to_string ( ) ) ;
146+ set. insert ( "OidbSvcTrpcTcp.0x7c2_5" . to_string ( ) ) ;
147+ set. insert ( "OidbSvcTrpcTcp.0x10db_1" . to_string ( ) ) ;
148+ set. insert ( "OidbSvcTrpcTcp.0x8a1_7" . to_string ( ) ) ;
149+ set. insert ( "OidbSvcTrpcTcp.0x89a_0" . to_string ( ) ) ;
150+ set. insert ( "OidbSvcTrpcTcp.0x89a_15" . to_string ( ) ) ;
151+ set. insert ( "OidbSvcTrpcTcp.0x88d_0" . to_string ( ) ) ;
152+ set. insert ( "OidbSvcTrpcTcp.0x88d_14" . to_string ( ) ) ;
153+ set. insert ( "OidbSvcTrpcTcp.0x112a_1" . to_string ( ) ) ;
154+ set. insert ( "OidbSvcTrpcTcp.0x587_74" . to_string ( ) ) ;
155+ set. insert ( "OidbSvcTrpcTcp.0x587_103" . to_string ( ) ) ;
156+ set. insert ( "OidbSvcTrpcTcp.0x1100_1" . to_string ( ) ) ;
157+ set. insert ( "OidbSvcTrpcTcp.0x1102_1" . to_string ( ) ) ;
158+ set. insert ( "OidbSvcTrpcTcp.0x1103_1" . to_string ( ) ) ;
159+ set. insert ( "OidbSvcTrpcTcp.0x1107_1" . to_string ( ) ) ;
160+ set. insert ( "OidbSvcTrpcTcp.0x1105_1" . to_string ( ) ) ;
161+ set. insert ( "OidbSvcTrpcTcp.0xf88_1" . to_string ( ) ) ;
162+ set. insert ( "OidbSvcTrpcTcp.0xf89_1" . to_string ( ) ) ;
163+ set. insert ( "OidbSvcTrpcTcp.0xf57_1" . to_string ( ) ) ;
164+ set. insert ( "OidbSvcTrpcTcp.0xf57_106" . to_string ( ) ) ;
165+ set. insert ( "OidbSvcTrpcTcp.0xf57_9" . to_string ( ) ) ;
166+ set. insert ( "OidbSvcTrpcTcp.0xf55_1" . to_string ( ) ) ;
167+ set. insert ( "OidbSvcTrpcTcp.0xf67_1" . to_string ( ) ) ;
168+ set. insert ( "OidbSvcTrpcTcp.0xf67_5" . to_string ( ) ) ;
169+ set. insert ( "OidbSvcTrpcTcp.0x10c0_1" . to_string ( ) ) ;
170+ set. insert ( "OidbSvcTrpcTcp.0x10c3_1" . to_string ( ) ) ;
171+ set. insert ( "OidbSvcTrpcTcp.0x1ba9" . to_string ( ) ) ;
172+ set. insert ( "OidbSvcTrpcTcp.0x6d9_4" . to_string ( ) ) ;
173+
174+ set
175+ }
176+
177+ pub fn is_whitelisted ( & self , cmd : & str ) -> bool {
178+ self . whitelist . contains ( cmd)
179+ }
180+
181+ async fn decode_hex_field ( hex_str : & str ) -> Result < Bytes , String > {
182+ hex:: decode ( hex_str)
183+ . map ( Bytes :: from)
184+ . map_err ( |e| format ! ( "Failed to decode hex string: {}" , e) )
185+ }
186+ }
187+
188+ impl Default for DefaultSignProvider {
189+ fn default ( ) -> Self {
190+ Self :: new ( )
191+ }
192+ }
193+
194+ #[ async_trait]
195+ impl SignProvider for DefaultSignProvider {
196+ async fn sign ( & self , cmd : & str , seq : u32 , data : & [ u8 ] ) -> Option < SignResult > {
197+ if !self . is_whitelisted ( cmd) {
198+ tracing:: debug!( cmd = cmd, "Command not in whitelist, skipping sign" ) ;
199+ return None ;
200+ }
201+
202+ let request = SignRequest {
203+ cmd : cmd. to_string ( ) ,
204+ seq,
205+ src : hex:: encode ( data) ,
206+ } ;
207+
208+ let response = match self . client
209+ . post ( SIGN_API_URL )
210+ . json ( & request)
211+ . send ( )
212+ . await
213+ {
214+ Ok ( resp) => resp,
215+ Err ( e) => {
216+ tracing:: error!( error = %e, cmd = cmd, seq = seq, "Failed to send sign request" ) ;
217+ return None ;
218+ }
219+ } ;
220+
221+ let sign_response: SignResponse = match response. json ( ) . await {
222+ Ok ( data) => data,
223+ Err ( e) => {
224+ tracing:: error!( error = %e, cmd = cmd, seq = seq, "Failed to parse sign response" ) ;
225+ return None ;
226+ }
227+ } ;
228+
229+ let sign = match Self :: decode_hex_field ( & sign_response. value . sign ) . await {
230+ Ok ( bytes) => bytes,
231+ Err ( e) => {
232+ tracing:: error!( error = e, field = "sign" , "Failed to decode hex" ) ;
233+ return None ;
234+ }
235+ } ;
236+
237+ let token = match Self :: decode_hex_field ( & sign_response. value . token ) . await {
238+ Ok ( bytes) => bytes,
239+ Err ( e) => {
240+ tracing:: error!( error = e, field = "token" , "Failed to decode hex" ) ;
241+ return None ;
242+ }
243+ } ;
244+
245+ let extra = match Self :: decode_hex_field ( & sign_response. value . extra ) . await {
246+ Ok ( bytes) => bytes,
247+ Err ( e) => {
248+ tracing:: error!( error = e, field = "extra" , "Failed to decode hex" ) ;
249+ return None ;
250+ }
251+ } ;
252+
253+ Some ( SignResult {
254+ sign,
255+ token,
256+ extra,
257+ } )
258+ }
259+
260+ fn platform ( & self ) -> & str {
261+ "default"
262+ }
263+ }
264+ }
265+
266+ #[ cfg( feature = "sign-provider" ) ]
267+ pub use default:: DefaultSignProvider ;
0 commit comments