Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion UID2.Client.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<package>
<metadata>
<id>UID2.Client</id>
<version>5.1.2</version>
<version>5.1.3</version>
<title>UID2 Client C# SDK</title>
<authors>UID2 team</authors>
<owners>UID2 team</owners>
Expand Down
4 changes: 2 additions & 2 deletions src/UID2.Client/UID2Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public async Task<RefreshResponse> RefreshAsync(CancellationToken token)

private string GetAssemblyNameAndVersion()
{
var version = "5.1.2";
var version = "5.1.3";
return "uid-client-net-" + version;
}

Expand Down Expand Up @@ -163,4 +163,4 @@ private async Task<RefreshResponse> RefreshInternal(CancellationToken token)
}
}
}
}
}
4 changes: 2 additions & 2 deletions src/UID2.Client/Utils/UID2TokenGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ private static string GenerateUid2TokenWithDebugInfo(string uid, Key masterKey,
var firstChar = uid.Substring(0, 1);
var identityType = (firstChar == "F" || firstChar == "B") ? IdentityType.Phone : IdentityType.Email; //see UID2-79+Token+and+ID+format+v3

rootStreamWriter.Write((byte)((encryptParams.IdentityScope << 4) | ((int)identityType << 2)));
rootStreamWriter.Write((byte)((encryptParams.IdentityScope << 4) | ((int)identityType << 2) | 3));
rootStreamWriter.Write((byte)adTokenVersion);
rootStreamWriter.Write((int)masterKey.Id);

Expand Down Expand Up @@ -209,4 +209,4 @@ private static byte[] EncryptGCM(byte[] data, byte[] iv, byte[] secret)
return cipherText;
}
}
}
}
54 changes: 39 additions & 15 deletions test/UID2.Client.Test/EncryptionTestsV4.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public void crossPlatformConsistencyCheck_Base64UrlTestCases()

}

public void crossPlatformConsistencyCheck_Base64UrlTest(byte[] rawInput, String expectedBase64URLStr)
public void crossPlatformConsistencyCheck_Base64UrlTest(byte[] rawInput, string expectedBase64URLStr)
{
var stream = new MemoryStream();
var writer = new BigEndianByteWriter(stream);
Expand All @@ -65,7 +65,7 @@ public void crossPlatformConsistencyCheck_Base64UrlTest(byte[] rawInput, String
[Fact]
public void crossPlatformConsistencyCheck_Decrypt()
{
String crossPlatformAdvertisingToken =
string crossPlatformAdvertisingToken =
"AIAAAACkOqJj9VoxXJNnuX3v-ymceRf8_Av0vA5asOj9YBZJc1kV1vHdmb0AIjlzWnFF-gxIlgXqhRFhPo3iXpugPBl3gv4GKnGkw-Zgm2QqMsDPPLpMCYiWrIUqHPm8hQiq9PuTU-Ba9xecRsSIAN0WCwKLwA_EDVdzmnLJu64dQoeYmuu3u1G2EuTkuMrevmP98tJqSUePKwnfK73-0Zdshw";
//Sunday, 1 January 2023 1:01:01 AM UTC
var referenceTimestampMs = 1672534861000L;
Expand Down Expand Up @@ -93,8 +93,8 @@ public void crossPlatformConsistencyCheck_Decrypt()
client.RefreshJson(KeySetToJson(MASTER_KEY, SITE_KEY));

//verify that the dynamically created ad token can be decrypted
String runtimeAdvertisingToken =
UID2TokenGenerator.GenerateUid2TokenV4(EXAMPLE_UID, masterKey, SITE_ID, siteKey, encryptParams);
string runtimeAdvertisingToken =
GenerateUid2TokenV4(EXAMPLE_UID, masterKey, SITE_ID, siteKey, encryptParams);
//best effort check as the token might simply just not require padding
Assert.Equal(-1, runtimeAdvertisingToken.IndexOf('='));

Expand All @@ -107,14 +107,38 @@ public void crossPlatformConsistencyCheck_Decrypt()
res = client.Decrypt(crossPlatformAdvertisingToken, NOW);
Assert.Equal(EXAMPLE_UID, res.Uid);
}

private static void ValidateAdvertisingToken(string advertisingTokenString, IdentityScope identityScope, IdentityType identityType) {
string firstChar = advertisingTokenString.Substring(0, 1);
if (identityScope == IdentityScope.UID2)
Assert.Equal(identityType == IdentityType.Email ? "A" : "B", firstChar);
else
Assert.Equal(identityType == IdentityType.Email ? "E" : "F", firstChar);

string secondChar = advertisingTokenString.Substring(1, 1);
Assert.Equal("4", secondChar);

//No URL-unfriendly characters allowed:
Assert.Equal(-1, advertisingTokenString.IndexOf('='));
Assert.Equal(-1, advertisingTokenString.IndexOf('+'));
Assert.Equal(-1, advertisingTokenString.IndexOf('/'));
}

private static string GenerateUid2TokenV4(string uid, Key masterKey, int siteId, Key siteKey, UID2TokenGenerator.Params tokenGeneratorParams)
{
string advertisingToken = UID2TokenGenerator.GenerateUid2TokenV4(uid, masterKey, siteId, siteKey, tokenGeneratorParams);
ValidateAdvertisingToken(advertisingToken, IdentityScope.UID2, IdentityType.Email);
return advertisingToken;
}


[Fact]
public void SmokeTest()
{
var client = new UID2Client("ep", "ak", CLIENT_SECRET, IdentityScope.UID2);
var refreshResult = client.RefreshJson(KeySetToJson(MASTER_KEY, SITE_KEY));
Assert.True(refreshResult.Success);
string advertisingToken = UID2TokenGenerator.GenerateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, UID2TokenGenerator.DefaultParams);
string advertisingToken = GenerateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, UID2TokenGenerator.DefaultParams);
var res = client.Decrypt(advertisingToken, NOW);
Assert.True(res.Success);
Assert.Equal(EXAMPLE_UID, res.Uid);
Expand All @@ -124,7 +148,7 @@ public void SmokeTest()
public void EmptyKeyContainer()
{
var client = new UID2Client("ep", "ak", CLIENT_SECRET, IdentityScope.UID2);
var advertisingToken = UID2TokenGenerator.GenerateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, UID2TokenGenerator.DefaultParams);
var advertisingToken = GenerateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, UID2TokenGenerator.DefaultParams);
var res = client.Decrypt(advertisingToken, NOW);
Assert.False(res.Success);
Assert.Equal(DecryptionStatus.NotInitialized, res.Status);
Expand All @@ -134,7 +158,7 @@ public void EmptyKeyContainer()
public void ExpiredKeyContainer()
{
var client = new UID2Client("ep", "ak", CLIENT_SECRET, IdentityScope.UID2);
var advertisingToken = UID2TokenGenerator.GenerateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, UID2TokenGenerator.DefaultParams);
var advertisingToken = GenerateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, UID2TokenGenerator.DefaultParams);

Key masterKeyExpired = new Key(MASTER_KEY_ID, -1, NOW, NOW.AddHours(-2), NOW.AddHours(-1), MASTER_SECRET);
Key siteKeyExpired = new Key(SITE_KEY_ID, SITE_ID, NOW, NOW.AddHours(-2), NOW.AddHours(-1), SITE_SECRET);
Expand All @@ -149,7 +173,7 @@ public void ExpiredKeyContainer()
public void NotAuthorizedForMasterKey()
{
var client = new UID2Client("ep", "ak", CLIENT_SECRET, IdentityScope.UID2);
var advertisingToken = UID2TokenGenerator.GenerateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, UID2TokenGenerator.DefaultParams);
var advertisingToken = GenerateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, UID2TokenGenerator.DefaultParams);

Key anotherMasterKey = new Key(MASTER_KEY_ID + SITE_KEY_ID + 1, -1, NOW, NOW, NOW.AddHours(1), MASTER_SECRET);
Key anotherSiteKey = new Key(MASTER_KEY_ID + SITE_KEY_ID + 2, SITE_ID, NOW, NOW, NOW.AddHours(1), SITE_SECRET);
Expand All @@ -163,7 +187,7 @@ public void NotAuthorizedForMasterKey()
public void InvalidPayload()
{
var client = new UID2Client("ep", "ak", CLIENT_SECRET, IdentityScope.UID2);
byte[] payload = UID2Base64UrlCoder.Decode(UID2TokenGenerator.GenerateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, UID2TokenGenerator.DefaultParams));
byte[] payload = UID2Base64UrlCoder.Decode(GenerateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, UID2TokenGenerator.DefaultParams));
var advertisingToken = UID2Base64UrlCoder.Encode(payload.SkipLast(1).ToArray());

client.RefreshJson(KeySetToJson(MASTER_KEY, SITE_KEY));
Expand All @@ -180,7 +204,7 @@ public void TokenExpiryAndCustomNow()

var client = new UID2Client("ep", "ak", CLIENT_SECRET, IdentityScope.UID2);
client.RefreshJson(KeySetToJson(MASTER_KEY, SITE_KEY));
var advertisingToken = UID2TokenGenerator.GenerateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, encryptParams);
var advertisingToken = GenerateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, encryptParams);

var res = client.Decrypt(advertisingToken, expiry.AddSeconds(1));
Assert.Equal(DecryptionStatus.ExpiredToken, res.Status);
Expand All @@ -195,7 +219,7 @@ public void EncryptDataSiteIdFromToken()
byte[] data = { 1, 2, 3, 4, 5, 6 };
var client = new UID2Client("ep", "ak", CLIENT_SECRET, IdentityScope.UID2);
client.RefreshJson(KeySetToJson(MASTER_KEY, SITE_KEY));
string advertisingToken = UID2TokenGenerator.GenerateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, UID2TokenGenerator.DefaultParams);
string advertisingToken = GenerateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, UID2TokenGenerator.DefaultParams);
var encrypted = client.EncryptData(EncryptionDataRequest.ForData(data).WithAdvertisingToken(advertisingToken));
Assert.Equal(EncryptionStatus.Success, encrypted.Status);
var decrypted = client.DecryptData(encrypted.EncryptedData);
Expand All @@ -209,7 +233,7 @@ public void EncryptDataSiteIdFromTokenCustomSiteKeySiteId()
byte[] data = { 1, 2, 3, 4, 5, 6 };
var client = new UID2Client("ep", "ak", CLIENT_SECRET, IdentityScope.UID2);
client.RefreshJson(KeySetToJson(MASTER_KEY, SITE_KEY));
string advertisingToken = UID2TokenGenerator.GenerateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID2, SITE_KEY, UID2TokenGenerator.DefaultParams);
string advertisingToken = GenerateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID2, SITE_KEY, UID2TokenGenerator.DefaultParams);
var encrypted = client.EncryptData(EncryptionDataRequest.ForData(data).WithAdvertisingToken(advertisingToken));
Assert.Equal(EncryptionStatus.Success, encrypted.Status);
var decrypted = client.DecryptData(encrypted.EncryptedData);
Expand All @@ -223,7 +247,7 @@ public void EncryptDataSiteIdAndTokenSet()
byte[] data = { 1, 2, 3, 4, 5, 6 };
var client = new UID2Client("ep", "ak", CLIENT_SECRET, IdentityScope.UID2);
client.RefreshJson(KeySetToJson(MASTER_KEY, SITE_KEY));
var advertisingToken = UID2TokenGenerator.GenerateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, UID2TokenGenerator.DefaultParams);
var advertisingToken = GenerateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, UID2TokenGenerator.DefaultParams);
Assert.Throws<ArgumentException>(() =>
client.EncryptData(EncryptionDataRequest.ForData(data).WithAdvertisingToken(advertisingToken).WithSiteId(SITE_KEY.SiteId)));
}
Expand All @@ -235,7 +259,7 @@ public void EncryptDataTokenDecryptKeyExpired()
var client = new UID2Client("ep", "ak", CLIENT_SECRET, IdentityScope.UID2);
Key key = new Key(SITE_KEY_ID, SITE_ID2, NOW, NOW, NOW.AddDays(-1), MakeTestSecret(9));
client.RefreshJson(KeySetToJson(MASTER_KEY, key));
string advertisingToken = UID2TokenGenerator.GenerateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, key, UID2TokenGenerator.DefaultParams);
string advertisingToken = GenerateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, key, UID2TokenGenerator.DefaultParams);
var encrypted = client.EncryptData(EncryptionDataRequest.ForData(data).WithAdvertisingToken(advertisingToken));
Assert.Equal(EncryptionStatus.NotAuthorizedForKey, encrypted.Status);
}
Expand All @@ -249,7 +273,7 @@ public void EncryptDataTokenExpired()
byte[] data = { 1, 2, 3, 4, 5, 6 };
var client = new UID2Client("ep", "ak", CLIENT_SECRET, IdentityScope.UID2);
client.RefreshJson(KeySetToJson(MASTER_KEY, SITE_KEY));
var advertisingToken = UID2TokenGenerator.GenerateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, encryptParams);
var advertisingToken = GenerateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, encryptParams);
var encrypted = client.EncryptData(EncryptionDataRequest.ForData(data).WithAdvertisingToken(advertisingToken));
Assert.Equal(EncryptionStatus.TokenDecryptFailure, encrypted.Status);

Expand Down