9

Wow... look at all the "panic stories" online this week regarding using an iPhone's UDID.

 [[UIDevice currentDevice] uniqueIdentifier]

What SHOULD we be using instead?

What if the phone is sold to another user... and an app has stored some data on a remote server, based on the phone's UDID?

(Of course, I want to avoid the problems with the app store's "encryption restrictions".)

Patty
  • 109
  • 1
  • 2
  • 2
    I don't know what the stories are this week. And you should turn this into a specific question. What were you planning to use the UDID for? Surely not a full user credential replacement? – marcc Oct 05 '10 at 04:02
  • what are you trying to do? I use a salted md5ed version of the UDID to known from which device data was synced to another device. I think this is okay. I'm not reporting anything to my server to see what people are doing whit my app. The bad thing is not the use of udid, the bad thing are those "spy" functions. Everything those guys are doing whit UDIDs can be achived on another way. – Matthias Bauch Oct 05 '10 at 04:08
  • The UDID is being used to "identify the unique device or user"... to "save and retreive data"... and I'm sure some of it is VERY private info. What should be used instead? Something were a user can't pretend to be another user. All without checking email addresses or user name or passwords. – Patty Oct 05 '10 at 05:28
  • Didn't you have a big problem with md5 (or any) kind of encryption when submitting the app to the store? – Patty Oct 05 '10 at 05:29
  • What are a few of those "done another way" methods? (Without dealing with Apple's ton of paperwork for "using encryption".) – Patty Oct 05 '10 at 05:30
  • I've used MD5 or salted MD5 in 3 different apps and there were no problems with Apple. I think their fear of "using encryption" is only worth mentioning if you are encrypting all your data. – AlexVogel Oct 05 '10 at 09:32
  • MD5 is not an encryption algorithm, by the by. It is a hashing algorithm, the two are different. – Stefan H Jan 12 '11 at 17:01
  • Restricting encryption isn't Apple's idea -- they'd probably prefer not to have to bother. US law prevents companies from exporting products containing certain kinds of encryption. Since the App Store effectively exports software from the US to the rest of the world, the question about encryption is unavoidable. – Caleb Aug 20 '11 at 11:07
  • 1
    You shouldn't have used the UDID for anything in the first place. It's beyond me why Apple made it available to developers in the first place. – Sven Aug 20 '11 at 19:56
  • There are a few good answers provided. I recommend you accept one! – djskinner Jul 13 '12 at 10:52

7 Answers7

3

Why not use the Mac Address and possibly then hash it up.

There is an excellent UIDevice-Extension Category here

    - (NSString *) macaddress
{
    int                 mib[6];
    size_t              len;
    char                *buf;
    unsigned char       *ptr;
    struct if_msghdr    *ifm;
    struct sockaddr_dl  *sdl;

    mib[0] = CTL_NET;
    mib[1] = AF_ROUTE;
    mib[2] = 0;
    mib[3] = AF_LINK;
    mib[4] = NET_RT_IFLIST;

    if ((mib[5] = if_nametoindex("en0")) == 0) {
        printf("Error: if_nametoindex error\n");
        return NULL;
    }

    if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
        printf("Error: sysctl, take 1\n");
        return NULL;
    }

    if ((buf = malloc(len)) == NULL) {
        printf("Could not allocate memory. error!\n");
        return NULL;
    }

    if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
        printf("Error: sysctl, take 2");
        return NULL;
    }

    ifm = (struct if_msghdr *)buf;
    sdl = (struct sockaddr_dl *)(ifm + 1);
    ptr = (unsigned char *)LLADDR(sdl);
    NSString *outstring = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X", 
                           *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)];
    // NSString *outstring = [NSString stringWithFormat:@"%02X%02X%02X%02X%02X%02X", 
    //                       *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)];
    free(buf);

    return outstring;
}

You could possibly hash this with the model?

Lee Armstrong
  • 11,420
  • 15
  • 74
  • 122
  • Maybe I'm misunderstanding the question, or your answer, but this seems to be the *opposite* of what is desired -- which is an ID that can represent another user that is *not* tied to that device (and therefore sold along with the phone even if wiped, etc.). – Nicole Jul 19 '12 at 22:13
  • He did ask for something to replace the UDID which was tied to the device! – Lee Armstrong Jul 20 '12 at 08:46
  • I don't see that in the question anywhere. What I see is a question for a unique identifier, and then a statement which I interpret to be saying the OP *does not* want the ID to be transferred when the phone is sold. – Nicole Jul 20 '12 at 16:30
2

As I asked this morning in this post, there are some alternative :

1- first, as Apple recommands, identify per install instead of indentifying per device. Therefore, you can use CFUUIDRef. Example :

NSString *uuid = nil;
CFUUIDRef theUUID = CFUUIDCreate(kCFAllocatorDefault);
if (theUUID) {
  uuid = NSMakeCollectable(CFUUIDCreateString(kCFAllocatorDefault, theUUID));
  [uuid autorelease];
  CFRelease(theUUID);
}

2- If you care about a worldwide unique identifier, so you could store this identifier on iCloud.

3- At last, if you really need an identifier that remains after app re-install (that not occurs so frequently), you can use Keychains (Apple's keychain doc). But will apple team like it ?

Community
  • 1
  • 1
Martin
  • 11,881
  • 6
  • 64
  • 110
1

Like this:

@interface UIDevice (UIDeviceAppIdentifier)
@property (readonly) NSString *deviceApplicationIdentifier;
@end

@implementation UIDevice (UIDeviceAppIdentifier)
- (NSString *) deviceApplicationIdentifier
{ 
  static NSString     *name    = @"theDeviceApplicationIdentifier";
  NSUserDefaults  *defaults = [NSUserDefaults standardUserDefaults];  
  NSString              *value     = [defaults objectForKey: name];

  if (!value)
    {
      value = (NSString *) CFUUIDCreateString (NULL, CFUUIDCreate(NULL));    
      [defaults setObject: value forKey: name];
      [defaults synchronize];
  }
  return value;
}
@end

the iOS documentation more or less describes use of CFUUIDCreate() to create an identifier and suggests using UserDefaults to store it.

GoZoner
  • 67,920
  • 20
  • 95
  • 145
1

UUID is just depreciated and so will be around for a while, Apple have not said much about this depreciation much yet, I would wait until they have more to say about this and maybe the will offer some alternative.

Nathan Day
  • 5,981
  • 2
  • 24
  • 40
0

The recommended way is by using UUID generation, and associate that with something that the user him/herself is willing to provide to the app.

Then, store this data externally, where it could be retrieved again. There are probably other ways to do this easily, but this is the recommended way.

Jesse Armand
  • 1,842
  • 3
  • 17
  • 26
  • The problem with this is that it will not be persistent across re-install of the same app on the same device. That was the purpose of device UUIDs. – gcamp Aug 20 '11 at 13:21
  • Associate it with a given user id. Isn't that the purpose of identification? It should be based on user consent. If it's worked around by using a MAC address and some other combination of it, then that really is no different than using UDID. If they disallow UDID because of some security/privacy concern, then they would also discourage other types of hardware identification. – Jesse Armand Aug 20 '11 at 18:46
0

One solution would be to have the application issue a free in-app purchase.

This purchase would be:

  1. Trackable, with a unique number (purchase) number which would be meaningful only to your app.

  2. Movable, if the person switches devices

  3. Retrievable, if the app is deleted (or the phone is wiped and reloaded) - the In-App purchases can be restored.

Brad
  • 11,262
  • 8
  • 55
  • 74
0

Apple's documentation says:

"Do not use the uniqueIdentifier property. To create a unique identifier specific to your app, you can call the CFUUIDCreate function to create a UUID, and write it to the defaults database using the NSUserDefaults class."

Here's a quick snippet:

CFUUIDRef udid = CFUUIDCreate(NULL);

NSString *udidString = (NSString *) CFUUIDCreateString(NULL, udid);
Alex Zak
  • 1,924
  • 2
  • 18
  • 26
  • Sadly, the returned UUID is not consistent across installations of the app. (i.e. delete the app, reinstall, and you will get a completely different UUID) – lorean Dec 19 '11 at 20:13
  • See my response below that uses UserDefaults to store a UUID upon creation. – GoZoner Apr 05 '12 at 23:58