Skip to content

Commit da979ce

Browse files
authored
Fixed setting the correct IdentityType value in the ad token (#7)
1 parent b583777 commit da979ce

File tree

2 files changed

+41
-3
lines changed

2 files changed

+41
-3
lines changed

tests/test_encryption.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from tests.uid2_token_generator import UID2TokenGenerator, Params
77
from uid2_client import decrypt_token, encrypt_data, decrypt_data, encryption_block_size, EncryptionError, Uid2Base64UrlCoder, AdvertisingTokenVersion
88
from uid2_client.identity_scope import IdentityScope
9+
from uid2_client.identity_type import IdentityType
910
from uid2_client.keys import *
1011

1112
_master_secret = bytes([139, 37, 241, 173, 18, 92, 36, 232, 165, 168, 23, 18, 38, 195, 123, 92, 160, 136, 185, 40, 91, 173, 165, 221, 168, 16, 169, 164, 38, 139, 8, 155])
@@ -567,6 +568,38 @@ def test_decrypt_data_v2(self):
567568
self.assertEqual(data, decrypted.data)
568569
self.assertEqual(format_time(now), format_time(decrypted.encrypted_at))
569570

571+
572+
def test_raw_uid_produces_correct_identity_type_in_token(self):
573+
#v2 +12345678901. Although this was generated from a phone number, it's a v2 raw UID which doesn't encode this
574+
# information, so token assumes email by default.
575+
self.verify_identity_type("Q4bGug8t1xjsutKLCNjnb5fTlXSvIQukmahYDJeLBtk=",
576+
IdentityType.Email.value)
577+
self.verify_identity_type("BEOGxroPLdcY7LrSiwjY52+X05V0ryELpJmoWAyXiwbZ",
578+
IdentityType.Phone.value) #v3 +12345678901
579+
self.verify_identity_type("oKg0ZY9ieD/CGMEjAA0kcq+8aUbLMBG0MgCT3kWUnJs=",
580+
IdentityType.Email.value) #v2 [email protected]
581+
self.verify_identity_type("AKCoNGWPYng/whjBIwANJHKvvGlGyzARtDIAk95FlJyb",
582+
IdentityType.Email.value) #v3 [email protected]
583+
self.verify_identity_type("EKCoNGWPYng/whjBIwANJHKvvGlGyzARtDIAk95FlJyb",
584+
IdentityType.Email.value) #v3 EUID [email protected]
585+
586+
def verify_identity_type(self, raw_uid, expected_identity_type):
587+
token = UID2TokenGenerator.generate_uid2_token_v4(raw_uid, _master_key, _site_id, _site_key)
588+
keys = EncryptionKeysCollection([_master_key, _site_key])
589+
result = decrypt_token(token, keys)
590+
self.assertEqual(raw_uid, result.uid2)
591+
self.assertEqual(expected_identity_type, get_token_identity_type(token))
592+
593+
594+
def get_token_identity_type(id):
595+
firstChar = id[0]
596+
if 'A' == firstChar or 'E' == firstChar: #from UID2-79+Token+ and +ID+format+v3
597+
return IdentityType.Email.value
598+
elif 'F' == firstChar or 'B' == firstChar:
599+
return IdentityType.Phone.value
600+
601+
raise Exception("unknown IdentityType")
602+
570603
def format_time(t):
571604
s = t.strftime('%Y-%m-%d %H:%M:%S.%f')
572605
return s[:-3]

tests/uid2_token_generator.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,8 @@
1313

1414
class Params:
1515
def __init__(self, expiry=dt.datetime.now(tz=timezone.utc) + dt.timedelta(hours=1),
16-
identity_scope=IdentityScope.UID2.value, identity_type=IdentityType.Email.value):
16+
identity_scope=IdentityScope.UID2.value):
1717
self.identity_scope = identity_scope
18-
self.identity_type = identity_type
1918
self.token_expiry = expiry
2019
if not isinstance(expiry, dt.datetime):
2120
self.token_expiry = dt.datetime.now(tz=timezone.utc) + expiry
@@ -84,7 +83,13 @@ def generate_uid2_token_with_debug_info(id_str, master_key, site_id, site_key, p
8483
master_payload += int.to_bytes(site_key.key_id, 4, 'big')
8584
master_payload += _encrypt_gcm(site_payload, None, site_key.secret)
8685

87-
token = int.to_bytes((params.identity_scope << 4 | params.identity_type << 2), 1, 'big')
86+
first_char = id_str[0]
87+
# see UID2-79+Token+and+ID+format+v3
88+
identity_type = IdentityType.Email.value
89+
if (first_char == 'F') or (first_char == 'B'):
90+
identity_type = IdentityType.Phone.value
91+
92+
token = int.to_bytes((params.identity_scope << 4 | identity_type << 2), 1, 'big')
8893
token += int.to_bytes(version, 1, 'big')
8994
token += int.to_bytes(master_key.key_id, 4, 'big')
9095
token += _encrypt_gcm(master_payload, None, master_key.secret)

0 commit comments

Comments
 (0)