SKAdNetwork 2.0 install postback verification

Hi,

I'm trying to verify the signature in the sample provided here:
https://developer.apple.com/documentation/storekit/skadnetwork/verifying_an_install_validation_postback

I created the following files:
  1. apple.pub

Code Block
-----BEGIN PUBLIC KEY-----
MEkwEwYHKoZIzj0CAQYIKoZIzj0DAQEDMgAEMyHD625uvsmGq4C43cQ9BnfN2xsl
VT5V1nOmAMP6qaRRUll3PB1JYmgSm+62sosG
-----END PUBLIC KEY-----


2. signature.bin
Contains base64 decoding of
Code Block
MDYCGQCsQ4y8d4BlYU9b8Qb9BPWPi+ixk/OiRysCGQDZZ8fpJnuqs9my8iSQVbJO/oU1AXUROYU=


3. message.bin
Contains the '\u2063' delimited string:
Code Block
2.0⁣com.example⁣42⁣525463029⁣6aafb7a5-0170-41b5-bbe4-fe71dedf1e28⁣1⁣1234567891


But trying to verify the signature using the command below returns "Verification Failure":
Code Block
openssl dgst -sha256 -verify apple.pub -signature signature.bin message.bin


What's the problem and how can the signature be verified using openssl?

3. message.bin

Can you post a hex dump of that?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"
I also run into the same problem. the hexdump of the message.bin I have:

Code Block
00000000 32 2e 30 e2 81 a3 63 6f 6d 2e 65 78 61 6d 70 6c |2.0...com.exampl|
00000010 65 e2 81 a3 34 32 e2 81 a3 35 32 35 34 36 33 30 |e...42...5254630|
00000020 32 39 e2 81 a3 36 61 61 66 62 37 61 35 2d 30 31 |29...6aafb7a5-01|
00000030 37 30 2d 34 31 62 35 2d 62 62 65 34 2d 66 65 37 |70-41b5-bbe4-fe7|
00000040 31 64 65 64 66 31 65 32 38 e2 81 a3 31 e2 81 a3 |1dedf1e28...1...|
00000050 31 32 33 34 35 36 37 38 39 31 |1234567891|
0000005a


@eskimo
After posting, I noticed:

redownload Note: use the strings “true” or “false” to represent the Boolean value of the redownload parameter.

but still getting verification failure.

The hex dumps:
Code Block
$ xxd message.bin
00000000: 322e 30e2 81a3 636f 6d2e 6578 616d 706c 2.0...com.exampl
00000010: 65e2 81a3 3432 e281 a335 3235 3436 3330 e...42...5254630
00000020: 3239 e281 a336 6161 6662 3761 352d 3031 29...6aafb7a5-01
00000030: 3730 2d34 3162 352d 6262 6534 2d66 6537 70-41b5-bbe4-fe7
00000040: 3164 6564 6631 6532 38e2 81a3 7472 7565 1dedf1e28...true
00000050: e281 a331 3233 3435 3637 3839 31 ...1234567891

Code Block
$ xxd signature.bin
00000000: 3036 0219 00ac 438c bc77 8065 614f 5bf1 06....C..w.eaO[.
00000010: 06fd 04f5 8f8b e8b1 93f3 a247 2b02 1900 ...........G+...
00000020: d967 c7e9 267b aab3 d9b2 f224 9055 b24e .g..&{.....$.U.N
00000030: fe85 3501 7511 3985 ..5.u.9.

Thanks for all the extra info. Alas, I’ve got nothing )-: I was hoping that there was some obvious crypto-level issue in play here but at this point I’m thinking that it’s probably something SKAdNetwork specific. I don’t support that API and thus don’t have any insight in that side of it.

My best suggestion right now is that you open a DTS tech support incident and talk to our SKAdNetwork specialist.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"
Will do, thanks!
Hello, I am also working on SKAdNetwork, so I will contact you
18811497871 @163.com
Could you share your findings here? Thanks
Hi,

We were able to get a live postback at Singular and successfully validated its signature using the steps described by @fruitshake.

It looks like the current example in Apple’s documentation doesn’t have a valid signature, but the real signatures work as expected.

We wrote a blog post on how to test SKAdNetwork - check it out at:
singular.net/blog/ios14-skadnetwork-test-setup

Hope that’s helpful!

It looks like the current example in Apple’s documentation doesn’t have a valid signature

Indeed. We are working to fix that. Sorry about the confusion.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"
@eskimo kindly update on this thread when the example is fixed. Thank you!
The sample response remains broken after a week. There are several issues with the sample response as pointed out in the thread https://developer.apple.com/forums/thread/657368 which prevent proper testing in preparation for submitting.

When may we expect the sample to be corrected and additional guidance added to the post?

Thank you

When may we expect the sample to be corrected … ?

Sorry, but I can’t offer a specific timelines.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"

(r. 66808193)
Any updates here? Looking for a valid sample so we can verify that our code works.

So much time passed but Apple still didn't update the signature to fit with the Public Key. So we are unable to actually validate that what we are doing is right..

So we are unable to actually validate that what we are doing is right.

I checked on the bug referenced above (r. 66808193) and it’s reported as fixed so I sat down to try this for myself. Pasted in below is some Swift code that verifies the example in the documentation. I built this using Xcode 12.5. When I run it on my Mac, running macOS 11.6, it prints:

Postback(version: "3.0", adNetworkID: "example123.skadnetwork", campaignID: 42, transactionID: "6aafb7a5-0170-41b5-bbe4-fe71dedf1e28", appID: 525463029, attributionSignature: 70 bytes, redownload: true, sourceAppID: 1234567891, fidelityType: 1, conversionValue: 20, didWin: true)

I’m not sure why it’s not working for you but this snippet should give you a baseline to work from.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

import Foundation
import CryptoKit

struct Postback: Codable {
    var version: String
    var adNetworkID: String
    var campaignID: Int
    var transactionID: String
    var appID: Int
    var attributionSignature: Data
    var redownload: Bool
    var sourceAppID: Int
    var fidelityType: Int
    var conversionValue: Int
    var didWin: Bool
    
    enum CodingKeys: String, CodingKey {
        case version = "version"
        case adNetworkID = "ad-network-id"
        case campaignID = "campaign-id"
        case transactionID = "transaction-id"
        case appID = "app-id"
        case attributionSignature = "attribution-signature"
        case redownload = "redownload"
        case sourceAppID = "source-app-id"
        case fidelityType = "fidelity-type"
        case conversionValue = "conversion-value"
        case didWin = "did-win"
    }
}

extension Postback {

    private static let keyBytes = Data(base64Encoded: "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEWdp8GPcGqmhgzEFj9Z2nSpQVddayaPe4FMzqM9wib1+aHaaIzoHoLN9zW4K8y4SPykE3YVK3sVqW6Af0lfx3gg==")!
    private static let publicKeyFor2point1AndLater = try! P256.Signing.PublicKey(derRepresentation: keyBytes)

    init(verifyingJSON: Data) throws {
        let decoder = JSONDecoder()
        self = try decoder.decode(Postback.self, from: verifyingJSON)
        // The key works for version 2.1 and up, but I’m chosing to only support
        // version 3.0.
        guard self.version == "3.0" else {
            // Clearly a better error is called for (-:
            throw NSError(domain: NSPOSIXErrorDomain, code: Int(ENOTTY), userInfo: nil)
        }
        let message = [
            self.version,
            self.adNetworkID,
            String(self.campaignID),
            String(self.appID),
            self.transactionID,
            self.redownload ? "true" : "false",
            String(self.fidelityType),
            self.didWin ? "true" : "false"
        ].joined(separator: "\u{2063}")
        let signature = try P256.Signing.ECDSASignature(derRepresentation: self.attributionSignature)
        let isValid = Self.publicKeyFor2point1AndLater.isValidSignature(signature, for: Data(message.utf8))
        guard isValid else {
            throw NSError(domain: NSPOSIXErrorDomain, code: Int(ENOTTY), userInfo: nil)
        }
    }
}

func main() throws {
    let postbackJSON = """
        {
          "version": "3.0",
          "ad-network-id": "example123.skadnetwork",
          "campaign-id": 42,
          "transaction-id": "6aafb7a5-0170-41b5-bbe4-fe71dedf1e28",
          "app-id": 525463029,
          "attribution-signature": "MEQCIE0nS32ZERP3oKRi/A8omsYq259wWJb7GIsW1/ULsEqoAiAQrBlTZTJNK25MtnGDRwoldRy1CwkFIEMXJAzLRchx0Q==",
          "redownload": true,
          "source-app-id": 1234567891,
          "fidelity-type": 1,
          "conversion-value": 20,
          "did-win": true
        }
        """
    let pb = try Postback(verifyingJSON: Data(postbackJSON.utf8))
    print(pb)
}

try! main()
SKAdNetwork 2.0 install postback verification
 
 
Q