If I create a form with a date input, I can only send current time and date. But if I change the system time than this will take wrong input. Is there any way to get actual current time and date??
While my earlier approach does work, I think there’s an easier solution. This is based on the Posix clock API. The reason why I didn’t consider this earlier is that this API is a relatively recent addition, being added to the system in the 2016 OS release (macOS 10.12, iOS 10, and friends). See the clock_gettime man page for more background on this API.
The key thing to note here is that CLOCK_MONOTONIC ‘counts’ across sleep, unlikely the original Mach absolute time API. This allows your app to initially establish a trusted base time while the app is online and then determine a current trusted time relative to that.
The nice thing here is that there’s no messing around with other clocks, like gettimeofday, or with kern.boottime, which has always been a bit of a worry [1].
The main drawback continues to be that, if the user restarts their device, you can’t re-establish a trusted time until it comes online.
Oh, and it also raises the question about how to detect whether the device has been restarted. My recommendation is that you use a Posix semaphore for that. For example:
func restartState() -> RestartState {
let sem = sem_open(NAME, O_CREAT | O_EXCL)
if sem == SEM_FAILED {
let err = errno
switch err {
case EEXIST: return .hasNotRestarted
default: return .unknown(error: err)
}
} else {
let ok = sem_close(sem) >= 0
assert(ok)
return .hasRestarted
}
}
enum RestartState {
case hasRestarted
case hasNotRestarted
case unknown(error: CInt)
}
The basic idea is:
-
Create a semaphore with the exclusive flag (
O_EXCL). -
If that works, the semaphore previously didn’t exist so this is the first time you’ve run this code since the device was restarted.
-
If it fails, you’ve run this code previously.
This relies on Posix semaphores being cleaned up on restart, which is a reasonable assumption IMO.
For more background on Posix semaphore, see sem_open man page.
The only tricky part here is the value to use for NAME. Posix semaphores are an IPC mechanism and the iOS sandbox puts strict limits on IPC. To avoid conflicts, set NAME to GGG/NNN, where GGG is an app group ID and NNN is a name of your choosing.
IMPORTANT Posix semaphore names are limited to 31 UTF-8 characters (PSEMNAMLEN) so use a short app group ID and name.
Note This convention was documented in the App Sandbox Design Guide, which is no longer available from Apple )-: [2] I’ve filed a bug (r. 110052019) to get it added to the App Groups Entitlement docs, which discusses Posix semaphores in the abstract but misses out this key detail.
Finally, I want to reiterate some points from my earlier post:
-
The best way to get a secure timestamp is to use the network to get it from some trusted source.
-
The technique described above is only relevant if you need to do this while the network is unavailable.
-
If you end up using this technique, please file an enhancement request explaining why you need a secure timestamp. And I’d appreciate you posting your bug number here, just for the record.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] My main concern here is kern.boottime, because it’s a source of entropy. See the footnote in this post.
[2] You can see an old copy of the Wayback Machine.
<https://web.archive.org/web/20221223145702mp_/https://developer.apple.com/library/archive/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW24>