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.
问题:
回答1:
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)
回答2:
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.
回答3:
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);
}
回答4:
There is no apple documentation or specification which specifies the layout to this string.
AFAIK only Apple knows which UDID are real and which are false.
A educated guess would be they are 40 characters in length, consisting of alphanumeric characters. (a-f0-9)
RegEx pattern:
[a-z0-9]{40}
回答5:
to validate UDID try following regex ^([A-F0-9]{40})$
or you could go here and just paste it.
If you are using [[UIDevice currentDevice].identifierForVendor UUIDString]
(which you should) - then it's just a guid, have a look at this
regex is (^([0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12})$
)
or you could paste it here.
Hope this saves you some time.
回答6:
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.