XYKeyChain.m 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. //
  2. // XYKeyChain.m
  3. // XYUUID
  4. //
  5. // Created by steve on 2016/7/21.
  6. // Copyright © 2020 guojunliu.github.io. All rights reserved.
  7. //
  8. #import "XYKeyChain.h"
  9. #import <Security/Security.h>
  10. @implementation XYKeyChain
  11. + (NSMutableDictionary *)getKeychainQueryMap:(NSString *)serviceDomain {
  12. NSMutableDictionary *queryMap = [[NSMutableDictionary alloc] init];
  13. [queryMap setObject:serviceDomain forKey:(__bridge id<NSCopying>)kSecAttrAccount];
  14. [queryMap setObject:serviceDomain forKey:(__bridge id<NSCopying>)kSecAttrService];
  15. [queryMap setObject:(__bridge id)(kSecClassGenericPassword) forKey:(__bridge id<NSCopying>)kSecClass];
  16. [queryMap setObject:(__bridge id)kSecAttrAccessibleAfterFirstUnlock forKey:(__bridge id<NSCopying>)kSecAttrAccessible];
  17. return queryMap;
  18. }
  19. + (BOOL)setData:(id)data serviceDomain:(NSString *)serviceDomain {
  20. NSMutableDictionary *queryMap = [self getKeychainQueryMap:serviceDomain];
  21. SecItemDelete((__bridge CFDictionaryRef)(queryMap));
  22. NSData *archivedData;
  23. if (@available(iOS 13.0, macOS 13.0, *)) {
  24. NSError *error;
  25. archivedData = [NSKeyedArchiver archivedDataWithRootObject:data requiringSecureCoding:YES error:&error];
  26. if (error) {
  27. return NO;
  28. }
  29. }
  30. else {
  31. archivedData = [NSKeyedArchiver archivedDataWithRootObject:data];
  32. }
  33. [queryMap setObject:archivedData forKey:(__bridge id<NSCopying>)(kSecValueData)];
  34. OSStatus status = SecItemAdd((__bridge CFDictionaryRef)(queryMap), NULL);
  35. return status == errSecSuccess?YES:NO;
  36. }
  37. + (id)getDataWithServiceDomain:(NSString *)serviceDomain {
  38. id data = nil;
  39. NSMutableDictionary *queryMap = [self getKeychainQueryMap:serviceDomain];
  40. [queryMap setObject:(id)kCFBooleanTrue forKey:(__bridge id<NSCopying>)(kSecReturnData)];
  41. [queryMap setObject:(__bridge id)(kSecMatchLimitOne) forKey:(__bridge id<NSCopying>)(kSecMatchLimit)];
  42. CFTypeRef result = NULL;
  43. CFDictionaryRef cfDicRef = (__bridge_retained CFDictionaryRef)queryMap;
  44. if (SecItemCopyMatching(cfDicRef, &result) == noErr) {
  45. if (@available(iOS 13.0, *)) {
  46. NSError *error;
  47. data = [NSKeyedUnarchiver unarchivedObjectOfClass:[NSString class] fromData:(__bridge NSData*)result error:&error];
  48. }
  49. else {
  50. data = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData*)result];
  51. }
  52. CFRelease(result);
  53. }
  54. return data;
  55. }
  56. + (BOOL)deleteDataWithServiceDomain:(NSString *)serviceDomain {
  57. NSMutableDictionary *queryMap = [self getKeychainQueryMap:serviceDomain];
  58. OSStatus status = SecItemDelete((__bridge CFDictionaryRef)(queryMap));
  59. return status == errSecSuccess?YES:NO;
  60. }
  61. @end