瀏覽代碼

Switch from Apple Sample Code to SSKeychain for keychain access

Felix Paul Kühne 10 年之前
父節點
當前提交
3dad4dc4c7
共有 5 個文件被更改,包括 8 次插入405 次删除
  1. 1 0
      Podfile
  2. 0 74
      Sources/KeychainItemWrapper.h
  3. 0 313
      Sources/KeychainItemWrapper.m
  4. 7 12
      Sources/VLCKeychainCoordinator.m
  5. 0 6
      VLC for iOS.xcodeproj/project.pbxproj

+ 1 - 0
Podfile

@@ -13,6 +13,7 @@ pod 'InAppSettingsKit', '2.2.2'
 pod 'upnpx', '1.3.3'
 pod 'SSKeychain'
 pod 'HockeySDK'
+pod 'SSKeychain'
 pod 'box-ios-sdk-v2', :git => 'git://github.com/carolanitz/box-ios-sdk-v2.git', :commit => 'd2df30aa5f76d30910e06f3ef5aff49025de3cf1' #has a logout function added
 
 end

+ 0 - 74
Sources/KeychainItemWrapper.h

@@ -1,74 +0,0 @@
-/*
-     File: KeychainItemWrapper.h
- Abstract: 
- Objective-C wrapper for accessing a single keychain item.
- 
-  Version: 1.2
- 
- Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
- Inc. ("Apple") in consideration of your agreement to the following
- terms, and your use, installation, modification or redistribution of
- this Apple software constitutes acceptance of these terms.  If you do
- not agree with these terms, please do not use, install, modify or
- redistribute this Apple software.
- 
- In consideration of your agreement to abide by the following terms, and
- subject to these terms, Apple grants you a personal, non-exclusive
- license, under Apple's copyrights in this original Apple software (the
- "Apple Software"), to use, reproduce, modify and redistribute the Apple
- Software, with or without modifications, in source and/or binary forms;
- provided that if you redistribute the Apple Software in its entirety and
- without modifications, you must retain this notice and the following
- text and disclaimers in all such redistributions of the Apple Software.
- Neither the name, trademarks, service marks or logos of Apple Inc. may
- be used to endorse or promote products derived from the Apple Software
- without specific prior written permission from Apple.  Except as
- expressly stated in this notice, no other rights or licenses, express or
- implied, are granted by Apple herein, including but not limited to any
- patent rights that may be infringed by your derivative works or by other
- works in which the Apple Software may be incorporated.
- 
- The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
- MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
- THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
- FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
- OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
- 
- IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
- MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
- AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
- STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
- 
- Copyright (C) 2010 Apple Inc. All Rights Reserved.
- 
-*/
-
-#import <UIKit/UIKit.h>
-
-/*
-    The KeychainItemWrapper class is an abstraction layer for the iPhone Keychain communication. It is merely a 
-    simple wrapper to provide a distinct barrier between all the idiosyncracies involved with the Keychain
-    CF/NS container objects.
-*/
-@interface KeychainItemWrapper : NSObject
-{
-    NSMutableDictionary *keychainItemData;		// The actual keychain item data backing store.
-    NSMutableDictionary *genericPasswordQuery;	// A placeholder for the generic keychain item query used to locate the item.
-}
-
-@property (nonatomic, retain) NSMutableDictionary *keychainItemData;
-@property (nonatomic, retain) NSMutableDictionary *genericPasswordQuery;
-
-// Designated initializer.
-- (id)initWithIdentifier: (NSString *)identifier accessGroup:(NSString *) accessGroup;
-- (void)setObject:(id)inObject forKey:(id)key;
-- (id)objectForKey:(id)key;
-
-// Initializes and resets the default generic keychain item data.
-- (void)resetKeychainItem;
-
-@end

+ 0 - 313
Sources/KeychainItemWrapper.m

@@ -1,313 +0,0 @@
-/*
-     File: KeychainItemWrapper.m 
- Abstract: 
- Objective-C wrapper for accessing a single keychain item.
-  
-  Version: 1.2 
-  
- Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple 
- Inc. ("Apple") in consideration of your agreement to the following 
- terms, and your use, installation, modification or redistribution of 
- this Apple software constitutes acceptance of these terms.  If you do 
- not agree with these terms, please do not use, install, modify or 
- redistribute this Apple software. 
-  
- In consideration of your agreement to abide by the following terms, and 
- subject to these terms, Apple grants you a personal, non-exclusive 
- license, under Apple's copyrights in this original Apple software (the 
- "Apple Software"), to use, reproduce, modify and redistribute the Apple 
- Software, with or without modifications, in source and/or binary forms; 
- provided that if you redistribute the Apple Software in its entirety and 
- without modifications, you must retain this notice and the following 
- text and disclaimers in all such redistributions of the Apple Software. 
- Neither the name, trademarks, service marks or logos of Apple Inc. may 
- be used to endorse or promote products derived from the Apple Software 
- without specific prior written permission from Apple.  Except as 
- expressly stated in this notice, no other rights or licenses, express or 
- implied, are granted by Apple herein, including but not limited to any 
- patent rights that may be infringed by your derivative works or by other 
- works in which the Apple Software may be incorporated. 
-  
- The Apple Software is provided by Apple on an "AS IS" basis.  APPLE 
- MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 
- THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 
- FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 
- OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 
-  
- IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 
- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 
- MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 
- AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 
- STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 
- POSSIBILITY OF SUCH DAMAGE. 
-  
- Copyright (C) 2010 Apple Inc. All Rights Reserved. 
-  
-*/ 
-
-#import "KeychainItemWrapper.h"
-#import <Security/Security.h>
-
-/*
-
-These are the default constants and their respective types,
-available for the kSecClassGenericPassword Keychain Item class:
-
-kSecAttrAccessGroup			-		CFStringRef
-kSecAttrCreationDate		-		CFDateRef
-kSecAttrModificationDate    -		CFDateRef
-kSecAttrDescription			-		CFStringRef
-kSecAttrComment				-		CFStringRef
-kSecAttrCreator				-		CFNumberRef
-kSecAttrType                -		CFNumberRef
-kSecAttrLabel				-		CFStringRef
-kSecAttrIsInvisible			-		CFBooleanRef
-kSecAttrIsNegative			-		CFBooleanRef
-kSecAttrAccount				-		CFStringRef
-kSecAttrService				-		CFStringRef
-kSecAttrGeneric				-		CFDataRef
- 
-See the header file Security/SecItem.h for more details.
-
-*/
-
-@interface KeychainItemWrapper (PrivateMethods)
-/*
-The decision behind the following two methods (secItemFormatToDictionary and dictionaryToSecItemFormat) was
-to encapsulate the transition between what the detail view controller was expecting (NSString *) and what the
-Keychain API expects as a validly constructed container class.
-*/
-- (NSMutableDictionary *)secItemFormatToDictionary:(NSDictionary *)dictionaryToConvert;
-- (NSMutableDictionary *)dictionaryToSecItemFormat:(NSDictionary *)dictionaryToConvert;
-
-// Updates the item in the keychain, or adds it if it doesn't exist.
-- (void)writeToKeychain;
-
-@end
-
-@implementation KeychainItemWrapper
-
-@synthesize keychainItemData, genericPasswordQuery;
-
-- (id)initWithIdentifier: (NSString *)identifier accessGroup:(NSString *) accessGroup;
-{
-    if (self = [super init])
-    {
-        // Begin Keychain search setup. The genericPasswordQuery leverages the special user
-        // defined attribute kSecAttrGeneric to distinguish itself between other generic Keychain
-        // items which may be included by the same application.
-        genericPasswordQuery = [[NSMutableDictionary alloc] init];
-        
-		[genericPasswordQuery setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];
-        [genericPasswordQuery setObject:identifier forKey:(id)kSecAttrGeneric];
-		
-		// The keychain access group attribute determines if this item can be shared
-		// amongst multiple apps whose code signing entitlements contain the same keychain access group.
-		if (accessGroup != nil)
-		{
-#if TARGET_IPHONE_SIMULATOR
-			// Ignore the access group if running on the iPhone simulator.
-			// 
-			// Apps that are built for the simulator aren't signed, so there's no keychain access group
-			// for the simulator to check. This means that all apps can see all keychain items when run
-			// on the simulator.
-			//
-			// If a SecItem contains an access group attribute, SecItemAdd and SecItemUpdate on the
-			// simulator will return -25243 (errSecNoAccessForItem).
-#else			
-			[genericPasswordQuery setObject:accessGroup forKey:(id)kSecAttrAccessGroup];
-#endif
-		}
-		
-		// Use the proper search constants, return only the attributes of the first match.
-        [genericPasswordQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
-        [genericPasswordQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes];
-        
-        NSDictionary *tempQuery = [NSDictionary dictionaryWithDictionary:genericPasswordQuery];
-        
-        NSMutableDictionary *outDictionary = nil;
-        
-        if (! SecItemCopyMatching((CFDictionaryRef)tempQuery, (CFTypeRef *)&outDictionary) == noErr)
-        {
-            // Stick these default values into keychain item if nothing found.
-            [self resetKeychainItem];
-			
-			// Add the generic attribute and the keychain access group.
-			[keychainItemData setObject:identifier forKey:(id)kSecAttrGeneric];
-			if (accessGroup != nil)
-			{
-#if TARGET_IPHONE_SIMULATOR
-				// Ignore the access group if running on the iPhone simulator.
-				// 
-				// Apps that are built for the simulator aren't signed, so there's no keychain access group
-				// for the simulator to check. This means that all apps can see all keychain items when run
-				// on the simulator.
-				//
-				// If a SecItem contains an access group attribute, SecItemAdd and SecItemUpdate on the
-				// simulator will return -25243 (errSecNoAccessForItem).
-#else			
-				[keychainItemData setObject:accessGroup forKey:(id)kSecAttrAccessGroup];
-#endif
-			}
-		}
-        else
-        {
-            // load the saved data from Keychain.
-            self.keychainItemData = [self secItemFormatToDictionary:outDictionary];
-        }
-       
-		[outDictionary release];
-    }
-    
-	return self;
-}
-
-- (void)dealloc
-{
-    [keychainItemData release];
-    [genericPasswordQuery release];
-    
-	[super dealloc];
-}
-
-- (void)setObject:(id)inObject forKey:(id)key 
-{
-    if (inObject == nil) return;
-    id currentObject = [keychainItemData objectForKey:key];
-    if (![currentObject isEqual:inObject])
-    {
-        [keychainItemData setObject:inObject forKey:key];
-        [self writeToKeychain];
-    }
-}
-
-- (id)objectForKey:(id)key
-{
-    return [keychainItemData objectForKey:key];
-}
-
-- (void)resetKeychainItem
-{
-	OSStatus junk = noErr;
-    if (!keychainItemData) 
-    {
-        self.keychainItemData = [[NSMutableDictionary alloc] init];
-    }
-    else if (keychainItemData)
-    {
-        NSMutableDictionary *tempDictionary = [self dictionaryToSecItemFormat:keychainItemData];
-		junk = SecItemDelete((CFDictionaryRef)tempDictionary);
-        NSAssert( junk == noErr || junk == errSecItemNotFound, @"Problem deleting current dictionary." );
-    }
-    
-    // Default attributes for keychain item.
-    [keychainItemData setObject:@"" forKey:(id)kSecAttrAccount];
-    [keychainItemData setObject:@"" forKey:(id)kSecAttrLabel];
-    [keychainItemData setObject:@"" forKey:(id)kSecAttrDescription];
-    
-	// Default data for keychain item.
-    [keychainItemData setObject:@"" forKey:(id)kSecValueData];
-}
-
-- (NSMutableDictionary *)dictionaryToSecItemFormat:(NSDictionary *)dictionaryToConvert
-{
-    // The assumption is that this method will be called with a properly populated dictionary
-    // containing all the right key/value pairs for a SecItem.
-    
-    // Create a dictionary to return populated with the attributes and data.
-    NSMutableDictionary *returnDictionary = [NSMutableDictionary dictionaryWithDictionary:dictionaryToConvert];
-    
-    // Add the Generic Password keychain item class attribute.
-    [returnDictionary setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];
-    
-    // Convert the NSString to NSData to meet the requirements for the value type kSecValueData.
-	// This is where to store sensitive data that should be encrypted.
-    NSString *passwordString = [dictionaryToConvert objectForKey:(id)kSecValueData];
-    [returnDictionary setObject:[passwordString dataUsingEncoding:NSUTF8StringEncoding] forKey:(id)kSecValueData];
-    
-    return returnDictionary;
-}
-
-- (NSMutableDictionary *)secItemFormatToDictionary:(NSDictionary *)dictionaryToConvert
-{
-    // The assumption is that this method will be called with a properly populated dictionary
-    // containing all the right key/value pairs for the UI element.
-    
-    // Create a dictionary to return populated with the attributes and data.
-    NSMutableDictionary *returnDictionary = [NSMutableDictionary dictionaryWithDictionary:dictionaryToConvert];
-    
-    // Add the proper search key and class attribute.
-    [returnDictionary setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
-    [returnDictionary setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];
-    
-    // Acquire the password data from the attributes.
-    NSData *passwordData = NULL;
-    if (SecItemCopyMatching((CFDictionaryRef)returnDictionary, (CFTypeRef *)&passwordData) == noErr)
-    {
-        // Remove the search, class, and identifier key/value, we don't need them anymore.
-        [returnDictionary removeObjectForKey:(id)kSecReturnData];
-        
-        // Add the password to the dictionary, converting from NSData to NSString.
-        NSString *password = [[[NSString alloc] initWithBytes:[passwordData bytes] length:[passwordData length] 
-                                                     encoding:NSUTF8StringEncoding] autorelease];
-        [returnDictionary setObject:password forKey:(id)kSecValueData];
-    }
-    else
-    {
-        // Don't do anything if nothing is found.
-        NSAssert(NO, @"Serious error, no matching item found in the keychain.\n");
-    }
-    
-    [passwordData release];
-   
-	return returnDictionary;
-}
-
-- (void)writeToKeychain
-{
-    NSDictionary *attributes = NULL;
-    NSMutableDictionary *updateItem = NULL;
-	OSStatus result;
-    
-    if (SecItemCopyMatching((CFDictionaryRef)genericPasswordQuery, (CFTypeRef *)&attributes) == noErr)
-    {
-        // First we need the attributes from the Keychain.
-        updateItem = [NSMutableDictionary dictionaryWithDictionary:attributes];
-        // Second we need to add the appropriate search key/values.
-        [updateItem setObject:[genericPasswordQuery objectForKey:(id)kSecClass] forKey:(id)kSecClass];
-        
-        // Lastly, we need to set up the updated attribute list being careful to remove the class.
-        NSMutableDictionary *tempCheck = [self dictionaryToSecItemFormat:keychainItemData];
-        [tempCheck removeObjectForKey:(id)kSecClass];
-		
-#if TARGET_IPHONE_SIMULATOR
-		// Remove the access group if running on the iPhone simulator.
-		// 
-		// Apps that are built for the simulator aren't signed, so there's no keychain access group
-		// for the simulator to check. This means that all apps can see all keychain items when run
-		// on the simulator.
-		//
-		// If a SecItem contains an access group attribute, SecItemAdd and SecItemUpdate on the
-		// simulator will return -25243 (errSecNoAccessForItem).
-		//
-		// The access group attribute will be included in items returned by SecItemCopyMatching,
-		// which is why we need to remove it before updating the item.
-		[tempCheck removeObjectForKey:(id)kSecAttrAccessGroup];
-#endif
-        
-        // An implicit assumption is that you can only update a single item at a time.
-		
-        result = SecItemUpdate((CFDictionaryRef)updateItem, (CFDictionaryRef)tempCheck);
-		NSAssert( result == noErr, @"Couldn't update the Keychain Item." );
-    }
-    else
-    {
-        // No previous item found; add the new one.
-        result = SecItemAdd((CFDictionaryRef)[self dictionaryToSecItemFormat:keychainItemData], NULL);
-		NSAssert( result == noErr, @"Couldn't add the Keychain Item." );
-    }
-}
-
-@end

+ 7 - 12
Sources/VLCKeychainCoordinator.m

@@ -13,7 +13,7 @@
 #import "VLCKeychainCoordinator.h"
 #import "PAPasscodeViewController.h"
 #import "VLCAppDelegate.h"
-#import "KeychainItemWrapper.h"
+#import "SSKeychain.h"
 
 NSString *const VLCPasscodeValidated = @"VLCPasscodeValidated";
 
@@ -44,9 +44,7 @@ NSString *const VLCPasscode = @"org.videolan.vlc-ios.passcode";
 
 - (NSString *)_obtainPasscode
 {
-    KeychainItemWrapper *keychain = [[KeychainItemWrapper alloc] initWithIdentifier:VLCPasscode
-                                                                        accessGroup:kVLCApplicationGroupIdentifier];
-    NSString *passcode = [keychain objectForKey:(__bridge id)kSecValueData];
+    NSString *passcode = [SSKeychain passwordForService:VLCPasscode account:VLCPasscode];
 
     if (!passcode) {
         /* legacy passcode retrieval */
@@ -109,15 +107,12 @@ NSString *const VLCPasscode = @"org.videolan.vlc-ios.passcode";
 
 - (void)setPasscode:(NSString *)passcode
 {
-    if (!passcode)
-        passcode = @"";
-
-    KeychainItemWrapper *keychain = [[KeychainItemWrapper alloc] initWithIdentifier:VLCPasscode
-                                                                        accessGroup:kVLCApplicationGroupIdentifier];
-    [keychain setObject:(__bridge id)kSecAttrAccessibleAfterFirstUnlock forKey:(__bridge id)kSecAttrAccessible];
-    [keychain setObject:passcode forKey:(__bridge id)kSecValueData];
+    if (!passcode) {
+        [SSKeychain deletePasswordForService:VLCPasscode account:VLCPasscode];
+        return;
+    }
 
-    keychain = nil;
+    [SSKeychain setPassword:passcode forService:VLCPasscode account:VLCPasscode];
 }
 
 @end

+ 0 - 6
VLC for iOS.xcodeproj/project.pbxproj

@@ -165,7 +165,6 @@
 		7DB638AB185BC0890003887C /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7DB638AA185BC0890003887C /* Images.xcassets */; };
 		7DB847D71A5871570002DC30 /* VLCOneDriveObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DB847D61A5871570002DC30 /* VLCOneDriveObject.m */; };
 		7DBB788A1B30423B00894467 /* VLCKeychainCoordinator.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DBB78891B30423B00894467 /* VLCKeychainCoordinator.m */; };
-		7DBB788D1B305D7E00894467 /* KeychainItemWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DBB788C1B305D7E00894467 /* KeychainItemWrapper.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
 		7DBBF182183AB3B80009A339 /* VLCAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DBBF181183AB3B80009A339 /* VLCAppDelegate.m */; };
 		7DBBF19A183AB4300009A339 /* VLCCloudStorageTableViewCell~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7DBBF185183AB4300009A339 /* VLCCloudStorageTableViewCell~ipad.xib */; };
 		7DBBF19B183AB4300009A339 /* VLCCloudStorageTableViewCell~iphone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7DBBF186183AB4300009A339 /* VLCCloudStorageTableViewCell~iphone.xib */; };
@@ -607,8 +606,6 @@
 		7DB847D61A5871570002DC30 /* VLCOneDriveObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCOneDriveObject.m; path = Sources/VLCOneDriveObject.m; sourceTree = SOURCE_ROOT; };
 		7DBB78881B30423B00894467 /* VLCKeychainCoordinator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCKeychainCoordinator.h; path = Sources/VLCKeychainCoordinator.h; sourceTree = SOURCE_ROOT; };
 		7DBB78891B30423B00894467 /* VLCKeychainCoordinator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCKeychainCoordinator.m; path = Sources/VLCKeychainCoordinator.m; sourceTree = SOURCE_ROOT; };
-		7DBB788B1B305D7E00894467 /* KeychainItemWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KeychainItemWrapper.h; path = Sources/KeychainItemWrapper.h; sourceTree = SOURCE_ROOT; };
-		7DBB788C1B305D7E00894467 /* KeychainItemWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KeychainItemWrapper.m; path = Sources/KeychainItemWrapper.m; sourceTree = SOURCE_ROOT; };
 		7DBBF180183AB3B80009A339 /* VLCAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCAppDelegate.h; path = Sources/VLCAppDelegate.h; sourceTree = SOURCE_ROOT; };
 		7DBBF181183AB3B80009A339 /* VLCAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCAppDelegate.m; path = Sources/VLCAppDelegate.m; sourceTree = SOURCE_ROOT; };
 		7DBBF185183AB4300009A339 /* VLCCloudStorageTableViewCell~ipad.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = "VLCCloudStorageTableViewCell~ipad.xib"; path = "Resources/VLCCloudStorageTableViewCell~ipad.xib"; sourceTree = SOURCE_ROOT; };
@@ -1387,8 +1384,6 @@
 			children = (
 				7DBB78881B30423B00894467 /* VLCKeychainCoordinator.h */,
 				7DBB78891B30423B00894467 /* VLCKeychainCoordinator.m */,
-				7DBB788B1B305D7E00894467 /* KeychainItemWrapper.h */,
-				7DBB788C1B305D7E00894467 /* KeychainItemWrapper.m */,
 			);
 			name = Keychain;
 			sourceTree = "<group>";
@@ -1969,7 +1964,6 @@
 				7D50903218F41C7900180139 /* VLCAlertView.m in Sources */,
 				7DBBF182183AB3B80009A339 /* VLCAppDelegate.m in Sources */,
 				7D3784C0183A9938009EE944 /* VLCLinearProgressIndicator.m in Sources */,
-				7DBB788D1B305D7E00894467 /* KeychainItemWrapper.m in Sources */,
 				DD3EA6311AF50CFE007FF096 /* VLCWatchMessage.m in Sources */,
 				41CD695D1A29D72600E60BCE /* VLCBoxTableViewController.m in Sources */,
 				7D3784C1183A9938009EE944 /* VLCMenuButton.m in Sources */,