Posts under App & System Services topic

Post

Replies

Boosts

Views

Activity

New features for APNs token authentication now available
Team-scoped keys introduce the ability to restrict your token authentication keys to either development or production environments. Topic-specific keys in addition to environment isolation allow you to associate each key with a specific Bundle ID streamlining key management. For detailed instructions on accessing these features, read our updated documentation on establishing a token-based connection to APNs.
0
0
1.9k
Feb ’25
Voice Isolation problem - iphone14 ios 26.3
Hi, After updating my iPhone from iOS 26 to iOS 26.3, I’ve been experiencing issues with the Voice Isolation feature. Whenever I enable Voice Isolation while using the microphone in apps, my voice becomes unclear. The people I’m speaking with say they can’t hear me clearly and have difficulty understanding what I’m saying. I never had this problem before updating to iOS 26. To try to fix the issue, I have: Restarted my device Updated from iOS 26 to iOS 26.3 Unfortunately, the problem still persists. For comparison, I also have an iPad Air 3 running iPadOS 18.5, and Voice Isolation works perfectly fine on that device. Please advise on how this issue can be resolved. Thank you.
1
0
14
28m
iOS printing – Finishing (Punch) options not applied for images unless a preset is selected
When printing image/photo files via AirPrint, selected finishing options (e.g., Punch) are not applied unless a preset is chosen. reproduction steps: Select an image on iOS Tap Print → choose printer/server Set Finishing Options → Punch Print Observed: Finishing options not applied IPP trace shows no finisher attributes in the request working scenario: Select any Preset (e.g., Color) before printing Finishing options are then included in IPP and applied Note: Issue does not occur when printing PDFs from iOS; finisher attributes are sent correctly. Is this expected AirPrint behavior for image jobs, or could this be a bug in how iOS constructs the IPP request for photos?
2
0
51
2h
Getting a basic URL Filter to work
I haven’t been able to get this to work at any level! I’m running into multiple issues, any light shed on any of these would be nice: I can’t implement a bloom filter that produces the same output as can be found in the SimpleURLFilter sample project, after following the textual description of it that’s available in the documentation. No clue what my implementation is doing wrong, and because of the nature of hashing, there is no way to know. Specifically: The web is full of implementations of FNV-1a and MurmurHash3, and they all produce different hashes for the same input. Can we get the proper hashes for some sample strings, so we know which is the “correct” one? Similarly, different implementations use different encodings for the strings to hash. Which should we use here? The formulas for numberOfBits and numberOfHashes give Doubles and assign them to Ints. It seems we should do this conversing by rounding them, is this correct? Can we get a sample correct value for the combined hash, so we can verify our implementations against it? Or ignoring all of the above, can we have the actual code instead of a textual description of it? 😓 I managed to get Settings to register my first attempt at this extension in beta 1. Now, in beta 2, any other project (including the sample code) will redirect to Settings, show the Allow/Deny message box, I tap Allow, and then nothing happens. This must be a bug, right? Whenever I try to enable the only extension that Settings accepted (by setting its isEnabled to true), its status goes to .stopped and the error is, of course, .unknown. How do I debug this? While the extension is .stopped, ALL URL LOADS are blocked on the device. Is this to be expected? (shouldFailClosed is set to false) Is there any way to manually reload the bloom filter? My app ships blocklist updates with background push, so it would be wasteful to fetch the filter at a fixed interval. If so, can we opt out of the periodic fetch altogether? I initially believed the API to be near useless because I didn’t know of its “fuzzy matching” capabilities, which I’ve discovered by accident in a forum post. It’d be nice if those were documented somewhere! Thanks!!
39
1
3.2k
2h
iOS App terminated by Watchdog (Signal 9) in Background state despite reporting call
iOS App terminated by Watchdog (Signal 9) in Background state despite reporting call Description I have successfully implemented VoIP pushes for the Killed state, where CallKit triggers correctly. However, when the app is in the Background state (suspended), it consistently crashes with an NSInternalInconsistencyException. The app process is killed by the iOS Watchdog because it fails to satisfy the requirement of posting an incoming call in the same run loop as the push receipt, or the completion handler is not being released fast enough by the JS bridge. Environment React Native Version: .78 React Native CallKeep Version: 4.3.14 React Native VoIP Push Notification Version: 3.3.3 iOS Version: 18.x Device: Physical iPhone [iphone 13 pro] The Issue When a VoIP push arrives while the app is in the Background: pushRegistry:didReceiveIncomingPushWithPayload: is called. RNCallKeep.reportNewIncomingCall is triggered on the Main Thread. The app is terminated by the system before the CallKit UI is fully established or before the completion() closure is executed. Current Implementation (AppDelegate.swift) func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) { let payloadDict = payload.dictionaryPayload let callerName = payloadDict["callerName"] as? String ?? "Unknown Caller" let callUUIDString = payloadDict["uuid"] as? String ?? UUID().uuidString let userGUID = payloadDict["guid"] as? String ?? "0" RNCallKeep.reportNewIncomingCall( callUUIDString, handle: userGUID, handleType: "generic", hasVideo: false, localizedCallerName: callerName, supportsHolding: true, supportsDTMF: true, supportsGrouping: true, supportsUngrouping: true, fromPushKit: true, payload: ["userGuid": userGUID], withCompletionHandler: { } ) RNVoipPushNotificationManager.didReceiveIncomingPush(with: payload, forType: type.rawValue) completion() } Logs Exception Type: EXC_CRASH (SIGKILL) Exception Note: EXC_CORPSE_NOTIFY Termination Reason: TCC 1 | [CoreFoundation] Killing app because it never posted an incoming call to the system after receiving a PushKit VoIP push. Observed Behavior Killed State: Works perfectly. Foreground State: Works perfectly. Background State: The phone may vibrate once, but the app process is killed before the CallKit UI appears. Questions/Suspected Causes Is RNVoipPushNotificationManager.addCompletionHandler causing a delay in the background run loop that triggers the Watchdog? Should completion() be called immediately in Swift for the Background state, rather than waiting for VoipPushNotification.onVoipNotificationCompleted in JS? Is there a known issue with RNCallKeep not being able to present the UI while the app is in a suspended background state?
0
0
9
2h
Timed-Wait for main thread
The scenario is, in a macOS app (primarly), main thread needs to wait for some time for a certain 'event'. When that event occurs, the main thread is signaled, it gets unblocked and moves on. An example is, during shutdown, a special thread known as shutdown thread waits for all other worker threads to return (thread join operation). When all threads have returned, the shutdown thread signals the main thread, which was waiting on a timer, to continue with the shutdown flow. If shutdown thread signals the main thread before the later's timer expires, it means all threads have returned. If main thread's timer expires first, it means some threads have failed to join (probably stuck in infinite loop due to bug, disk I/O etc.). This post is to understand how main thread can wait for some time for the shutdown thread. There are two ways: a) dispatch_semaphore_t b) pthread conditional variable (pthread_cond_t) and mutex (pthread_mutex_t). Expanding a bit on option (b) using conditional variable and mutex: // This method is invoked on the main thread bool ConditionSignal::TimedWait() noexcept { struct timespec ts; pthread_mutex_t * mutex = (pthread_mutex_t *) (&vPosix.vMutexStorage[0]); pthread_cond_t * cond = (pthread_cond_t *) (&vPosix.vCondVarStorage[0]); // Set the timer to 3 sec. clock_gettime(CLOCK_REALTIME, &ts); ts.tv_sec += 3; pthread_mutex_lock(mutex); LOG("Main thread has acquired the mutex and is waiting!"); int wait_result = pthread_cond_timedwait(cond, mutex, &ts); switch (wait_result) { case 0: LOG("Main thread signaled!"); return true; case ETIMEDOUT: LOG("Main thread's timer expired!"); return false; default: LOG("Error: Unexpected return value from pthread_cond_timedwait: " + std::to_string(wait_result)); break; } return false; } // This method is invoked on shutdown thread after all worker threads have returned. void ConditionSignal::Raise() noexcept { pthread_mutex_t * mutex = (pthread_mutex_t *) (&vPosix.vMutexStorage); pthread_cond_t * cond = (pthread_cond_t *) (&vPosix.vCondVarStorage); pthread_mutex_lock(mutex); LOG("[Shutdown thread]: Signalling main thread..."); pthread_cond_signal(cond); pthread_mutex_unlock(mutex); } Both options allow the main thread to wait for some time (for shutdown thread) and continue execution. However, when using dispatch_semaphore_t, I get the following warning: Thread Performance Checker: Thread running at User-interactive quality-of-service class waiting on a lower QoS thread running at Default quality-of-service class. Investigate ways to avoid priority inversions Whereas, with conditional variables, there are no warnings. I understand the warning - holding the main thread can prevent it from responding to user events, thus causing the app to freeze. And in iOS, the process is killed if main thread takes more than 5 secs to return from applicationWillTerminate(_:) delegate method. But in this scenario, the main thread is on a timed-wait, for some milliseconds i.e., it is guaranteed to not get blocked indefinitely. While this is described for macOS, this functionality is required for all Apple OSes. What is the recommend way?
3
0
71
2h
URL Filter Network Extension
Hello team, I am trying to find out a way to block urls in the chrome browser if it is found in local blocked list cache. I found URL Filter Network very much suitable for my requirement. But I see at multiple places that this solution is only for Enterprise level or MDM or supervised device. So can I run this for normal user ? as my targeting audience would be bank users. One more thing how can I test this in development environment if we need supervised devices and do we need special entitlement ? When trying to run sample project in the simulator then getting below error
9
0
164
2h
macOS VPN apps outside of the App Store
Apple is encouraging VPN apps on macOS to transition to Network Extension APIs, if they haven't done so yet, see: TN3165: Packet Filter is not API WWDC25: Filter and tunnel network traffic with NetworkExtension Using Network Extension is fine for VPN apps that are distributed via the Mac App Store. Users get one pop-up requesting permission to add VPN configurations and that's it. However, VPN apps that are distributed outside of the App Store (using Developer ID) cannot use Network Extension in the same way, such apps need to install a System Extension first (see TN3134: Network Extension provider deployment). Installing a System Extension is a very poor user experience. There is a pop-up informing about a system extension, which the user has to manually enable. The main button is "OK", which only dismisses the pop-up and in such case there is little chance that the user will be able to find the correct place to enable the extension. The other button in that pop-up navigates to the correct screen in System Settings, where the user has to enable a toggle. Then there is a password prompt. Then the user has to close the System Settings and return to the app. This whole dance is not necessary for VPN apps on the Mac App Store, because they work with "app extensions" rather than "system extensions". As a developer of a VPN app that is distributed outside of the App Store, my options are: Implement VPN functionality in an alternative way, without Network Extension. This is discouraged by Apple. Use a System Extension with Network Extension. This is going to discourage my users. I have submitted feedback to Apple: FB19631390. But I wonder, why did Apple create this difference in the first place? Is there a chance that they will either improve the System Extension installation process or even allow "app extensions" outside of the Mac App Store?
6
0
283
2h
WeatherKit Limits and Sharing
I work on an open source app called Meteorologist (https://sourceforge.net/projects/heat-meteo/). One of the sources the users are allowed to use is Apple's WeatherKit. The app is compiled by me and free to download by anybody. My developer account has the free level of WeatherKit so 500,000 calls/month and every once in a while the app actually hits that limit, shutting that weather source/service down for the app. Is there any way to ask users of the app to somehow get their own account (or already have a developer account) and can register their license so it doesn't all bump up against the one (my) "license"? If so, how would that be passed to WeatherKit? The only thought I have is that they would need to compile the code on their own and sign their own copy. Thanks for any and all feedback and thoughts. Ed
2
0
21
3h
How to make postfix to log in /var/log/mail.log
I am running postfix on macOS Sequoia, and need it to log any kind of error to fix them. I found that in this version of macOS, syslogd is configured with the file /etc/asl/com.apple.mail, which contains: # mail facility has its own log file ? [= Facility mail] claim only > /var/log/mail.log mode=0644 format=bsd rotate=seq compress file_max=5M all_max=50M * file /var/log/mail.log which is its install configuration and seems correct. Postfix is started ( by launchd ) and running ( ps ax | grep master ), but on sending errors occur, and nothing is logged. How to make postfix to log in /var/log/mail.log which is the normal way on millions of postfix servers around the world?
1
0
33
3h
How to modify the launchctl config to start Postfix?
On Sequoia, I want to configure my postfix as a server. And for this I have to change the way postfix is started from: /System/Library/LaunchDaemons/com.apple.postfix.master.plist But this file is on the read only / file system. Then I just unloaded this startup, and made a new one in: /Library/LaunchDaemons/com.apple.postfix.master.plist and I was able to start it. But on the next system boot, the system one in /System/Library/LaunchDaemons was started again. How should I cleanly and permanently achieve this server basic modification?
2
0
51
3h
How to monitor heart rate in background without affecting Activity Rings?
I'm developing a watchOS nap app that detects when the user falls asleep by monitoring heart rate changes. == Technical Implementation == HKWorkoutSession (.mindAndBody) for background execution HKAnchoredObjectQuery for real-time heart rate data CoreMotion for movement detection == Battery Considerations == Heart rate monitoring ONLY active when user explicitly starts a session Monitoring continues until user is awakened OR 60-minute limit is reached If no sleep detected within 60 minutes, session auto-ends (user may have abandoned or forgotten to stop) App displays clear UI indicating monitoring is active Typical session: 15-30 minutes, keeping battery usage minimal == The Problem == HKWorkoutSession affects Activity Rings during the session. Users receive "Exercise goal reached" notifications while resting — confusing. == What I've Tried == Not using HKLiveWorkoutBuilder → Activity Rings still affected Using builder but not calling finishWorkout() (per https://developer.apple.com/forums/thread/780220) → Activity Rings still affected WKExtendedRuntimeSession (self-care type) (per https://developer.apple.com/forums/thread/721077) → Only ~10 min runtime, need up to 60 min HKObserverQuery + enableBackgroundDelivery (per https://developer.apple.com/forums/thread/779101) → ~4 updates/hour, too slow for real-time detection Audio background session for continuous processing (suggested in https://developer.apple.com/forums/thread/130287) → Concerned about App Store rejection for non-audio app; if official approves this technical route, I can implement in this direction Some online resources mention "Health Monitoring Entitlement" from WWDC 2019 Session 251, but I could not find any official documentation for this entitlement. Apple Developer Support also confirmed they cannot locate it? == My Question == Is there any supported way to: Monitor heart rate in background for up to 60 minutes WITHOUT affecting Activity Rings or creating workout records? If this requires a special entitlement or API access, please advise on the application process. Or allow me to submit a code-level support request. Any guidance would be greatly appreciated. Thank you!
1
0
254
4h
My EndpointSecurity Client process is kicked by OS on Mac sleep/wake cycle
Hi, I develop an ES client applying rule-engine evaluating ES events (mostly File-system events). It is a bit non-standard not being deployed as a System-Extension, but rather as a global daemon. On some Macs, I sometimes see "crash reports" for the ES process, all sharing Termination Reason: Namespace ENDPOINTSECURITY, Code 2 EndpointSecurity client terminated because it failed to respond to a message before its deadline All of these happen not while normal Mac usage, but rather right at Mac wakeup time after sleep. My guess is, some ES_AUTH events (with deadline) arrive when Mac goes to sleep, and somehow my high-priority dispatch_queue handling them is "put to sleep" mid processing them, so when the Mac wakes up - event handling continues long after the deadline passed, and MacOS decides to kick the process. Questions: What is the recommended behavior with ES vs Sleep/Wake cycles? (we're not an antivirus, and we don't care much to clear events or go "blind" for such time) Can I specify somewhere in the info.plist of my bundle (this is built like an App) that my process should't be put to sleep, or that the OS should sleep it only when it becomes idle, or some other way tells the OS it is "ready for sleep" ? If not -- How do I observe the scenario so I can suspend my event handling IN TIME and resume on wake? Thanks!
0
0
7
4h
Can NWConnection.receive(minimumIncompleteLength:maximumLength:) return nil data for UDP while connection remains .ready?
I’m using Network Framework with UDP and calling: connection.receive(minimumIncompleteLength: 1, maximumLength: 1500) { data, context, isComplete, error in ... // Some Logic } Is it possible for this completion handler to be called with data==nil if I haven't received any kind of error, i.e., error==nil and the connection is still in the .ready state?
2
0
56
4h
Extended Runtime API - Health Monitoring
In the WWDC 2019 session "Extended Runtime for WatchOS apps" the video talks about an entitlement being required to use the HR sensor judiciously in the background. It provides a link to request the entitlement which no longer works: http://developer.apple.com/contect/request/health-monitoring The session video is also quite hard to find these days. Does anyone know why this is the case? Is the API and entitlement still available? Is there a supported way to run, even periodically, in the background on the Watch app (ignoring the background observer route which is known to be unreliable) and access existing HR sensor data
0
0
3
4h
Transaction.updates sending me duplicated transactions after marking finished()
Hey y'all, I'm reaching out because of an observed issue that I am experience both in sandbox and in production environments. This issue does not occur when using the Local StoreKit configurations. For context, my app only implements auto-renewing subscriptions. I'm trying to track with my own analytics every time a successful purchase is made, whether in the app or externally through Subscription Settings. I'm seeming too many events for just one purchase. My app is observing Transaction.updates. When I make a purchase with Product.purchase(_:), I successfully handle the purchase result. After a few seconds, I receive 2-3 new transactions in my Transaction.updates, even though I already handled and finished the Purchase result. The transactions seem to have the same transactionId, and values such as revocationDate, expirationDate, and isUpgraded don't seem to change between any of them. For purchases made outside the app, I get the same issue. Transaction gets handled in updates several times. Note that this is not an issue if a subscription renews. I use `Transaction.reason
1
0
34
4h
CloudKit, CoreData and Swift 6 for sharing between users
I have started from here: Apple's guide on the sharing core data objects between iCloud users and I have created a sample project that has Collections and Items. Everything works great while I stay on Swift 5, like with the initial project. I would like to migrate to Swift 6 (Default Actor Isolaton @MainActor, Approachable Concurrency: Yes) on the project and I am stuck at extension CDCollection: Transferable { ... }. When compiling with Swift 5, there is a warning: Conformance of 'NSManagedObject' to 'Sendable' is unavailable in iOS; this is an error in the Swift 6 language mode. After resolving almost all compile-time warnings I'm left with: Conformance of 'CDCollection' to protocol 'Transferable' crosses into main actor-isolated code and can cause data races. Which I don't think will work, because of the warning shown above. It can be worked around like: nonisolated extension CDCollection: Transferable, @unchecked Sendable Then there are errors: let persistentContainer = PersistenceController.shared.persistentContainer Main actor-isolated static property 'shared' can not be referenced from a nonisolated context. I've created the following class to have a Sendable object: struct CDCollectionTransferable: Transferable { var objectID: NSManagedObjectID var persistentContainer: NSPersistentCloudKitContainer public static var transferRepresentation: some TransferRepresentation { CKShareTransferRepresentation { collectionToExport in let persistentContainer = collectionToExport.persistentContainer let ckContainer = CloudKitProvider.container var collectionShare: CKShare? if let shareSet = try? persistentContainer.fetchShares( matching: [collectionToExport.objectID]), let (_, share) = shareSet.first { collectionShare = share } /** Return the existing share if the collection already has a share. */ if let share = collectionShare { return .existing(share, container: ckContainer) } /** Otherwise, create a new share for the collection and return it. Use uriRepresentation of the object in the Sendable closure. */ let collectionURI = collectionToExport.objectID .uriRepresentation() return .prepareShare(container: ckContainer) { let collection = await persistentContainer.viewContext .perform { let coordinator = persistentContainer.viewContext .persistentStoreCoordinator guard let objectID = coordinator?.managedObjectID( forURIRepresentation: collectionURI ) else { fatalError( "Failed to return the managed objectID for: \(collectionURI)." ) } return persistentContainer.viewContext.object( with: objectID ) } let (_, share, _) = try await persistentContainer.share( [collection], to: nil ) return share } } } } And I'm able to compile and run the app with this change: let transferable = CDCollectionTransferable( objectID: collection.objectID, persistentContainer: PersistenceController.shared .persistentContainer ) ToolbarItem { ShareLink( item: transferable, preview: SharePreview("Share \(collection.name)!") ) { MenuButtonLabel( title: "New Share", systemImage: "square.and.arrow.up" ) } } The app crashes when launched with libdispatch.dylib`_dispatch_assert_queue_fail: 0x1052c6ea4 <+0>: sub sp, sp, #0x50 0x1052c6ea8 <+4>: stp x20, x19, [sp, #0x30] 0x1052c6eac <+8>: stp x29, x30, [sp, #0x40] 0x1052c6eb0 <+12>: add x29, sp, #0x40 0x1052c6eb4 <+16>: adrp x8, 63 0x1052c6eb8 <+20>: add x8, x8, #0xa0c ; "not " 0x1052c6ebc <+24>: adrp x9, 62 0x1052c6ec0 <+28>: add x9, x9, #0x1e5 ; "" 0x1052c6ec4 <+32>: stur xzr, [x29, #-0x18] 0x1052c6ec8 <+36>: cmp w1, #0x0 0x1052c6ecc <+40>: csel x8, x9, x8, ne 0x1052c6ed0 <+44>: ldr x10, [x0, #0x48] 0x1052c6ed4 <+48>: cmp x10, #0x0 0x1052c6ed8 <+52>: csel x9, x9, x10, eq 0x1052c6edc <+56>: stp x9, x0, [sp, #0x10] 0x1052c6ee0 <+60>: adrp x9, 63 0x1052c6ee4 <+64>: add x9, x9, #0x9db ; "BUG IN CLIENT OF LIBDISPATCH: Assertion failed: " 0x1052c6ee8 <+68>: stp x9, x8, [sp] 0x1052c6eec <+72>: adrp x1, 63 0x1052c6ef0 <+76>: add x1, x1, #0x9a6 ; "%sBlock was %sexpected to execute on queue [%s (%p)]" 0x1052c6ef4 <+80>: sub x0, x29, #0x18 0x1052c6ef8 <+84>: bl 0x105301b18 ; symbol stub for: asprintf 0x1052c6efc <+88>: ldur x19, [x29, #-0x18] 0x1052c6f00 <+92>: str x19, [sp] 0x1052c6f04 <+96>: adrp x0, 63 0x1052c6f08 <+100>: add x0, x0, #0xa11 ; "%s" 0x1052c6f0c <+104>: bl 0x1052f9ef8 ; _dispatch_log 0x1052c6f10 <+108>: adrp x8, 95 0x1052c6f14 <+112>: str x19, [x8, #0x1f0] -> 0x1052c6f18 <+116>: brk #0x1 The app still crashes when I comment this code, and all Core Data related warnings. I'm quite stuck now as I want to use Swift 6. Has anyone figured CloudKit, CoreData and Swift 6 for sharing between users?
1
0
31
5h
Unable to create record in public cloudkit database for missing/not authenticated iCloud user
While testing record creation in public CloudKit database for authenticated user I am able to do so without any issues. But for devices missing iCloud account or authentication expired I am seeing the below error: ▿ <CKError 0x97a959200: "Permission Failure" (10/2007); server message = "CREATE operation not permitted"; op = 67331DE3AF3DD666; uuid = 1F3ACD4F-A799-4CD4-ADF0-EDE9E12F2DCB; container ID = "***"> _nsError : <CKError 0x97a959200: "Permission Failure" (10/2007); server message = "CREATE operation not permitted"; op = 67331DE3AF3DD666; uuid = 1F3ACD4F-A799-4CD4-ADF0-EDE9E12F2DCB; container ID = "***"> I am unable to add create/write permission to _world security role in dashboard. Is this something not supported by Cloudkit? Only authenticated iCloud users will be able to create and write data to public database as well?
1
0
18
5h
Mac Assigning NSManagedObject to NSPersistentStore
Hello, I have a iOS app I was looking at porting to Mac. I'm having an issue with both the Mac (Designed for iPad) and Mac Catalyst Destinations. I can't test Mac due to too many build issues. I'm trying to assign a new NSManagedObject into a NSPersistentStore. let object = MyObject(context: context) context.assign(object, to: nsPersistentStore) This works fine for iOS/iOS Simulator/iPhone/iPad. But on the Mac it's crashing with FAULT: NSInvalidArgumentException: Can't assign an object to a store that does not contain the object's entity.; { Thread 1: "Can't assign an object to a store that does not contain the object's entity."
0
0
16
20h
Continuous "Tag mismatch" (AES-GCM) decrypting Apple Pay Web token - Suspected KDF / PartyV environment issue
I'm implementing payment processing with Apple Pay on the web, but I've been stuck right at the final step of the flow: decrypting the payment data sent by Apple. Here is a summary of my implementation: The backend language is Java. The frontend portal requests the session and performs the payment using the endpoints exposed by the backend. I created .p12 files from the .cer files returned by the Apple Developer portal for both certificates (Merchant Identity and Payment Processing) and I'm using them in my backend. The merchant validation works perfectly; the user is able to request a session and proceed to the payment sheet. However, when the frontend sends the encrypted token back to my sale endpoint, the problem begins. My code consistently fails when trying to decrypt the data (inside the paymentData node) throwing a javax.crypto.AEADBadTagException: Tag mismatch! I can confirm that the certificate used by Apple to encrypt the payment data is the correct one. The hash received from the PKPaymentToken (header.publicKeyHash) object exactly matches the hash generated manually on my side from my .p12 file. In the decryption process, I'm using Bouncy Castle only to calculate the Elliptic Curve (ECC) shared secret. For the final AES-GCM decryption, I am using Java's native provider since I already have the bytes of the shared secret calculated. (Originally, I was doing it entirely with BC, but it failed with the exact same error). We have exhaustively verified our cryptographic implementation: We successfully reconstruct the ephemeralPublicKey and compute the ECDH Shared Secret using our Payment Processing Certificate's private key (prime256v1). We perform the Key Derivation Function (KDF) using id-aes256-GCM, PartyU as Apple, and counter 00000001. For PartyV, we have tried calculating the SHA-256 hash of our exact Merchant ID string. We also extracted the exact ASN.1 hex payload from the certificate's extension OID 1.2.840.113635.100.6.32 and used it as PartyV. We have tried generating brand new CSRs and Processing Certificates via OpenSSL directly from the terminal. Despite having the correct ECDH shared secret (and confirming Apple used our public key via the hash), the AES tag validation always fails.et, the AES tag validation always fails. Given that the math seems correct and the public key hashes match, could there be an environment mismatch (Sandbox vs. Production) or a domain validation issue causing Apple to encrypt the payload with a dummy PartyV or scramble the data altogether? Any guidance on this behavior or the exact PartyV expected in this scenario would be highly appreciated.
0
0
23
20h