Mac App Store Receipt Validation Code? - cocoa

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?

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:
NPReceiptVerification
ValidateStoreReceipt
AppReceiptParser
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).

In order to validate against the real receipt after testing, change this line of code in your main.m file:
if (!validateReceiptAtPath(#"~/Desktop/receipt"))
to
#ifdef USE_SAMPLE_RECEIPT // defined for debug version
NSString *pathToReceipt = #"~/Desktop/receipt";
#else
NSString *pathToReceipt = [[[NSBundle mainBundle] bundlePath]
stringByAppendingPathComponent:#"Contents/_MASReceipt/receipt"];
#endif
if (!validateReceiptAtPath(pathToReceipt))
exit(173); //receipt did not validate
and in your compiler settings, "Other C Flags" for your Debug Configuration should include -DUSE_SAMPLE_RECEIPT
courtesy http://jesusagora.org/groups/futurebasic/0::53562:get:1read.html

Be sure to check that you are validating a receipt for your app. Easy to do all the crypto and verification of signatures for the wrong receipt.
See http://pastebin.com/1eWf9LCg where it looks like Angry Birds missed this bit and left them open to people substituting in a receipt from a free app.
Alan Quatermain also has code to do this up on github. https://github.com/AlanQuatermain/mac-app-store-validation-sample
It should not be used as-is to avoid automated removal.

You could try NPReceiptVerification. It's the easiest way to add receipt verification to your app. You just add the class files to your project, set the version and bundle identifier, and everything else is handled automatically.

I reviewed Alan Quartermain's code and it looks good. Something to think about:
the last parameter here could/should be a compiled requirement stating that the code must be signed by YOUR certificate and no-one else's.
When the developer submits an app to the store for approval, the signing certificates are as follows:
3rd Party Mac Developer Application: me
Apple Worldwide Developer Relations Certification Authority
Apple Root CA
After the app is delivered from the App Store to the end user, the signing certificates are as follows:
Apple Mac OS Application Signing
Apple Worldwide Developer Relations Certification Authority
Apple Root CA
Also, I suggest only exit(173) when the receipt is missing, but everything else is in order.

You can Refer the RVNReceiptValidation it is easy to implement. Just you have to set the Bundle id in RVNReceiptValidation.m file and version of your App. Remember to get the receipt from the apple you have to launch the app from the Finder. This Class also helps in the implementation of InApp Purchase.

I'd propose to implement the code verification routines as C functions, not ObjC methods.
This technique makes it (a bit) harder to locate receipt checking code, since fewer method-names get compiled into the binary.

RVNReceiptValidation is great and it uses CommonCrypto rather than the now deprecated by Apple, openssl. you will have to attach a valid receipt to your project to debug it. Do this by getting a valid receipt from another app bundle and create a build phase in your test environment to add it to your bundle. I suggest the following techniques for obfuscation:
Encrypt the kRVNBundleID and kRVNBundleVersion and decrypt them when you compare them to the CFBundleIdentifier and CFBundleShortVersionString.
I create an array of function pointers with random values and change them to valid pointers to the functions in RVNReceiptValuation at run time before executing them using code like this:
static void testFunction(void);
typedef void (*functionPtr)(void);
functionPtr obfuscationArray[8] = {
(functionPtr)0xA243F6A8,
(functionPtr)0x885308D3,
(functionPtr)0x13198A2E,
(functionPtr)0x03707344,
(functionPtr)0xA4093822,
(functionPtr)0x299F31D0,
(functionPtr)0x082EFA98,
(functionPtr)0xEC4E6C89};
int main(int argc, const char * argv[]) {
functionPtr myFuncPtr;
obfuscationArray[3] = &testFunction;
myFuncPtr = obfuscationArray[3];
(myFuncPtr)();
return 0;
}
static void testFunction(void){
printf("function executed\n");
}

I'll elaborate on priller's answer. If Apple provided a code sample for the validation process then it would be very easy for a Bad Guy to take your compiled app and scan through it for the code corresponding to the validation process. The Bad Guy would know exactly what the compiled code looks like if you use a standard code sample from Apple. Once the Bad Guy has found that section of the code it is pretty trivial to modify the app's compiled code to just skip the receipt verification stage, rendering the entire thing useless.
All that said, a determined cracker is probably going to get around any copy protection you put in place regardless of what you do. The games industry (for example) spends a lot of time trying to protect their software, and cracked versions seem to always be available.

When creating the sample receipt from Apple Docs, be sure not to include any extra characters after 'end' else the uudecode will fail.

Yes, in their docs it says, "It is important that you employ a solution that is unique to your application."

roddi's ValidateStoreReceipt worked for me before, but it does not work any more.
I wrote a blog post about the solution: http://vinceyuan.blogspot.com/2012/07/validate-mac-app-store-receipt-2012.html
Copied here:
roddi's code is still working. You need not change it. (Just need to get the latest version)
Follow these steps (internet required):
Log out from Mac App Store app.
Remove USE_SAMPLE_RECEIPT flag from your project settings -> Preprocessor Macros.
Compile your project
Find this app in Finder
Double click it in Finder to run. Do not run it in Xcode.
The OS will ask you to log in with your Apple ID. Do not log in with your real iTunes account. You need to log in with the test account. Find it or create it in the iTunesconnect website.
The OS will say something like "Your app is broken. Download it in App Store". Ignore this message. If you "Show Package Contents" of this app in Finder, you will see there is a file _MASReceipt/receipt. The OS installed a development receipt. We will not need the old sample receipt any more. That's why we remove USE_SAMPLE_RECEIPT debugging flag.
Done. You can debug your app now.

Even with NPReceiptValidation you still should validate the security of your application bundle including the signing certificates. This is documented in the WWDR recommendations for developers.
A solution:
http://itunes.apple.com/us/app/apptight-pro-app-store-code/id427083596?mt=12
One potential problem with NPReceiptValidation is that method selectors on Cocoa objects are very easy to hijack. It's the most popular way of extending apps.
Here's another tool for assisting with In-App purchase parsing:
http://itunes.apple.com/us/app/pkcs-7viewer/id547539804?mt=12

Related

Is it still possible to publish an Electron app to the Mac Store?

I'm trying to successfully submit my Electron app to the Mac Store. I want to put it into TestFlight, similar to how I am submitting the corresponding iOS app. Ultimately, I want both of these processes to be part of a CI pipeline. The iOS version of this is ready to go.
For the Electron app, I'm using Electron-Builder to do the packaging and signing, and leveraging electron-builder-notarize to get past the Apple notarization step. After about a week of diving down several rabbit holes that became full-fledged rabbit warren metropolises, I finally have a working combination of configuration settings, certificates, plists, and pixie dust in place that my pipeline successfully builds and notarizes my "mas" target package.
I thought that once I had gotten past the rather hellish notarization step, I would be pretty much out of the woods -- after all, Apple 'notarized' it (and sent me an email to prove it). But when I use the Apple Transporter app to post it to the App Store (I'm using this manually for now until I prove this works, then later I'll use the CLI commands for it to complete my CI implementation) it reports the app is rejected with 5 issues. These are actually variations of the same thing:
Electron.app' is already in use by another application.
Electron.app/Contents/Frameworks/Electron Helper (GPU).app' is already in use by another application.
/Electron.app/Contents/Frameworks/Electron Helper (Plugin).app' is already in use by another application.
Electron.app/Contents/Frameworks/Electron Helper (Renderer).app' is already in use by another application.
Electron.app/Contents/Frameworks/Electron Helper.app' is already in use by another application.
I thought Electron-Builder was supposed to deal with these internal ids. My "mas" block of the config looks like
"mas": {
"type": "distribution",
"hardenedRuntime": false,
"provisioningProfile": "embedded.provisionprofile",
"entitlements": "build/entitlements.mas.plist",
"entitlementsInherit": "build/entitlements.mas.inherit.plist",
"entitlementsLoginHelper": "build/entitlements.mas.loginhelper.plist",
"publish": null
},
which I believe is what is needed to specify that these inner binaries are signed. Perhaps not. Copying others who also had to abandon the docs is not necessarily a guarantee of success. But these things did get me this far.
I've scoured SO and other Internet sites, and of course the poorly written and often obscure official documentation sources, but I can't find the answer to this.
In my travels, I happened across this blog which makes me think that even if I get past this part, there may still be a long bumpy road ahead, and it may turn out to be a dead end.
I notice a lot of developers have commented they chose to abandon the Mac store and instead simply self-publish with their own URL link for download. That seems to be a shame, at the very least, and certainly not my preference.
It makes we wonder if this is even possible. Many of the posts (not to mention the docs) contain outdated information, and few posts are more recent than more than a year. Many things have changed. Maybe everyone threw in the towel. Am I on a futile quest?
I believe I found the answer to the main question of "is it possible?" I may still run into other issues, but I've discovered the main problem.
My Electron project is in a different construction than that of the "Electron-quick-start" template, so the Electron-builder packaging and signing steps do not find what they are looking for in all the normal places.
I am not 100% sure I can successfully reconstruct my project into the 'canonical' format, but that appears to be the solution.
I was able to create a basic quick-start app and upload it to the App Store in a matter of minutes, so all the parts do in fact work. The project just need to be of the right construction.

Is there a way to detect if a macOS app running is from the Mac App Store or not?

I have this app of mine that is distributed on the Mac App Store and outside it, from my own site.
I need to detect, at run time, what version is running, so I can do some decisions inside the code.
Is there a way to detect that? How can I differentiate that? Is there a way to know if the app is signed for the App Store or not?
Edit: I have found this library but this is not good because it tells the app is not from the app store simply if the receipt is missing. But the receipt may be missing for other reasons. The lack of receipt is not a good enough reason.
I see two ways to do this:
Make a compile-time flag. Compile it one way for submission to the App Store, the other way for distribution outside the App Store.
Rather than just checking your app's code signature validity (as the library you found does), call SecCodeCopySigningInformation to get signature details, and look at the kSecCodeInfoCertificates array to see whether it includes your Developer ID cert or the "Apple Mac OS Application Signing" cert used by the App Store.
IMO the second option is significantly more complex and fragile; for example, if Apple changes how they sign App Store apps, your code may break. I'd go with the first option.

Do I need to protect my desktop app if distributed over AppStore?

I have made a simple desktop app that I want to sell through the AppStore. Of course I want to be protected against piracy. Does AppStore give any protection? How does that process work?
For instance, what prevents a dishonest person from buying my app and then upload it on a torrent and share it with others. If these other people download my app, will they automatically be asked for their identity check (Apple ID and password), the first time they try to use my app, thus preventing them from using it if they have not bought it legally.
If this identity check does not happen automatically, then do I need to add some code in my app that will ask for the identity check. If so, where can I find info about how to do that?
I'm not entirely sure how this process works. Could somebody shed some light on it?
Mac App Store slips a receipt each time it is downloaded into the bundle. The receipt contains information about the computer used (the so called GUID) and the user logged into the App Store.
See here how you should validate the receipt:
https://developer.apple.com/library/mac/releasenotes/General/ValidateAppStoreReceipt/Introduction.html#//apple_ref/doc/uid/TP40010573
If you implement the GUID validation as described in the document, the app will not run on any other computer.
Also check the signature of your code to make sure it has not been tampered:
Verifying app's signature by code
Your application, when downloaded from the App Store, contains a receipt. The receipt contains proof that it was downloaded onto this computer from the App Store, and the ID of the application. There are instructions somewhere on Apple's website that tell you how to verify the receipt and what to do if the verification fails.
That said, you are much better off concentrating on writing an app that people actually want to buy. People who pirate your app wouldn't hand over money if it couldn't be pirated. They would do without it, pick some free app, or pick a different app that they can pirate.
And I'm quite sure that any copy protection you build into your app yourself will get it rejected from the App Store.
Even though the answers I've got were helpful, they didn't quite provide the answer I needed. Looking around I found a software called Receigen from Laurent Etiemble, and the FAQ on his site (http://receigen.etiemble.com/faq.html) gave many answers for what I was looking for. For instance
What is an App Store receipt validation ? Why is it needed ?
Basically, an App Store receipt is what an application must check to ensure that the copy is genuine and can be run.
What happens if I don't check the App Store receipt ?
Well, anybody with a copy of your application can run it, with or without proper authorization.
Is the code receipt validation easy to write?
No because it requires deep understanding of cryptography and secure coding techniques.
It didn't hurt either that Receigen generated code that freed me from dealing with receipt validation code. Receigen takes care of this part so I can focus on what is really important for me: my application.
Yes, it costs money but personally I am more than glad to pay it, because I find this part of the development tedious, boring and complex.
TPInAppReceipt is a great package for this.
I was able to easily add local receipt validation after trying many others solutions less successfully:
https://github.com/tikhop/TPInAppReceipt

Signing of binary by someone else

I am trying to figure out if I am in a potential bind here. I am having someone else develop my app and I have given them complete access to my developer account to create the certificates to build the binary. I have uploaded the binary using the Application Loader and it it now waiting for review by Apple. My question is when it comes time to update the app, will I be able to do so without using the programmer who signed the certificate? When I become competent I'd like to do this myself but I'm clearly not there yet. I don't want to be in a situation where I have to keep going back to the same programmer to do the smallest thing.
Yes, provided you:
Have them send you the signing assets as described in "Exporting Your Code Signing Assets to Your File System" in the Xcode documentation. Note that they will still be able to sign using your key.
Have them send you the original project, obviously.
Once you part ways with them you should change the passwords of any accounts they've been given access to, like Apple ID and iTunes Connect.
At a later date, or as a last resort, you can create new signing assets as described in "Reset You Signing and Provisioning Assets..." in the Tools Workflow Guide.
So, most important going forward, they must not have access to any Apple accounts belonging to you.

Mac App Store - Copy Protection, or not, or what?

the license agreement for the Mac Developer Program explicitly states that I am not to implement my own copy protection process in my Mac app.
Yet, in the developer documentation, Apple also says this:
You can add receipt validation code to
your application to prevent
unauthorized copies of your
application from running.
I am confused here. Does the Mac App Store provide any form of built-in copy protection for Mac apps? The above statement from Apple would seem to indicate that it does not.
The statement suggests that if I do not implement these receipt checks, then unauthorised copies of my Mac App CAN run on other Macs.
I'm not allowed to implement (or rather, keep an existing) copy protection, but I am expected to verify receipts manually, using various fragments of code and pseudo-code provided by Apple, simply to provide the most basic level of protection. Is this interpretation correct?
Is this a miscommunication from Apple, or is this really how things are done?
Ref: http://developer.apple.com/devcenter/mac/documents/validating.html
Thanks.
(Please note that I'm not after a debate on the philosophy of copy-protection or the merits of Apple's approach. Rather, I'm just interested in the technical requirements for getting a Mac app on to the App Store.)
Yes, you are correct. It's their way or the highway.

Resources