On March 21, 2013, Apple added an announcement to notify all iOS developers that “using UDID inside the app would no longer be approved by Apple App Store starting from May 1st, 2013”.
Starting May 1, the App Store will no longer accept new apps or app updates that access UDIDs. Please update your apps and servers to associate users with the Vendor or Advertising identifiers introduced in iOS 6.
Reference: Announcement Link
As an alternative, Apple makes a suggestion of using the IDFV (Identifier for Vender) or ADID (Advertising Identifier). It is not an “Mandatory” solution for replacing the using of UDID, in other words, we could still use some 3rd-party solutions such as openUDID or SecureUDID.
However, we would foresee it may become another official standard of iOS in the very near future. Let alone openUDID and secureUDID – the two most popular alternative solutions have announced their retirement.
Now, being an alternative to the FULLY retired UDID, Apple provides not one but two solutions (IDFV and ADID), and we can still use the 3rd-party ones (openUDID, SecureUDID, etc). Apparently, using Apple’s solutions would be the best and safest just because it is from Apple. However, questions may still exists:
- Can IDFV or ADID fully replace other solutions?
- For IDFV and ADID, which one should be used and when is it to choose one over the other?
In order to answer these questions, we may need to go through the entire story of UDID on iOS and find out the pros and cons for each alternative. The purpose here is not to make a conclusion on “which one is the best”, but instead, we just want to make a fully understand before we actually go for a solution.
Table of Contents
Identify an iOS device
The following table outlines all available (or former available) solutions that are used to “identify an iOS device“.
|Methods (Provider)||Summary||Usage & Annotation|
|UDID (Apple)||-. The legacy method for getting the “REAL” unique identifier of any iOS device. -. Deprecated since iOS 5, and banned in iOS 7.||-. By calling the method: NSString *udid = [[UIDevice currentDevice] uniqueIdentifier];-. In iOS 7, calling the method will return a 40-character string starting with FFFFFFFF, followed by the hex value of getting IDFV: -[UIDevice identifierForVendor]-. String example: bb4d786633053a0b9c0da20d54ea7e38e8776da4|
|CFUUID (Apple)||-. CFUUID has been around since iOS 2.0, which is a part of CoreFoundation package.||-. Use the method: CFUUIDCreate. -. Not persist. Every time, calling the method will generate a different string. -. String example:68753A44-4D6F-1226-9C60-0050E4C00067|
|NSUUID (Apple)||-. Introduced sine iOS 6. -. Similar to CFUUID, but a ObjC interface.||-. Call the method: NSString *uuid = [[NSUUID UUID] UUIDString];-. Not persist. Every time, calling the method will generate a different string. -. String example:68753A44-4D6F-1226-9C60-0050E4C00067|
|MAC+MD5 (Unix Syscall)||-. Use Unix Syscall to get the “REAL” MAC address of the device, and then use MD5 to generate an string. Since MAC address is unique crossing all devices, the output string is also unique. -. Banned in iOS 7.||-. A very concrete method to get a unique identifier for the device, since it never changes since the device being built out. -. In IOS 7, any attempt to getting the MAC address will return a same static value for ALL devices which are running iOS 7.|
|openUDID (3rd-Pary)||-. Generate a unique string based on several sources.-. Store the string to the system’s “Pasteboards”, which can be accessible for ALL apps. -. Also store the string in each app’s sandbox (by NSUserDefault) to increase the persistency. -. Persistency changed in iOS 7.||-. The most popular alternative solution since iOS 5. -. Call the method: NSString *openUDID = [OpenUDID value];-. In iOS 7, the “Pasteboards” is on longer being shared within ALL apps. Instead, each “app vender” has individual “Pasteboards”.-. String example:68753A44-4D6F-1226-9C60-0050E4C00067|
|SecureUDID (3rd-Pary)||-. Generate a unique string based on CFUUID. -. Store the string to the system’s “Pasteboards”, which can be accessible for ALL apps. -. Persistency changed in iOS 7.||-. In iOS 7, the “Pasteboards” is on longer being shared within ALL apps. Instead, each “app vender” has individual “Pasteboards”.|
|Identifier for Vendor (IDFV) (Apple)||-. Introduced since IOS 6.-. Return an object of NSUUID.||-. Call the method: NSString *idfv = [[[UIDevice currentDevice] identifierForVendor] UUIDString]; -. The string is the same for apps that come from the same vender on the same device. -. Once all the apps from the same vender are uninstalled and then re-installed, the value will be reset. -. String example:599F9C00-92DC-4B5C-9464-7971F01F8370|
|Advertiser Identifier (ADID) (Apple)||-. Introduced since IOS 6.-. Return an object of NSUUID.||-. Call the method: NSString *adId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];-. Persisted by the system, accessible by ALL apps. -. Can be reset by several “User” operations. -. String example:1E2DFA89-496A-47FD-9941-DF1FC4E6484A|
Identifier for Vendor (IDFV)
The unique string generated by this method is “Vender and Device Specific“, which means the value only persists within the apps that come from the same vender on the same device. In other words, a different value will be returned for apps on the same devices that come from a different vender, and for apps on different devices regardless of vender.
A “vender” is defined by the FIRST TWO parts of the reverse DNS formatted CFBundleIdentifier. For example, the bundle identifiers “com.example.app1” and “com.example.app2” will come from the same vender, while “com.anotherexample.app3” will be the different.
Advertiser Identifier (ADID)
The value generated by this method can be persisted across the whole system, which means any app on the same device will get the same value. However, the persistency of this value can be easily affected by many “user” operations:
- System Reset – path: Settings.app -> General -> Reset -> Reset All Content and Settings
- Reset ADID – pat: Settings.app -> General -> About -> Advertising -> Reset Advertising Identifier (iOS 7: Settings.app -> Privacy -> Advertising -> Reset Advertising Identifier)
When openUDID is released, it is designed for providing a UDID-like “device wide” unique identifier, which means that this identifier will be shared across all apps that use openUDID method.
Here are some technical highlights of openUDID:
- A 160-bit ID – the first 128 bits are a MD5 on the result of [NSProcessInfo -globallyUniqueString]; the latter 32 bits are from the output of arc4random().
- Use UIPasteboard to store the ID.
- In UIPasteboard, it uses 100 custom pasteboard items, named “org.OpenUDID.slot.N”, where N is [0, 99].
- Each app picks one of the 100 slots (save the choice locally in NSUserDefaults), and saves the current openUDID inside it. If the app does not have from its local preference, it will go through all 100 slots and choose the UDID that is represented most frequently.
- If all slots are empty, it will generate a new openUDID.
Although SecureUDID uses the similar technique as openUDID to store the identifier and share it within apps on the device – UIPasteboard, it is designed with some security related goals – where is also the name from.
Instead of sharing the ID across all apps on the device, it is only accessible for the apps that share the same “secret” – a crypto key used to encrypt the ID before storing back to UIPasteboard.
Here are some technical highlights of SecureUDID:
- Use UIPasteboard to store the ID – 64 slots (“org.secureudid-N”, where N is [0, 63]) to store the ID as well as some metadata.
- A 128-bit ID, generated by CFUUIDCreate().
- The “secret” is a SHA1 hash of the concatenation of two values – a domain string and a private key.
Limitations of using UIPasteboard based UDID Frameworks
Although openUDID, SecureUDID or any other UIPasteboard based UDID Frameworks
can provide certain level of persistency in the device-specific ID, this persistency cannot be guaranteed in all situations. It is technically possible for two different devices to generate the same ID, and for the same device to generate different IDs.
Here are some typical situations that may affect the uniqueness / persistency of the ID:
- The user / other app opts-out of the system (explicitly or implicitly).
- Once device is backed up and then restored to another device.
- The data stored in UIPasteboard is removed / corrupted by user intervention, UIPasteboard data purge, or by a malicious application.
- All apps that use the UDID framework are uninstalled from a device, right after a UIPasteboard data purge.
Changes since iOS 7
Although using the “REAL” device UDID has been deprecated since iOS 5, the actual API is still working correctly. Apple only does a “policy enforcement” on the apps that need to be available on the Apple App Store.
However when iOS 7 comes, it has been changed, not only for the device UDID retrieval but also for the using of MAC address as well as all UIPasteboard based UDID Frameworks.
- The API for getting device UDID becomes malfunctioning – it returns a 40-character string starting with FFFFFFFF, followed by the hex value of getting IDFV: [UIDevice identifierForVendor] instead of a real device UDID.
- The method for getting MAC address returns a same value for ALL devices that run iOS 7.
- Pasteboards will be ONLY shared within the apps that come from the same vender, not ALL apps on the device.
Based on the third change, it becomes impossible for using UIPasteboard based UDID Frameworks (openUDID or seCureUDID) to generate a unique ID that represents the device.
However, you can still use them to create the ID to distinguish the different user of the same app running on the different devices because of its uniqueness / persistency. But, the point is, “IDFV” can also achieve that. Then, is there any reason of still using these 3rd-party solutions, without choosing an Apple one?
Comparison and Conclusion
The following tables provide a clear view on the iOS availability and persistency of these methods:
|Methods||iOS 2||iOS 3||iOS 4||iOS 5||iOS 6||iOS 7|
|Methods||Launch App||Return from Background||Reset Advertising Identifier ||Re-install App ||Reboot System ||Reset System ||Upgrade System||Re-install System|
Here are the legends & annotations:
- √ – YES
- X – NO
- ? – TBD
 – Reset Advertising Identifier | Settings.app -> General -> About -> Advertising -> Reset Advertising Identifier (iOS 7: Settings.app -> Privacy -> Advertising -> Reset Advertising Identifier).
 – Re-install App | Remove all apps that come from the same vender before the re-installation.
 – Reboot System | Hold on “Home” and “Power” buttons.
 – Reset System | Settings.app -> General -> Reset -> Reset All Content and Settings
For the actions of “System Upgrade” and “System Re-install”, currently we still have not found a concrete way to test on the real devices. So far, it is only under a guess. Especially, the “System Upgrade” can be done either on the air or via iTunes, which may have a different consequence.