Eight Methods of Obtaining Unique Identifier of Equipment by iOS

  • 2021-07-06 11:55:05
  • OfStack

8 kinds of iOS to obtain equipment only 1 identification method, I hope it is useful to everyone.

UDID

UDID (Unique Device Identifier), the only identification code of iOS device is a 40-bit 106-ary sequence (UDID of escaped device can be changed by some tools), and mobile network can use UDID to identify mobile device.

Many developers associate UDID with the user's real name, password, address and other data. Web snoopers will collect these data from multiple applications, and then get a lot of private data of this person. At the same time, most applications do transmit UDID and private information frequently. In order to avoid class actions, Apple finally decided to abolish this 1 practice in iOS 5.

Now the application trying to obtain UDID has been banned and is not allowed to go on shelves.

MAC Address

The MAC (Medium/Media Access Control) address, used to represent the identifier of every site on the Internet, is a 6-byte (48-bit) 106-ary sequence. The first three bytes are "Organizationally Unique Identifier" assigned by RA, the registration authority of IEEE, to different manufacturers, and the last three bytes are assigned by each manufacturer to the adapter interface produced by itself, which is called extension identifier.

The MAC address is used to distinguish the uniqueness of devices on the network. All devices accessing the network have an MAC address, and they are definitely uniqueness. There may be multiple MAC addresses on an iPhone, including WIFI, SIM, etc., but there is one WIFI on iTouch and iPad, so just get the MAC address of WIFI. 1 will take MD5 (MAC address + bundleID) to get the only one identity.

However, MAC address and UDID 1 have privacy problems. After iOS 7, all devices requesting MAC address will return a fixed value, and this method will not break itself.

OpenUDID

After UDID was abandoned, developers needed to find an alternative UDID, which was not controlled by Apple. Therefore, OpenUDID became the most widely used open source UDID alternative at that time. OpenUDID uses a very clever way to store identifiers between different programs: a special name is used in the sticker board to store identifiers, which can be obtained by other applications.

After iOS 7, Apple restricted the pasting board, which made it impossible to share one OpenUDID between applications on the same device.

UUID + self-storage

UUID (Universally Unique IDentifier), a universal only 1 identifier, is a 32-bit 106-ary sequence connected by small horizontal lines: 8-4-4-12, which is obtained by NSUUID (after iOS 6) [NSUUID UUID]. UUIDString or CFUUID (after iOS 2) CFBridgingRelease (ES90kCFAllocatorDefault, CFUUIDCreate (kCFAllocatorDefault)).

Push token + bundleID

Pushing token ensures that the device is only 1, but it can only work if there is a network. This method does not depend on the device itself, but depends on apple push, and apple push sometimes suffers from ventilation.

IDFA

IDFA-identifierForIdentifier (advertisement identifier), all APP on the same device will get the same value, which is specially set by Apple for each advertisement provider to track users. Although iPhone is traceable by default, and most users are unaware of this setting, users can reset the value of this ID in Settings-Privacy-Ad Tracking, or limit the use of this ID, so the value may not be obtained.

IDFV

IDFV-identifierForVendor (Vendor identifier), obtained by [UIDevice currentDevice]. identifierForVendor. UUIDString. It is matched by the first two parts of the inversion of bundleID. If the same is the same Vendor, for example, for com. mayan. app_1 and com. mayan. app_2, it belongs to the same Vendor and shares the same IDFV. Different from IDFA, the value 1 of IDFV can be obtained, so it is very suitable for identifying users as the main ID for internal user behavior analysis. However, if the user removes the APP, the IDFV value is reset and the APP is installed again, and the IDFV value is different from the previous one.

IDFV + keychain

Through the analysis of the above methods of storing only 1 logo, each has its advantages and disadvantages. Many methods are prohibited by Apple or have too many loopholes, which are less and less used by developers. Now Apple mainly pushes IDFA and IDFV, which are external and internal respectively, but IDFV will change when APP is reinstalled, so my method is to store it in keychain through IDFV generated for the first time, and get it from keychain every time in the future.


#import <UIKit/UIKit.h>
@interface MYVendorToll : NSObject
+ (NSString *)getIDFV;
@end


#import "MYVendorToll.h"
#import "MYKeyChainTool.h"

@implementation MYVendorToll


+ (NSString *)getIDFV
{
 NSString *IDFV = (NSString *)[MYKeyChainTool load:@"IDFV"];

 if ([IDFV isEqualToString:@""] || !IDFV) {

  IDFV = [UIDevice currentDevice].identifierForVendor.UUIDString;
  [MYKeyChainTool save:@"IDFV" data:IDFV];
 }

 return IDFV;
}

@end


#import <Foundation/Foundation.h>

@interface MYKeyChainTool : NSObject


+ (void)save:(NSString *)service data:(id)data;
+ (id)load:(NSString *)service;
+ (void)deleteKeyData:(NSString *)service;

@end


#import "MYKeyChainTool.h"

@implementation MYKeyChainTool


+ (NSMutableDictionary *)getKeychainQuery:(NSString *)service {
 return [NSMutableDictionary dictionaryWithObjectsAndKeys:
   (id)kSecClassGenericPassword,(id)kSecClass,
   service, (id)kSecAttrService,
   service, (id)kSecAttrAccount,
   (id)kSecAttrAccessibleAfterFirstUnlock,(id)kSecAttrAccessible,
   nil];
}

+ (void)save:(NSString *)service data:(id)data {
 //Get search dictionary
 NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
 //Delete old item before add new item
 SecItemDelete((CFDictionaryRef)keychainQuery);
 //Add new object to search dictionary(Attention:the data format)
 [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
 //Add item to keychain with the search dictionary
 SecItemAdd((CFDictionaryRef)keychainQuery, NULL);
}

+ (id)load:(NSString *)service {
 id ret = nil;
 NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
 //Configure the search setting
 //Since in our simple case we are expecting only a single attribute to be returned (the password) we can set the attribute kSecReturnData to kCFBooleanTrue
 [keychainQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
 [keychainQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
 CFDataRef keyData = NULL;
 if (SecItemCopyMatching((CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {
  @try {
   ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];
  } @catch (NSException *e) {
   NSLog(@"Unarchive of %@ failed: %@", service, e);
  } @finally {
  }
 }
 if (keyData)
  CFRelease(keyData);
 return ret;
}

+ (void)deleteKeyData:(NSString *)service {
 NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
 SecItemDelete((CFDictionaryRef)keychainQuery);
}

@end


Related articles: