// UDIDTools.h
// Udidtools////
Created by Lovell on 9/9/16. copyright©2016 Lovell. All rights reserved.
#import <Foundation/Foundation.h>
@interface udidtools:nsobject
* * @brief obtain Unique Device Identity
*
/+ (nsstring*) UDID;
@end
UDIDTOOLS.M//Udidtools////Created by Lovell on 9/9/16. copyright©2016 Lovell.
All rights reserved. #import "UDIDTools.h" #import <Security/Security.h> #include <sys/socket.h> #include <sys/sysctl.h > #include <net/if.h> #include <net/if_dl.h>//Replace the identity with your company ' s domain static con
St Char kkeychainudiditemidentifier[] = "UUID";
static const char kkeychainudidaccessgroup[] = "YOURAPPID.com.cnblogs.smileEvday";
@implementation Udidtools + (nsstring*) UDID {nsstring *udid = [Udidtools getudidfromkeychain];
if (!udid) {nsstring *sysversion = [Uidevice currentdevice].systemversion;
CGFloat Version = [Sysversion Floatvalue];
if (version >= 7.0) {udid = [udidtools _udid_ios7];
else if (version >= 2.0) {udid = [udidtools _UDID_IOS6];
} [Udidtools Settudidtokeychain:udid];
return udid; } * * IOS 6.0 *Use WiFi ' s MAC address */+ (nsstring*) _udid_ios6 {return [Udidtools getmacaddress];} * * iOS 7.0 * Starting from iOS 7, the system always returns the "value 02:00:00:00:00:00 *" When you ask for the MAC ad
Dress on any device. * Use Identifierforvendor + keychain * Make sure UDID consistency atfer app Delete and reinstall */+ (nsstring*) _udid_i
OS7 {return [[Uidevice Currentdevice].identifierforvendor uuidstring];} #pragma mark-#pragma mark Helper method to get MAC address//Http://stackoverflow.com/questions/677530/how-can-i
-programmatically-get-the-mac-address-of-an-iphone + (NSString *) getmacaddress {int mgmtinfobase[6];
char *msgbuffer = NULL;
size_t length;
unsigned char macaddress[6];
struct IF_MSGHDR *interfacemsgstruct;
struct SOCKADDR_DL *socketstruct;
NSString *errorflag = nil; Setup The Management Information Base (MIB) mgmtinfobase[0] = CTL_net; Request network subsystem mgmtinfobase[1] = Af_route;
Routing Table Info Mgmtinfobase[2] = 0; MGMTINFOBASE[3] = Af_link; Request link layer information mgmtinfobase[4] = net_rt_iflist; Request all configured interfaces//with the all configured interfaces requested, get handle index if (mgmtinfob
ASE[5] = If_nametoindex ("En0")) = = 0) Errorflag = @ "If_nametoindex failure"; else {//Get the size of the data available (store in Len) if (Sysctl (Mgmtinfobase, 6, NULL, &len
Gth, NULL, 0) < 0) Errorflag = @ "Sysctl mgmtinfobase failure";
else {//Alloc memory based on above call if ((Msgbuffer = malloc (length)) = = NULL)
Errorflag = @ "Buffer allocation failure"; else {//Get system information, store in buffer if (Sysctl mgmtinfobase, 6,
Msgbuffer, &length, NULL, 0) < 0) Errorflag = @ "Sysctl msgbuffer failure"; }}//Befor going any further ... if (Errorflag!= NULL) {NSLog (@ "Error:%@", Errorfla
g);
if (Msgbuffer) {free (msgbuffer);
return errorflag;
}//Map Msgbuffer to Interface message structure interfacemsgstruct = (struct IF_MSGHDR *) Msgbuffer;
Map to LINK-LEVEL socket structure socketstruct = (struct SOCKADDR_DL *) (interfacemsgstruct + 1); Copy link Layer address data in the socket structure to a array memcpy (&macaddress, Socketstruct->sdl_data + so
Cketstruct->sdl_nlen, 6); Read from char array into a string object, to traditional MAC address format nsstring *macaddressstring = [Nsstri ng stringwithformat:@ "%02x:%02x:%02x:%02x:%02x:%02x", Macaddress[0], macaddress[1], macaddress[2], macAddress[3],
MACADDRESS[4], macaddress[5]];
NSLog (@ "MAC address:%@", macaddressstring); RelEase the buffer memory free (msgbuffer);
return macaddressstring;
#pragma mark-#pragma mark Helper method to make Identityforvendor consistency + (nsstring*) Getudidfromkeychain {
Nsmutabledictionary *dictforquery = [[Nsmutabledictionary alloc] init];
[Dictforquery SetValue: (ID) Ksecclassgenericpassword Forkey: (ID) ksecclass];
Set Attr Description for query [Dictforquery setvalue:[nsstring Stringwithutf8string:kkeychainudiditemidentifier]
Forkey:ksecattrdescription]; Set Attr Identity for query NSData *keychainitemid = [NSData datawithbytes:kkeychainudiditemidentifier length:s
Trlen (Kkeychainudiditemidentifier)];
[Dictforquery setobject:keychainitemid Forkey: (ID) ksecattrgeneric]; The Keychain Access group attribute determines if this item can be shared//amongst multiple apps whose code SIGNI
ng entitlements contain the same Keychain Access group. NSString *accessgroup = [NSString Stringwithutf8string:kkeychainudidaCcessgroup]; if (Accessgroup!= nil) {#if target_iphone_simulator//Ignore The Access group if running on the IPHONE Simu
Lator. Apps that are built for the simulator aren ' t signed, so there ' s no Keychain Access group//for the Simulato R to check.
This means so all apps can be all keychain items when run//on the simulator. If A Secitem contains an Access group attribute, Secitemadd and secitemupdate on the//simulator would retur
n-25243 (Errsecnoaccessforitem).
#else [Dictforquery setobject:accessgroup forkey: (ID) ksecattraccessgroup];
#endif} [Dictforquery SetValue: (ID) kcfbooleantrue Forkey: (ID) ksecmatchcaseinsensitive];
[Dictforquery SetValue: (ID) ksecmatchlimitone Forkey: (ID) ksecmatchlimit];
[Dictforquery SetValue: (ID) kcfbooleantrue Forkey: (ID) ksecreturndata];
Osstatus queryerr = NOERR;
NSData *udidvalue = nil;
NSString *udid = nil; Queryerr = secitemcopymatching((Cfdictionaryref) Dictforquery, (cftyperef*) &udidvalue);
Nsmutabledictionary *dict = nil;
[Dictforquery SetValue: (ID) kcfbooleantrue Forkey: (ID) ksecreturnattributes];
Queryerr = secitemcopymatching (cfdictionaryref) dictforquery, (cftyperef*) &dict); if (Queryerr = = Errsecitemnotfound) {NSLog (@ "Keychain Item:%@ not Found!!!", [NSString Stringwithutf8string:kkey
Chainudiditemidentifier]); else if (Queryerr!= errsecsuccess) {NSLog (@ Keychain Item query Error!!!
Error code:%ld ", Queryerr);
} if (Queryerr = = errsecsuccess) {NSLog (@ "Keychain Item:%@", udidvalue);
if (udidvalue) {udid = [nsstring stringWithUTF8String:udidValue.bytes];
[Udidvalue release];
[Dict release];
[Dictforquery release];
return udid;
} + (BOOL) Settudidtokeychain: (nsstring*) udid {nsmutabledictionary *dictforadd = [[Nsmutabledictionary alloc] init]; [Dictforadd SetValue: (ID)Ksecclassgenericpassword Forkey: (ID) ksecclass];
[Dictforadd setvalue:[nsstring Stringwithutf8string:kkeychainudiditemidentifier] forKey:kSecAttrDescription];
[Dictforadd setvalue:@ "UUID" Forkey: (ID) ksecattrgeneric];
Default attributes for keychain item.
[Dictforadd setobject:@ "" Forkey: (ID) ksecattraccount];
[Dictforadd setobject:@ "" Forkey: (ID) Ksecattrlabel]; The Keychain Access group attribute determines if this item can be shared//amongst multiple apps whose code SIGNI
ng entitlements contain the same Keychain Access group.
NSString *accessgroup = [NSString Stringwithutf8string:kkeychainudidaccessgroup]; if (Accessgroup!= nil) {#if target_iphone_simulator//Ignore The Access group if running on the IPHONE Simu
Lator. Apps that are built for the simulator aren ' t signed, so there ' s no Keychain Access group//for the Simulato R to check. This means-all apps can-all keychain items when run//on THe simulator. If A Secitem contains an Access group attribute, Secitemadd and secitemupdate on the//simulator would retur
n-25243 (Errsecnoaccessforitem).
#else [Dictforadd setobject:accessgroup forkey: (ID) ksecattraccessgroup];
#endif} const char *UDIDSTR = [Udid utf8string];
NSData *keychainitemvalue = [NSData datawithbytes:udidstr Length:strlen (UDIDSTR)];
[Dictforadd setvalue:keychainitemvalue Forkey: (ID) ksecvaluedata];
Osstatus writeerr = NOERR;
if ([Udidtools Getudidfromkeychain]) {//There is item in keychain [Udidtools Updateudidinkeychain:udid];
[Dictforadd release];
return YES;
else {//Add item to Keychain Writeerr = Secitemadd ((cfdictionaryref) Dictforadd, NULL); if (Writeerr!= errsecsuccess) {NSLog (@ "ADD keychain Item Error!!!
Error code:%ld ", Writeerr);
[Dictforadd release];
return NO; } else{NSLog (@ "ADD keychain Item Success!!!");
[Dictforadd release];
return YES;
} [Dictforadd release];
return NO;
} + (BOOL) removeudidfromkeychain {nsmutabledictionary *dicttodelete = [[Nsmutabledictionary alloc] init];
[Dicttodelete SetValue: (ID) Ksecclassgenericpassword Forkey: (ID) ksecclass]; NSData *keychainitemid = [NSData datawithbytes:kkeychainudiditemidentifier Length:strlen (
Kkeychainudiditemidentifier)];
[Dicttodelete setvalue:keychainitemid Forkey: (ID) ksecattrgeneric];
Osstatus deleteerr = NOERR;
Deleteerr = Secitemdelete ((cfdictionaryref) dicttodelete); if (Deleteerr!= errsecsuccess) {NSLog (@ "Delete UUID from keychain Error!!!
Error code:%ld ", Deleteerr);
[Dicttodelete release];
return NO;
else {NSLog (@ "DELETE success!!!");}
[Dicttodelete release];
return YES; } + (BOOL) Updateudidinkeychain: (nsstring*) Newudid {nsmutabledictionary *dictforquery = [[Nsmutabledictionary alloc] init];
[Dictforquery SetValue: (ID) Ksecclassgenericpassword Forkey: (ID) ksecclass]; NSData *keychainitemid = [NSData datawithbytes:kkeychainudiditemidentifier Length:strlen (
Kkeychainudiditemidentifier)];
[Dictforquery setvalue:keychainitemid Forkey: (ID) ksecattrgeneric];
[Dictforquery SetValue: (ID) kcfbooleantrue Forkey: (ID) ksecmatchcaseinsensitive];
[Dictforquery SetValue: (ID) ksecmatchlimitone Forkey: (ID) ksecmatchlimit];
[Dictforquery SetValue: (ID) kcfbooleantrue Forkey: (ID) ksecreturnattributes];
Nsdictionary *queryresult = nil; Secitemcopymatching ((cfdictionaryref) dictforquery