Hello,
I'm implementing AppAttest for one of our apps. Though the Attestation procedure works fine, the assertion signed by the private key on the device (via generateAssertion) can't be verified at the server with the public key saved during the attestation.
Environment
AppAttest entitlement: development
iOS 14
Server: Nodejs
The client (app) and server code specific to assertion is below.
Client side code (app)
if let clientData = self.prepareClientData(withChallenge: challenge) {
		// generate assertion
		let clientDataHash = Data(SHA256.hash(data: clientData))
		DCAppAttestService.shared.generateAssertion(keyId!, clientDataHash: clientDataHash) { assertion, error in
				guard error == nil else {
						print ("ERROR: Assertion not available right now")
						return
				}
				// create assertion request
				var urlRequest = URLRequest(url: URL(string: self.assertEP)!)
				urlRequest.httpMethod = "POST"
				urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
				let clientDataString = clientData.base64EncodedString()
				let assertionString = assertion!.base64EncodedString()
				let assertRequest: [String: Any] = ["clientData": clientDataString, "assertion": assertionString]
				let jsonData: Data
				do {
						jsonData = try JSONSerialization.data(withJSONObject: assertRequest, options: [])
						urlRequest.httpBody = jsonData
				} catch {
						print (error)
						return
				}
				
				// send assertion request to server
				let task = URLSession.shared.dataTask(with: urlRequest) { data, response, error in
						guard error == nil else {
								// request sending failed, try again later
								print (error!)
								return
						}
						
						self.extractAssertionResponse(withData: data)
				}
				task.resume()
		}
}
Server side Assertion verification code
function verifyAssertion(clientDataBuffer, assertionBuffer) {
		try {
				let assert = cbor.decodeAllSync(assertionBuffer)[0];
				let authData = assert.authenticatorData; // buffer
				let signature = assert.signature; // buffer
				// compute client Data Hash
				let clientDataHash = crypto.createHash('sha256').update(clientDataBuffer).digest('base64');
				let clientDataHashBuffer = Buffer.from(clientDataHash, 'base64');
				// compute composite hash
				let compositeBuffer = Buffer.concat([authData, clientDataHashBuffer]);
				let nonce = crypto.createHash('sha256').update(compositeBuffer).digest('base64'); // base64 string
				let nonceBuffer = Buffer.from(nonce, 'base64');
				// load public key
				let keyObj = crypto.createPublicKey(k_publicKeyPem);
				// verify signature
				let verifier = crypto.createVerify('sha256').update(nonceBuffer);
				let sign_verify = verifier.verify(keyObj, signature);
				console.log("sign_verify: ", sign_verify);
		} catch (e) {
				console.log(e);
		}
}
The verifier.verify() call always results in 'false'.
I've tried 'hex' and 'base64' variations on the signature, but didn't work.
I've verified that the sha256(publicKey) received at the server is equal to the keyId.
let keybuf = Buffer.from(k_publicKeyRaw, 'base64');
let keySHA = crypto.createHash('sha256').update(keybuf).digest('base64');
let keyVerified = (keySHA === k_keyId);
Also verified that the clientDataHash generated at the server is the same as clientDataHash generated within the app.
Does crypto Verify not compatible with the generated signatures? If not, what's the suggested way to do it?
I've tried all the encodings supported by crypto Verify.verify but none of those worked.
crypto.getHashes();
Please help.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
If I have generated a master shared secret and an app-specific shared secret for a non-consumable in-app purchase, which one would Apple send in the Refund notification?
The refunds notification testing is not supported in sandbox, so can't really test to figure out which one to configure.
I've learned that during receipt validation, either of these secrets can be used.
My question is related to AppStore callbacks, specifically, the refund notification callback.
Does the app-specific secret takes precedence over the master one?
Can you choose which shared secret to use for App Store callbacks?
Thanks
Topic:
App Store Distribution & Marketing
SubTopic:
App Store Connect
Tags:
App Store Connect
App Store Server Notifications