Giter VIP home page Giter VIP logo

lockbox's Introduction

Lockbox

Build Status CocoaPods CocoaPods CocoaPods

Lockbox is an Objective-C utility class for storing data securely in the keychain. Use it to store small, sensitive bits of data securely.

Looking for a Swift version? Check out Strongbox.

Overview

There are some bits of data that an app sometimes needs to store that are sensitive:

  • Usernames
  • Passwords
  • In-App Purchase unlocked feature bits
  • and anything else that, if in the wrong hands, would be B-A-D.

The thing to realize is that data stored in NSUserDefaults is stored in the clear! For that matter, most everything stored in your app's sandbox is also there in the clear.

Surprisingly, new and experienced app developers alike often do not realize this, until it's too late.

The Lockbox class methods make it easy to store and retrieve NSStrings, NSArrays, NSSets, NSDictionarys, and NSDates any Foundation-based object that conforms to NSSecureCoding into and from the key chain. You are spared having to deal with the keychain APIs directly!

For greater security, and to avoid possible collisions between data stored by your app with data stored by other apps (yours or other developers), the keys you provide in the class methods for storing and retrieving data are prefixed with your app's bundle id. The class methods provide some convenience by simplifying the use of Lockbox. But if you need to be able to access a common set of keys between your app, and say, an iOS8 extension, you may need to override the key prefix. For that, you can instantiate your own instance of Lockbox, providing your custom key prefix, and call the same methods (as instance methods) as you would call on the class. (The signatures are the same between class and instance methods. In fact, the class methods operate on a class-static Lockbox instance.)

The one caveat to keep in mind is that the keychain is really not meant to store large chunks of data, so don't try and store a huge array of data with these APIs simply because you want it secure. In this case, consider alternative encryption techniques.

Methods

Lockbox 3 includes the following methods, shown here as class methods. The same methods (as instance methods) may be called on your own Lockbox instances.

General object storage and retrieval

  • +archiveObject:forKey:
  • +archiveObject:forKey:accessibility:
  • +unarchiveObject:forKey:

These methods use an NSKeyedArchiver and NSKeyedUnarchiver, respectively, to encode and decode your objects. Your objects must conform toe NSSecureCoding.

The +archiveObject:forKey:... methods return BOOL indicating if the keychain operation succeeded or failed. The method +unarchiveObjectForKey: method returns a non-nil value on success or nil on failure. The returned value is of type id, but you assign this to whatever you know the data type should be. For example:

NSDate *today = [NSDate date];
[Lockbox archiveObject:today forKey:@"theDate"];
...

NSDate *theDate = [Lockbox unarchiveObjectForKey:@"theDate"];

See below for notes on the accessibility argument.

See below for information about migrating from Lockbox v2.x APIs to Lockbox v3 APIs.

Lockbox 2.x and older include the following deprecated methods, shown here as class methods. The same methods (as instance methods) may be called on your own Lockbox instances.

NSString (deprecated)

  • +setString:forKey:
  • +setString:forKey:accessibility:
  • +stringForKey:

NSArray (deprecated)

  • +setArray:forKey:
  • +setArray:forKey:accessibility:
  • +arrayForKey:

NSSet (deprecated)

  • +setSet:forKey:
  • +setSet:forKey:accessibility:
  • +setForKey:

NSDictionary (deprecated)

  • +setDictionary:forKey:
  • +setDictionary:forKey:accessibility:
  • +dictionaryForKey:

NSDate (deprecated)

  • +setDateForKey:
  • +setDateForKey:accessibility:
  • +dateForKey:

All the setXxx methods return BOOL, indicating if the keychain operation succeeded or failed. The xxxForKey methods return a non-nil value on success, or nil on failure.

The setXxx methods will overwrite values for keys that already exist in the keychain, or simply add a keychain entry for the key/value pair if it's not already there.

In all the methods you can use a simple key name, like "MyKey", but know that under the hood Lockbox is prefixing that key with your app's bundle id (if you are using the Class methods, your own key if you are using a Lockbox instance). So the actual key used to store and retrieve the data looks more like "com.mycompany.myapp.MyKey" or "my.custom.key.MyKey". This ensures that your app, and only your app, has access to your data.

The methods with an accessibility argument take a Keychain Item Accessibility Constant. You can use this to control when your keychain item should be readable. For example, passing kSecAttrAccessibleWhenUnlockedThisDeviceOnly will make it accessible only while the device is unlocked, and will not migrate this item to a new device or installation. The methods without a specific accessibility argument will use kSecAttrAccessibleWhenUnlocked, the default in recent iOS versions.

Migrating to Lockbox v3 APIs

There is no automatic migration from the old setXxx methods to the new archive/unarchive methods. In fact, that would be nearly impossible as there is no way to know what you stored for any given key to be able to retrieve the data correctly. The v3 APIs are incompatible with the v2.x APIs.

Manual migration is required. You'll need to fetch your data using the now deprecated type-specific v2.x methods, and then store the data again using the new archiveObjectForKey: method.

You might do this at launch, one time, for all your Lockbox data stored using the old methods. Then make a note by storing another key, either via Lockbox or in User Defaults or somewhere else, that you've done this migration in your app. So on subsequent launches, you wouldn't have to do the migration again. In fact, that would be redundant and probably mess up your data.

ARC Support

As of v2.0, Lockbox is ARC-only. For non-ARC support, use v1.4.9.

Requirements & Limitations

To use this class you will need to add the Security framework to your project.

Your project will have to have Keychain Sharing enabled for Lockbox to access the keychain, but you can remove any Keychain Groups that Xcode adds. The entititlement is apparently required for any keychain access, not just sharing.

This class was written for use under Cocoa Touch and iOS. The code and tests run fine in the iOS simulator under Mac OS. But there are some issues using this class under Cocoa and Mac OS. There are some keychain API differences between the 2 platforms, as it happens. Feel free to fork this repo to make it work for both Cocoa and Cocoa Touch and I'll be happy to consider your pull request!

Note on running unittests on device

If you experience SecItemCopyMatching errors with code 34018 on Lockbox methods while running your app unit tests target on device, your can avoid these by code signing your unit tests .xcttest folder.

Add Run Script phase to your unit tests target Build Phases with:

codesign --verify --force --sign "$CODE_SIGN_IDENTITY" "$CODESIGNING_FOLDER_PATH"

Docs

Link to latest CocoaDocs: cocoadocs.org/docsets/Lockbox/

License

See the LICENSE file for details.

lockbox's People

Contributors

alexkobachijp avatar chrisledet avatar compressed avatar ewertonapolonio avatar granoff avatar humblehacker avatar msnexploder avatar mxsasha avatar rorz avatar stannedelchev avatar thanhturin avatar westonplatter avatar xjki avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lockbox's Issues

Occasional Nil value for String.

At the moment I am using Lockbox to store a sessionToken in keychain.

Occasionally Lockbox returns a nil value when returning the sessionToken string.

Should i be returning the value from Lockbox every time I make a network request, or should I be assigning it to a property within the application when it's first retrieved?

Is there an issue with getting data stored in keychain?

podspec does not define minimum iOS version

The podspec for Lockbox does not state a minimum iOS version. The impact of this appears to be that the system assumes it's been compiled just for the latest version of iOS. This generates this warning:

ld: warning: object file (.../Build/Products/Debug-iphoneos/Lockbox/libLockbox.a(Lockbox-dummy.o)) was built for newer iOS version (11.2) than being linked (9.0)

Doesn't work under iOS 10

When running version 3.0.2 under iOS 10 I get the error:

[Lockbox setData:forKey:accessibility:] [Line 167] SecItemAdd failed for key com.xxx: -34018

I also tried running the same code under iOS 9.3.1 and it seems to work fine.

Lockbox unarchiveObjectForKey: returns nil sometimes

Hello,

I use LockBox to store a refresh token and some urls, but sometimes when I call [Lockbox unarchiveObjectForKey:myKey] it returns nil. I don't know why :/

Here is how I save the data : (the infos came from a WS call)

[Lockbox archiveObject:oauthDico[@"baseUrl"] forKey:kOAuthBaseUrl]; [Lockbox archiveObject:oauthDico[@"getTokenEndpoint"] forKey:kOAuthTokenEndPoint]; [Lockbox archiveObject:oauthDico[@"refreshTokenEndpoint"] forKey:kOAuthRefreshTokenEndPoint];`

and this is how I retrieve it :

NSString* requestUrl = [NSString stringWithFormat:@"%@%@", [Lockbox unarchiveObjectForKey:kOAuthBaseUrl], [Lockbox unarchiveObjectForKey:kOAuthTokenEndPoint]];

and as I told, sometimes, I didn't figured out when excatly, the unarchive method returns nil, which is very problematic for a login url :p

Thanks for your help
Max

Delete item.

Hi,
I am curious about something.Why there are no methods about deleting Item from keychain?Is there any particular reason about this?

Working with Mac

Hi, I am using this file to develop an application for MAC, but the program suspends in

+(BOOL)setString:(NSString *)value forKey:(NSString *)key
{
return [self setString:value forKey:key accessibility:DEFAULT_ACCESSIBILITY]; // here the program suspends
}

screen shot 2014-01-22 at 12 03 27 pm

overwriting keys

this fails for me on the mac on line 3 that tries to set the new key @"1". only the first setting for a key ever succeeds

assert([Lockbox setString:@"1" forKey:@"test"]);
assert([[Lockbox stringForKey:@"test"] isEqualToString:@"1"]);
assert([Lockbox setString:@"2" forKey:@"test"]);
assert([[Lockbox stringForKey:@"test"] isEqualToString:@"2"]);

Add version number

Having a version number would make Dependency Management somewhat easier.
(Especially with CocoaPods - #2)

Upgrading from Swift 2.3 -> 3 leaves old values inaccessible.

I'm running into an unfortunate issue after upgrading from Swift 2.3 to Swift 3. I was initially using Lockbox 1.4.9 to store important values in Keychain. Now that I've upgraded to Swift 3 and updated Lockbox's methods (changing stringForKey to string(forKey:) ), I can't seem to access the stored values anymore as they all return nil. They're still in the keychain as I can still access them when I install the Swift 2.3 version of my app.

What's my best course of action here?

Remove UIKit import

A nit-pick perhaps, but this library doesn't utilize any part of UIKit so its inclusion is puzzling and seemingly unnecessary. Please correct me if I'm wrong though.

Save data for coredata

I am working on rss feed based project. I am saving data which entered by user in coredata. is it possible to it also save in lockbox like [Name , websitename , feedurl]
and when user uninstall app and install again then data will be copies from lockbox to coredata ?

Here is my method for save coredata .

          - (void)feedParserDidFinish:(MWFeedParser *)parser {
                 NSFetchRequest *fetchrequestforside=[NSFetchRequest      fetchRequestWithEntityName:@"Sidetablename"]; //Sidetablename is entity
                 fetchrequestforside.predicate=[NSPredicate predicateWithFormat:@"feedurl = %@", self.Feedlink];
              NSManagedObjectContext *context = [self managedObjectContext];
             if ([[context executeFetchRequest:fetchrequestforside error:NULL] count] == 0) {
                // Create a new managed object

                NSError *error = nil;

                NSPredicate *predicate=[NSPredicate predicateWithFormat:@"feedurl contains %@",check ]; //check is urlstring
                [fetchrequestforside setPredicate:predicate];
                NSMutableArray *checkp = [[context executeFetchRequest:fetchrequestforside error:&error]mutableCopy];


                if (checkp.count<=0) //if coredata will find url then notstore in coredata else storeprocedure
      {

                NSManagedObject *newDevice1 = [NSEntityDescription insertNewObjectForEntityForName:@"Sidetablename" inManagedObjectContext:context];

                if (self.Name)
                {
                    [newDevice1 setValue:self.Name forKey:@"name"];


                }
                if (self.WebsiteName)
                {
                    [newDevice1 setValue:self.WebsiteName forKey:@"websitename"];

                }

                if (self.Feedlink)
                {
                    [newDevice1 setValue:self.Feedlink forKey:@"feedurl"];

                }




                NSError *error = nil;
                if (![context save:&error]) {
                        NSLog(@"Can't Save! %@ %@", error, [error localizedDescription]); // Getting error here through nslog //CoreData: error: (1555) UNIQUE constraint failed: ZSIDETABLENAME.Z_PK

                    }

LockBox doesn't save info in xcode 8

[Lockbox archiveObject:self.passwordTextField.text forKey:kPassword]; [Lockbox archiveObject:self.numberTextField.text forKey:kPhone];

When i try to unarchive it returns nil in simulator, but on the real device it works.
In Xcode 7 it works perfect.

SecItemCopyMatching failed for key

Somewhy I get this in my console when using Lockbox:

+[Lockbox objectForKey:] [Line 110] SecItemCopyMatching failed for key com.magin.MaginSpeedMode.udidKey2: -25308
+[Lockbox setObject:forKey:accessibility:] [Line 94] SecItemAdd failed for key com.magin.MaginSpeedMode.udidKey2: -25308

Wiping Clean Keychain Keys

Hey guys,

My app started prompting an error message for duplicate keys in the keychain [error -25299]:

CKLs-iPhone-5S securityd[78] : securityd_xpc_dictionary_handler MyApp[2571] add The operation couldn’t be completed. (OSStatus error -25299 - duplicate item O,genp,E99372E2,L,ck,XYZ6M5UYJ9.com.mydomain.myapp,0,acct,svce,v_Data,20151218165347.298588Z,2CAE5650)

CKLs-iPhone-5S MyApp[2571] : SecOSStatusWith error:[-25299] The operation couldn’t be completed. (OSStatus error -25299 - Remote error : The operation couldn‚Äôt be completed. (OSStatus error -25299 - duplicate item O,genp,E99372E2,L,ck,XYZ6M5UYJ9.com.mydomain.myapp,0,acct,svce,v_Data,20151218165347.298588Z,2CAE5650))

I couldn't solve it by using the initWithKeyPrefix method, although overriding the _defaultKeyPrefix value within the initialize method solved the problem.

I'd like to know if there is a way to manually clean all keys stored by Lockbox. I imagine this is an issue with the Keychain rather than Lockbox.

Sharing keys with iOS Today Widget

Hi guys,

is that possible to share the lockbox instance and it's data between multiple targets, where one of them is an iOS Widget?

Thanks

memory leak

I noticed a memory leak in my (ARC-only) KCMutableDictionary that I think applies to Lockbox as well. In +objectForKey:, the CFRelease(data) is required for ARC as well as non-ARC. I assume that the reason is that the nature of the return from SecItemCopyMatching (through an argument pointer) isn't, and perhaps can't be, picked up by the analyzer.

iOS 12 Deprecation

Lockbox/Lockbox.m:199:58 'initForWritingWithMutableData:' is deprecated: first deprecated in iOS 12.0 - Use -initRequiringSecureCoding: instead
Lockbox/Lockbox.m:214:68 'initForReadingWithData:' is deprecated: first deprecated in iOS 12.0 - Use -initForReadingFromData:error: instead

I'll probably end up fixing this myself anyway, but if someone beats me to it, all the better.

Migration to archiveObject

I don't see anything in the readme to guide on migration to the new archiveObject and unarchiveObjectForKey methods, so I assumed it was just straightforward change to the name of the method being called, perhaps with casting as needed. Yet after doing this, I'm running into this error when trying to run my app on a device that had previously used the set* commands of the previous version:

2016-02-10 16:24:59.504 iATN[3326:539804] *** Terminating app due to uncaught exception   
'NSInvalidArgumentException', reason: '*** -[NSKeyedUnarchiver initForReadingWithData:]: 
incomprehensible archive (0x50, 0x57, 0x3d, 0x25, 0x62, 0x61, 0x42, 0x25)'
*** First throw call stack:
(0x2b493f8f 0x39b44c8b 0x2b493ed5 0x2c165315 0xac2cc9 0xac3b87 0x16ae90 0x170710 0x16a818 0x16bedc 0x16c21c 0x140514 0x142800 0x2eb810b3 0x2ed77929 0x2ed79fe9 0x2ed84c69 0x2ed7878b 0x3207aec9 0x2b459db5 0x2b459079 0x2b457bb3 0x2b3a3f31 0x2b3a3d43 0x2eb7ac87 0x2eb75879 0x152e84 0x3a0f6aaf)
libc++abi.dylib: terminating with uncaught exception of type NSException

Is there more to the migration than just changing the methods being called, and casting as appropriate?

In my case I was doing some array and string storage with the previous version, in a Swift app.

Lockbox +setDictionary: converts `NSNumber` into `NSString`

Right now if you have a dictionary {@"num": @123}, and you save it into using Lockbox +setDictionary:.
After that if you retrieve it using Lockbox +dictionaryForKey:, you will get {@"num": @"123"}. Notice that what was NSNumber now an NSString.

This may be a limitation by iOS Keychain. But it would be better if the object saved in the dictionary was NSNumber, it should be retrieved back as NSNumber not NSString. Or if this is not possible, at least add a note about this limitation in a comment or something. :)

Thanks!

Lockbox used in cocoa Mac app that did not ovverite my value for same key

i used Lockbox.h and Lockbox.m file in to my mac application for store user_id and session_id after logged in user. But that give me alwasy same id and session id after all i used another logged in id here following is my approach.

AFTER LOGIN:

          NSLog(@"==%@ and sessiong %@",[dict2 objectForKey:@"user_id"],[dict2 objectForKey:@"session_id"]);

             [Lockbox setString:[dict2 objectForKey:@"user_id"] forKey:@"user_id"];
             [Lockbox setString:[dict2 objectForKey:@"session_id"] forKey:@"session_id"];
             [Lockbox setString:[dict2 objectForKey:@"username"] forKey:@"username"];
             [Lockbox setString:@"1" forKey:@"started"];


              NSLog(@"==%@ and sessiong %@",[Lockbox stringForKey:@"user_id"],[Lockbox stringForKey:@"session_id"]);

i got always same NSLog of last printed:

and at logout time i set nil for each stored key:

[Lockbox setString:nil forKey:@"user_id"];
[Lockbox setString:nil forKey:@"session_id"];
[Lockbox setString:nil forKey:@"LastCount"];
[Lockbox setString:nil forKey:@"deviceToken"];
[Lockbox setString:nil forKey:@"lastLoginEmail"];

So my question is that is there anything need to change while we use these class in cocoa mac application. Please help me for this issue

Not work in Xcode 11

An exception occurs when using the library. When used in Xcode 11. I have used it with Objetive C.

cash

Exception Type: EXC_CRASH (SIGKILL)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Termination Reason: Namespace SPRINGBOARD, Code 0x8badf00d
Termination Description: SPRINGBOARD, process-exit watchdog transgression: application<cn.baoxiaosheng.mobile>:18532 exhausted real (wall clock) time allowance of 5.00 seconds | ProcessVisibility: Background | ProcessState: Running | WatchdogEvent: process-exit | WatchdogVisibility: Background | WatchdogCPUStatistics: ( | "Elapsed total CPU time (seconds): 3.810 (user 3.810, system 0.000), 38% CPU", | "Elapsed application CPU time (seconds): 0.042, 0% CPU" | )
Triggered by Thread: 0

Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x00000001a6896634 mach_msg_trap + 8
1 libsystem_kernel.dylib 0x00000001a6895aa0 mach_msg + 72
2 libdispatch.dylib 0x00000001a67487cc _dispatch_mach_send_and_wait_for_reply + 564
3 libdispatch.dylib 0x00000001a6748b94 dispatch_mach_send_with_result_and_wait_for_reply$VARIANT$mp + 52
4 libxpc.dylib 0x00000001a668c440 xpc_connection_send_message_with_reply_sync + 236
5 Security 0x00000001a78eb224 securityd_message_with_reply_sync + 96
6 Security 0x00000001a78ebc38 securityd_send_sync_and_do + 80
7 Security 0x00000001a796c17c __SecItemCopyMatching_block_invoke_2 + 236
8 Security 0x00000001a796b054 __SecItemAuthDoQuery_block_invoke + 312
9 Security 0x00000001a796992c SecItemAuthDo + 124
10 Security 0x00000001a796a2d4 SecItemAuthDoQuery + 552
11 Security 0x00000001a796c084 __SecItemCopyMatching_block_invoke + 104
12 Security 0x00000001a7967f48 SecOSStatusWith + 48
13 Security 0x00000001a796a6f4 SecItemCopyMatching + 348
14 baoxs 0x0000000100b9556c -[Lockbox dataForKey:] + 3200364 (Lockbox.m:180)
15 baoxs 0x0000000100b9572c -[Lockbox unarchiveObjectForKey:] + 3200812 (Lockbox.m:0)
16 baoxs 0x00000001008f05c4 +[BXSUserManager isUserLoggedIn] + 427460 (BXSUserManager.m:0)

Add framework

Would be nice to have a framework target for those of us building for iOS8+ and using tools like Carthage.

How to save NSData in Dictionary format

Hello,
I have been using your project for a long time now and I really like the simplicity it provides to using keychains safely. However, I was curious to know how one would save NSData into a NSMutableDictionary, and saving that dictionary into the keychain using Lockbox?

My scenario is as follows:

  1. I'm using Realm (https://realm.io/) with encryption for my persistent data storage, and would like to store the key in the keychain using Lockbox
  2. Realm has a strict requirement that the key be exactly 64 bytes long.
  3. The password is to be stored inside a NSMutableDictionary, which is persisted in the keychain via Lockbox. This is because our platform can be used by multiple users, and we want to keep user details grouped up together via using a dictionary

I'm noticing that when I retrieve the value from Lockbox, the value is a NSString, and is also much longer in length. If memory serves correctly, a 64 byte length NSData became 160+ byte length NSString.

Thanks

Question: Is it time to drop non-ARC support?

I think its time to move this class forward. With iOS8's release imminent, and ARC now available for years, the conditional code in Lockbox to support both ARC and non-ARC is cluttering things up (IMO).

What do people think: Continue to mainting the ARC/non-ARC conditional code, or dump it soon?

Comments welcome. Thanks!

Exception thrown when unarchiveObjectForKey called on ios 8

Hi,

I have notice that because the use of[[NSKeyedUnarchiver alloc] initForReadingWithData:data],
It will throw NSInvalidArgumentException
[NSKeyedUnarchiver initForReadingWithData:]: incomprehensible archive (xxx,xxx,xxx,0x0, 0x0, 0x0, 0x0, 0x0)

This only happens on ios8 ... it won't happen on ios9 ...
but It think it might be safer to catch the exception within unarchiveObjectForKey.. so ppl using this library won't have unexpected exception happen to them
Thanks

SecItemCopy and SecItemAdd errors

Below is a sample code snippet from my program. I originally was trying to store an NSArray in keychain but when I retrieved it it would no longer be an array of GLAAccount *objects, but an array of strings, so I could not access the property on the objects in the array. Now I encode the object's properties into a string and then decode it after I pull it from the keychain using class methods for the object class, in this case GLAAccount. Occasionally, when I pass data to the view controller the below code is in, the saveAccess method is run and I get a secAddItem error and if I load the data from keychain I get a secCopyItemError. I have set the accessibility as
kSecAttrAccessibleWhenUnlocked. Any thoughts?

//save data from self.accounts in keychain
- (void)saveAccess{
    //clean up the stringArray
    [self.stringArray removeAllObjects];

    //encode every account into a string and add it to string array
    for(GLAAccount *account in self.accounts){
        NSString *string = [GLAAccount encodeAccountObject:account];
        [self.stringArray addObject:string];
    }

    //save string array into keychain
    NSString *key = [NSString stringWithFormat:@"%@accounts", self.currentUser.username];
    [Lockbox setArray:self.stringArray forKey:key accessibility:kSecAttrAccessibleWhenUnlocked];
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.