@@ -48,6 +48,28 @@ def cross_platform_consistency_check_base64_url_test(self, raw_input, expected_b
4848 decoded = Uid2Base64UrlCoder .decode (base64_url_encoded_str )
4949 self .assertEqual (decoded , raw_input )
5050
51+ def validate_advertising_token (self , advertising_token_string , identity_scope , identity_type ):
52+ first_char = advertising_token_string [0 ]
53+ if identity_scope == IdentityScope .UID2 :
54+ self .assertEqual ("A" if identity_type == IdentityType .Email .value else "B" , first_char )
55+ else :
56+ self .assertEqual ("E" if identity_type == IdentityType .Email .value else "F" , first_char )
57+
58+ second_char = advertising_token_string [1 ]
59+ self .assertEqual ("4" , second_char )
60+
61+ # No URL-unfriendly characters allowed
62+ self .assertEqual (- 1 , advertising_token_string .find ("=" ))
63+ self .assertEqual (- 1 , advertising_token_string .find ("+" ))
64+ self .assertEqual (- 1 , advertising_token_string .find ("/" ))
65+
66+
67+ def generate_uid2_token_v4 (self , uid , master_key , site_id , site_key , params = Params (), identity_type = IdentityType .Email , identity_scope = IdentityScope .UID2 ):
68+ advertising_token = UID2TokenGenerator .generate_uid2_token_v4 (uid , master_key , site_id , site_key , params )
69+ self .validate_advertising_token (advertising_token , identity_scope , identity_type )
70+ return advertising_token
71+
72+
5173 def test_cross_platform_consistency_decrypt (self ):
5274 crossPlatformAdvertisingToken = "AIAAAACkOqJj9VoxXJNnuX3v-ymceRf8_Av0vA5asOj9YBZJc1kV1vHdmb0AIjlzWnFF-gxIlgXqhRFhPo3iXpugPBl3gv4GKnGkw-Zgm2QqMsDPPLpMCYiWrIUqHPm8hQiq9PuTU-Ba9xecRsSIAN0WCwKLwA_EDVdzmnLJu64dQoeYmuu3u1G2EuTkuMrevmP98tJqSUePKwnfK73-0Zdshw" ;
5375 # Sunday, 1 January 2023 1:01:01 AM UTC
@@ -78,7 +100,7 @@ def test_cross_platform_consistency_decrypt(self):
78100 params = Params (dt .timedelta (days = 1 * 365 * 20 ))
79101
80102 # verify that the dynamically created ad token can be decrypted
81- runtime_advertising_token = UID2TokenGenerator .generate_uid2_token_v4 (_example_id , master_key , _site_id , site_key , params )
103+ runtime_advertising_token = self .generate_uid2_token_v4 (_example_id , master_key , _site_id , site_key , params )
82104 # best effort check as the token might simply just not require padding
83105 self .assertEqual (- 1 , runtime_advertising_token .find ('=' ))
84106 self .assertEqual (- 1 , runtime_advertising_token .find ('+' ))
@@ -91,8 +113,9 @@ def test_cross_platform_consistency_decrypt(self):
91113 result = decrypt (crossPlatformAdvertisingToken , EncryptionKeysCollection ([_master_key , _site_key ]))
92114 self .assertEqual (_example_id , result .uid2 )
93115
116+
94117 def test_decrypt_token_v4 (self ):
95- token = UID2TokenGenerator .generate_uid2_token_v4 (_example_id , _master_key , _site_id , _site_key )
118+ token = self .generate_uid2_token_v4 (_example_id , _master_key , _site_id , _site_key )
96119
97120 keys = EncryptionKeysCollection ([_master_key , _site_key ])
98121 result = decrypt (token , keys )
@@ -101,7 +124,7 @@ def test_decrypt_token_v4(self):
101124
102125
103126 def test_decrypt_token_v4_empty_keys (self ):
104- token = UID2TokenGenerator .generate_uid2_token_v4 (_example_id , _master_key , _site_id , _site_key )
127+ token = self .generate_uid2_token_v4 (_example_id , _master_key , _site_id , _site_key )
105128
106129 keys = EncryptionKeysCollection ([])
107130
@@ -110,7 +133,7 @@ def test_decrypt_token_v4_empty_keys(self):
110133
111134
112135 def test_decrypt_token_v4_no_master_key (self ):
113- token = UID2TokenGenerator .generate_uid2_token_v4 (_example_id , _master_key , _site_id , _site_key )
136+ token = self .generate_uid2_token_v4 (_example_id , _master_key , _site_id , _site_key )
114137
115138 keys = EncryptionKeysCollection ([_site_key ])
116139
@@ -119,7 +142,7 @@ def test_decrypt_token_v4_no_master_key(self):
119142
120143
121144 def test_decrypt_token_v4_no_site_key (self ):
122- token = UID2TokenGenerator .generate_uid2_token_v4 (_example_id , _master_key , _site_id , _site_key )
145+ token = self .generate_uid2_token_v4 (_example_id , _master_key , _site_id , _site_key )
123146
124147 keys = EncryptionKeysCollection ([_master_key ])
125148
@@ -138,7 +161,7 @@ def test_decrypt_token_v4_invalid_version(self):
138161
139162 def test_decrypt_token_v4_expired (self ):
140163 params = Params (dt .timedelta (seconds = - 1 ))
141- token = UID2TokenGenerator .generate_uid2_token_v4 (_example_id , _master_key , _site_id , _site_key , params )
164+ token = self .generate_uid2_token_v4 (_example_id , _master_key , _site_id , _site_key , params )
142165
143166 keys = EncryptionKeysCollection ([_master_key , _site_key ])
144167
@@ -149,7 +172,7 @@ def test_decrypt_token_v4_expired(self):
149172 def test_decrypt_token_v4_custom_now (self ):
150173 expiry = dt .datetime (2021 , 3 , 22 , 9 , 1 , 2 , tzinfo = timezone .utc )
151174 params = Params (expiry )
152- token = UID2TokenGenerator .generate_uid2_token_v4 (_example_id , _master_key , _site_id , _site_key , params )
175+ token = self .generate_uid2_token_v4 (_example_id , _master_key , _site_id , _site_key , params )
153176
154177 keys = EncryptionKeysCollection ([_master_key , _site_key ])
155178
@@ -162,7 +185,7 @@ def test_decrypt_token_v4_custom_now(self):
162185
163186 def test_decrypt_token_v4_invalid_payload (self ):
164187 params = Params (dt .timedelta (seconds = - 1 ))
165- token = UID2TokenGenerator .generate_uid2_token_v4 (_example_id , _master_key , _site_id , _site_key , params )
188+ token = self .generate_uid2_token_v4 (_example_id , _master_key , _site_id , _site_key , params )
166189
167190 keys = EncryptionKeysCollection ([_master_key , _site_key ])
168191
@@ -596,6 +619,7 @@ def test_decrypt_data_v2(self):
596619 self .assertEqual (format_time (now ), format_time (decrypted .encrypted_at ))
597620
598621
622+ # TODO - deduplicate the logic in sharing_test.py that has been copied from this file
599623 def test_raw_uid_produces_correct_identity_type_in_token (self ):
600624 #v2 +12345678901. Although this was generated from a phone number, it's a v2 raw UID which doesn't encode this
601625 # information, so token assumes email by default.
@@ -611,7 +635,7 @@ def test_raw_uid_produces_correct_identity_type_in_token(self):
611635 IdentityType .
Email .
value )
#v3 EUID [email protected] 612636
613637 def verify_identity_type (self , raw_uid , expected_identity_type ):
614- token = UID2TokenGenerator .generate_uid2_token_v4 (raw_uid , _master_key , _site_id , _site_key )
638+ token = self .generate_uid2_token_v4 (raw_uid , _master_key , _site_id , _site_key , Params (), expected_identity_type )
615639 keys = EncryptionKeysCollection ([_master_key , _site_key ])
616640 result = decrypt (token , keys )
617641 self .assertEqual (raw_uid , result .uid2 )
0 commit comments