Mac App Store收据验证码?

时间:2010-11-23 21:54:14

标签: cocoa macos validation app-store

想知道是否有人有新的Mac App Store收据验证的教程或工作代码?到目前为止我能找到的唯一参考文献是Apple关于该主题的一流文档和一个编译但没有大量内联注释的开源项目,所以除非你是一个加密的高手,否则很难理解。 / p>

仅限注册开发者的Apple文档:

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

Roddi的ValidateStoreReceipt(看起来很有希望,但却很少记录):

https://github.com/roddi/ValidateStoreReceipt

还想知道为什么Apple不仅提供有效的验证工作代码?

还有其他好的参考资料吗?

13 个答案:

答案 0 :(得分:29)

很难为Mac App Store收据验证提供通用解决方案,主要是因为这是一段非常敏感的代码,必须难以绕过(参见Apple documentation)。

这些GitHub项目是了解在收据验证中必须执行哪些步骤的非常好的起点:

一旦你理解了必须做的事情,这里有一些建议:

  • 不要使用Objective-C类或方法。 Objective-C包含大量元数据,其动态特性使其暴露于运行时注入。
  • 仅使用C函数调用。即使你需要更多的CoreFoundation框架代码,你也可以完美地完成Foundation框架的功能(NSString,NSArray,NSDictionary,...)。
  • 不要动态链接OpenSSL库,因为它已在Mac OS X Lion中弃用。如果您想使用OpenSSL,请静态链接以确保拥有最新版本。
  • 使用系统功能进行加密。自10.5以来,Mac OS X具有相同的功能。例如,要计算SHA-1哈希,可以使用CC_SHA1函数。
  • 不要在代码中以明文形式输入字符串。对它们进行编码或加密。如果您没有这样做,请提示您的代码位置。
  • 不要在代码中使用数字常量。通过一些简单的操作(+, - ,/或*)在运行时计算它们。同样,如果您没有这样做,请提示您的代码位置。
  • 通过将测试和对NSApplicationMain的调用嵌入到复杂的循环中,避免进行简单的验证测试。
  • 避免直接调用NSApplicationMain。使用函数指针隐藏调用。如果您没有这样做,请提示您的代码位置。
  • 对于您的应用程序的每个版本,请稍微修改验证代码,使其永远不变。

请记住,收据验证是必要的,并且看起来并不简单。它可能会占用您在应用程序上花费的大量时间。

所以我建议你看看这个应用程序:Receigen(免责声明:我是这个应用程序的开发者)。

答案 1 :(得分:6)

为了在测试后验证真实收据,请在 main.m 文件中更改此行代码:

if (!validateReceiptAtPath(@"~/Desktop/receipt"))

#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

在您的编译器设置中,调试配置的“其他C标志”应包括-DUSE_SAMPLE_RECEIPT

礼貌http://jesusagora.org/groups/futurebasic/0::53562:get:1read.html

答案 2 :(得分:5)

请务必检查您是否正在验证应用的收据。容易对错误的收据进行所有加密和签名验证。

请参阅http://pastebin.com/1eWf9LCg,看起来“愤怒的小鸟”错过了这一点,让人们可以在免费应用程序的收据中替换它们。

Alan Quatermain也有代码在github上执行此操作。 https://github.com/AlanQuatermain/mac-app-store-validation-sample

不应该原样使用它来避免自动删除。

答案 3 :(得分:3)

我查看了Alan Quartermain的代码,看起来不错。需要考虑的事情:

  

这里的最后一个参数可能/应该是编译的要求,说明代码必须由您的证书和其他人签名。

当开发者将应用程序提交到商店进行审批时,签名证书如下:

3rd Party Mac Developer Application: me
Apple Worldwide Developer Relations Certification Authority
Apple Root CA

将应用程序从App Store交付给最终用户后,签名证书如下:

Apple Mac OS Application Signing
Apple Worldwide Developer Relations Certification Authority
Apple Root CA

另外,我建议只在缺少收据时退出(173),但其他所有内容都是有序的。

答案 4 :(得分:3)

您可以尝试NPReceiptVerification。这是向您的应用添加收据验证的最简单方法。您只需将类文件添加到项目中,设置版本和包标识符,其他所有内容都将自动处理。

答案 5 :(得分:2)

我建议将代码验证例程实现为C函数,而不是ObjC方法。

这种技术使得(有点)更难找到收据检查代码,因为更少的方法名称被编译到二进制文件中。

答案 6 :(得分:2)

您可以参考RVNReceiptValidation,这很容易实现。只需要在RVNReceiptValidation.m文件和应用版本中设置Bundle id。记得从苹果获得收据,你必须从Finder启动应用程序。此类还有助于实施InApp购买。

答案 7 :(得分:1)

我将详细说明priller的答案。如果Apple为验证过程提供了代码示例,那么Bad Guy将很容易获取已编译的应用程序并扫描它以获取与验证过程相对应的代码。如果您使用Apple的标准代码示例,Bad Guy会确切地知道编译代码的样子。一旦Bad Guy找到了代码的这一部分,将app的编译代码修改为跳过收据验证阶段就变得非常简单了,使整个事情变得毫无用处。

所有这一切,无论你做什么,一个坚定的破解者可能会绕过你实施的任何版权保护。游戏行业(例如)花费大量时间来保护他们的软件,并且破解版本似乎总是可用。

答案 8 :(得分:1)

从Apple Docs创建样本收据时,请确保在“结束”之后不要包含任何额外字符,否则uudecode将失败。

答案 9 :(得分:0)

是的,在他们的文档中说,“使用您的应用程序独有的解决方案非常重要。”

答案 10 :(得分:0)

即使使用NPReceiptValidation,您仍应验证应用程序包的安全性,包括签名证书。这在开发人员的WWDR建议中有记录。

解决方案: http://itunes.apple.com/us/app/apptight-pro-app-store-code/id427083596?mt=12

NPReceiptValidation的一个潜在问题是Cocoa对象上的方法选择器很容易被劫持。这是扩展应用程序最流行的方式。

这是辅助应用内购买解析的另一个工具:

http://itunes.apple.com/us/app/pkcs-7viewer/id547539804?mt=12

答案 11 :(得分:0)

roddi的ValidateStoreReceipt之前曾为我工作,但它不再起作用了。 我写了一篇关于解决方案的博客文章:http://vinceyuan.blogspot.com/2012/07/validate-mac-app-store-receipt-2012.html

复制到这里: roddi的代码仍然有效。你不需要改变它。 (只需要获得最新版本) 请遵循以下步骤(需要互联网):

  1. 从Mac App Store应用程序退出。
  2. 从项目设置中删除USE_SAMPLE_RECEIPT标记 - >预处理器宏。
  3. 编译项​​目
  4. 在Finder中找到此应用
  5. 在Finder中双击它以运行。不要在Xcode中运行它。
  6. 操作系统会要求您使用Apple ID登录。请勿使用您的真实iTunes帐户登录。您需要使用测试帐户登录。在iTunesconnect网站上找到它或创建它。
  7. 操作系统会说"你的应用程序坏了。在App Store下载#34;忽略此消息。如果你"显示包装内容"在Finder中的这个应用程序,你会看到有一个文件_MASReceipt /收据。操作系统安装了开发收据。我们不再需要旧的样品收据了。这就是我们删除USE_SAMPLE_RECEIPT调试标志的原因。
  8. 完成。您现在可以调试您的应用程序。

答案 12 :(得分:0)

RVNReceiptValidation很棒,它使用CommonCrypto而不是现在由Apple openssl弃用的。您必须将有效的收据附加到项目中才能进行调试。为此,请从另一个应用程序包中获取有效收据,并在测试环境中创建一个构建阶段,以将其添加到您的包中。我建议采用以下迷惑技术:

对kRVNBundleID和kRVNBundleVersion进行加密,然后将它们与CFBundleIdentifier和CFBundleShortVersionString进行比较。

我创建了一个带有随机值的函数指针数组,并在运行时将它们更改为指向RVNReceiptValuation中函数的有效指针,然后使用如下代码执行它们:

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");
}