Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSDate: Get precise time independent of device clock? [duplicate]

Possible Duplicate:
How can I locally detect iPhone clock advancement by a user between app runs?
Is there a way to determine the actual time and date in iOS (not the time of the device)
Is there a clock in iOS that can be used that cannot be changed by the user

Brief

I am working with an auto-renewable subscription-based app. When the app receives the latest receipt from Apple, it stores the expires_date_ms key in NSUserDefaults. Thirty days after that date, the app checks with Apple to see if the subscription is still active. The app can be considered an offline app, but it must connect to the internet once every 30 days in order to check the subscription status. This time comparison will be used to tell the user he/she must connect.

Problem

I am using the code below to compare the current time with the expires_date_ms:

NSTimeInterval expDateMS = [[productInfo objectForKey:@"expires_date_ms"] doubleValue];
NSTimeInterval currentDateMS = ([[NSDate date] timeIntervalSince1970] * 1000);

if (currentDateMS > expDateMS)
    subExpired = YES;

This is fine and works well, but from what I can tell there's a loophole that can be exploited - if the user sets the device's clock back a hour/month/decade, the time comparison will become unreliable because [NSDate date] uses the device's current time (please correct me if I'm wrong).

Question

Is there any way of retrieving a device-independent time in milliseconds? One that can be accurately and reliably measured with no regards to the device clock?

like image 556
lobianco Avatar asked Aug 31 '12 19:08

lobianco


1 Answers

While Kevin and H2CO3 are completely correct, there are other solutions for the purposes of checking a subscription (which I would hope does not need millisecond accuracy....)

First watch UIApplicationSignificantTimeChangeNotification so that you get notifications of when the time changes suddenly. This will even be delivered to you if you were suspended (though I don't believe you will receive it if you were terminated). This gets called when there is a carrier time update, and I believe it is called when there is manual time update (check). It also is called at local midnight and at DST changes. The point is that it's called pretty often when the time suddenly changes.

Keep track of what time it was when you go into the background. Keep track of what time it is when you come back into the foreground. If time moves radically backwards (more than a day or two), kindly suggest that you would like access to the network to check things. Whenever you check-in with your server, it should tell you what time it thinks it is. You can use that to synchronize the system.

You can similarly keep track of your actual runtime. If it gets wildly out of sync with apparent runtime, then again, request access to the network to sync things up.

I'm certain that attackers would be able to sneak 35 days or whatever out of this system rather than 30, but anyone willing to work that hard will just crack your software and take the check out entirely. The focus here is the uncommitted attacker who is just messing with their clock. And that you can catch pretty well.

You should test this carefully, and be very hesitant to accuse the user of anything. Just connecting to your server should always be enough to get a legitimate user working again.

like image 144
Rob Napier Avatar answered Sep 17 '22 13:09

Rob Napier