@@ -24,7 +24,7 @@ async function makePostRequest(url, body, accessToken = null) {
2424 "X-Proxy-URL" : url ,
2525 "Content-Type" : "application/json" ,
2626 "X-Authorization" : `Bearer ${ accessToken } ` ,
27- "X-Firebase-Token" : encryptFirebaseToken ( user . firebaseToken , user . accessToken ) ,
27+ "X-Firebase-Token" : await encryptFirebaseToken ( user . firebaseToken , user . accessToken ) ,
2828 } ,
2929 body : body ,
3030 } ) ;
@@ -171,17 +171,50 @@ async function makePostRequest(url, body, accessToken = null) {
171171}
172172
173173// source: trust me bro
174- function encryptFirebaseToken ( firebaseToken , authToken ) {
175- let { sub, jti } = getJWTPayload ( authToken ) ;
174+ async function encryptFirebaseToken ( firebaseToken , authToken ) {
175+ const { sub, jti } = getJWTPayload ( authToken ) ;
176176
177- const key = sub . replaceAll ( "-" , "" ) ;
178- const iv = jti . slice ( 0 , 16 ) ;
177+ // 1. Create key from sub (hex string)
178+ const keyHex = sub . replaceAll ( "-" , "" ) ;
179179
180- let cipher = crypto . createCipheriv ( "aes-256-cbc" , key , iv ) ;
180+ if ( keyHex . length !== 32 && keyHex . length !== 64 ) {
181+ throw new Error ( "Key must be 32 or 64 hex characters (16 or 32 bytes)" ) ;
182+ }
183+
184+ // Padding if needed (this is how Node treats 16-byte keys for AES-256)
185+ let keyBytes = hexStringToBytes ( keyHex ) ;
186+ if ( keyBytes . length === 16 ) {
187+ // Extend to 32 bytes by padding with zeros
188+ let padded = new Uint8Array ( 32 ) ;
189+ padded . set ( keyBytes ) ;
190+ keyBytes = padded ;
191+ }
192+
193+ // 2. IV from jti.slice(0, 16) using UTF-8 encoding
194+ const iv = new TextEncoder ( ) . encode ( jti . slice ( 0 , 16 ) ) ;
195+
196+ // 3. Import key
197+ const cryptoKey = await crypto . subtle . importKey ( "raw" , keyBytes , { name : "AES-CBC" } , false , [ "encrypt" ] ) ;
181198
182- let encrypted = cipher . update ( firebaseToken , "utf8" , "base64" ) ;
199+ // 4. Encrypt
200+ const plaintext = new TextEncoder ( ) . encode ( firebaseToken ) ;
201+ const encryptedBuffer = await crypto . subtle . encrypt ( { name : "AES-CBC" , iv } , cryptoKey , plaintext ) ;
202+
203+ // 5. Convert to base64
204+ return bufferToBase64 ( encryptedBuffer ) ;
205+ }
206+
207+ function hexStringToBytes ( hex ) {
208+ const bytes = new Uint8Array ( hex . length / 2 ) ;
209+ for ( let i = 0 ; i < bytes . length ; i ++ ) {
210+ bytes [ i ] = parseInt ( hex . substr ( i * 2 , 2 ) , 16 ) ;
211+ }
212+ return bytes ;
213+ }
183214
184- return encrypted + cipher . final ( "base64" ) ;
215+ function bufferToBase64 ( buffer ) {
216+ const binary = String . fromCharCode ( ...new Uint8Array ( buffer ) ) ;
217+ return btoa ( binary ) ;
185218}
186219
187220async function makeGetRequest ( url , accessToken = null ) {
0 commit comments