I have to validate receipts from In-App Purchases inside an iPhone application (iOS 7 only).
Unfortunately, cryptography, openssl and In-App Purchases are completely new for me so I have some problems to get them working.
I'm following the guide provided by Apple to verify receipts locally and I included openssl in my project as static library. This is the code provided by Apple to verify receipt signature using OpenSSL:
BIO *b_receipt;
BIO *b_x509;
PKCS7 *p7 = d2i_PKCS7_bio(b_receipt, NULL);
X509_STORE *store = X509_STORE_new();
X509 *appleRootCA = d2i_X509_bio(b_x509, NULL);
X509_STORE_add_cert(store, appleRootCA);
BIO *b_receiptPayload;
int result = PKCS7_verify(p7, NULL, store, NULL, b_receiptPayload, 0);
if (result == 1)
{
// Receipt signature is Valid
// b_receiptPayload contains the payload
}
I use this code to get the receipt and the certificate:
NSData *receiptData = [NSData dataWithContentsOfURL:[[NSBundle mainBundle] appStoreReceiptURL]];
NSData *certificateData = [NSData dataWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"AppleIncRootCertificate" withExtension:@"cer"]];
How can I use these two NSData
to initialize BIO
variables b_receipt
and b_x509
?
From http://www.openssl.org/docs/crypto/BIO_s_mem.html:
BIO *BIO_new_mem_buf(void *buf, int len);
creates a read-only memory BIO object from a given buffer. In your case
BIO *b_receipt = BIO_new_mem_buf((void *)[receiptData bytes], (int)[receiptData length]);
The data is read directly from the supplied buffer. If receiptData
is valid as long
as b_receipt
is used, you need not copy the data.
BIO_new_mem_buf()
does not modify the buffer, therefore you can safely add a
void *
cast to avoid a "Passing 'const void *' to parameter of type 'void *' discards qualifiers" warning.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With