@@ -105,12 +105,25 @@ def _decrypt_token(token, keys, domain_name, client_type, now):
105105 elif token_bytes [1 ] == AdvertisingTokenVersion .ADVERTISING_TOKEN_V3 .value :
106106 return _decrypt_token_v3 (base64 .b64decode (token ), keys , domain_name , client_type , now , AdvertisingTokenVersion .ADVERTISING_TOKEN_V3 )
107107 elif token_bytes [1 ] == AdvertisingTokenVersion .ADVERTISING_TOKEN_V4 .value :
108- # same as V3 but use Base64URL encoding
109- return _decrypt_token_v3 (Uid2Base64UrlCoder . decode ( token ), keys , domain_name , client_type , now , AdvertisingTokenVersion .ADVERTISING_TOKEN_V4 )
108+ # Accept either base64 or base64url encoding.
109+ return _decrypt_token_v3 (base64 . b64decode ( _base64url_to_base64 ( token ) ), keys , domain_name , client_type , now , AdvertisingTokenVersion .ADVERTISING_TOKEN_V4 )
110110 else :
111111 return DecryptedToken .make_error (DecryptionStatus .VERSION_NOT_SUPPORTED )
112112
113113
114+ def _base64url_to_base64 (value ):
115+ value = value .replace ('-' , '+' ).replace ('_' , '/' )
116+ input_size_mod4 = len (value ) % 4
117+ if input_size_mod4 == 0 :
118+ return value
119+ elif input_size_mod4 == 2 :
120+ return value + '=='
121+ elif input_size_mod4 == 3 :
122+ return value + '='
123+ else :
124+ raise EncryptionError ('invalid payload' )
125+
126+
114127def _token_has_valid_lifetime (keys , client_type , generated_or_now , expires , now ):
115128 # generated_or_now allows "now" for token v2, since v2 does not contain a "token generated" field.
116129 # v2 therefore checks against remaining lifetime rather than total lifetime
@@ -294,7 +307,6 @@ def encrypt(uid2, identity_scope, keys, keyset_id=None, **kwargs):
294307 return EncryptionDataResponse .make_error (EncryptionStatus .ENCRYPTION_FAILURE )
295308
296309
297-
298310# DEPRECATED, DO NOT CALL
299311def encrypt_data (data , identity_scope , ** kwargs ):
300312 """Encrypt arbitrary binary data.
0 commit comments