Is there a way to validate an iPhone device ID? I want to be able to accept device IDs submitted from iPhone users via HTTP request and validate that they are tied to a legitimate device.
If theres a way to validate the Id then theres a way to create a real fake id.
I agree with Tyler comment, there is a way to create Ids (easy) and to validate them (also easy) but to create a "fake" id will require scanning the entire keyspace (hard) or stealing the private key that generated the key (that's how TLS in fact works). some my initial comment is not valid.
Never the less, this is not how the Apple device Id works, AFAIK they generate the id from various values id of the hardware (MAC address for example)
If you grab it directly using [[UIDevice currentDevice] uniqueIdentifier]
rather than prompting a user for it then there's no reason why it wouldn't be a legitimate device ID.
To validate a request came from your app, you could send the UUID and a hash, where hash = SHA1(UUID + SECRET_KEY_STORED_IN_APP). Then do the same hash function on the server side and verify they match. You could add a time stamp to as a nonce, where you'd send UUID, timestamp, hash with hash = SHA1(UUID + SECRET_KEY_STORED_IN_APP + TIMESTAMP).
This is certainly not fail proof and has many limitations, but does it make it harder to spoof a UUID.
In response to Martin Gorton, 3rd party libraries cannot trust UIDevice uniqueIdentifier- it is trivial to spoof this using Objective C method swizzling.
Method swizzling swaps two selectors (uniqueIdentifier and spoofUniqueIdentifier) for a class (UIDevice). After the swizzle, subsequent calls to UIDevice uniqueIdentifier will return the spoofed UDID. This can be helpful for testing UDID-keyed libraries that you don't have a valid UDID for.
here is some sample code from http://marccodes.posterous.com/method-swizzling-uidevice-to-spoof-udid :
#import <objc/runtime.h>
// swap a class's instance method selectors, we do this to overload existing methods in category declarations
void swizzleMethodsForClass(Class c, SEL origMethodSel, SEL newMethodSel)
{
NSLog(@"swizzling %@ instance methods: %@ -> %@", NSStringFromClass(c),
NSStringFromSelector(origMethodSel), NSStringFromSelector(newMethodSel));
Method origMethod = class_getInstanceMethod(c, origMethodSel);
Method newMethod = class_getInstanceMethod(c, newMethodSel);
// check if method is inherited from superclass
if(class_addMethod(c, origMethodSel, method_getImplementation(newMethod), method_getTypeEncoding(newMethod)))
class_replaceMethod(c, newMethodSel, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
// exchange un-subclassed method
else
method_exchangeImplementations(origMethod, newMethod);
}
@interface UIDevice (SpoofUDID)
@end
#define UDID_TO_SPOOF @"e0101010d38bde8e6740011211af315301010223"
@implementation UIDevice (SpoofUDID)
// swizzle this instance method for UIDevice class
- (NSString *) spoofUniqueIdentifier
{
static NSString *spoofUDID = UDID_TO_SPOOF;
NSLog(@"spoofing %@ instead of %@", spoofUDID, [[UIDevice currentDevice]
spoofUniqueIdentifier]);
return spoofUDID;
}
@end
// call this from your app delegate
- (void) initUDID
{
NSString *UDID = [[UIDevice currentDevice] uniqueIdentifier];
NSLog(@"this is my old udid: %@", UDID);
swizzleMethodsForClass([UIDevice class], @selector(uniqueIdentifier), @selector(spoofUniqueIdentifier));
NSString *UDID2 = [[UIDevice currentDevice] uniqueIdentifier];
NSLog(@"this is my new udid: %@", UDID2);
}