I'm attempting to verify the deprecated iOS transactionReceipt; and I'm stuck on the verifying the signature.
I've base64 decoded the receipt and parsed the initial plist, resulting with:
payload = {
"signature"=>"AnTJSzQAjehWYmnqlofOYVqrXJ51UNZr9//2HXq3MB9i2aPjVilv38ixmZoO/9YfPlRHYDusXT2IpYbDs4pFZNw/mQL1TzkIIetYea4OyjuV5KluEB4LKVol7nmHfd27HI6PM6jBDZKLmpktmNVCmfnheT+jlMjLx7eZKjHSFhlRAAADVzCCA1MwggI7oAMCAQICCBup4+PAhm/LMA0GCSqGSIb3DQEBBQUAMH8xCzAJBgNVBAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSYwJAYDVQQLDB1BcHBsZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEzMDEGA1UEAwwqQXBwbGUgaVR1bmVzIFN0b3JlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTE0MDYwNzAwMDIyMVoXDTE2MDUxODE4MzEzMFowZDEjMCEGA1UEAwwaUHVyY2hhc2VSZWNlaXB0Q2VydGlmaWNhdGUxGzAZBgNVBAsMEkFwcGxlIGlUdW5lcyBTdG9yZTETMBEGA1UECgwKQXBwbGUgSW5jLjELMAkGA1UEBhMCVVMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMmTEuLgjimLwRJxy1oEf0esUNDVEIe6wDsnnal14hNBt1v195X6n93YO7gi3orPSux9D554SkMp+Sayg84lTc362UtmYLpWnb34nqyGx9KBVTy5OGV4ljE1OwC+oTnRM+QLRCmeNxMbPZhS47T+eZtDEhVB9usk3+JM2Cogfwo7AgMBAAGjcjBwMB0GA1UdDgQWBBSJaEeNuq9Df6ZfN68Fe+I2u22ssDAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFDYd6OKdgtIBGLUyaw7XQwuRWEM6MA4GA1UdDwEB/wQEAwIHgDAQBgoqhkiG92NkBgUBBAIFADANBgkqhkiG9w0BAQUFAAOCAQEAeaJV2U51rxfcqAAe5C2/fEW8KUl4iO4lMuta7N6XzP1pZIz1NkkCtIIweyNj5URYHK+HjRKSU9RLguNl0nkfxqObiMckwRudKSq69NInrZyCD66R4K77nb9lMTABSSYlsKt8oNtlhgR/1kjSSRQcHktsDcSiQGKMdkSlp4AyXf7vnHPBe4yCwYV2PpSN04kboiJ3pBlxsGwV/ZlL26M2ueYHKYCuXhdqFwxVgm52h3oeJOOt/vY4EcQq7eqHm6m03Z9b7PRzYM2KGXHDmOMk7vDpeMVlLDPSGYz1+U3sDxJzebSpbaJmT7imzUKfggEY7xxf4czfH0yj5wNzSGTOvQ==",
"purchase-info"=>"ewoJIm9yaWdpbmFsLXB1cmNoYXNlLWRhdGUtcHN0IiA9ICIyMDE1LTExLTE3IDA4OjM0OjQxIEFtZXJpY2EvTG9zX0FuZ2VsZXMiOwoJInB1cmNoYXNlLWRhdGUtbXMiID0gIjE0NDc4MjEyODEwMDAiOwoJInVuaXF1ZS1pZGVudGlmaWVyIiA9ICJkZDBlMzNlYmY1NmJiMWYzYWQ0YzJkYmFhN2EwYjMzYWM2OGIwZTg1IjsKCSJvcmlnaW5hbC10cmFuc2FjdGlvbi1pZCIgPSAiMTAwMDAwMDE4MDYzNjIyNiI7CgkiZXhwaXJlcy1kYXRlIiA9ICIxNDQ4MzQ2ODgxMDAwIjsKCSJ0cmFuc2FjdGlvbi1pZCIgPSAiMTAwMDAwMDE4MTI5ODczNCI7Cgkib3JpZ2luYWwtcHVyY2hhc2UtZGF0ZS1tcyIgPSAiMTQ0Nzc3ODA4MTAwMCI7Cgkid2ViLW9yZGVyLWxpbmUtaXRlbS1pZCIgPSAiMTAwMDAwMDAzMDkzODcxMyI7CgkiYnZycyIgPSAiMSI7CgkidW5pcXVlLXZlbmRvci1pZGVudGlmaWVyIiA9ICI0RTVFMUEzQi1GMDFBLTQ4NTUtODIwRi1GMzQ5RjEyNDIxNDgiOwoJImV4cGlyZXMtZGF0ZS1mb3JtYXR0ZWQtcHN0IiA9ICIyMDE1LTExLTIzIDIyOjM0OjQxIEFtZXJpY2EvTG9zX0FuZ2VsZXMiOwoJIml0ZW0taWQiID0gIjEwMjg5NTA3OTciOwoJImV4cGlyZXMtZGF0ZS1mb3JtYXR0ZWQiID0gIjIwMTUtMTEtMjQgMDY6MzQ6NDEgRXRjL0dNVCI7CgkicHJvZHVjdC1pZCIgPSAieWVhcmx5IjsKCSJwdXJjaGFzZS1kYXRlIiA9ICIyMDE1LTExLTE4IDA0OjM0OjQxIEV0Yy9HTVQiOwoJIm9yaWdpbmFsLXB1cmNoYXNlLWRhdGUiID0gIjIwMTUtMTEtMTcgMTY6MzQ6NDEgRXRjL0dNVCI7CgkiYmlkIiA9ICJjb20ubWJhYXN5Lmlvcy5kZW1vIjsKCSJwdXJjaGFzZS1kYXRlLXBzdCIgPSAiMjAxNS0xMS0xNyAyMDozNDo0MSBBbWVyaWNhL0xvc19BbmdlbGVzIjsKCSJxdWFudGl0eSIgPSAiMSI7Cn0=",
"environment"=>"Sandbox",
"pod"=>"100",
"signing-status"=>"0"
}
So now I want to verify the signature, here is what I have so far:
version, sig, cert_length, cert = payload.fetch('signature')
.unpack('m').first
.unpack('c a128 N a*')
return false unless
version == 2 &&
sig.size == 128 &&
cert.size == cert_length
cert = OpenSSL::X509::Certificate.new cert
digest = OpenSSL::Digest::SHA1.new
digest << version.to_s
digest << payload.fetch('purchase-info').unpack('m').first
cert.public_key.verify OpenSSL::Digest::SHA1.new, sig, digest.digest
The result from cert.public_key.verify
is always false which is not what I want since I'm working from a real receipt.
I'm using this Quora post as a guide which has given me insight into how to unpack the signature, and I have successfully extracted all the parts from the blob.
Perhaps encoding is an issue? sig
and data
are both ASCII-8BIT
and version
is an integer.
I appreciate your help on this.
Validate the receipt Locate and load the app receipt from the app's bundle. The class Bundle provides the location of the receipt with the property appStoreReceiptURL . Decode the app receipt as a PKCS #7 container and verify that the chain of trust for the container's signature matches the Apple root certificate.
StoreKit provides a simple and secure way to purchase digital goods or services in your apps across all Apple platforms, so people can start playing, gaming, reading, and more, right away.
To request the receipt using the SKReceiptRefreshRequest object, you initialize it, attach a delegate , and then call the request's start() method. The receipt refresh request displays a system prompt that asks users to authenticate with their App Store credentials.
Hereby the answer according to https://gist.github.com/lxcid/4441003
message = [version, payload.fetch('purchase-info').unpack('m').first].pack('CA*')
cert.public_key.verify OpenSSL::Digest::SHA1.new, sig, message
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