views:

1506

answers:

5

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.

A: 

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)

Shay Erlichmen
what if there were a central DB of valid IDS?
Roger Nolan
Probably there is, but apple would never let you get near it. I don't know of any (major) company there ever did let you browse their serial numbers.
Shay Erlichmen
This statement is based on a misunderstanding of how modern crypto works. Modern crypto is based on the idea that there are functions which are easy to compute but are hard to invert. For example, in public key crypto, anyone can encrypt a message, but only the recipient can decrypt it. If a only a small fraction of all UDID's are valid, then it would be time-consuming to produce fake ones.
Tyler
@Tyler, your right, answer updated. 10x.
Shay Erlichmen
A: 

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.

Martin Gordon
I think bpapa is trying to stop non-iphone clients written by hostile users accessing his service.
Roger Nolan
He might want to try generating some kind of signature to ensure the message hasn't been faked. For example, see Flickr's signing mechanism (#8 on this page: http://flickr.com/services/api/auth.spec.html)
Martin Gordon
+4  A: 

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.

baalexander
If there's a secret stored in the application binary, it can be gotten and then shared. The only way to get a secret safely would be at initial launch, call a Web service over SSL, get a key, and store it in the phone's Keychain. But the minute you do that, someone else can imitate your app and get the key also.
bbrown
all security is a cost benefit trade off. This is better than plaintext which is in turn better than nothing.
Roger Nolan
A: 

You could have them sign up for push notification

anon
A: 

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);
        }
mr_marc