[
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2013, rmaddy\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n  Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n  Redistributions in binary form must reproduce the above copyright notice, this\n  list of conditions and the following disclaimer in the documentation and/or\n  other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
  },
  {
    "path": "README.md",
    "content": "# VerifyStoreReceiptiOS\nRick Maddy, Matthew Stevens, Ruotger Skupin, Apple, Dave Carlton, Fraser Hess, anlumo, yene, David Keegan, Alessandro Segala.\n\nThese files are based off of the [roddi/ValidateStoreReceipt](https://github.com/roddi/ValidateStoreReceipt) project.\n\nFor details on iOS receipt validation from Apple, see [Receipt Validation Programming Guide](https://developer.apple.com/library/ios/releasenotes/General/ValidateAppStoreReceipt/Introduction.html) (Developer membership needed).\n\nUnfortunately this document doesn't tell you how to process this receipt in detail, quote:\n\n    The payload of the PKCS7 container is encoded using ASN.1, as described by ITU-T X.690.\n\nThis validator parses and validates the payload and the PKCS7 container itself. \n\nThanks to Matthew Stevens for coming up with the parser code. Thanks to Dave Carlton for polishing it a bit. Thanks to Fraser Hess for more polish and correcting my non-native English. Thanks to anlumo for the certificate checking code. Thanks to Alessandro Segala for the In-App purchasing code.\n\nMissing from this project: \n\n- Apple's root certificate. This may be obtained from http://www.apple.com/certificateauthority/\n- Any measures to make your app cracker proof.\n\n## Installation\n\nIf you have an app that is more or less ready for the App Store, I think you will be able figure it out. Important is that you link with the dependencies listed in VerifyStoreReceipt.m.\n\n## Using It\n\nThis class depends on OpenSSL being statically linked into your project. Please see https://github.com/x2on/OpenSSL-for-iPhone for one approach to getting that done.\n\nBe aware that there will be people trying to crack your app. So cover your tracks. I won't go into details but Blocks and Grand Central Dispatch seem to be good tools for that.\n\n## Sample Project\n\nThe sample project shows one possible way to make use of this receipt verifier. Please note that the sample app requires that you use the [OpenSSL-for-iPhone](https://github.com/x2on/OpenSSL-for-iPhone) project. Put both projects in a common parent directory. There are plenty of tasks that need to be completed to make the sample code complete but it is a framework to get you started. Like the notes in the VerifyStoreReceipt.m file, the code in the sample app should not be used as-is. If everyone uses the same code, it will be easy for hackers to work around the code making the receipt checking worthless.\n\n## License\n\n Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n \n Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n \n Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in\n the documentation and/or other materials provided with the distribution.\n \n Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived \n from this software without specific prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, \n BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT \n SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL \n DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS \n INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE \n OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "VerifyStoreReceipt/Images.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"60x60\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"76x76\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"76x76\",\n      \"scale\" : \"2x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "VerifyStoreReceipt/Images.xcassets/LaunchImage.launchimage/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"orientation\" : \"portrait\",\n      \"idiom\" : \"iphone\",\n      \"extent\" : \"full-screen\",\n      \"minimum-system-version\" : \"7.0\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"orientation\" : \"portrait\",\n      \"idiom\" : \"iphone\",\n      \"subtype\" : \"retina4\",\n      \"extent\" : \"full-screen\",\n      \"minimum-system-version\" : \"7.0\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"orientation\" : \"portrait\",\n      \"idiom\" : \"ipad\",\n      \"extent\" : \"full-screen\",\n      \"minimum-system-version\" : \"7.0\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"orientation\" : \"landscape\",\n      \"idiom\" : \"ipad\",\n      \"extent\" : \"full-screen\",\n      \"minimum-system-version\" : \"7.0\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"orientation\" : \"portrait\",\n      \"idiom\" : \"ipad\",\n      \"extent\" : \"full-screen\",\n      \"minimum-system-version\" : \"7.0\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"orientation\" : \"landscape\",\n      \"idiom\" : \"ipad\",\n      \"extent\" : \"full-screen\",\n      \"minimum-system-version\" : \"7.0\",\n      \"scale\" : \"2x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "VerifyStoreReceipt/RMAppDelegate.h",
    "content": "//\n//  RMAppDelegate.h\n//  VerifyStoreReceipt\n//\n//  Created by Rick Maddy on 11/16/13.\n//  Copyright (c) 2013 Rick Maddy. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface RMAppDelegate : UIResponder <UIApplicationDelegate>\n\n@property (strong, nonatomic) UIWindow *window;\n\n@end\n"
  },
  {
    "path": "VerifyStoreReceipt/RMAppDelegate.m",
    "content": "//\n//  RMAppDelegate.m\n//  VerifyStoreReceipt\n//\n//  Created by Rick Maddy on 11/16/13.\n//  Copyright (c) 2013 Rick Maddy. All rights reserved.\n//\n\n#import \"RMAppDelegate.h\"\n#import \"VerifyStoreReceipt.h\"\n#import <StoreKit/StoreKit.h>\n\n// Per the instructions in VerifyStoreReceipt.m:\n// These must be updated with actual values\n#warning -- These values should be obfuscated\nconst NSString * global_bundleVersion = @\"1.0.2\";\nconst NSString * global_bundleIdentifier = @\"com.example.SampleApp\";\n\n@interface RMAppDelegate () <SKRequestDelegate>\n\n@end\n\n@implementation RMAppDelegate\n\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {\n    [self beginReceiptCheck];\n    \n    // Empty white screen - there is no UI in this sample app\n    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];\n    self.window.backgroundColor = [UIColor whiteColor];\n    [self.window makeKeyAndVisible];\n\n    return YES;\n}\n\n- (void)beginReceiptCheck {\n    if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {\n        // See if there is an existing receipt or not\n        NSString *appRecPath = [[[NSBundle mainBundle] appStoreReceiptURL] path];\n        if ([[NSFileManager defaultManager] fileExistsAtPath:appRecPath]) {\n            // There is an existing receipt, see if it is valid.\n            [self validateReceipt:appRecPath tryAgain:YES];\n        } else {\n            // There is no receipt, request one\n            [self requestNewReceipt];\n        }\n    } else {\n        // Nothing to do under iOS 6 or earlier. This code requires iOS 7 or later\n    }\n}\n\n- (void)requestNewReceipt {\n    // TODO - this should be updated with the proper use of \"Reachability\"\n    // Begin a request for a receipt from Apple\n    SKReceiptRefreshRequest *req = [[SKReceiptRefreshRequest alloc] initWithReceiptProperties:nil];\n    req.delegate = self;\n    [req start];\n}\n\n- (void)validateReceipt:(NSString *)path tryAgain:(BOOL)again {\n    // See if the current receipt is valid or not\n    BOOL valid = verifyReceiptAtPath(path);\n    if (valid) {\n        // TODO\n        // We have a valid receipt, clear any failures and give the user the full app\n        // You may also perform further checks. At this point all we know is that there is a valid receipt.\n        //  - You may wish to get details about in-app purchases from the receipt so you can enable just the right\n        //    set of in-app purchases in your app.\n        //  - You may wish to check when the user purchased the app.\n        // See the constants in VerifyStoreReceipt.h for data you can obtain from the receipt:\n        // NSDictionary *info = dictionaryWithAppStoreReceipt(path);\n        // NSArray *iaps = obtainInAppPurchases(path);\n        \n        // Note - this may be called on a background thread. Be sure to do any UI work on the main thread\n        /*\n        dispatch_async(dispatch_get_main_queue(), ^{\n            // Any desired UI updates\n        });\n         */\n    } else {\n        NSLog(@\"Receipt is invalid\");\n        if (again) {\n            // Try one more time to get a valid receipt. This will be reached if the current receipt is stale.\n            [self requestNewReceipt];\n        } else {\n            // TODO\n            // Invalid receipt. This probably means your app was cracked. You have various options:\n            // 1) Cripple the app in some fashion\n            // 2) Terminate the app\n            // 3) Alert the user\n            // What you do here is up to you and how you wish to handle an invalid receipt\n        }\n    }\n}\n\n- (void)trackFailedAttempt {\n    // TODO\n    // This will be reached if the code has been unable to obtain a receipt. There are various, legitimate reasons\n    // for such problems. But it could also mean the user has a jailbroken device that is deliberately preventing\n    // the app from getting a valid receipt.\n    // You need to decide how to handle these cases. You can choose to try again later. You can choose to limit how\n    // many failed attempts are allowed before treating these failures the same as having an invalid receipt.\n    // It's all up to you on what to do here.\n\n    // Note - this may be called on a background thread. Be sure to do any UI work on the main thread\n    /*\n    dispatch_async(dispatch_get_main_queue(), ^{\n         // Any desired UI updates\n    });\n     */\n}\n\n#pragma mark SKRequestDelegate methods\n\n- (void)requestDidFinish:(SKRequest *)request {\n    // The request for a receipt completed\n    NSString  *appRecPath = [[[NSBundle mainBundle] appStoreReceiptURL] path];\n    if ([[NSFileManager defaultManager] fileExistsAtPath:appRecPath]) {\n        NSLog(@\"Receipt exists\");\n        \n        [self validateReceipt:appRecPath tryAgain:NO];\n    } else {\n        NSLog(@\"Receipt request done but there is no receipt\");\n        \n        // This can happen if the user cancels the login screen for the store.\n        // If we get here it means there is no receipt and an attempt to get it failed because the user cancelled\n        // the login.\n        [self trackFailedAttempt];\n    }\n}\n\n- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {\n    NSLog(@\"Error tryung to request receipt: %@\", error);\n    \n    // Unable to get/refresh the receipt\n    NSString *appRecPath = [[[NSBundle mainBundle] appStoreReceiptURL] path];\n    if ([[NSFileManager defaultManager] fileExistsAtPath:appRecPath]) {\n        // There is an existing receipt but we failed to get a new one. This means the existing receipt is invalid\n        [self trackFailedAttempt];\n    } else {\n        // There is no receipt and we were unable to get a new one\n        [self trackFailedAttempt];\n    }\n}\n\n@end\n"
  },
  {
    "path": "VerifyStoreReceipt/VerifyStoreReceipt-Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleDisplayName</key>\n\t<string>${PRODUCT_NAME}</string>\n\t<key>CFBundleExecutable</key>\n\t<string>${EXECUTABLE_NAME}</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>com.maddyhome.iphone.${PRODUCT_NAME:rfc1034identifier}</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>${PRODUCT_NAME}</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1.0</string>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>UIRequiredDeviceCapabilities</key>\n\t<array>\n\t\t<string>armv7</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations~ipad</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationPortraitUpsideDown</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "VerifyStoreReceipt/VerifyStoreReceipt-Prefix.pch",
    "content": "//\n//  Prefix header\n//\n//  The contents of this file are implicitly included at the beginning of every source file.\n//\n\n#import <Availability.h>\n\n#ifndef __IPHONE_3_0\n#warning \"This project uses features only available in iOS SDK 3.0 and later.\"\n#endif\n\n#ifdef __OBJC__\n    #import <UIKit/UIKit.h>\n    #import <Foundation/Foundation.h>\n#endif\n"
  },
  {
    "path": "VerifyStoreReceipt/VerifyStoreReceipt.h",
    "content": "//\n//  VerifyStoreReceipt.h\n//\n//  Based on validatereceipt.h\n//  Created by Ruotger Skupin on 23.10.10.\n//  Copyright 2010-2011 Matthew Stevens, Ruotger Skupin, Apple, Alessandro Segala. All rights reserved.\n//\n//  Modified for iOS, converted to ARC, and added additional fields by Rick Maddy 2013-08-20\n//  Copyright 2013 Rick Maddy. All rights reserved.\n//\n\n/*\n Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n \n Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n \n Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in\n the documentation and/or other materials provided with the distribution.\n \n Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived\n from this software without specific prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,\n BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\n SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\n OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import <Foundation/Foundation.h>\n\nextern NSString *kReceiptBundleIdentifer;\nextern NSString *kReceiptBundleIdentiferData;\nextern NSString *kReceiptVersion;\nextern NSString *kReceiptOpaqueValue;\nextern NSString *kReceiptHash;\nextern NSString *kReceiptInApp;\nextern NSString *kReceiptOriginalVersion;\nextern NSString *kReceiptExpirationDate;\n\nextern NSString *kReceiptInAppQuantity;\nextern NSString *kReceiptInAppProductIdentifier;\nextern NSString *kReceiptInAppTransactionIdentifier;\nextern NSString *kReceiptInAppPurchaseDate;\nextern NSString *kReceiptInAppOriginalTransactionIdentifier;\nextern NSString *kReceiptInAppOriginalPurchaseDate;\nextern NSString *kReceiptInAppSubscriptionExpirationDate;\nextern NSString *kReceiptInAppCancellationDate;\nextern NSString *kReceiptInAppWebOrderLineItemID;\n\nNSDictionary *dictionaryWithAppStoreReceipt(NSString *receiptPath);\nNSArray *obtainInAppPurchases(NSString *receiptPath);\nBOOL verifyReceiptAtPath(NSString *receiptPath);\n"
  },
  {
    "path": "VerifyStoreReceipt/VerifyStoreReceipt.m",
    "content": "//\n//  validatereceipt.m\n//\n//  Based on validatereceipt.m\n//  Created by Ruotger Skupin on 23.10.10.\n//  Copyright 2010-2011 Matthew Stevens, Ruotger Skupin, Apple, Dave Carlton, Fraser Hess, anlumo, David Keegan, Alessandro Segala. All rights reserved.\n//\n//  Modified for iOS, converted to ARC, and added additional fields by Rick Maddy 2013-08-20\n//  Copyright 2013 Rick Maddy. All rights reserved.\n//\n\n/*\n Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n \n Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n \n Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in\n the documentation and/or other materials provided with the distribution.\n \n Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived\n from this software without specific prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,\n BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\n SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\n OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import \"VerifyStoreReceipt.h\"\n\n// link with Foundation.framework, Security.framework, libssl and libCrypto (via -lssl -lcrypto in Other Linker Flags)\n\n#import <Security/Security.h>\n\n#include <openssl/pkcs7.h>\n#include <openssl/objects.h>\n#include <openssl/sha.h>\n#include <openssl/x509.h>\n#include <openssl/err.h>\n\n\n#ifndef YES_I_HAVE_READ_THE_WARNING_AND_I_ACCEPT_THE_RISK\n\n#warning --- DON'T USE THIS CODE AS IS! IF EVERYONE USES THE SAME CODE\n#warning --- IT IS PRETTY EASY TO BUILD AN AUTOMATIC CRACKING TOOL\n#warning --- FOR APPS USING THIS CODE!\n#warning --- BY USING THIS CODE YOU ACCEPT TAKING THE RESPONSIBILITY FOR\n#warning --- ANY DAMAGE!\n#warning ---\n#warning --- YOU HAVE BEEN WARNED!\n\n// if you want to take that risk, add \"-DYES_I_HAVE_READ_THE_WARNING_AND_I_ACCEPT_THE_RISK\" in the build settings at \"Other C Flags\"\n\n#endif // YES_I_HAVE_READ_THE_WARNING_AND_I_ACCEPT_THE_RISK\n\n#define VRCFRelease(object) if(object) CFRelease(object)\n\nNSString *kReceiptBundleIdentifier\t\t\t\t= @\"BundleIdentifier\";\nNSString *kReceiptBundleIdentifierData\t\t\t= @\"BundleIdentifierData\";\nNSString *kReceiptVersion\t\t\t\t\t\t= @\"Version\";\nNSString *kReceiptOpaqueValue\t\t\t\t\t= @\"OpaqueValue\";\nNSString *kReceiptHash\t\t\t\t\t\t\t= @\"Hash\";\nNSString *kReceiptInApp\t\t\t\t\t\t\t= @\"InApp\";\nNSString *kReceiptOriginalVersion               = @\"OrigVer\";\nNSString *kReceiptExpirationDate                = @\"ExpDate\";\n\nNSString *kReceiptInAppQuantity\t\t\t\t\t= @\"Quantity\";\nNSString *kReceiptInAppProductIdentifier\t\t= @\"ProductIdentifier\";\nNSString *kReceiptInAppTransactionIdentifier\t= @\"TransactionIdentifier\";\nNSString *kReceiptInAppPurchaseDate\t\t\t\t= @\"PurchaseDate\";\nNSString *kReceiptInAppOriginalTransactionIdentifier\t= @\"OriginalTransactionIdentifier\";\nNSString *kReceiptInAppOriginalPurchaseDate\t\t= @\"OriginalPurchaseDate\";\nNSString *kReceiptInAppSubscriptionExpirationDate = @\"SubExpDate\";\nNSString *kReceiptInAppCancellationDate         = @\"CancelDate\";\nNSString *kReceiptInAppWebOrderLineItemID       = @\"WebItemId\";\n\n\nNSData *appleRootCert(void) {\n    // Obtain the Apple Inc. root certificate from http://www.apple.com/certificateauthority/\n    // Download the Apple Inc. Root Certificate ( http://www.apple.com/appleca/AppleIncRootCertificate.cer )\n    // Add the AppleIncRootCertificate.cer to your app's resource bundle.\n\n    NSData *cert = [NSData dataWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@\"AppleIncRootCertificate\" withExtension:@\"cer\"]];\n    \n\treturn cert;\n}\n\n// ASN.1 values for In-App Purchase values\n#define INAPP_ATTR_START\t1700\n#define INAPP_QUANTITY\t\t1701\n#define INAPP_PRODID\t\t1702\n#define INAPP_TRANSID\t\t1703\n#define INAPP_PURCHDATE\t\t1704\n#define INAPP_ORIGTRANSID\t1705\n#define INAPP_ORIGPURCHDATE\t1706\n#define INAPP_ATTR_END\t\t1707\n#define INAPP_SUBEXP_DATE   1708\n#define INAPP_WEBORDER      1711\n#define INAPP_CANCEL_DATE   1712\n\nNSArray *parseInAppPurchasesData(NSData *inappData) {\n\tint type = 0;\n\tint xclass = 0;\n\tlong length = 0;\n    \n\tNSUInteger dataLenght = [inappData length];\n\tconst uint8_t *p = [inappData bytes];\n    \n\tconst uint8_t *end = p + dataLenght;\n    \n\tNSMutableArray *resultArray = [NSMutableArray array];\n    \n\twhile (p < end) {\n\t\tASN1_get_object(&p, &length, &type, &xclass, end - p);\n        \n\t\tconst uint8_t *set_end = p + length;\n        \n\t\tif(type != V_ASN1_SET) {\n\t\t\tbreak;\n\t\t}\n        \n\t\tNSMutableDictionary *item = [[NSMutableDictionary alloc] initWithCapacity:6];\n        \n\t\twhile (p < set_end) {\n\t\t\tASN1_get_object(&p, &length, &type, &xclass, set_end - p);\n\t\t\tif (type != V_ASN1_SEQUENCE) {\n\t\t\t\tbreak;\n            }\n            \n\t\t\tconst uint8_t *seq_end = p + length;\n            \n\t\t\tint attr_type = 0;\n\t\t\tint attr_version = 0;\n            \n\t\t\t// Attribute type\n\t\t\tASN1_get_object(&p, &length, &type, &xclass, seq_end - p);\n\t\t\tif (type == V_ASN1_INTEGER) {\n\t\t\t\tif(length == 1) {\n\t\t\t\t\tattr_type = p[0];\n\t\t\t\t}\n\t\t\t\telse if(length == 2) {\n\t\t\t\t\tattr_type = p[0] * 0x100 + p[1]\n\t\t\t\t\t;\n\t\t\t\t}\n\t\t\t}\n\t\t\tp += length;\n            \n\t\t\t// Attribute version\n\t\t\tASN1_get_object(&p, &length, &type, &xclass, seq_end - p);\n\t\t\tif (type == V_ASN1_INTEGER && length == 1) {\n                // clang analyser hit (wontfix at the moment, since the code might come in handy later)\n                // But if someone has a convincing case throwing that out, I might do so, Roddi\n\t\t\t\tattr_version = p[0];\n\t\t\t}\n\t\t\tp += length;\n            \n\t\t\t// Only parse attributes we're interested in\n\t\t\tif ((attr_type > INAPP_ATTR_START && attr_type < INAPP_ATTR_END) || attr_type == INAPP_SUBEXP_DATE || attr_type == INAPP_WEBORDER || attr_type == INAPP_CANCEL_DATE) {\n\t\t\t\tNSString *key = nil;\n                \n\t\t\t\tASN1_get_object(&p, &length, &type, &xclass, seq_end - p);\n\t\t\t\tif (type == V_ASN1_OCTET_STRING) {\n\t\t\t\t\t//NSData *data = [NSData dataWithBytes:p length:(NSUInteger)length];\n                    \n\t\t\t\t\t// Integers\n\t\t\t\t\tif (attr_type == INAPP_QUANTITY || attr_type == INAPP_WEBORDER) {\n\t\t\t\t\t\tint num_type = 0;\n\t\t\t\t\t\tlong num_length = 0;\n\t\t\t\t\t\tconst uint8_t *num_p = p;\n\t\t\t\t\t\tASN1_get_object(&num_p, &num_length, &num_type, &xclass, seq_end - num_p);\n\t\t\t\t\t\tif (num_type == V_ASN1_INTEGER) {\n\t\t\t\t\t\t\tNSUInteger quantity = 0;\n\t\t\t\t\t\t\tif (num_length) {\n\t\t\t\t\t\t\t\tquantity += num_p[0];\n\t\t\t\t\t\t\t\tif (num_length > 1) {\n\t\t\t\t\t\t\t\t\tquantity += num_p[1] * 0x100;\n\t\t\t\t\t\t\t\t\tif (num_length > 2) {\n\t\t\t\t\t\t\t\t\t\tquantity += num_p[2] * 0x10000;\n\t\t\t\t\t\t\t\t\t\tif (num_length > 3) {\n\t\t\t\t\t\t\t\t\t\t\tquantity += num_p[3] * 0x1000000;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n                            \n\t\t\t\t\t\t\tNSNumber *num = [[NSNumber alloc] initWithUnsignedInteger:quantity];\n                            if (attr_type == INAPP_QUANTITY) {\n                                [item setObject:num forKey:kReceiptInAppQuantity];\n                            } else if (attr_type == INAPP_WEBORDER) {\n                                [item setObject:num forKey:kReceiptInAppWebOrderLineItemID];\n                            }\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n                    \n\t\t\t\t\t// Strings\n\t\t\t\t\tif (attr_type == INAPP_PRODID ||\n                        attr_type == INAPP_TRANSID ||\n                        attr_type == INAPP_ORIGTRANSID ||\n                        attr_type == INAPP_PURCHDATE ||\n                        attr_type == INAPP_ORIGPURCHDATE ||\n                        attr_type == INAPP_SUBEXP_DATE ||\n                        attr_type == INAPP_CANCEL_DATE) {\n                        \n\t\t\t\t\t\tint str_type = 0;\n\t\t\t\t\t\tlong str_length = 0;\n\t\t\t\t\t\tconst uint8_t *str_p = p;\n\t\t\t\t\t\tASN1_get_object(&str_p, &str_length, &str_type, &xclass, seq_end - str_p);\n\t\t\t\t\t\tif (str_type == V_ASN1_UTF8STRING) {\n\t\t\t\t\t\t\tswitch (attr_type) {\n\t\t\t\t\t\t\t\tcase INAPP_PRODID:\n\t\t\t\t\t\t\t\t\tkey = kReceiptInAppProductIdentifier;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase INAPP_TRANSID:\n\t\t\t\t\t\t\t\t\tkey = kReceiptInAppTransactionIdentifier;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase INAPP_ORIGTRANSID:\n\t\t\t\t\t\t\t\t\tkey = kReceiptInAppOriginalTransactionIdentifier;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n                            \n\t\t\t\t\t\t\tif (key) {\n\t\t\t\t\t\t\t\tNSString *string = [[NSString alloc] initWithBytes:str_p\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlength:(NSUInteger)str_length\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  encoding:NSUTF8StringEncoding];\n\t\t\t\t\t\t\t\t[item setObject:string forKey:key];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (str_type == V_ASN1_IA5STRING) {\n\t\t\t\t\t\t\tswitch (attr_type) {\n\t\t\t\t\t\t\t\tcase INAPP_PURCHDATE:\n\t\t\t\t\t\t\t\t\tkey = kReceiptInAppPurchaseDate;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase INAPP_ORIGPURCHDATE:\n\t\t\t\t\t\t\t\t\tkey = kReceiptInAppOriginalPurchaseDate;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase INAPP_SUBEXP_DATE:\n\t\t\t\t\t\t\t\t\tkey = kReceiptInAppSubscriptionExpirationDate;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase INAPP_CANCEL_DATE:\n\t\t\t\t\t\t\t\t\tkey = kReceiptInAppCancellationDate;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n                            \n\t\t\t\t\t\t\tif (key) {\n\t\t\t\t\t\t\t\tNSString *string = [[NSString alloc] initWithBytes:str_p\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlength:(NSUInteger)str_length\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  encoding:NSASCIIStringEncoding];\n\t\t\t\t\t\t\t\t[item setObject:string forKey:key];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n                \n\t\t\t\tp += length;\n\t\t\t}\n            \n\t\t\t// Skip any remaining fields in this SEQUENCE\n\t\t\twhile (p < seq_end) {\n\t\t\t\tASN1_get_object(&p, &length, &type, &xclass, seq_end - p);\n\t\t\t\tp += length;\n\t\t\t}\n\t\t}\n        \n\t\t// Skip any remaining fields in this SET\n\t\twhile (p < set_end) {\n\t\t\tASN1_get_object(&p, &length, &type, &xclass, set_end - p);\n\t\t\tp += length;\n\t\t}\n        \n\t\t[resultArray addObject:item];\n\t}\n    \n\treturn resultArray;\n}\n\n// ASN.1 values for the App Store receipt\n#define ATTR_START 1\n#define BUNDLE_ID 2\n#define VERSION 3\n#define OPAQUE_VALUE 4\n#define HASH 5\n#define ATTR_END 6\n#define INAPP_PURCHASE 17\n#define ORIG_VERSION 19\n#define EXPIRE_DATE 21\n\nNSDictionary *dictionaryWithAppStoreReceipt(NSString *receiptPath) {\n\tNSData * rootCertData = appleRootCert();\n    \n\tERR_load_PKCS7_strings();\n\tERR_load_X509_strings();\n\tOpenSSL_add_all_digests();\n    \n\t// Expected input is a PKCS7 container with signed data containing\n\t// an ASN.1 SET of SEQUENCE structures. Each SEQUENCE contains\n\t// two INTEGERS and an OCTET STRING.\n    \n\tconst char * path = [[receiptPath stringByStandardizingPath] fileSystemRepresentation];\n\tFILE *fp = fopen(path, \"rb\");\n\tif (fp == NULL) {\n\t\treturn nil;\n    }\n    \n\tPKCS7 *p7 = d2i_PKCS7_fp(fp, NULL);\n\tfclose(fp);\n    \n\t// Check if the receipt file was invalid (otherwise we go crashing and burning)\n\tif (p7 == NULL) {\n\t\treturn nil;\n\t}\n    \n\tif (!PKCS7_type_is_signed(p7)) {\n\t\tPKCS7_free(p7);\n\t\treturn nil;\n\t}\n    \n\tif (!PKCS7_type_is_data(p7->d.sign->contents)) {\n\t\tPKCS7_free(p7);\n\t\treturn nil;\n\t}\n    \n\tint verifyReturnValue = 0;\n\tX509_STORE *store = X509_STORE_new();\n\tif (store) {\n\t\tconst uint8_t *data = (uint8_t *)(rootCertData.bytes);\n\t\tX509 *appleCA = d2i_X509(NULL, &data, (long)rootCertData.length);\n\t\tif (appleCA) {\n\t\t\tBIO *payload = BIO_new(BIO_s_mem());\n\t\t\tX509_STORE_add_cert(store, appleCA);\n            \n\t\t\tif (payload) {\n\t\t\t\tverifyReturnValue = PKCS7_verify(p7,NULL,store,NULL,payload,0);\n\t\t\t\tBIO_free(payload);\n\t\t\t}\n            \n\t\t\tX509_free(appleCA);\n\t\t}\n        \n\t\tX509_STORE_free(store);\n\t}\n    \n\tEVP_cleanup();\n    \n\tif (verifyReturnValue != 1) {\n\t\tPKCS7_free(p7);\n\t\treturn nil;\n\t}\n    \n\tASN1_OCTET_STRING *octets = p7->d.sign->contents->d.data;\n\tconst uint8_t *p = octets->data;\n\tconst uint8_t *end = p + octets->length;\n    \n\tint type = 0;\n\tint xclass = 0;\n\tlong length = 0;\n    \n\tASN1_get_object(&p, &length, &type, &xclass, end - p);\n\tif (type != V_ASN1_SET) {\n\t\tPKCS7_free(p7);\n\t\treturn nil;\n\t}\n    \n\tNSMutableDictionary *info = [NSMutableDictionary dictionary];\n    \n\twhile (p < end) {\n\t\tASN1_get_object(&p, &length, &type, &xclass, end - p);\n\t\tif (type != V_ASN1_SEQUENCE) {\n\t\t\tbreak;\n        }\n        \n\t\tconst uint8_t *seq_end = p + length;\n        \n\t\tint attr_type = 0;\n\t\tint attr_version = 0;\n        \n\t\t// Attribute type\n\t\tASN1_get_object(&p, &length, &type, &xclass, seq_end - p);\n\t\tif (type == V_ASN1_INTEGER && length == 1) {\n\t\t\tattr_type = p[0];\n\t\t}\n\t\tp += length;\n        \n\t\t// Attribute version\n\t\tASN1_get_object(&p, &length, &type, &xclass, seq_end - p);\n\t\tif (type == V_ASN1_INTEGER && length == 1) {\n\t\t\tattr_version = p[0];\n\t\t\tattr_version = attr_version;\n\t\t}\n\t\tp += length;\n        \n\t\t// Only parse attributes we're interested in\n\t\tif ((attr_type > ATTR_START && attr_type < ATTR_END) || attr_type == INAPP_PURCHASE || attr_type == ORIG_VERSION || attr_type == EXPIRE_DATE) {\n\t\t\tNSString *key = nil;\n            \n\t\t\tASN1_get_object(&p, &length, &type, &xclass, seq_end - p);\n\t\t\tif (type == V_ASN1_OCTET_STRING) {\n                NSData *data = [NSData dataWithBytes:p length:(NSUInteger)length];\n                \n\t\t\t\t// Bytes\n\t\t\t\tif (attr_type == BUNDLE_ID || attr_type == OPAQUE_VALUE || attr_type == HASH) {\n\t\t\t\t\tswitch (attr_type) {\n\t\t\t\t\t\tcase BUNDLE_ID:\n\t\t\t\t\t\t\t// This is included for hash generation\n\t\t\t\t\t\t\tkey = kReceiptBundleIdentifierData;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OPAQUE_VALUE:\n\t\t\t\t\t\t\tkey = kReceiptOpaqueValue;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase HASH:\n\t\t\t\t\t\t\tkey = kReceiptHash;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif (key) {\n                        [info setObject:data forKey:key];\n                    }\n\t\t\t\t}\n                \n\t\t\t\t// Strings\n\t\t\t\tif (attr_type == BUNDLE_ID || attr_type == VERSION || attr_type == ORIG_VERSION) {\n\t\t\t\t\tint str_type = 0;\n\t\t\t\t\tlong str_length = 0;\n\t\t\t\t\tconst uint8_t *str_p = p;\n\t\t\t\t\tASN1_get_object(&str_p, &str_length, &str_type, &xclass, seq_end - str_p);\n\t\t\t\t\tif (str_type == V_ASN1_UTF8STRING) {\n\t\t\t\t\t\tswitch (attr_type) {\n\t\t\t\t\t\t\tcase BUNDLE_ID:\n\t\t\t\t\t\t\t\tkey = kReceiptBundleIdentifier;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase VERSION:\n\t\t\t\t\t\t\t\tkey = kReceiptVersion;\n\t\t\t\t\t\t\t\tbreak;\n                            case ORIG_VERSION:\n                                key = kReceiptOriginalVersion;\n                                break;\n\t\t\t\t\t\t}\n                        \n\t\t\t\t\t\tif (key) {\n                            NSString *string = [[NSString alloc] initWithBytes:str_p\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlength:(NSUInteger)str_length\n                                                                      encoding:NSUTF8StringEncoding];\n                            [info setObject:string forKey:key];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n                \n\t\t\t\t// In-App purchases\n\t\t\t\tif (attr_type == INAPP_PURCHASE) {\n\t\t\t\t\tNSArray *inApp = parseInAppPurchasesData(data);\n                    NSArray *current = info[kReceiptInApp];\n                    if (current) {\n                        info[kReceiptInApp] = [current arrayByAddingObjectsFromArray:inApp];\n                    } else {\n                        [info setObject:inApp forKey:kReceiptInApp];\n                    }\n\t\t\t\t}\n\t\t\t}\n\t\t\tp += length;\n\t\t}\n        \n\t\t// Skip any remaining fields in this SEQUENCE\n\t\twhile (p < seq_end) {\n\t\t\tASN1_get_object(&p, &length, &type, &xclass, seq_end - p);\n\t\t\tp += length;\n\t\t}\n\t}\n    \n\tPKCS7_free(p7);\n    \n\treturn info;\n}\n\n\nNSArray *obtainInAppPurchases(NSString *receiptPath) {\n\t// According to the documentation, we need to validate the receipt first.\n\t// If the receipt is not valid, no In-App purchase is valid.\n\t// This performs a \"quick\" validation. Please use validateReceiptAtPath to perform a full validation.\n    \n\tNSDictionary *receipt = dictionaryWithAppStoreReceipt(receiptPath);\n\tif (!receipt) {\n\t\treturn nil;\n    }\n    \n\tNSArray *purchases = [receipt objectForKey:kReceiptInApp];\n\tif(!purchases || ![purchases isKindOfClass:[NSArray class]]) {\n\t\treturn nil;\n    }\n    \n\treturn purchases;\n}\n\nextern const NSString * global_bundleVersion;\nextern const NSString * global_bundleIdentifier;\n\n// in your project define those two somewhere as such:\n// const NSString * global_bundleVersion = @\"1.0.2\";\n// const NSString * global_bundleIdentifier = @\"com.example.SampleApp\";\n\nBOOL verifyReceiptAtPath(NSString *receiptPath) {\n\t// it turns out, it's a bad idea, to use these two NSBundle methods in your app:\n\t//\n\t// bundleVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@\"CFBundleVersion\"];\n\t// bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];\n\t//\n\t// http://www.craftymind.com/2011/01/06/mac-app-store-hacked-how-developers-can-better-protect-themselves/\n\t//\n\t// so use hard coded values instead (probably even somehow obfuscated)\n    \n\tNSString *bundleVersion = (NSString*)global_bundleVersion;\n\tNSString *bundleIdentifier = (NSString*)global_bundleIdentifier;\n\n\t// avoid making stupid mistakes --> check again\n\tNSCAssert([bundleVersion isEqualToString:[[NSBundle mainBundle] objectForInfoDictionaryKey:@\"CFBundleVersion\"]],\n              @\"whoops! check the hard-coded CFBundleVersion!\");\n\tNSCAssert([bundleIdentifier isEqualToString:[[NSBundle mainBundle] bundleIdentifier]],\n              @\"whoops! check the hard-coded bundle identifier!\");\n\tNSDictionary *receipt = dictionaryWithAppStoreReceipt(receiptPath);\n    \n\tif (!receipt) {\n\t\treturn NO;\n    }\n    \n    unsigned char uuidBytes[16];\n    NSUUID *vendorUUID = [[UIDevice currentDevice] identifierForVendor];\n    [vendorUUID getUUIDBytes:uuidBytes];\n    \n\tNSMutableData *input = [NSMutableData data];\n\t[input appendBytes:uuidBytes length:sizeof(uuidBytes)];\n\t[input appendData:[receipt objectForKey:kReceiptOpaqueValue]];\n\t[input appendData:[receipt objectForKey:kReceiptBundleIdentifierData]];\n    \n\tNSMutableData *hash = [NSMutableData dataWithLength:SHA_DIGEST_LENGTH];\n\tSHA1([input bytes], [input length], [hash mutableBytes]);\n    \n\tif ([bundleIdentifier isEqualToString:[receipt objectForKey:kReceiptBundleIdentifier]] &&\n        [bundleVersion isEqualToString:[receipt objectForKey:kReceiptVersion]] &&\n        [hash isEqualToData:[receipt objectForKey:kReceiptHash]]) {\n\t\treturn YES;\n\t}\n    \n\treturn NO;\n}\n"
  },
  {
    "path": "VerifyStoreReceipt/en.lproj/InfoPlist.strings",
    "content": "/* Localized versions of Info.plist keys */\n\n"
  },
  {
    "path": "VerifyStoreReceipt/main.m",
    "content": "//\n//  main.m\n//  VerifyStoreReceipt\n//\n//  Created by Rick Maddy on 11/16/13.\n//  Copyright (c) 2013 Rick Maddy. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n#import \"RMAppDelegate.h\"\n\nint main(int argc, char * argv[])\n{\n    @autoreleasepool {\n        return UIApplicationMain(argc, argv, nil, NSStringFromClass([RMAppDelegate class]));\n    }\n}\n"
  },
  {
    "path": "VerifyStoreReceipt.h",
    "content": "//\n//  VerifyStoreReceipt.h\n//\n//  Based on validatereceipt.h\n//  Created by Ruotger Skupin on 23.10.10.\n//  Copyright 2010-2011 Matthew Stevens, Ruotger Skupin, Apple, Alessandro Segala. All rights reserved.\n//\n//  Modified for iOS, converted to ARC, and added additional fields by Rick Maddy 2013-08-20\n//  Copyright 2013 Rick Maddy. All rights reserved.\n//\n\n/*\n Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n \n Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n \n Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in\n the documentation and/or other materials provided with the distribution.\n \n Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived\n from this software without specific prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,\n BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\n SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\n OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import <Foundation/Foundation.h>\n\nextern NSString *kReceiptBundleIdentifer;\nextern NSString *kReceiptBundleIdentiferData;\nextern NSString *kReceiptVersion;\nextern NSString *kReceiptOpaqueValue;\nextern NSString *kReceiptHash;\nextern NSString *kReceiptInApp;\nextern NSString *kReceiptOriginalVersion;\nextern NSString *kReceiptExpirationDate;\n\nextern NSString *kReceiptInAppQuantity;\nextern NSString *kReceiptInAppProductIdentifier;\nextern NSString *kReceiptInAppTransactionIdentifier;\nextern NSString *kReceiptInAppPurchaseDate;\nextern NSString *kReceiptInAppOriginalTransactionIdentifier;\nextern NSString *kReceiptInAppOriginalPurchaseDate;\nextern NSString *kReceiptInAppSubscriptionExpirationDate;\nextern NSString *kReceiptInAppCancellationDate;\nextern NSString *kReceiptInAppWebOrderLineItemID;\n\nNSDictionary *dictionaryWithAppStoreReceipt(NSString *receiptPath);\nNSArray *obtainInAppPurchases(NSString *receiptPath);\nBOOL verifyReceiptAtPath(NSString *receiptPath);\n"
  },
  {
    "path": "VerifyStoreReceipt.m",
    "content": "//\n//  validatereceipt.m\n//\n//  Based on validatereceipt.m\n//  Created by Ruotger Skupin on 23.10.10.\n//  Copyright 2010-2011 Matthew Stevens, Ruotger Skupin, Apple, Dave Carlton, Fraser Hess, anlumo, David Keegan, Alessandro Segala. All rights reserved.\n//\n//  Modified for iOS, converted to ARC, and added additional fields by Rick Maddy 2013-08-20\n//  Copyright 2013 Rick Maddy. All rights reserved.\n//\n\n/*\n Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n \n Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n \n Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in\n the documentation and/or other materials provided with the distribution.\n \n Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived\n from this software without specific prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,\n BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\n SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\n OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import \"VerifyStoreReceipt.h\"\n\n// link with Foundation.framework, Security.framework, libssl and libCrypto (via -lssl -lcrypto in Other Linker Flags)\n\n#import <Security/Security.h>\n\n#include <openssl/pkcs7.h>\n#include <openssl/objects.h>\n#include <openssl/sha.h>\n#include <openssl/x509.h>\n#include <openssl/err.h>\n\n\n#ifndef YES_I_HAVE_READ_THE_WARNING_AND_I_ACCEPT_THE_RISK\n\n#warning --- DON'T USE THIS CODE AS IS! IF EVERYONE USES THE SAME CODE\n#warning --- IT IS PRETTY EASY TO BUILD AN AUTOMATIC CRACKING TOOL\n#warning --- FOR APPS USING THIS CODE!\n#warning --- BY USING THIS CODE YOU ACCEPT TAKING THE RESPONSIBILITY FOR\n#warning --- ANY DAMAGE!\n#warning ---\n#warning --- YOU HAVE BEEN WARNED!\n\n// if you want to take that risk, add \"-DYES_I_HAVE_READ_THE_WARNING_AND_I_ACCEPT_THE_RISK\" in the build settings at \"Other C Flags\"\n\n#endif // YES_I_HAVE_READ_THE_WARNING_AND_I_ACCEPT_THE_RISK\n\n#define VRCFRelease(object) if(object) CFRelease(object)\n\nNSString *kReceiptBundleIdentifier\t\t\t\t= @\"BundleIdentifier\";\nNSString *kReceiptBundleIdentifierData\t\t\t= @\"BundleIdentifierData\";\nNSString *kReceiptVersion\t\t\t\t\t\t= @\"Version\";\nNSString *kReceiptOpaqueValue\t\t\t\t\t= @\"OpaqueValue\";\nNSString *kReceiptHash\t\t\t\t\t\t\t= @\"Hash\";\nNSString *kReceiptInApp\t\t\t\t\t\t\t= @\"InApp\";\nNSString *kReceiptOriginalVersion               = @\"OrigVer\";\nNSString *kReceiptExpirationDate                = @\"ExpDate\";\n\nNSString *kReceiptInAppQuantity\t\t\t\t\t= @\"Quantity\";\nNSString *kReceiptInAppProductIdentifier\t\t= @\"ProductIdentifier\";\nNSString *kReceiptInAppTransactionIdentifier\t= @\"TransactionIdentifier\";\nNSString *kReceiptInAppPurchaseDate\t\t\t\t= @\"PurchaseDate\";\nNSString *kReceiptInAppOriginalTransactionIdentifier\t= @\"OriginalTransactionIdentifier\";\nNSString *kReceiptInAppOriginalPurchaseDate\t\t= @\"OriginalPurchaseDate\";\nNSString *kReceiptInAppSubscriptionExpirationDate = @\"SubExpDate\";\nNSString *kReceiptInAppCancellationDate         = @\"CancelDate\";\nNSString *kReceiptInAppWebOrderLineItemID       = @\"WebItemId\";\n\n\nNSData *appleRootCert(void) {\n    // Obtain the Apple Inc. root certificate from http://www.apple.com/certificateauthority/\n    // Download the Apple Inc. Root Certificate ( http://www.apple.com/appleca/AppleIncRootCertificate.cer )\n    // Add the AppleIncRootCertificate.cer to your app's resource bundle.\n\n    NSData *cert = [NSData dataWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@\"AppleIncRootCertificate\" withExtension:@\"cer\"]];\n    \n\treturn cert;\n}\n\n// ASN.1 values for In-App Purchase values\n#define INAPP_ATTR_START\t1700\n#define INAPP_QUANTITY\t\t1701\n#define INAPP_PRODID\t\t1702\n#define INAPP_TRANSID\t\t1703\n#define INAPP_PURCHDATE\t\t1704\n#define INAPP_ORIGTRANSID\t1705\n#define INAPP_ORIGPURCHDATE\t1706\n#define INAPP_ATTR_END\t\t1707\n#define INAPP_SUBEXP_DATE   1708\n#define INAPP_WEBORDER      1711\n#define INAPP_CANCEL_DATE   1712\n\nNSArray *parseInAppPurchasesData(NSData *inappData) {\n\tint type = 0;\n\tint xclass = 0;\n\tlong length = 0;\n    \n\tNSUInteger dataLenght = [inappData length];\n\tconst uint8_t *p = [inappData bytes];\n    \n\tconst uint8_t *end = p + dataLenght;\n    \n\tNSMutableArray *resultArray = [NSMutableArray array];\n    \n\twhile (p < end) {\n\t\tASN1_get_object(&p, &length, &type, &xclass, end - p);\n        \n\t\tconst uint8_t *set_end = p + length;\n        \n\t\tif(type != V_ASN1_SET) {\n\t\t\tbreak;\n\t\t}\n        \n\t\tNSMutableDictionary *item = [[NSMutableDictionary alloc] initWithCapacity:6];\n        \n\t\twhile (p < set_end) {\n\t\t\tASN1_get_object(&p, &length, &type, &xclass, set_end - p);\n\t\t\tif (type != V_ASN1_SEQUENCE) {\n\t\t\t\tbreak;\n            }\n            \n\t\t\tconst uint8_t *seq_end = p + length;\n            \n\t\t\tint attr_type = 0;\n\t\t\tint attr_version = 0;\n            \n\t\t\t// Attribute type\n\t\t\tASN1_get_object(&p, &length, &type, &xclass, seq_end - p);\n\t\t\tif (type == V_ASN1_INTEGER) {\n\t\t\t\tif(length == 1) {\n\t\t\t\t\tattr_type = p[0];\n\t\t\t\t}\n\t\t\t\telse if(length == 2) {\n\t\t\t\t\tattr_type = p[0] * 0x100 + p[1]\n\t\t\t\t\t;\n\t\t\t\t}\n\t\t\t}\n\t\t\tp += length;\n            \n\t\t\t// Attribute version\n\t\t\tASN1_get_object(&p, &length, &type, &xclass, seq_end - p);\n\t\t\tif (type == V_ASN1_INTEGER && length == 1) {\n                // clang analyser hit (wontfix at the moment, since the code might come in handy later)\n                // But if someone has a convincing case throwing that out, I might do so, Roddi\n\t\t\t\tattr_version = p[0];\n\t\t\t}\n\t\t\tp += length;\n            \n\t\t\t// Only parse attributes we're interested in\n\t\t\tif ((attr_type > INAPP_ATTR_START && attr_type < INAPP_ATTR_END) || attr_type == INAPP_SUBEXP_DATE || attr_type == INAPP_WEBORDER || attr_type == INAPP_CANCEL_DATE) {\n\t\t\t\tNSString *key = nil;\n                \n\t\t\t\tASN1_get_object(&p, &length, &type, &xclass, seq_end - p);\n\t\t\t\tif (type == V_ASN1_OCTET_STRING) {\n\t\t\t\t\t//NSData *data = [NSData dataWithBytes:p length:(NSUInteger)length];\n                    \n\t\t\t\t\t// Integers\n\t\t\t\t\tif (attr_type == INAPP_QUANTITY || attr_type == INAPP_WEBORDER) {\n\t\t\t\t\t\tint num_type = 0;\n\t\t\t\t\t\tlong num_length = 0;\n\t\t\t\t\t\tconst uint8_t *num_p = p;\n\t\t\t\t\t\tASN1_get_object(&num_p, &num_length, &num_type, &xclass, seq_end - num_p);\n\t\t\t\t\t\tif (num_type == V_ASN1_INTEGER) {\n\t\t\t\t\t\t\tNSUInteger quantity = 0;\n\t\t\t\t\t\t\tif (num_length) {\n\t\t\t\t\t\t\t\tquantity += num_p[0];\n\t\t\t\t\t\t\t\tif (num_length > 1) {\n\t\t\t\t\t\t\t\t\tquantity += num_p[1] * 0x100;\n\t\t\t\t\t\t\t\t\tif (num_length > 2) {\n\t\t\t\t\t\t\t\t\t\tquantity += num_p[2] * 0x10000;\n\t\t\t\t\t\t\t\t\t\tif (num_length > 3) {\n\t\t\t\t\t\t\t\t\t\t\tquantity += num_p[3] * 0x1000000;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n                            \n\t\t\t\t\t\t\tNSNumber *num = [[NSNumber alloc] initWithUnsignedInteger:quantity];\n                            if (attr_type == INAPP_QUANTITY) {\n                                [item setObject:num forKey:kReceiptInAppQuantity];\n                            } else if (attr_type == INAPP_WEBORDER) {\n                                [item setObject:num forKey:kReceiptInAppWebOrderLineItemID];\n                            }\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n                    \n\t\t\t\t\t// Strings\n\t\t\t\t\tif (attr_type == INAPP_PRODID ||\n                        attr_type == INAPP_TRANSID ||\n                        attr_type == INAPP_ORIGTRANSID ||\n                        attr_type == INAPP_PURCHDATE ||\n                        attr_type == INAPP_ORIGPURCHDATE ||\n                        attr_type == INAPP_SUBEXP_DATE ||\n                        attr_type == INAPP_CANCEL_DATE) {\n                        \n\t\t\t\t\t\tint str_type = 0;\n\t\t\t\t\t\tlong str_length = 0;\n\t\t\t\t\t\tconst uint8_t *str_p = p;\n\t\t\t\t\t\tASN1_get_object(&str_p, &str_length, &str_type, &xclass, seq_end - str_p);\n\t\t\t\t\t\tif (str_type == V_ASN1_UTF8STRING) {\n\t\t\t\t\t\t\tswitch (attr_type) {\n\t\t\t\t\t\t\t\tcase INAPP_PRODID:\n\t\t\t\t\t\t\t\t\tkey = kReceiptInAppProductIdentifier;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase INAPP_TRANSID:\n\t\t\t\t\t\t\t\t\tkey = kReceiptInAppTransactionIdentifier;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase INAPP_ORIGTRANSID:\n\t\t\t\t\t\t\t\t\tkey = kReceiptInAppOriginalTransactionIdentifier;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n                            \n\t\t\t\t\t\t\tif (key) {\n\t\t\t\t\t\t\t\tNSString *string = [[NSString alloc] initWithBytes:str_p\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlength:(NSUInteger)str_length\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  encoding:NSUTF8StringEncoding];\n\t\t\t\t\t\t\t\t[item setObject:string forKey:key];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (str_type == V_ASN1_IA5STRING) {\n\t\t\t\t\t\t\tswitch (attr_type) {\n\t\t\t\t\t\t\t\tcase INAPP_PURCHDATE:\n\t\t\t\t\t\t\t\t\tkey = kReceiptInAppPurchaseDate;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase INAPP_ORIGPURCHDATE:\n\t\t\t\t\t\t\t\t\tkey = kReceiptInAppOriginalPurchaseDate;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase INAPP_SUBEXP_DATE:\n\t\t\t\t\t\t\t\t\tkey = kReceiptInAppSubscriptionExpirationDate;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase INAPP_CANCEL_DATE:\n\t\t\t\t\t\t\t\t\tkey = kReceiptInAppCancellationDate;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n                            \n\t\t\t\t\t\t\tif (key) {\n\t\t\t\t\t\t\t\tNSString *string = [[NSString alloc] initWithBytes:str_p\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlength:(NSUInteger)str_length\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  encoding:NSASCIIStringEncoding];\n\t\t\t\t\t\t\t\t[item setObject:string forKey:key];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n                \n\t\t\t\tp += length;\n\t\t\t}\n            \n\t\t\t// Skip any remaining fields in this SEQUENCE\n\t\t\twhile (p < seq_end) {\n\t\t\t\tASN1_get_object(&p, &length, &type, &xclass, seq_end - p);\n\t\t\t\tp += length;\n\t\t\t}\n\t\t}\n        \n\t\t// Skip any remaining fields in this SET\n\t\twhile (p < set_end) {\n\t\t\tASN1_get_object(&p, &length, &type, &xclass, set_end - p);\n\t\t\tp += length;\n\t\t}\n        \n\t\t[resultArray addObject:item];\n\t}\n    \n\treturn resultArray;\n}\n\n// ASN.1 values for the App Store receipt\n#define ATTR_START 1\n#define BUNDLE_ID 2\n#define VERSION 3\n#define OPAQUE_VALUE 4\n#define HASH 5\n#define ATTR_END 6\n#define INAPP_PURCHASE 17\n#define ORIG_VERSION 19\n#define EXPIRE_DATE 21\n\nNSDictionary *dictionaryWithAppStoreReceipt(NSString *receiptPath) {\n\tNSData * rootCertData = appleRootCert();\n    \n\tERR_load_PKCS7_strings();\n\tERR_load_X509_strings();\n\tOpenSSL_add_all_digests();\n    \n\t// Expected input is a PKCS7 container with signed data containing\n\t// an ASN.1 SET of SEQUENCE structures. Each SEQUENCE contains\n\t// two INTEGERS and an OCTET STRING.\n    \n\tconst char * path = [[receiptPath stringByStandardizingPath] fileSystemRepresentation];\n\tFILE *fp = fopen(path, \"rb\");\n\tif (fp == NULL) {\n\t\treturn nil;\n    }\n    \n\tPKCS7 *p7 = d2i_PKCS7_fp(fp, NULL);\n\tfclose(fp);\n    \n\t// Check if the receipt file was invalid (otherwise we go crashing and burning)\n\tif (p7 == NULL) {\n\t\treturn nil;\n\t}\n    \n\tif (!PKCS7_type_is_signed(p7)) {\n\t\tPKCS7_free(p7);\n\t\treturn nil;\n\t}\n    \n\tif (!PKCS7_type_is_data(p7->d.sign->contents)) {\n\t\tPKCS7_free(p7);\n\t\treturn nil;\n\t}\n    \n\tint verifyReturnValue = 0;\n\tX509_STORE *store = X509_STORE_new();\n\tif (store) {\n\t\tconst uint8_t *data = (uint8_t *)(rootCertData.bytes);\n\t\tX509 *appleCA = d2i_X509(NULL, &data, (long)rootCertData.length);\n\t\tif (appleCA) {\n\t\t\tBIO *payload = BIO_new(BIO_s_mem());\n\t\t\tX509_STORE_add_cert(store, appleCA);\n            \n\t\t\tif (payload) {\n\t\t\t\tverifyReturnValue = PKCS7_verify(p7,NULL,store,NULL,payload,0);\n\t\t\t\tBIO_free(payload);\n\t\t\t}\n            \n\t\t\tX509_free(appleCA);\n\t\t}\n        \n\t\tX509_STORE_free(store);\n\t}\n    \n\tEVP_cleanup();\n    \n\tif (verifyReturnValue != 1) {\n\t\tPKCS7_free(p7);\n\t\treturn nil;\n\t}\n    \n\tASN1_OCTET_STRING *octets = p7->d.sign->contents->d.data;\n\tconst uint8_t *p = octets->data;\n\tconst uint8_t *end = p + octets->length;\n    \n\tint type = 0;\n\tint xclass = 0;\n\tlong length = 0;\n    \n\tASN1_get_object(&p, &length, &type, &xclass, end - p);\n\tif (type != V_ASN1_SET) {\n\t\tPKCS7_free(p7);\n\t\treturn nil;\n\t}\n    \n\tNSMutableDictionary *info = [NSMutableDictionary dictionary];\n    \n\twhile (p < end) {\n\t\tASN1_get_object(&p, &length, &type, &xclass, end - p);\n\t\tif (type != V_ASN1_SEQUENCE) {\n\t\t\tbreak;\n        }\n        \n\t\tconst uint8_t *seq_end = p + length;\n        \n\t\tint attr_type = 0;\n\t\tint attr_version = 0;\n        \n\t\t// Attribute type\n\t\tASN1_get_object(&p, &length, &type, &xclass, seq_end - p);\n\t\tif (type == V_ASN1_INTEGER && length == 1) {\n\t\t\tattr_type = p[0];\n\t\t}\n\t\tp += length;\n        \n\t\t// Attribute version\n\t\tASN1_get_object(&p, &length, &type, &xclass, seq_end - p);\n\t\tif (type == V_ASN1_INTEGER && length == 1) {\n\t\t\tattr_version = p[0];\n\t\t\tattr_version = attr_version;\n\t\t}\n\t\tp += length;\n        \n\t\t// Only parse attributes we're interested in\n\t\tif ((attr_type > ATTR_START && attr_type < ATTR_END) || attr_type == INAPP_PURCHASE || attr_type == ORIG_VERSION || attr_type == EXPIRE_DATE) {\n\t\t\tNSString *key = nil;\n            \n\t\t\tASN1_get_object(&p, &length, &type, &xclass, seq_end - p);\n\t\t\tif (type == V_ASN1_OCTET_STRING) {\n                NSData *data = [NSData dataWithBytes:p length:(NSUInteger)length];\n                \n\t\t\t\t// Bytes\n\t\t\t\tif (attr_type == BUNDLE_ID || attr_type == OPAQUE_VALUE || attr_type == HASH) {\n\t\t\t\t\tswitch (attr_type) {\n\t\t\t\t\t\tcase BUNDLE_ID:\n\t\t\t\t\t\t\t// This is included for hash generation\n\t\t\t\t\t\t\tkey = kReceiptBundleIdentifierData;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OPAQUE_VALUE:\n\t\t\t\t\t\t\tkey = kReceiptOpaqueValue;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase HASH:\n\t\t\t\t\t\t\tkey = kReceiptHash;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif (key) {\n                        [info setObject:data forKey:key];\n                    }\n\t\t\t\t}\n                \n\t\t\t\t// Strings\n\t\t\t\tif (attr_type == BUNDLE_ID || attr_type == VERSION || attr_type == ORIG_VERSION) {\n\t\t\t\t\tint str_type = 0;\n\t\t\t\t\tlong str_length = 0;\n\t\t\t\t\tconst uint8_t *str_p = p;\n\t\t\t\t\tASN1_get_object(&str_p, &str_length, &str_type, &xclass, seq_end - str_p);\n\t\t\t\t\tif (str_type == V_ASN1_UTF8STRING) {\n\t\t\t\t\t\tswitch (attr_type) {\n\t\t\t\t\t\t\tcase BUNDLE_ID:\n\t\t\t\t\t\t\t\tkey = kReceiptBundleIdentifier;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase VERSION:\n\t\t\t\t\t\t\t\tkey = kReceiptVersion;\n\t\t\t\t\t\t\t\tbreak;\n                            case ORIG_VERSION:\n                                key = kReceiptOriginalVersion;\n                                break;\n\t\t\t\t\t\t}\n                        \n\t\t\t\t\t\tif (key) {\n                            NSString *string = [[NSString alloc] initWithBytes:str_p\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlength:(NSUInteger)str_length\n                                                                      encoding:NSUTF8StringEncoding];\n                            [info setObject:string forKey:key];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n                \n\t\t\t\t// In-App purchases\n\t\t\t\tif (attr_type == INAPP_PURCHASE) {\n\t\t\t\t\tNSArray *inApp = parseInAppPurchasesData(data);\n                    NSArray *current = info[kReceiptInApp];\n                    if (current) {\n                        info[kReceiptInApp] = [current arrayByAddingObjectsFromArray:inApp];\n                    } else {\n                        [info setObject:inApp forKey:kReceiptInApp];\n                    }\n\t\t\t\t}\n\t\t\t}\n\t\t\tp += length;\n\t\t}\n        \n\t\t// Skip any remaining fields in this SEQUENCE\n\t\twhile (p < seq_end) {\n\t\t\tASN1_get_object(&p, &length, &type, &xclass, seq_end - p);\n\t\t\tp += length;\n\t\t}\n\t}\n    \n\tPKCS7_free(p7);\n    \n\treturn info;\n}\n\n\nNSArray *obtainInAppPurchases(NSString *receiptPath) {\n\t// According to the documentation, we need to validate the receipt first.\n\t// If the receipt is not valid, no In-App purchase is valid.\n\t// This performs a \"quick\" validation. Please use validateReceiptAtPath to perform a full validation.\n    \n\tNSDictionary *receipt = dictionaryWithAppStoreReceipt(receiptPath);\n\tif (!receipt) {\n\t\treturn nil;\n    }\n    \n\tNSArray *purchases = [receipt objectForKey:kReceiptInApp];\n\tif(!purchases || ![purchases isKindOfClass:[NSArray class]]) {\n\t\treturn nil;\n    }\n    \n\treturn purchases;\n}\n\nextern const NSString * global_bundleVersion;\nextern const NSString * global_bundleIdentifier;\n\n// in your project define those two somewhere as such:\n// const NSString * global_bundleVersion = @\"1.0.2\";\n// const NSString * global_bundleIdentifier = @\"com.example.SampleApp\";\n\nBOOL verifyReceiptAtPath(NSString *receiptPath) {\n\t// it turns out, it's a bad idea, to use these two NSBundle methods in your app:\n\t//\n\t// bundleVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@\"CFBundleVersion\"];\n\t// bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];\n\t//\n\t// http://www.craftymind.com/2011/01/06/mac-app-store-hacked-how-developers-can-better-protect-themselves/\n\t//\n\t// so use hard coded values instead (probably even somehow obfuscated)\n    \n\tNSString *bundleVersion = (NSString*)global_bundleVersion;\n\tNSString *bundleIdentifier = (NSString*)global_bundleIdentifier;\n\n\t// avoid making stupid mistakes --> check again\n\tNSCAssert([bundleVersion isEqualToString:[[NSBundle mainBundle] objectForInfoDictionaryKey:@\"CFBundleVersion\"]],\n              @\"whoops! check the hard-coded CFBundleVersion!\");\n\tNSCAssert([bundleIdentifier isEqualToString:[[NSBundle mainBundle] bundleIdentifier]],\n              @\"whoops! check the hard-coded bundle identifier!\");\n\tNSDictionary *receipt = dictionaryWithAppStoreReceipt(receiptPath);\n    \n\tif (!receipt) {\n\t\treturn NO;\n    }\n    \n    unsigned char uuidBytes[16];\n    NSUUID *vendorUUID = [[UIDevice currentDevice] identifierForVendor];\n    [vendorUUID getUUIDBytes:uuidBytes];\n    \n\tNSMutableData *input = [NSMutableData data];\n\t[input appendBytes:uuidBytes length:sizeof(uuidBytes)];\n\t[input appendData:[receipt objectForKey:kReceiptOpaqueValue]];\n\t[input appendData:[receipt objectForKey:kReceiptBundleIdentifierData]];\n    \n\tNSMutableData *hash = [NSMutableData dataWithLength:SHA_DIGEST_LENGTH];\n\tSHA1([input bytes], [input length], [hash mutableBytes]);\n    \n\tif ([bundleIdentifier isEqualToString:[receipt objectForKey:kReceiptBundleIdentifier]] &&\n        [bundleVersion isEqualToString:[receipt objectForKey:kReceiptVersion]] &&\n        [hash isEqualToData:[receipt objectForKey:kReceiptHash]]) {\n\t\treturn YES;\n\t}\n    \n\treturn NO;\n}\n"
  },
  {
    "path": "VerifyStoreReceipt.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t1D79532E183835580062D190 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D79532D183835580062D190 /* Foundation.framework */; };\n\t\t1D795330183835580062D190 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D79532F183835580062D190 /* CoreGraphics.framework */; };\n\t\t1D795332183835580062D190 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D795331183835580062D190 /* UIKit.framework */; };\n\t\t1D795338183835580062D190 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1D795336183835580062D190 /* InfoPlist.strings */; };\n\t\t1D79533A183835580062D190 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D795339183835580062D190 /* main.m */; };\n\t\t1D79533E183835580062D190 /* RMAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D79533D183835580062D190 /* RMAppDelegate.m */; };\n\t\t1D795340183835580062D190 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1D79533F183835580062D190 /* Images.xcassets */; };\n\t\t1D795347183835580062D190 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D795346183835580062D190 /* XCTest.framework */; };\n\t\t1D795348183835580062D190 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D79532D183835580062D190 /* Foundation.framework */; };\n\t\t1D795349183835580062D190 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D795331183835580062D190 /* UIKit.framework */; };\n\t\t1D79535E183835D80062D190 /* VerifyStoreReceipt.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D79535D183835D80062D190 /* VerifyStoreReceipt.m */; };\n\t\t1D795360183836170062D190 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D79535F183836170062D190 /* Security.framework */; };\n\t\t1D7953631838367B0062D190 /* libcrypto.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D7953611838367B0062D190 /* libcrypto.a */; };\n\t\t1D7953641838367B0062D190 /* libssl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D7953621838367B0062D190 /* libssl.a */; };\n\t\t1D795366183837D70062D190 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D795365183837D70062D190 /* StoreKit.framework */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\t1D79534A183835580062D190 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 1D795322183835570062D190 /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 1D795329183835580062D190;\n\t\t\tremoteInfo = VerifyStoreReceipt;\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXFileReference section */\n\t\t1D79532A183835580062D190 /* VerifyStoreReceipt.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = VerifyStoreReceipt.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t1D79532D183835580062D190 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };\n\t\t1D79532F183835580062D190 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };\n\t\t1D795331183835580062D190 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };\n\t\t1D795335183835580062D190 /* VerifyStoreReceipt-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = \"VerifyStoreReceipt-Info.plist\"; sourceTree = \"<group>\"; };\n\t\t1D795337183835580062D190 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = \"<group>\"; };\n\t\t1D795339183835580062D190 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = \"<group>\"; };\n\t\t1D79533B183835580062D190 /* VerifyStoreReceipt-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = \"VerifyStoreReceipt-Prefix.pch\"; sourceTree = \"<group>\"; };\n\t\t1D79533C183835580062D190 /* RMAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RMAppDelegate.h; sourceTree = \"<group>\"; };\n\t\t1D79533D183835580062D190 /* RMAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RMAppDelegate.m; sourceTree = \"<group>\"; };\n\t\t1D79533F183835580062D190 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = \"<group>\"; };\n\t\t1D795345183835580062D190 /* VerifyStoreReceiptTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = VerifyStoreReceiptTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t1D795346183835580062D190 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };\n\t\t1D79535C183835D80062D190 /* VerifyStoreReceipt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VerifyStoreReceipt.h; sourceTree = \"<group>\"; };\n\t\t1D79535D183835D80062D190 /* VerifyStoreReceipt.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VerifyStoreReceipt.m; sourceTree = \"<group>\"; };\n\t\t1D79535F183836170062D190 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };\n\t\t1D7953611838367B0062D190 /* libcrypto.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libcrypto.a; path = \"../OpenSSL-for-iPhone/lib/libcrypto.a\"; sourceTree = \"<group>\"; };\n\t\t1D7953621838367B0062D190 /* libssl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libssl.a; path = \"../OpenSSL-for-iPhone/lib/libssl.a\"; sourceTree = \"<group>\"; };\n\t\t1D795365183837D70062D190 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t1D795327183835580062D190 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t1D795366183837D70062D190 /* StoreKit.framework in Frameworks */,\n\t\t\t\t1D7953631838367B0062D190 /* libcrypto.a in Frameworks */,\n\t\t\t\t1D7953641838367B0062D190 /* libssl.a in Frameworks */,\n\t\t\t\t1D795360183836170062D190 /* Security.framework in Frameworks */,\n\t\t\t\t1D795330183835580062D190 /* CoreGraphics.framework in Frameworks */,\n\t\t\t\t1D795332183835580062D190 /* UIKit.framework in Frameworks */,\n\t\t\t\t1D79532E183835580062D190 /* Foundation.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t1D795342183835580062D190 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t1D795347183835580062D190 /* XCTest.framework in Frameworks */,\n\t\t\t\t1D795349183835580062D190 /* UIKit.framework in Frameworks */,\n\t\t\t\t1D795348183835580062D190 /* Foundation.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t1D795321183835570062D190 = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t1D795333183835580062D190 /* VerifyStoreReceipt */,\n\t\t\t\t1D79532C183835580062D190 /* Frameworks */,\n\t\t\t\t1D79532B183835580062D190 /* Products */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t1D79532B183835580062D190 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t1D79532A183835580062D190 /* VerifyStoreReceipt.app */,\n\t\t\t\t1D795345183835580062D190 /* VerifyStoreReceiptTests.xctest */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t1D79532C183835580062D190 /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t1D795365183837D70062D190 /* StoreKit.framework */,\n\t\t\t\t1D7953611838367B0062D190 /* libcrypto.a */,\n\t\t\t\t1D7953621838367B0062D190 /* libssl.a */,\n\t\t\t\t1D79535F183836170062D190 /* Security.framework */,\n\t\t\t\t1D79532D183835580062D190 /* Foundation.framework */,\n\t\t\t\t1D79532F183835580062D190 /* CoreGraphics.framework */,\n\t\t\t\t1D795331183835580062D190 /* UIKit.framework */,\n\t\t\t\t1D795346183835580062D190 /* XCTest.framework */,\n\t\t\t);\n\t\t\tname = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t1D795333183835580062D190 /* VerifyStoreReceipt */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t1D79533C183835580062D190 /* RMAppDelegate.h */,\n\t\t\t\t1D79533D183835580062D190 /* RMAppDelegate.m */,\n\t\t\t\t1D79535C183835D80062D190 /* VerifyStoreReceipt.h */,\n\t\t\t\t1D79535D183835D80062D190 /* VerifyStoreReceipt.m */,\n\t\t\t\t1D79533F183835580062D190 /* Images.xcassets */,\n\t\t\t\t1D795334183835580062D190 /* Supporting Files */,\n\t\t\t);\n\t\t\tpath = VerifyStoreReceipt;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t1D795334183835580062D190 /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t1D795335183835580062D190 /* VerifyStoreReceipt-Info.plist */,\n\t\t\t\t1D795336183835580062D190 /* InfoPlist.strings */,\n\t\t\t\t1D795339183835580062D190 /* main.m */,\n\t\t\t\t1D79533B183835580062D190 /* VerifyStoreReceipt-Prefix.pch */,\n\t\t\t);\n\t\t\tname = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t1D795329183835580062D190 /* VerifyStoreReceipt */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 1D795356183835580062D190 /* Build configuration list for PBXNativeTarget \"VerifyStoreReceipt\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t1D795326183835580062D190 /* Sources */,\n\t\t\t\t1D795327183835580062D190 /* Frameworks */,\n\t\t\t\t1D795328183835580062D190 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = VerifyStoreReceipt;\n\t\t\tproductName = VerifyStoreReceipt;\n\t\t\tproductReference = 1D79532A183835580062D190 /* VerifyStoreReceipt.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n\t\t1D795344183835580062D190 /* VerifyStoreReceiptTests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 1D795359183835580062D190 /* Build configuration list for PBXNativeTarget \"VerifyStoreReceiptTests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t1D795341183835580062D190 /* Sources */,\n\t\t\t\t1D795342183835580062D190 /* Frameworks */,\n\t\t\t\t1D795343183835580062D190 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t1D79534B183835580062D190 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = VerifyStoreReceiptTests;\n\t\t\tproductName = VerifyStoreReceiptTests;\n\t\t\tproductReference = 1D795345183835580062D190 /* VerifyStoreReceiptTests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.unit-test\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t1D795322183835570062D190 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tCLASSPREFIX = RM;\n\t\t\t\tLastUpgradeCheck = 0500;\n\t\t\t\tORGANIZATIONNAME = \"Rick Maddy\";\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t1D795344183835580062D190 = {\n\t\t\t\t\t\tTestTargetID = 1D795329183835580062D190;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 1D795325183835570062D190 /* Build configuration list for PBXProject \"VerifyStoreReceipt\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t);\n\t\t\tmainGroup = 1D795321183835570062D190;\n\t\t\tproductRefGroup = 1D79532B183835580062D190 /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t1D795329183835580062D190 /* VerifyStoreReceipt */,\n\t\t\t\t1D795344183835580062D190 /* VerifyStoreReceiptTests */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t1D795328183835580062D190 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t1D795338183835580062D190 /* InfoPlist.strings in Resources */,\n\t\t\t\t1D795340183835580062D190 /* Images.xcassets in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t1D795343183835580062D190 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t1D795326183835580062D190 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t1D79533A183835580062D190 /* main.m in Sources */,\n\t\t\t\t1D79533E183835580062D190 /* RMAppDelegate.m in Sources */,\n\t\t\t\t1D79535E183835D80062D190 /* VerifyStoreReceipt.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t1D795341183835580062D190 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\t1D79534B183835580062D190 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 1D795329183835580062D190 /* VerifyStoreReceipt */;\n\t\t\ttargetProxy = 1D79534A183835580062D190 /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin PBXVariantGroup section */\n\t\t1D795336183835580062D190 /* InfoPlist.strings */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t1D795337183835580062D190 /* en */,\n\t\t\t);\n\t\t\tname = InfoPlist.strings;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\t1D795354183835580062D190 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tARCHS = \"$(ARCHS_STANDARD_INCLUDING_64_BIT)\";\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 6.0;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t1D795355183835580062D190 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tARCHS = \"$(ARCHS_STANDARD_INCLUDING_64_BIT)\";\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = YES;\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 6.0;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t1D795357183835580062D190 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = \"VerifyStoreReceipt/VerifyStoreReceipt-Prefix.pch\";\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,\n\t\t\t\t\t\"../OpenSSL-for-iPhone/include\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = \"VerifyStoreReceipt/VerifyStoreReceipt-Info.plist\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"/Users/rick/projects/home/iphone/OpenSSL-for-iPhone/lib\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tWRAPPER_EXTENSION = app;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t1D795358183835580062D190 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = \"VerifyStoreReceipt/VerifyStoreReceipt-Prefix.pch\";\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,\n\t\t\t\t\t\"../OpenSSL-for-iPhone/include\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = \"VerifyStoreReceipt/VerifyStoreReceipt-Info.plist\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"/Users/rick/projects/home/iphone/OpenSSL-for-iPhone/lib\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tWRAPPER_EXTENSION = app;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t1D79535A183835580062D190 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tARCHS = \"$(ARCHS_STANDARD_INCLUDING_64_BIT)\";\n\t\t\t\tBUNDLE_LOADER = \"$(BUILT_PRODUCTS_DIR)/VerifyStoreReceipt.app/VerifyStoreReceipt\";\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(SDKROOT)/Developer/Library/Frameworks\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(DEVELOPER_FRAMEWORKS_DIR)\",\n\t\t\t\t);\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = \"VerifyStoreReceipt/VerifyStoreReceipt-Prefix.pch\";\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = \"VerifyStoreReceiptTests/VerifyStoreReceiptTests-Info.plist\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_HOST = \"$(BUNDLE_LOADER)\";\n\t\t\t\tWRAPPER_EXTENSION = xctest;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t1D79535B183835580062D190 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tARCHS = \"$(ARCHS_STANDARD_INCLUDING_64_BIT)\";\n\t\t\t\tBUNDLE_LOADER = \"$(BUILT_PRODUCTS_DIR)/VerifyStoreReceipt.app/VerifyStoreReceipt\";\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(SDKROOT)/Developer/Library/Frameworks\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(DEVELOPER_FRAMEWORKS_DIR)\",\n\t\t\t\t);\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = \"VerifyStoreReceipt/VerifyStoreReceipt-Prefix.pch\";\n\t\t\t\tINFOPLIST_FILE = \"VerifyStoreReceiptTests/VerifyStoreReceiptTests-Info.plist\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_HOST = \"$(BUNDLE_LOADER)\";\n\t\t\t\tWRAPPER_EXTENSION = xctest;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t1D795325183835570062D190 /* Build configuration list for PBXProject \"VerifyStoreReceipt\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t1D795354183835580062D190 /* Debug */,\n\t\t\t\t1D795355183835580062D190 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t1D795356183835580062D190 /* Build configuration list for PBXNativeTarget \"VerifyStoreReceipt\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t1D795357183835580062D190 /* Debug */,\n\t\t\t\t1D795358183835580062D190 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t};\n\t\t1D795359183835580062D190 /* Build configuration list for PBXNativeTarget \"VerifyStoreReceiptTests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t1D79535A183835580062D190 /* Debug */,\n\t\t\t\t1D79535B183835580062D190 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 1D795322183835570062D190 /* Project object */;\n}\n"
  },
  {
    "path": "VerifyStoreReceipt.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:VerifyStoreReceipt.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "VerifyStoreReceipt.xcodeproj/project.xcworkspace/xcuserdata/rick.xcuserdatad/WorkspaceSettings.xcsettings",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges</key>\n\t<true/>\n\t<key>SnapshotAutomaticallyBeforeSignificantChanges</key>\n\t<false/>\n</dict>\n</plist>\n"
  }
]