https://reysion.tistory.com/55


[IOS] UUID 생성 및 키체인 저장



앱에서 기기를 구분해야 할 때 예전에는 UDID를 사용 했었는데 

IOS5부터 기기의 유니크한 값을 이용하지 못하도록 UDID 사용을 제한하고 있다.

그래서 UUID를 사용해야 한다.


UUID는 생성할 때 마다 랜덤하게 변경 되며 기기별로 구분할 수 있는 유니크한(중복되지 않는) 값이다.

보통 앱을 처음 실행할 경우 UUID를 생성해서 값을 앱 내부에 저장하고 서버에도 저장을 해서 서버와 통신하며 해당 기기를 구분하게 된다.

그런데 UUID를 앱 내부에 파일이나 DB(sqlite, core data)... 형태로 저장할 경우 앱을 지웠다가 다시 설치 하면 없어지기 때문에 앱을 지우더라도 저장값을 유지하기 위해서 보통 키체인에 저장해서 불러온다. 

(재설치 하더라도 값을 그대로 가져온다.)


키체인은 보통 암호나 인증서들을 저장하는 용도로 쓰인다.

단, 공장초기화를 하면 키체인에 저장한 값은 지워진다.



[UUID 키체인 저장 방법]

KeyChain API들은 Security.framework에 정의 되어 있는데 C함수로 되어 있고 API를 쓰는 것이 쉽지 않아 애플에서 쉽게 사용할 수 있게 KeychainItemWrapper 예제 클래스를 제공하고 있다.

일단 KeychainItemWrapper를 다운 받고 프로젝트에 추가해야 한다. (download)


    KeychainItemWrapper.h

    KeychainItemWrapper.m


아래는 UUID를 생성해서 KeyChain에 저장하는 함수 이다.

//처음에 UUID KeyChain에서 불러오는데 nil이라면 UUID 생성해서 KeyChain 저장한다.

//저장 후에 다시 함수를 호출 하면 저장된 값을 리턴한다.

- (NSString*) getUUID

{

    // initialize keychaing item for saving UUID.

    KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"UUID" accessGroup:nil];

   

    NSString *uuid = [wrapper objectForKey:(__bridge id)(kSecAttrAccount)];


    if( uuid == nil || uuid.length == 0)

    {

        // if there is not UUID in keychain, make UUID and save it.

        CFUUIDRef uuidRef = CFUUIDCreate(NULL);

        CFStringRef uuidStringRef = CFUUIDCreateString(NULL, uuidRef);

        CFRelease(uuidRef);

        uuid = [NSString stringWithString:(__bridge NSString *) uuidStringRef];

        CFRelease(uuidStringRef);

        

        // save UUID in keychain

        [wrapper setObject:uuid forKey:(__bridge id)(kSecAttrAccount)];

    }

    

    return uuid;

}


KeyChin에 대하여 설명을 하면..

KeychainItemWrapper를 사용하여 키체인에 값을 등록하게 되는데..

- (id)initWithIdentifier: (NSString *)identifier accessGroup:(NSString *) accessGroup


//내부 앱에서만 사용할 경우 

KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"UUID" accessGroup:nil];


//Keychain Group끼리 공유할 경우

KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"UUID" accessGroup:@"???????.com.yourcompany.GenericKeychainSuite"];


KeychainItemWrapper 인스턴스를 생성할 때 저장할 값을 구별할 이름(initWithIdentifier)과 accessGroup을 지정해야 한다.


- accessGroup은 KeyChain Group을 지정하는 것인데 nil이면 내부 앱에서만 사용하는 것이고 nil이 아닌 값을 사용하면 같은 Keychain Group을 사용하는 앱에서 공유가 가능하다.


- Keychain Group을 확인하는 방법은 xcode6에서는 프로젝트 > TARGETS 프로젝트 > capabilities > Keychain Sharing 에서 확인하면 된다. (xcode5, 6)


- (id)objectForKey:(id)key


//키체인에 저장된 값을 가져온다.

NSString *uuid = [wrapper objectForKey:(__bridge id)(kSecAttrAccount)];


- (void)setObject:(id)inObject forKey:(id)key


// 키체인에 저장한다.

[wrapper setObject:uuid forKey:(__bridge id)(kSecAttrAccount)]; 


- KeychainItemWrapper를 사용하여 데이터를 저장할 때 사용할 수 있는 상수는 아래와 같다.

  (https://developer.apple.com/library/ios/documentation/Security/Reference/keychainservices/index.html)

   1) kSecAttrAccount : Account 정보

   2) kSecAttrLabel : 라벨 정보

   3) kSecAttrDescription : 설명

   4) kSecValueData : Data


- 예를들어 암호화된 비밀번호를 저장하기 위해서 kSecValueData를 Key로 하고 암호화된 비밀번호를 InObject로 하면 된다. 로그인 이름을 저장한다면 kSecAttrAccount를 Key로 하고 저장하면 된다.


[참고]

http://10apps.tistory.com/archive/20130403

http://dev-metal.blogspot.kr/2010/08/howto-use-keychain-in-iphone-sdk-to.html



출처: https://reysion.tistory.com/55 [미로의 노트]