If you are developing applications for Windows phone, you have probably read about the Standard and Advanced Anti-Piracy Protection available to developers to help protect your hard developed IP. If you haven’t done so yet, check out the Windows Marketplace anti-piracy model white paper available here. Advanced Anti-Piracy Protection (AAPP) is designed to thwart the illegitimate sharing of your Windows phone applications. Even if a hacker obtains the binaries from one device, AAPP will prevent that application from running on any other device. While Standard Anti-Piracy protection does not require any intervention by the developer, AAPP does require that you integrate code into your application. We will walk through how AAPP works, how you obtain the AAPP code from Microsoft and how to integrate the AAPP code into your application.
How Advanced Anti-Piracy Protection works
Installation Time: The Marketplace Client installs a license, derived from the application id and the device id, into the registry. The license is protected using RSA security.Application Run Time: The startup code (obtained from the Marketplace section of the Windows phone Developer Portal) in your application verifies that the license stored in the registry matches your application. You (the developer) has control over the error handling. You can choose to display an error and quit, shift into ‘demo’ mode, or do whatever you deem appropriate.
How to obtain the AAPP Code
Obtaining the AAPP code is part of the application submission process. You will see the following at Step 3 (Product Info).Clicking on ‘Show Managed Code…’ we see the following code:
- using System.Runtime.InteropServices;
- using System.Security.Cryptography;
- using System.Text;
- // ....
- static string m_certModulus = "a26T2aaMKaafWSaI5JOaaQ7...";
- static string m_certExponent = "DUPQ";
- static string m_appSku = "dddddddd-70e8-4b15-9c90-46fca72d6959";
- [DllImport("coredll.dll")]
- private extern static int GetDeviceUniqueID([In, Out] byte[] appdata,
- int cbApplictionData,
- int dwDeviceIDVersion,
- [In, Out] byte[] deviceIDOuput,
- out uint pcbDeviceIDOutput);
- static void Main()
- {
- //Pre-Initialization code
- // ....
- byte[] licenseBytes =
- Microsoft.Win32.Registry.CurrentUser.OpenSubKey(
- "Security\\Software\\Microsoft\\Marketplace\\Licenses\\")
- .GetValue(m_appSku) as byte[];
- string data = m_appSku.ToLower() + " " + GetUniqueDeviceID();
- RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
- //Create a new instance of RSAParameters.
- RSAParameters RSAKeyInfo = new RSAParameters();
- //Set RSAKeyInfo to the public key values.
- RSAKeyInfo.Modulus = Convert.FromBase64String(m_certModulus);
- RSAKeyInfo.Exponent = Convert.FromBase64String(m_certExponent);
- rsa.ImportParameters(RSAKeyInfo);
- byte[] bData = System.Text.Encoding.ASCII.GetBytes(data);
- if (null == licenseBytes ||
- !rsa.VerifyData(bData, new SHA1CryptoServiceProvider(),
- licenseBytes))
- {
- MessageBox.Show("Could not verify signature");
- }
- else
- {
- MessageBox.Show("License is valid!");
- }
- // ...
- // Post-initialization code
- Application.Run(new Form1());
- }
- public static string GetUniqueDeviceID()
- {
- // Call the GetDeviceUniqueID
- byte[] appData = Encoding.Unicode.GetBytes("Marketplace");
- int appDataSize = appData.Length;
- byte[] outData = new byte[20];
- uint outSize = 20;
- GetDeviceUniqueID(appData, appDataSize, 1, outData, out outSize);
- StringBuilder resultSB = new StringBuilder();
- foreach (byte b in outData)
- {
- resultSB.Append(string.Format("{0:x2}", b));
- }
- return resultSB.ToString();
- }
Integrating AAPP Code into your Application
This code has all the basics you need to implement the Advanced Anti-Piracy Protection. However there are a few gaps that you need to fill-in. I’ve put together a sample (HelloAAPP) that has these issues worked out. You can download it from here.- The code provided by the portal does not catch NullReferenceException thrown by the Registry class if the license key cannot be found. This is most commonly caused by installing the CAB outside of the Marketplace client. This is because during installation, the Marketplace client installs the license into the registry. Most often you will see this during your own ad hoc testing. To help you avoid this error, in Debug mode, the sample installs a test license into the registry. Additionally the sample includes a handler for this exception.
- In the portal code, if the validation succeeds or fails, the application will still run. In most cases you will want to notify the user and exit. The sample displays an error message and the application exits following the users response.
- In the portal code, if the validation succeeds, the code will notify the user telling them so. This notification is probably not necessary in a real world scenario. The sample simply continues if the validation succeeds. Note that in the sample the same validation (VerifyData) is called in both Debug and Release modes. In Debug mode the test license is validated using the test key. In Release mode the real license is validated using the public key included in the developer portal code.
- In the portal code, the error message does not have any context. A (hopefully) clearer message “License verification failed. Please install via Windows Marketplace for Mobile.” is used in the sample.
- In the portal code, there is no way to test the validation logic since there is currently no way to install a license. As mentioned above, the sample creates and uses a test license that tests the validation logic. This goal of the sample is to demonstrate a way to use a test license in Debug mode and a real license in Release mode with all other code being the same.
- The error message is not localized. In the sample, the message is localized in English and German (de-DE).
Please let me know in the comments if there any other gaps in the AAPP code that you have had to fill.
Thanks,
Mike

No comments:
Post a Comment