Mac App Store Receipt Validation Code?

Rei picture Rei · Nov 23, 2010 · Viewed 19.5k times · Source

Wondering if anyone has a tutorial or working code for the new Mac App Store's receipt validation? About the only references I've been able to find so far are Apple's stellar documentation on the topic and one open source project which compiles but doesn't have a lot of inline comments so it's hard to understand unless you are a crypto whiz.

Apple docs for registered devs only:

https://developer.apple.com/devcenter/mac/documents/validating.html

Roddi's ValidateStoreReceipt (looks promising, but sparsely documented):

https://github.com/roddi/ValidateStoreReceipt

Also wondering why Apple does not just provide working code for validation?

Any other good references out there?

Answer

Laurent Etiemble picture Laurent Etiemble · Oct 30, 2011

It is hard to provide a generic solution for Mac App Store receipt validation, mainly because this is a very sensitive piece of code that must be hard to bypass (cf. Apple documentation).

These GitHub projects are very good starting points to learn about what steps must be performed in receipt validation:

Once you have understood what must be done, here is some advice:

  • Don't use Objective-C classes or methods. Objective-C carries a lot of metadata, and its dynamic nature exposes it to runtime injection.
  • Only use C function calls. Even if you need more lines of code with the CoreFoundation framework, you can perfectly do what the Foundation framework can do (NSString, NSArray, NSDictionary, ...).
  • Don't link dynamically with the OpenSSL library as it has been deprecated in Mac OS X Lion. If you want to go with OpenSSL, link it statically to be sure to have the latest release.
  • Use system functions for cryptography. Mac OS X ships with equivalent functions since 10.5. For example, to compute a SHA-1 hash, you can use the CC_SHA1 function.
  • Don't put strings in plaintext in your code. Encode them or encrypt them. If you fail to do so, you give a hint about the location of your code.
  • Don't use numeric constants in your code. Compute them at runtime, with some simple operations (+, -, / or *). Again, if you fail to do so, you give a hint about the location of your code.
  • Avoid simple tests for validation by embedding your tests and the call to NSApplicationMain into a complex loop.
  • Avoid calling NSApplicationMain directly. Use a function pointer to hide the invocation. If you fail to do so, you give a hint about the location of your code.
  • For each release of your application, slightly modify the validation code so it is never the same.

Remember that receipt validation is necessary and is not simple as it seems. It can consume a lot of time that you may better spend on your application.

So I suggest you to take a look at this application: Receigen (Disclaimer: I am the developer of this application).