Skip to content

Commit

Permalink
Validate receipt using Apple Certificate data robotmedia#198
Browse files Browse the repository at this point in the history
Adds a method to provide Apple's certificate data as an alternative to the certificate url.
This can be useful when Apple's certificate is embedded in the source code (base64) instead of being in the app's resources. It's specially useful in Mac Apps, where anyone could replace the certificate in the bundle.

This change does not affect setAppleRootCertificateURL. The receipt can still be validated with the url of the certificate, but if the certificate data exists, it takes precedence over the url.
  • Loading branch information
everappz committed Mar 24, 2024
1 parent 9cc8cf0 commit 93039fb
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 2 deletions.
6 changes: 6 additions & 0 deletions RMStore/Optional/RMAppReceipt.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ __attribute__((availability(ios,introduced=7.0)))
*/
+ (void)setAppleRootCertificateURL:(NSURL*)url;

/**
Sets the data of the Apple Root certificate that will be used to verifiy the signature of the bundle receipt. This takes precedence over AppleRootCertificateURL if both are set. If none is provided, AppleRootCertificateURL will be used. If no certificate is available, no signature verification will be performed.
@param data containing the Apple Root certificate.
*/
+ (void)setAppleRootCertificateData:(NSData*)data;

@end

/** Represents an in-app purchase in the app receipt.
Expand Down
16 changes: 14 additions & 2 deletions RMStore/Optional/RMAppReceipt.m
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ static int RMASN1ReadInteger(const uint8_t **pp, long omax)

static NSURL *_appleRootCertificateURL = nil;

static NSData *_appleRootCertificateData = nil;

@implementation RMAppReceipt

- (instancetype)initWithASN1Data:(NSData*)asn1Data
Expand Down Expand Up @@ -215,6 +217,11 @@ + (void)setAppleRootCertificateURL:(NSURL*)url
_appleRootCertificateURL = url;
}

+ (void)setAppleRootCertificateData:(NSData*)data
{
_appleRootCertificateData = data;
}

#pragma mark - Utils

+ (NSData*)dataFromPCKS7Path:(NSString*)path
Expand All @@ -229,8 +236,13 @@ + (NSData*)dataFromPCKS7Path:(NSString*)path
if (!p7) return nil;

NSData *data;
NSURL *certificateURL = _appleRootCertificateURL ? : [[NSBundle mainBundle] URLForResource:@"AppleIncRootCertificate" withExtension:@"cer"];
NSData *certificateData = [NSData dataWithContentsOfURL:certificateURL];
NSData *certificateData = _appleRootCertificateData;

if( certificateData.length == 0 ) {
NSURL *certificateURL = _appleRootCertificateURL ? : [[NSBundle mainBundle] URLForResource:@"AppleIncRootCertificate" withExtension:@"cer"];
certificateData = [NSData dataWithContentsOfURL:certificateURL];
}

if (!certificateData || [self verifyPCKS7:p7 withCertificateData:certificateData])
{
struct pkcs7_st *contents = p7->d.sign->contents;
Expand Down

0 comments on commit 93039fb

Please sign in to comment.