Introduction
Receigen is an application that generates code in order to perform App Store receipt validation code for OS X and iOS. An App Store receipt is what an application must check to ensure that the current running copy is an authorized one and has properly been obtained. Apple provides a good introduction about receipt validation for OS X in this document and for iOS in this document. An in-depth article is also available on the objc.io website.
The main issue with the receipt validation is that the required code is tedious to write, to maintain and to change. Because, as an application developer, you should be freed from dealing with that kind of code, Receigen takes care of this part so you can focus on what is really important for you: your application.
As said above, Receigen not only frees you from dealing with receipt validation code, but it ensures that the code changes between each generation. Every time Receigen generates validation code, the constants and the strings are re-obfuscated, the checks are performed differently while the code flow changes.
Receigen has been thought of as a setup-and-forget tool: once properly integrated, you will never have to worry about receipt validation code again.
Receipt validation
OS X
On OS X, an application must perform the receipt validation phase immediately after it is launched, before displaying any user interface or spawning any child processes. This validation phase is mandatory as per Apple for every Mac App Store applications; failing to properly validate a receipt at startup can lead to application’s rejection.
The main steps are:
- Locating the receipt.
The receipt file is located into the application bundle with the
Contents/_MASReceipt/receipt
path. If no receipt file is present, the application must exit with a status of173
. - Loading the receipt.
The receipt file should be a valid PKCS#7 container, properly signed.
If the receipt file cannot be loaded and decoded, the application must exit with a status of
173
. - The information contained in the receipt should match the application’s one: the bundle identifier and the bundle version
If the information don’t match, the application must exit with a status of
173
. - The receipt file contains a hash value that can be verified by computing a SHA-1 hashing on the bundle identifier, the bundle version, the computer’s GUID and an opaque value.
If the hashes don’t match, the application must exit with a status of
173
. - If the Volume Purchase Program is used, check the expiration date of the receipt.
If the date is expired, the application must exit with a status of
173
. - If the validation succeeds, then the application can be run.
Note that even if exiting with a status code of 173
is required in most cases, Receigen can also generate validation code that behaves differently.
See the Customization guide to learn more about the possibilities.
iOS
On iOS, an application must perform the receipt validation to ensure that the application is legitimate. It is up to the developer to decide where to place these checks.
The main steps are:
- Locating the receipt.
The receipt file is located into the application sandbox and its path can be obtained by calling the
appStoreReceiptURL
method for the mainNSBundle
instance. If no receipt file is present, the application must trigger a receipt refresh request. - Loading the receipt. The receipt file should be a valid PKCS#7 container, properly signed. If the receipt file cannot be loaded and decoded, the application must trigger a receipt refresh request.
- The information contained in the receipt should match the application’s one: the bundle identifier and the bundle version If the information don’t match, the application must trigger a receipt refresh request.
- The receipt file contains a hash value that can be verified by computing a SHA-1 hashing on the bundle identifier, the bundle version, the computer’s GUID and an opaque value. If the hashes don’t match, the application must trigger a receipt refresh request.
- If the Volume Purchase Program is used, check the expiration date of the receipt. If the date is expired, the application must trigger a receipt refresh request.
- If the validation succeeds, then the application can be run.
Note that even if triggering a receipt refresh request is required in most cases, Receigen can also generate validation code that behaves differently. See the Customization guide to learn more about the possibilities.
Checking InApp purchases
This kind of check is only required if you deal with InApp purchases. The receipt file contains all the informations about the InApp purchases performed by the application.
In order to check the InApp purchases, the steps are the same as found in the Receipt Validation. The difference is that if the validation succeeds, then the InApp purchases contained in the receipt are examined. Given a list of InApp purchase product identifiers, the receipt InApp purchases entries are enumerated. For each product identifier a block is called to either provide purchase information or indicate that the product is not present in the receipt.
Going further
You can go further with Receigen by reading the available guides.