macos Mac App Store 收据验证码?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4261348/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 07:22:30  来源:igfitidea点击:

Mac App Store Receipt Validation Code?

cocoamacosvalidationapp-store

提问by Rei

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.

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

Apple docs for registered devs only:

仅适用于注册开发人员的 Apple 文档:

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

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

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

Roddi 的 ValidateStoreReceipt(看起来很有希望,但文档很少):

https://github.com/roddi/ValidateStoreReceipt

https://github.com/roddi/ValidateStoreReceipt

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

还想知道为什么 Apple 不只提供用于验证的工作代码?

Any other good references out there?

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

回答by Laurent Etiemble

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).

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

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

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

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

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).

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

回答by snibbe

In order to validate against the real receipt after testing, change this line of code in your main.mfile:

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

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

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

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

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

回答by koregan

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/1eWf9LCgwhere it looks like Angry Birds missed this bit and left them open to people substituting in a receipt from a free app.

请参阅http://pastebin.com/1eWf9LCg,其中 Angry Birds 似乎错过了这一点,并让人们可以使用免费应用程序的收据替换它们。

Alan Quatermain also has code to do this up on github. https://github.com/AlanQuatermain/mac-app-store-validation-sample

Alan Quatermain 在 github 上也有代码可以做到这一点。 https://github.com/AlanQuatermain/mac-app-store-validation-sample

It should not be used as-is to avoid automated removal.

不应按原样使用它以避免自动删除。

回答by indragie

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.

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

回答by C0C0AL0C0

I reviewed Alan Quartermain's code and it looks good. Something to think about:

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

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:

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

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.

另外,我建议只在收据丢失时退出(173),但其他一切都井然有序。

回答by SteAp

I'd propose to implement the code verification routines as C functions, not ObjC methods.

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

This technique makes it (a bit) harder to locate receipt checking code, since fewer method-names get compiled into the binary.

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

回答by Aravindhan

You can Refer the RVNReceiptValidationit is easy to implement. Just you have to set the Bundle id in RVNReceiptValidation.mfile 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.

您可以参考RVNReceiptValidation它很容易实现。只是您必须在RVNReceiptValidation.m应用程序的文件和版本中设置 Bundle id 。请记住要从 Apple 获取收据,您必须从 Finder 启动该应用程序。此类还有助于实现应用内购买。

回答by Billy Bob

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:

RVNreceiptValidation 很棒,它使用 CommonCrypto 而不是现在被 Apple 弃用的 openssl。您必须将有效的收据附加到您的项目中才能对其进行调试。通过从另一个应用程序包中获取有效收据并在您的测试环境中创建一个构建阶段以将其添加到您的包中来执行此操作。我建议使用以下混淆技术:

Encrypt the kRVNBundleID and kRVNBundleVersion and decrypt them when you compare them to the CFBundleIdentifier and CFBundleShortVersionString.

加密 kRVNBundleID 和 kRVNBundleVersion 并在将它们与 CFBundleIdentifier 和 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:

我创建了一个带有随机值的函数指针数组,并在运行时将它们更改为指向 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");
}

回答by pygar

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

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

回答by Pete Hodgson

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.

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

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.

尽管如此,一个坚定的破解者可能会绕过你设置的任何复制保护,无论你做什么。游戏行业(例如)花费大量时间试图保护他们的软件,而且破解版本似乎总是可用的。